From e8749bfa2bcf0582f7fa93699b4eb9d5924785e8 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Sat, 1 Oct 2011 10:48:00 +0200 Subject: beta 2011.10.01 10:48 --- tex/context/base/char-def.lua | 1 - tex/context/base/cont-new.mkii | 2 +- tex/context/base/cont-new.mkiv | 2 +- tex/context/base/context-version.pdf | Bin 4090 -> 4093 bytes tex/context/base/context-version.png | Bin 105529 -> 104816 bytes tex/context/base/context.mkii | 2 +- tex/context/base/context.mkiv | 8 +- tex/context/base/core-def.mkiv | 10 +- tex/context/base/core-two.lua | 14 +- tex/context/base/core-uti.lua | 85 +- tex/context/base/file-job.lua | 62 +- tex/context/base/file-job.mkvi | 89 +- tex/context/base/font-ini.mkiv | 16 +- tex/context/base/lpdf-ano.lua | 13 +- tex/context/base/mult-mes.lua | 11 +- tex/context/base/node-ref.lua | 7 +- tex/context/base/s-mag-01.tex | 2 +- tex/context/base/status-files.pdf | Bin 23886 -> 23917 bytes tex/context/base/status-lua.pdf | Bin 162417 -> 162771 bytes tex/context/base/strc-des.mkiv | 2 +- tex/context/base/strc-doc.lua | 49 +- tex/context/base/strc-lst.lua | 55 +- tex/context/base/strc-pag.lua | 38 +- tex/context/base/strc-ref.lua | 1553 +++++++++-------- tex/context/base/strc-ref.mkiv | 1830 -------------------- tex/context/base/strc-ref.mkvi | 1732 ++++++++++++++++++ tex/context/base/strc-rsc.lua | 154 ++ tex/context/base/tabl-tsp.mkiv | 3 +- tex/context/base/type-one.mkii | 124 ++ tex/context/base/util-pck.lua | 44 +- tex/context/base/util-sto.lua | 8 +- tex/context/base/util-tab.lua | 21 +- tex/generic/context/luatex/luatex-fonts-merged.lua | 2 +- 33 files changed, 3222 insertions(+), 2717 deletions(-) delete mode 100644 tex/context/base/strc-ref.mkiv create mode 100644 tex/context/base/strc-ref.mkvi create mode 100644 tex/context/base/strc-rsc.lua (limited to 'tex') diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua index 28d46ee93..7d16f193e 100644 --- a/tex/context/base/char-def.lua +++ b/tex/context/base/char-def.lua @@ -186695,4 +186695,3 @@ characters.data={ unicodeslot=0xE01EF, }, } - diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii index 20a06246e..df1d5f965 100644 --- a/tex/context/base/cont-new.mkii +++ b/tex/context/base/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2011.09.27 20:05} +\newcontextversion{2011.10.01 10:48} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv index 41106bfc6..e016a0439 100644 --- a/tex/context/base/cont-new.mkiv +++ b/tex/context/base/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2011.09.27 20:05} +\newcontextversion{2011.10.01 10:48} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf index 1347294c2..cc6037196 100644 Binary files a/tex/context/base/context-version.pdf and b/tex/context/base/context-version.pdf differ diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png index 4fe6a22e5..b60bce49d 100644 Binary files a/tex/context/base/context-version.png and b/tex/context/base/context-version.png differ diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii index 454c8fcae..6992af5ef 100644 --- a/tex/context/base/context.mkii +++ b/tex/context/base/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2011.09.27 20:05} +\edef\contextversion{2011.10.01 10:48} %D For those who want to use this: diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv index 0a44b2efb..5ff6de2ce 100644 --- a/tex/context/base/context.mkiv +++ b/tex/context/base/context.mkiv @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2011.09.27 20:05} +\edef\contextversion{2011.10.01 10:48} %D For those who want to use this: @@ -186,6 +186,8 @@ \loadmarkfile{lang-def} \loadmarkfile{lang-wrd} % can be optional +\loadmkvifile{file-job} % why so late? + \loadmarkfile{symb-ini} \loadmarkfile{sort-ini} @@ -210,7 +212,7 @@ \loadmarkfile{strc-ren} \loadmarkfile{strc-xml} \loadmarkfile{strc-def} % might happen later -\loadmarkfile{strc-ref} +\loadmkvifile{strc-ref} \loadmarkfile{strc-reg} \loadmarkfile{strc-lev} % experiment @@ -259,7 +261,7 @@ %loadmarkfile{page-mar} % also commented code in anch-pgr.mkiv \loadmarkfile{typo-mar} -\loadmkvifile{file-job} % why so late? +% \loadmkvifile{file-job} % why so late? \loadmarkfile{buff-ini} \loadmarkfile{buff-ver} diff --git a/tex/context/base/core-def.mkiv b/tex/context/base/core-def.mkiv index b341dd91b..9022044d7 100644 --- a/tex/context/base/core-def.mkiv +++ b/tex/context/base/core-def.mkiv @@ -67,17 +67,9 @@ % temporary here: -\ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \dospecialin } \else \let\in \dospecialin \fi -\ifdefined\at \let\normalmathat \at \unexpanded\def\at {\mathortext\normalmathat \dospecialat } \else \let\at \dospecialat \fi -\ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\dospecialabout} \else \let\about\dospecialabout \fi -\ifdefined\from \let\normalmathfrom \from \unexpanded\def\from {\mathortext\normalmathfrom \dospecialfrom } \else \let\from \dospecialfrom \fi -\ifdefined\over \let\normalmathover \over \unexpanded\def\over {\mathortext\normalmathover \dospecialabout} \else \let\over \dospecialabout \fi - \unexpanded\def\arg{\mathortext\normalmatharg\normaltextarg} -% for the moment here - -\enablemode[*nofonts] +% might move to \everydump or even disappear: \nonknuthmode diff --git a/tex/context/base/core-two.lua b/tex/context/base/core-two.lua index 1c0680ad8..f94b102bc 100644 --- a/tex/context/base/core-two.lua +++ b/tex/context/base/core-two.lua @@ -140,13 +140,13 @@ jobpasses.inlist = inlist -- interface -function commands.gettwopassdata (id) local r = get (id) if r then context(r) end end -function commands.getfirsttwopassdata(id) local r = first(id) if r then context(r) end end -function commands.getlasttwopassdata (id) local r = last (id) if r then context(r) end end -function commands.findtwopassdata (id) local r = find (id) if r then context(r) end end -function commands.gettwopassdatalist (id) local r = list (id) if r then context(r) end end -function commands.counttwopassdata (id) local r = count(id) if r then context(r) end end -function commands.checktwopassdata (id) local r = check(id) if r then context(r) end end +function commands.gettwopassdata (id) local r = get (id) if r then context(r) end end +function commands.getfirsttwopassdata(id) local r = first(id) if r then context(r) end end +function commands.getlasttwopassdata (id) local r = last (id) if r then context(r) end end +function commands.findtwopassdata (id,n) local r = find (id,n) if r then context(r) end end +function commands.gettwopassdatalist (id) local r = list (id) if r then context(r) end end +function commands.counttwopassdata (id) local r = count(id) if r then context(r) end end +function commands.checktwopassdata (id) local r = check(id) if r then context(r) end end commands.definetwopasslist = jobpasses.define commands.savetwopassdata = jobpasses.save diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua index 02411f13d..ca699d297 100644 --- a/tex/context/base/core-uti.lua +++ b/tex/context/base/core-uti.lua @@ -19,9 +19,11 @@ saves much runtime but at the cost of more memory usage.

local format, match = string.format, string.match local next, type, tostring = next, type, tostring +local concat = table.concat local definetable = utilities.tables.definetable local accesstable = utilities.tables.accesstable +local migratetable = utilities.tables.migratetable local serialize = table.serialize local packers = utilities.packers local allocate = utilities.storage.allocate @@ -32,7 +34,7 @@ local report_jobcontrol = logs.reporter("jobcontrol") job = job or { } local job = job -job.version = 1.14 +job.version = 1.15 -- some day we will implement loading of other jobs and then we need -- job.jobs @@ -66,7 +68,7 @@ end -- as an example we implement variables -local tobesaved, collected, checksums = allocate(), allocate(), allocate() +local tobesaved, collected, checksums = allocate(), allocate(), allocate() local jobvariables = { collected = collected, @@ -125,9 +127,9 @@ local jobpacker = packers.new(packlist,1.01) job.pack = true -local _save_, _load_ = { }, { } -- registers timing +local _save_, _load_, _others_ = { }, { }, { } -- registers timing -function job.save(filename) +function job.save(filename) -- we could return a table but it can get pretty large statistics.starttiming(_save_) local f = io.open(filename,'w') if f then @@ -135,9 +137,13 @@ function job.save(filename) f:write("-- ",comment[c],"\n") end f:write("\n") + f:write("local utilitydata = { }\n") + f:write("\n") for l=1,#savelist do - local list = savelist[l] - local target, data, finalizer = list[1], list[2], list[4] + local list = savelist[l] + local target = format("utilitydata.%s",list[1]) + local data = list[2] + local finalizer = list[4] if type(finalizer) == "function" then finalizer() end @@ -149,15 +155,17 @@ function job.save(filename) end if job.pack then packers.strip(jobpacker) - f:write(serialize(jobpacker,"job.packed",true,true),"\n") + f:write(serialize(jobpacker,"utilitydata.job.packed",true,true),"\n") end + f:write("\n") + f:write("return utilitydata\n") + f:write("\n") f:close() end statistics.stoptiming(_save_) end -function job.load(filename) - statistics.starttiming(_load_) +local function load(filename) local data = io.loaddata(filename) if data and data ~= "" then local version = tonumber(match(data,"^-- version: ([%d%.]+)")) @@ -165,24 +173,51 @@ function job.load(filename) report_jobcontrol("version mismatch with jobfile: %s <> %s", version or "?", job.version) else local data = loadstring(data) - if data then - data() - end - for l=1,#savelist do - local list = savelist[l] - local target, initializer = list[1], list[3] - local result = mark(accesstable(target)) - packers.unpack(result,job.packed,true) - if type(initializer) == "function" then - initializer(result) - end + return data and data() + end + end +end + +function job.load(filename) + statistics.starttiming(_load_) + local utilitydata = load(filename) + if utilitydata then + local jobpacker = utilitydata.job.packed + for l=1,#savelist do + local list = savelist[l] + local target = list[1] + local initializer = list[3] + local result = accesstable(target,utilitydata) + packers.unpack(result,jobpacker,true) + migratetable(target,mark(result)) + if type(initializer) == "function" then + initializer(result) end - job.packed = nil end end statistics.stoptiming(_load_) end +function job.loadother(filename) + statistics.starttiming(_load_) + _others_[#_others_+1] = file.nameonly(filename) + local utilitydata = load(filename) + if utilitydata then + local jobpacker = utilitydata.job.packed + local unpacked = { } + for l=1,#savelist do + local list = savelist[l] + local target = list[1] + local result = accesstable(target,utilitydata) + packers.unpack(result,jobpacker,true) + migratetable(target,result,unpacked) + end + unpacked.job.packed = nil -- nicer in inspecting + return unpacked + end + statistics.stoptiming(_load_) +end + -- eventually this will end up in strc-ini statistics.register("startup time", function() @@ -190,8 +225,12 @@ statistics.register("startup time", function() end) statistics.register("jobdata time",function() - if statistics.elapsedindeed(_save_) or statistics.elapsedindeed(_load_) then - return format("%s seconds saving, %s seconds loading", statistics.elapsedtime(_save_), statistics.elapsedtime(_load_)) + if statistics.elapsedindeed(_save_) or statistics.elapsedindeed(_load_) or #_others_ > 0 then + if #_others_ > 0 then + return format("%s seconds saving, %s seconds loading, other files: %s", statistics.elapsedtime(_save_), statistics.elapsedtime(_load_),concat(_others_," ")) + else + return format("%s seconds saving, %s seconds loading", statistics.elapsedtime(_save_), statistics.elapsedtime(_load_)) + end end end) diff --git a/tex/context/base/file-job.lua b/tex/context/base/file-job.lua index 2004cdb85..56bd1d92d 100644 --- a/tex/context/base/file-job.lua +++ b/tex/context/base/file-job.lua @@ -31,6 +31,7 @@ local v_project = variables.project local v_environment = variables.environment local v_product = variables.product local v_component = variables.component +local c_prefix = variables.prefix -- main code .. there is some overlap .. here we have loc:// @@ -346,11 +347,16 @@ local treestack = { } local top = tree.branches local root = tree +local project_stack = { } +local product_stack = { } +local component_stack = { } +local environment_stack = { } + local stacks = { - [v_project ] = { }, - [v_product ] = { }, - [v_component ] = { }, - [v_environment] = { }, + [v_project ] = project_stack, + [v_product ] = product_stack, + [v_component ] = component_stack, + [v_environment] = environment_stack, } -- @@ -396,6 +402,12 @@ end luatex.registerstopactions(logtree) +job.structure = job.structure or { } +job.structure.collected = job.structure.collected or { } +job.structure.tobesaved = root + +job.register('job.structure.collected',root) + -- component: small unit, either or not components itself -- product : combination of components @@ -467,6 +479,29 @@ local function topofstack(what) return stack and stack[#stack] or environment.jobname end +local function currentcomponent() -- only when in product + local product = product_stack[#product_stack] + if product and product ~= "" then + local component = component_stack[1] + if component and component ~= "" then + return component + end + end +end + +local function justacomponent() + local product = product_stack[#product_stack] + if not product or product == "" then + local component = component_stack[1] + if component and component ~= "" then + return component + end + end +end + +resolvers.jobs.currentcomponent = currentcomponent +resolvers.jobs.justacomponent = justacomponent + local done = { } local tolerant = false -- too messy, mkii user with the wrong sructure should adapt @@ -530,20 +565,21 @@ function commands.useenvironment(name) process(v_environment,name) end function commands.useproduct (name) process(v_product, name) end function commands.usecomponent (name) process(v_component, name) end --- -- todo: setsystemmode to currenttype +-- todo: setsystemmode to currenttype +-- todo: make start/stop commands at the tex end local start = { - [v_project] = context.starttext, - [v_product] = context.starttext, - [v_component] = context.starttext, - [v_environment] = nil, + [v_project] = context.startprojectindeed, + [v_product] = context.startproductindeed, + [v_component] = context.startcomponentindeed, + [v_environment] = context.startenvironmentindeed, } local stop = { - [v_project] = function() context.stoptext() context.signalendofinput(v_project) end, - [v_product] = function() context.stoptext() context.signalendofinput(v_product) end, - [v_component] = function() context.stoptext() context.signalendofinput(v_component) end, - [v_environment] = function() context.signalendofinput(v_environment) end, + [v_project] = context.stopprojectindeed, + [v_product] = context.stopproductindeed, + [v_component] = context.stopcomponentindeed, + [v_environment] = context.stopenvironmentindeed, } local function gotonextlevel(what,name) -- todo: something with suffix name diff --git a/tex/context/base/file-job.mkvi b/tex/context/base/file-job.mkvi index 47509754b..0213ff910 100644 --- a/tex/context/base/file-job.mkvi +++ b/tex/context/base/file-job.mkvi @@ -107,35 +107,35 @@ \unexpanded\def\processfileonce #name{\ctxcommand{processfileonce("#name")}} \unexpanded\def\processfilenone #name{\ctxcommand{processfilenone("#name")}} -\unexpanded\def\project {\doifnextoptionalelse\useproject \redoproject} -\unexpanded\def\product {\doifnextoptionalelse\useproduct \redoproduct} -\unexpanded\def\component {\doifnextoptionalelse\usecomponent \redocomponent} -\unexpanded\def\environment {\doifnextoptionalelse\useenvironment\redoenvironment} - -\def\redoproject #name {\ctxcommand{useproject ("#name")}} -\def\redoproduct #name {\ctxcommand{useproduct ("#name")}} -\def\redocomponent #name {\ctxcommand{usecomponent ("#name")}} -\def\redoenvironment #name {\ctxcommand{useenvironment("#name")}} - -\unexpanded\def\startproject {\doifnextoptionalelse\dostartproject \redostartproject} -\unexpanded\def\startproduct {\doifnextoptionalelse\dostartproduct \redostartproduct} -\unexpanded\def\startcomponent {\doifnextoptionalelse\dostartcomponent \redostartcomponent} -\unexpanded\def\startenvironment {\doifnextoptionalelse\dostartenvironment\redostartenvironment} - -\def\redostartproject #name {\ctxcommand{startproject ("#name")}} -\def\redostartproduct #name {\ctxcommand{startproduct ("#name")}} -\def\redostartcomponent #name {\ctxcommand{startcomponent ("#name")}} -\def\redostartenvironment #name {\ctxcommand{startenvironment("#name")}} - -\unexpanded\def\useproject [#name]{\ctxcommand{useproject ("#name")}} -\unexpanded\def\useproduct [#name]{\ctxcommand{useproduct ("#name")}} -\unexpanded\def\usecomponent [#name]{\ctxcommand{usecomponent ("#name")}} -\unexpanded\def\useenvironment [#name]{\ctxcommand{useenvironment("#name")}} - -\unexpanded\def\dostartproject [#name]{\ctxcommand{startproject ("#name")}} -\unexpanded\def\dostartproduct [#name]{\ctxcommand{startproduct ("#name")}} -\unexpanded\def\dostartcomponent [#name]{\ctxcommand{startcomponent ("#name")}} -\unexpanded\def\dostartenvironment[#name]{\ctxcommand{startenvironment("#name")}} +\unexpanded\def\project {\doifnextoptionalelse\useproject \do_project} +\unexpanded\def\product {\doifnextoptionalelse\useproduct \do_product} +\unexpanded\def\component {\doifnextoptionalelse\usecomponent \do_component} +\unexpanded\def\environment {\doifnextoptionalelse\useenvironment\do_environment} + +\def\do_project #name {\ctxcommand{useproject ("#name")}} +\def\do_product #name {\ctxcommand{useproduct ("#name")}} +\def\do_component #name {\ctxcommand{usecomponent ("#name")}} +\def\do_environment #name {\ctxcommand{useenvironment("#name")}} + +\unexpanded\def\startproject {\doifnextoptionalelse\do_startproject \redo_startproject} +\unexpanded\def\startproduct {\doifnextoptionalelse\do_startproduct \redo_startproduct} +\unexpanded\def\startcomponent {\doifnextoptionalelse\do_startcomponent \redo_startcomponent} +\unexpanded\def\startenvironment {\doifnextoptionalelse\do_startenvironment\redo_startenvironment} + +\def\redo_startproject #name {\ctxcommand{startproject ("#name")}} +\def\redo_startproduct #name {\ctxcommand{startproduct ("#name")}} +\def\redo_startcomponent #name {\ctxcommand{startcomponent ("#name")}} +\def\redo_startenvironment #name {\ctxcommand{startenvironment("#name")}} + +\unexpanded\def\useproject [#name]{\do_project {#name}} +\unexpanded\def\useproduct [#name]{\do_product {#name}} +\unexpanded\def\usecomponent [#name]{\do_component {#name}} +\unexpanded\def\useenvironment [#name]{\do_environment{#name}} + +\unexpanded\def\do_startproject [#name]{\ctxcommand{startproject ("#name")}} +\unexpanded\def\do_startproduct [#name]{\ctxcommand{startproduct ("#name")}} +\unexpanded\def\do_startcomponent [#name]{\ctxcommand{startcomponent ("#name")}} +\unexpanded\def\do_startenvironment[#name]{\ctxcommand{startenvironment("#name")}} \newconditional\endofinput % hack, needed because \endinput happens one level down in the input when we write from lua @@ -203,4 +203,35 @@ \neverypar\emptytoks +%D Wrappers (the signal is a synchronization with lua hack): + +\def\startprojectindeed + {\starttext} + +\def\stopprojectindeed + {\stoptext + \signalendofinput\v!project} + +\def\startproductindeed + {\starttext} + +\def\stopproductindeed + {\stoptext + \signalendofinput\v!product} + +\def\startcomponentindeed + {\starttext + \pushreferenceprefix\currentcomponent} + +\def\stopcomponentindeed + {\popreferenceprefix + \stoptext + \signalendofinput\v!component} + +\def\startenvironmentindeed + {} + +\def\stopenvironmentindeed + {\signalendofinput\v!project} + \protect \endinput diff --git a/tex/context/base/font-ini.mkiv b/tex/context/base/font-ini.mkiv index 37455551c..783d16820 100644 --- a/tex/context/base/font-ini.mkiv +++ b/tex/context/base/font-ini.mkiv @@ -2396,13 +2396,19 @@ \everyvbox{\zerostagepreloadfonts} \to \everydump -\def\firststagepreloadfonts % see core-def.mkiv - {\doifmodeelse{*nofonts} - {\writestatus\m!fonts{latin modern fonts are not preloaded}} +% \def\firststagepreloadfonts % see core-def.mkiv +% {\doifmodeelse{*nofonts} +% {\writestatus\m!fonts{latin modern fonts are not preloaded}} +% {\preloaddefaultfonts +% \writestatus\m!fonts{preloading latin modern fonts (first stage)}}} + +\def\firststagepreloadfonts % *nofonts -> *preloadfonts + {\doifmodeelse{*preloadfonts} {\preloaddefaultfonts - \writestatus\m!fonts{preloading latin modern fonts (first stage)}}} + \writestatus\m!fonts{preloading latin modern fonts (first stage)}} + {\writestatus\m!fonts{latin modern fonts are not preloaded}}} -\def\secondstagepreloadfonts % see core-def.mkiv +\def\secondstagepreloadfonts {\writestatus\m!fonts{preloading latin modern fonts (second stage)}% \preloaddefaultfonts} diff --git a/tex/context/base/lpdf-ano.lua b/tex/context/base/lpdf-ano.lua index ece0f7de3..eb85c3dea 100644 --- a/tex/context/base/lpdf-ano.lua +++ b/tex/context/base/lpdf-ano.lua @@ -323,10 +323,15 @@ end runners["inner"] = function(var,actions) if getinnermethod() == "names" then - local vir = var.i.references - local internal = vir and vir.internal - if internal then - var.inner = "aut:" .. internal + local vi = var.i + if vi then + local vir = vi.references + if vir then + local internal = vir.internal + if internal then + var.inner = "aut:" .. internal + end + end end else var.inner = nil diff --git a/tex/context/base/mult-mes.lua b/tex/context/base/mult-mes.lua index cdd6d5ad2..473c86d35 100644 --- a/tex/context/base/mult-mes.lua +++ b/tex/context/base/mult-mes.lua @@ -1097,14 +1097,15 @@ return { no = "ulovlig referanse %s", ro = "referinta eronata %s", }, - ["references:5"] = { - en = "number of unknown references: %s", - }, + -- ["number of unknown references: %s"] = { + -- }, ["references:6"] = { en = "number of illegal references: %s", }, - ["start: '%s'"] = {}, - ["stop: '%s'"] = {}, + ["start: '%s'"] = { + }, + ["stop: '%s'"] = { + }, ["stored: preamble '%s', state '%s', order '%s'"] = { nl = "opgeslagen: preamble '%s', status '%s', volgorde '%s'", }, diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua index 278a40b6e..b19ef5589 100644 --- a/tex/context/base/node-ref.lua +++ b/tex/context/base/node-ref.lua @@ -376,11 +376,10 @@ nodes.references = { -- todo: get rid of n (n is just a number, can be used for tracing, obsolete) -local function setreference(n,h,d,r) +local function setreference(h,d,r) topofstack = topofstack + 1 -- the preroll permits us to determine samepage (but delayed also has some advantages) -- so some part of the backend work is already done here ---~ stack[topofstack] = { n, h, d, codeinjections.prerollreference(r) } stack[topofstack] = { r, h, d, codeinjections.prerollreference(r) } -- texattribute[attribute] = topofstack -- todo -> at tex end texcount.lastreferenceattribute = topofstack @@ -533,14 +532,14 @@ function references.inject(prefix,reference,h,d,highlight,newwindow,layer) -- to else -- check set.highlight, set.newwindow,set.layer = highlight, newwindow, layer - setreference(tex.currentgrouplevel,h,d,set) -- sets attribute / todo: for set[*].error + setreference(h,d,set) -- sets attribute / todo: for set[*].error end end function references.injectcurrentset(h,d) -- used inside doifelse local currentset = references.currentset if currentset then - setreference(tex.currentgrouplevel,h,d,currentset) -- sets attribute / todo: for set[*].error + setreference(h,d,currentset) -- sets attribute / todo: for set[*].error end end diff --git a/tex/context/base/s-mag-01.tex b/tex/context/base/s-mag-01.tex index 6591fc23a..b90dceb66 100644 --- a/tex/context/base/s-mag-01.tex +++ b/tex/context/base/s-mag-01.tex @@ -288,7 +288,7 @@ [makeup] [corner={right,bottom},location={left,top}] [frame=off, - align=normal, % left, + align=normal, width=.8\textwidth, foregroundcolor=MainColor] {\getbuffer[abstract]} diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf index c8c6b27a5..a924c0fa0 100644 Binary files a/tex/context/base/status-files.pdf and b/tex/context/base/status-files.pdf differ diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf index e4e11892c..5cfbd901e 100644 Binary files a/tex/context/base/status-lua.pdf and b/tex/context/base/status-lua.pdf differ diff --git a/tex/context/base/strc-des.mkiv b/tex/context/base/strc-des.mkiv index aaec8de69..113d1e665 100644 --- a/tex/context/base/strc-des.mkiv +++ b/tex/context/base/strc-des.mkiv @@ -927,7 +927,7 @@ % macros. \def\reinstatedescriptionnumberentry#1% - {\xdef\currentdescriptionattribute {\ctxlua {tex.write(structures.references.getinternalreference(#1))}}% + {\xdef\currentdescriptionattribute {\ctxlua {structures.references.getinternalreference(#1)}}% \xdef\currentdescriptionsynchronize{\ctxlatelua{structures.lists.enhance(#1)}}} \installstructurelistprocessor{description}{\usestructurelistprocessor{number+title}} diff --git a/tex/context/base/strc-doc.lua b/tex/context/base/strc-doc.lua index 7532ac63f..cee649aa5 100644 --- a/tex/context/base/strc-doc.lua +++ b/tex/context/base/strc-doc.lua @@ -16,18 +16,17 @@ local concat = table.concat local max, min = math.max, math.min local allocate, mark = utilities.storage.allocate, utilities.storage.mark -local catcodenumbers = catcodes.numbers -local ctxcatcodes = tex.ctxcatcodes -local variables = interfaces.variables +local catcodenumbers = catcodes.numbers +local ctxcatcodes = tex.ctxcatcodes +local variables = interfaces.variables ---~ if not trackers then trackers = { register = function() end } end +local trace_sectioning = false trackers.register("structures.sectioning", function(v) trace_sectioning = v end) +local trace_detail = false trackers.register("structures.detail", function(v) trace_detail = v end) -local trace_sectioning = false trackers.register("structures.sectioning", function(v) trace_sectioning = v end) -local trace_detail = false trackers.register("structures.detail", function(v) trace_detail = v end) +local report_structure = logs.reporter("structure","sectioning") -local report_structure = logs.reporter("structure","sectioning") - -local structures, context = structures, context +local structures = structures +local context = context local helpers = structures.helpers local documents = structures.documents @@ -74,6 +73,19 @@ end documents.initialize() +-- -- -- components -- -- -- + +function documents.preset(numbers) + local nofnumbers = #numbers + data.numbers = numbers + data.depth = nofnumbers + data.ownnumbers = { } + for i=1,nofnumbers do + data.ownnumbers[i] = "" + end + sections.setnumber(nofnumbers,"-1") +end + -- -- -- sections -- -- -- local collected = allocate() @@ -209,12 +221,16 @@ end function sections.somelevel(given) -- old number - local numbers, ownnumbers, forced, status, olddepth = data.numbers, data.ownnumbers, data.forced, data.status, data.depth - local givenname = given.metadata.name + local numbers = data.numbers + local ownnumbers = data.ownnumbers + local forced = data.forced + local status = data.status + local olddepth = data.depth + local givenname = given.metadata.name local mappedlevel = levelmap[givenname] - local newdepth = tonumber(mappedlevel or (olddepth > 0 and olddepth) or 1) -- hm, levelmap only works for section-* - local directives = given.directives - local resetset = (directives and directives.resetset) or "" + local newdepth = tonumber(mappedlevel or (olddepth > 0 and olddepth) or 1) -- hm, levelmap only works for section-* + local directives = given.directives + local resetset = (directives and directives.resetset) or "" -- local resetter = sets.getall("structure:resets",data.block,resetset) -- a trick to permits userdata to overload title, ownnumber and reference -- normally these are passed as argument but nowadays we provide several @@ -334,6 +350,11 @@ function sections.somelevel(given) references.tag = references.tag or tags.getid(metadata.kind,metadata.name) + local setcomponent = structures.references.setcomponent + if setcomponent then + setcomponent(given) -- might move to the tex end + end + references.section = sections.save(given) -- given.numberdata = nil end diff --git a/tex/context/base/strc-lst.lua b/tex/context/base/strc-lst.lua index 1e54eddec..5b2297f0f 100644 --- a/tex/context/base/strc-lst.lua +++ b/tex/context/base/strc-lst.lua @@ -19,37 +19,38 @@ local lpegmatch = lpeg.match local simple_hash_to_string, settings_to_hash = utilities.parsers.simple_hash_to_string, utilities.parsers.settings_to_hash local allocate, checked = utilities.storage.allocate, utilities.storage.checked -local trace_lists = false trackers.register("structures.lists", function(v) trace_lists = v end) +local trace_lists = false trackers.register("structures.lists", function(v) trace_lists = v end) -local report_lists = logs.reporter("structure","lists") +local report_lists = logs.reporter("structure","lists") -local structures = structures -local lists = structures.lists -local sections = structures.sections -local helpers = structures.helpers -local documents = structures.documents -local pages = structures.pages -local tags = structures.tags -local references = structures.references +local structures = structures +local lists = structures.lists +local sections = structures.sections +local helpers = structures.helpers +local documents = structures.documents +local pages = structures.pages +local tags = structures.tags +local references = structures.references -local collected = allocate() -local tobesaved = allocate() -local cached = allocate() -local pushed = allocate() +local collected = allocate() +local tobesaved = allocate() +local cached = allocate() +local pushed = allocate() -lists.collected = collected -lists.tobesaved = tobesaved +lists.collected = collected +lists.tobesaved = tobesaved -lists.enhancers = lists.enhancers or { } -lists.internals = allocate(lists.internals or { }) -- to be checked -lists.ordered = allocate(lists.ordered or { }) -- to be checked -lists.cached = cached -lists.pushed = pushed +lists.enhancers = lists.enhancers or { } +lists.internals = allocate(lists.internals or { }) -- to be checked +lists.ordered = allocate(lists.ordered or { }) -- to be checked +lists.cached = cached +lists.pushed = pushed -references.specials = references.specials or { } +references.specials = references.specials or { } -local variables = interfaces.variables -local matchingtilldepth, numberatdepth = sections.matchingtilldepth, sections.numberatdepth +local variables = interfaces.variables +local matchingtilldepth = sections.matchingtilldepth +local numberatdepth = sections.numberatdepth -- -- -- -- -- -- @@ -121,6 +122,12 @@ function lists.push(t) pushed[i] = p r.listindex = p end + + local setcomponent = references.setcomponent + if setcomponent then + setcomponent(t) -- might move to the tex end + end + context(p) end diff --git a/tex/context/base/strc-pag.lua b/tex/context/base/strc-pag.lua index 9382fc2b5..95851d1f0 100644 --- a/tex/context/base/strc-pag.lua +++ b/tex/context/base/strc-pag.lua @@ -55,8 +55,8 @@ function pages.save(prefixdata,numberdata) report_pages("saving page %s.%s",realpage,userpage) end local data = { - number = userpage, - block = sections.currentblock(), + number = userpage, + block = sections.currentblock(), prefixdata = prefixdata and helpers.simplify(prefixdata), numberdata = numberdata and helpers.simplify(numberdata), } @@ -121,17 +121,29 @@ function pages.analyze(entry,pagespecification) if not references then return false, false, "no references" end - local realpage = references.realpage - if not realpage then - return false, false, "no realpage" + 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 - local pagedata = collected[realpage] if not pagedata then return false, false, "no pagedata" end - local section = references.section - if not section then - return pagedata, false, "no section" + 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 @@ -139,16 +151,16 @@ function pages.analyze(entry,pagespecification) return pagedata, false, "current spec blocks prefix" end -- stored preferences ---~ if entry.prefix == no then ---~ return pagedata, false, "entry blocks prefix" ---~ end + -- 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, sections.collected[references.section], "okay" + return pagedata, sectiondata, "okay" end function helpers.page(data,pagespec) diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua index a43b83cc3..8e3a3db82 100644 --- a/tex/context/base/strc-ref.lua +++ b/tex/context/base/strc-ref.lua @@ -6,77 +6,95 @@ if not modules then modules = { } end modules ['strc-ref'] = { license = "see context related readme files" } +-- beware, this is a first step in the rewrite (just getting rid of +-- the tuo file); later all access and parsing will also move to lua + +-- the useddata and pagedata names might change +-- todo: pack exported data + local format, find, gmatch, match, concat = string.format, string.find, string.gmatch, string.match, table.concat local texcount, texsetcount = tex.count, tex.setcount local rawget, tonumber = rawget, tonumber -local lpegmatch, lpegP, lpegS, lpegCs, lpegCt, lpegCf, lpegCc, lpegC, lpegCg = lpeg.match, lpeg.P, lpeg.S, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cc, lpeg.C, lpeg.Cg +local lpegmatch = lpeg.match +local copytable = table.copy -local allocate = utilities.storage.allocate -local mark = utilities.storage.mark -local setmetatableindex = table.setmetatableindex +local allocate = utilities.storage.allocate +local mark = utilities.storage.mark +local setmetatableindex = table.setmetatableindex -local trace_referencing = false trackers.register("structures.referencing", function(v) trace_referencing = v end) -local trace_analyzing = false trackers.register("structures.referencing.analyzing", function(v) trace_analyzing = v end) +local trace_referencing = false trackers.register("structures.referencing", function(v) trace_referencing = v end) +local trace_analyzing = false trackers.register("structures.referencing.analyzing", function(v) trace_analyzing = v end) +local trace_identifying = false trackers.register("structures.referencing.identifying", function(v) trace_identifying = v end) +local trace_importing = false trackers.register("structures.referencing.importing", function(v) trace_importing = v end) -local report_references = logs.reporter("structure","references") +local report_references = logs.reporter("references") +local report_unknown = logs.reporter("unknown") +local report_identifying = logs.reporter("references","identifying") +local report_importing = logs.reporter("references","importing") -local variables = interfaces.variables -local constants = interfaces.constants -local context = context +local variables = interfaces.variables +local constants = interfaces.constants +local context = context -local settings_to_array = utilities.parsers.settings_to_array -local unsetvalue = attributes.unsetvalue +local texcount = tex.count +local texconditionals = tex.conditionals --- beware, this is a first step in the rewrite (just getting rid of --- the tuo file); later all access and parsing will also move to lua +local currentcomponent = resolvers.jobs.currentcomponent +local justacomponent = resolvers.jobs.justacomponent --- the useddata and pagedata names might change --- todo: pack exported data +local logsnewline = logs.newline +local logspushtarget = logs.pushtarget +local logspoptarget = logs.poptarget + +local settings_to_array = utilities.parsers.settings_to_array +local unsetvalue = attributes.unsetvalue -local structures = structures -local helpers = structures.helpers -local sections = structures.sections -local references = structures.references -local lists = structures.lists -local counters = structures.counters +local structures = structures +local helpers = structures.helpers +local sections = structures.sections +local references = structures.references +local lists = structures.lists +local counters = structures.counters -- some might become local -references.defined = references.defined or allocate() - -local defined = references.defined -local derived = allocate() -local specials = allocate() -local runners = allocate() -local internals = allocate() -local exporters = allocate() -local imported = allocate() -local filters = allocate() -local executers = allocate() -local handlers = allocate() -local tobesaved = allocate() -local collected = allocate() -local tobereferred = allocate() -local referred = allocate() - -references.derived = derived -references.specials = specials -references.runners = runners -references.internals = internals -references.exporters = exporters -references.imported = imported -references.filters = filters -references.executers = executers -references.handlers = handlers -references.tobesaved = tobesaved -references.collected = collected -references.tobereferred = tobereferred -references.referred = referred +references.defined = references.defined or allocate() + +local defined = references.defined +local derived = allocate() +local specials = allocate() +local runners = allocate() +local internals = allocate() +local filters = allocate() +local executers = allocate() +local handlers = allocate() +local tobesaved = allocate() +local collected = allocate() +local tobereferred = allocate() +local referred = allocate() + +references.derived = derived +references.specials = specials +references.runners = runners +references.internals = internals +references.filters = filters +references.executers = executers +references.handlers = handlers +references.tobesaved = tobesaved +references.collected = collected +references.tobereferred = tobereferred +references.referred = referred + +local splitreference = references.splitreference +local splitprefix = references.splitprefix +local splitprefix = references.splitcomponent +local prefixsplitter = references.prefixsplitter +local componentsplitter = references.componentsplitter + +local currentreference = nil storage.register("structures/references/defined", references.defined, "structures.references.defined") -local currentreference = nil - local initializers = { } local finalizers = { } @@ -106,16 +124,16 @@ job.register('structures.references.collected', tobesaved, initializer, finalize local maxreferred = 1 local nofreferred = 0 -local function initializer() -- can we use a tobesaved as metatable for collected? - tobereferred = references.tobereferred - referred = references.referred - nofreferred = #referred -end +-- local function initializer() -- can we use a tobesaved as metatable for collected? +-- tobereferred = references.tobereferred +-- referred = references.referred +-- nofreferred = #referred +-- end local function initializer() -- can we use a tobesaved as metatable for collected? tobereferred = references.tobereferred referred = references.referred - setmetatableindex(referred,get) + setmetatableindex(referred,get) -- hm, what is get ? end -- We make the array sparse (maybe a finalizer should optionally return a table) because @@ -225,20 +243,30 @@ function references.currentorder(kind,name) context(orders[kind] and orders[kind][name] or lastorder) end +local function setcomponent(data) + -- we might consider doing this at the tex end, just like prefix + local component = currentcomponent() + if component then + local references = data and data.references + if references then + references.component = component + end + return component + end + -- but for the moment we do it here (experiment) +end + +references.setcomponent = setcomponent + function references.set(kind,prefix,tag,data) +-- setcomponent(data) + local pd = tobesaved[prefix] + if not pd then + pd = { } + tobesaved[prefix] = pd + end for ref in gmatch(tag,"[^,]+") do - local p, r = match(ref,"^(%-):(.-)$") - if p and r then - prefix, ref = p, r - else - prefix = "" - end if ref ~= "" then - local pd = tobesaved[prefix] - if not pd then - pd = { } - tobesaved[prefix] = pd - end pd[ref] = data context.dofinishsomereference(kind,prefix,ref) end @@ -250,166 +278,20 @@ function references.setandgetattribute(kind,prefix,tag,data,view) -- maybe do in texcount.lastdestinationattribute = references.setinternalreference(prefix,tag,nil,view) or -0x7FFFFFFF end -function references.enhance(prefix,tag,spec) +function references.enhance(prefix,tag) local l = tobesaved[prefix][tag] if l then l.references.realpage = texcount.realpageno end end --- this reference parser is just an lpeg version of the tex based one - --- local result = { } --- --- local lparent = lpegP("(") --- local rparent = lpegP(")") --- local lbrace = lpegP("{") --- local rbrace = lpegP("}") --- local dcolon = lpegP("::") --- local backslash = lpegP("\\") --- --- local reset = lpegP("") / function() result = { } end --- local b_token = backslash / function(s) result.has_tex = true return s end --- --- local o_token = 1 - rparent - rbrace - lparent - lbrace --- local a_token = 1 - rbrace --- local s_token = 1 - lparent - lbrace --- local i_token = 1 - lparent - lbrace --- local f_token = 1 - lparent - lbrace - dcolon --- --- local outer = (f_token )^1 / function (s) result.outer = s end --- local operation = lpegCs((b_token + o_token)^1) / function (s) result.operation = s end --- local arguments = lpegCs((b_token + a_token)^0) / function (s) result.arguments = s end --- local special = (s_token )^1 / function (s) result.special = s end --- local inner = (i_token )^1 / function (s) result.inner = s end --- --- local outer_reference = (outer * dcolon)^0 --- --- operation = outer_reference * operation -- special case: page(file::1) and file::page(1) --- --- local optional_arguments = (lbrace * arguments * rbrace)^0 --- local inner_reference = inner * optional_arguments --- local special_reference = special * lparent * (operation * optional_arguments + operation^0) * rparent --- --- local scanner = (reset * outer_reference * (special_reference + inner_reference)^-1 * -1) / function() return result end --- --- function references.split(str) --- return lpegmatch(scanner,str or "") --- end - --- the scanner accepts nested outer, but we don't care too much, maybe some day we will --- have both but currently the innermost wins - -local spaces = lpegP(" ")^0 -local lparent = lpegP("(") -local rparent = lpegP(")") -local lbrace = lpegP("{") -local rbrace = lpegP("}") -local dcolon = lpegP("::") -local backslash = lpegP("\\") - - lparent = spaces * lparent * spaces - rparent = spaces * rparent * spaces - lbrace = spaces * lbrace * spaces - rbrace = spaces * rbrace * spaces - dcolon = spaces * dcolon * spaces - -local endofall = spaces * lpegP(-1) - -local o_token = 1 - rparent - rbrace - lparent - lbrace -- can be made more efficient -local a_token = 1 - rbrace -local s_token = 1 - lparent - lbrace -local i_token = 1 - lparent - lbrace - endofall -local f_token = 1 - lparent - lbrace - dcolon - -local hastexcode = lpegCg(lpegCc("has_tex") * lpegCc(true)) -- cannot be made to work -local outer = lpegCg(lpegCc("outer") * lpegCs(f_token^1)) -local operation = lpegCg(lpegCc("operation") * lpegCs(o_token^1)) -local arguments = lpegCg(lpegCc("arguments") * lpegCs(a_token^0)) -local special = lpegCg(lpegCc("special") * lpegCs(s_token^1)) -local inner = lpegCg(lpegCc("inner") * lpegCs(i_token^1)) - - arguments = (lbrace * arguments * rbrace)^-1 - outer = (outer * dcolon)^-1 - operation = outer * operation -- special case: page(file::1) and file::page(1) - inner = inner * arguments - special = special * lparent * (operation * arguments)^-1 * rparent - -local scanner = spaces * lpegCf (lpegCt("") * outer * (special + inner)^-1 * endofall, rawset) - -local function splitreference(str) - if str and str ~= "" then - local t = lpegmatch(scanner,str) - if t then - local a = t.arguments - if a and find(a,"\\") then - t.has_tex = true - else - local o = t.arguments - if o and find(o,"\\") then - t.has_tex = true - end - end - return t - end - end -end - -references.split = splitreference - ---~ inspect(splitreference([[ ]])) ---~ inspect(splitreference([[ inner ]])) ---~ inspect(splitreference([[ special ( operation { argument, argument } ) ]])) ---~ inspect(splitreference([[ special ( operation { argument } ) ]])) ---~ inspect(splitreference([[ special ( operation { argument, \argument } ) ]])) ---~ inspect(splitreference([[ special ( operation { \argument } ) ]])) ---~ inspect(splitreference([[ special ( operation ) ]])) ---~ inspect(splitreference([[ special ( \operation ) ]])) ---~ inspect(splitreference([[ special ( o\peration ) ]])) ---~ inspect(splitreference([[ special ( ) ]])) ---~ inspect(splitreference([[ inner { argument } ]])) ---~ inspect(splitreference([[ inner { \argument } ]])) ---~ inspect(splitreference([[ inner { ar\gument } ]])) ---~ inspect(splitreference([[inner{a\rgument}]])) ---~ inspect(splitreference([[ inner { argument, argument } ]])) ---~ inspect(splitreference([[ inner { argument, \argument } ]])) -- fails: bug in lpeg? ---~ inspect(splitreference([[ inner { \argument, \argument } ]])) ---~ inspect(splitreference([[ outer :: ]])) ---~ inspect(splitreference([[ outer :: inner]])) ---~ inspect(splitreference([[ outer :: special (operation { argument,argument } ) ]])) ---~ inspect(splitreference([[ outer :: special (operation { } )]])) ---~ inspect(splitreference([[ outer :: special ( operation { argument, \argument } ) ]])) ---~ inspect(splitreference([[ outer :: special ( operation ) ]])) ---~ inspect(splitreference([[ outer :: special ( \operation ) ]])) ---~ inspect(splitreference([[ outer :: special ( ) ]])) ---~ inspect(splitreference([[ outer :: inner { argument } ]])) ---~ inspect(splitreference([[ special ( outer :: operation ) ]])) - ---~ inspect(splitreference([[]])) ---~ inspect(splitreference([[inner]])) ---~ inspect(splitreference([[special(operation{argument,argument})]])) ---~ inspect(splitreference([[special(operation)]])) ---~ inspect(splitreference([[special(\operation)]])) ---~ inspect(splitreference([[special()]])) ---~ inspect(splitreference([[inner{argument}]])) ---~ inspect(splitreference([[inner{\argument}]])) ---~ inspect(splitreference([[outer::]])) ---~ inspect(splitreference([[outer::inner]])) ---~ inspect(splitreference([[outer::special(operation{argument,argument})]])) ---~ inspect(splitreference([[outer::special(operation{argument,\argument})]])) ---~ inspect(splitreference([[outer::special(operation)]])) ---~ inspect(splitreference([[outer::special(\operation)]])) ---~ inspect(splitreference([[outer::special()]])) ---~ inspect(splitreference([[outer::inner{argument}]])) ---~ inspect(splitreference([[special(outer::operation)]])) - -- -- -- related to strc-ini.lua -- -- -- references.resolvers = references.resolvers or { } local resolvers = references.resolvers function resolvers.section(var) - local vi = lists.collected[var.i[2]] + local vi = var.i[3] or lists.collected[var.i[2]] if vi then var.i = vi var.r = (vi.references and vi.references.realpage) or (vi.pagedata and vi.pagedata.realpage) or 1 @@ -425,7 +307,7 @@ resolvers.formula = resolvers.section resolvers.note = resolvers.section function resolvers.reference(var) - local vi = var.i[2] + local vi = var.i[2] -- check if vi then var.i = vi var.r = (vi.references and vi.references.realpage) or (vi.pagedata and vi.pagedata.realpage) or 1 @@ -435,22 +317,26 @@ function resolvers.reference(var) end end -local function register_from_lists(collected,derived) +local function register_from_lists(collected,derived,pages,sections) local g = derived[""] if not g then g = { } derived[""] = g end -- global for i=1,#collected do local entry = collected[i] local m, r = entry.metadata, entry.references if m and r then - local prefix, reference = r.referenceprefix or "", r.reference or "" + local reference = r.reference or "" + local prefix = r.referenceprefix or "" + local component = r.component and r.component or "" if reference ~= "" then local kind, realpage = m.kind, r.realpage if kind and realpage then local d = derived[prefix] if not d then d = { } derived[prefix] = d end - local t = { kind, i } +local c = derived[component] if not c then c = { } derived[component] = c end + local t = { kind, i, entry } for s in gmatch(reference,"%s*([^,]+)") do if trace_referencing then report_references("list entry %s provides %s reference '%s' on realpage %s",i,kind,s,realpage) end +c[s] = c[s] or t -- share them d[s] = d[s] or t -- share them g[s] = g[s] or t -- first wins end @@ -458,6 +344,7 @@ local function register_from_lists(collected,derived) end end end +-- inspect(derived) end references.registerinitializer(function() register_from_lists(lists.collected,derived) end) @@ -502,9 +389,16 @@ references.files.data = references.files.data or { } local files = references.files.data +table.setmetatableindex(files, function(t,k) + -- we assume that it's a file anyway + local v = { k, k } + files[k] = v + return v +end) + function references.files.define(name,file,description) if name and name ~= "" then - files[name] = { file or "", description or file or ""} + files[name] = { file or "", description or file or "" } end end @@ -605,31 +499,6 @@ function references.whatfrom(name) context((urls[name] and variables.url) or (files[name] and variables.file) or variables.unknown) end ---~ function references.from(name) ---~ local u = urls[name] ---~ if u then ---~ local url, file, description = u[1], u[2], u[3] ---~ if description ~= "" then ---~ context.dofromurldescription(description) ---~ -- ok ---~ elseif file and file ~= "" then ---~ context.dofromurlliteral(url .. "/" .. file) ---~ else ---~ context(dofromurlliteral,url) ---~ end ---~ else ---~ local f = files[name] ---~ if f then ---~ local description, file = f[1], f[2] ---~ if description ~= "" then ---~ context.dofromfiledescription(description) ---~ else ---~ context.dofromfileliteral(file) ---~ end ---~ end ---~ end ---~ end - function references.from(name) local u = urls[name] if u then @@ -655,160 +524,6 @@ function references.from(name) end end --- export - -exporters.references = exporters.references or { } -exporters.lists = exporters.lists or { } - -function exporters.references.generic(data) - local useddata = {} - local entries, userdata = data.entries, data.userdata - if entries then - for k, v in next, entries do - useddata[k] = v - end - end - if userdata then - for k, v in next, userdata do - useddata[k] = v - end - end - return useddata -end - -function exporters.lists.generic(data) - local useddata = { } - local titledata, numberdata = data.titledata, data.numberdata - if titledata then - useddata.title = titledata.title - end - if numberdata then - local numbers = numberdata.numbers - local t, tn = { }, 0 - for i=1,#numbers do - local n = numbers[i] - if n ~= 0 then - tn = tn + 1 - t[tn] = n - end - end - useddata.number = concat(t,".") - end - return useddata -end - -local function referencer(data) - local references = data.references - local realpage = references.realpage - local numberdata = jobpages.tobesaved[realpage] - local specification = numberdata.specification - return { - realpage = references.realpage, - number = numberdata.number, - conversion = specification.conversion, - -- prefix = only makes sense when bywhatever - } -end - --- Exported and imported references ... not yet used but don't forget it --- and redo it. - -function references.export(usedname) - local exported = { } - local e_references, e_lists = exporters.references, exporters.lists - local g_references, g_lists = e_references.generic, e_lists.generic - -- todo: pagenumbers - -- todo: some packing - for prefix, references in next, references.tobesaved do - local pe = exported[prefix] if not pe then pe = { } exported[prefix] = pe end - for key, data in next, references do - local metadata = data.metadata - local exporter = e_references[metadata.kind] or g_references - if exporter then - pe[key] = { - metadata = { - kind = metadata.kind, - catcodes = metadata.catcodes, - coding = metadata.coding, -- we can omit "tex" - }, - useddata = exporter(data), - pagedata = referencer(data), - } - end - end - end - local pe = exported[""] if not pe then pe = { } exported[""] = pe end - for n, data in next, lists.tobesaved do - local metadata = data.metadata - local exporter = e_lists[metadata.kind] or g_lists - if exporter then - local result = { - metadata = { - kind = metadata.kind, - catcodes = metadata.catcodes, - coding = metadata.coding, -- we can omit "tex" - }, - useddata = exporter(data), - pagedata = referencer(data), - } - for key in gmatch(data.references.reference,"[^,]+") do - pe[key] = result - end - end - end - local e = { - references = exported, - version = 1.00, - } - io.savedata(file.replacesuffix(usedname or tex.jobname,"tue"),table.serialize(e,true)) -end - -function references.import(usedname) - if usedname then - local jdn = imported[usedname] - if not jdn then - local filename = files[usedname] - if filename then -- only registered files - filename = filename[1] - else - filename = usedname - end - local data = io.loaddata(file.replacesuffix(filename,"tue")) or "" - if data == "" then - interfaces.showmessage("references",24,filename) - data = nil - else - data = loadstring(data) - if data then - data = data() - end - if data then - -- version check - end - if not data then - interfaces.showmessage("references",25,filename) - end - end - if data then - interfaces.showmessage("references",26,filename) - jdn = data - jdn.filename = filename - else - jdn = { filename = filename, references = { }, version = 1.00 } - end - imported[usedname] = jdn - imported[filename] = jdn - end - return jdn - else - return nil - end -end - -function references.load(usedname) - -- gone -end - function references.define(prefix,reference,list) local d = defined[prefix] if not d then d = { } defined[prefix] = d end d[reference] = { "defined", list } @@ -907,42 +622,6 @@ end references.currentset = nil ---~ local b, e = "\\ctxlua{local jc = structures.references.currentset;", "}" ---~ local o, a = 'jc[%s].operation=[[%s]];', 'jc[%s].arguments=[[%s]];' ---~ ---~ function references.expandcurrent() -- todo: two booleans: o_has_tex& a_has_tex ---~ local currentset = references.currentset ---~ if currentset and currentset.has_tex then ---~ local done = false ---~ for i=1,#currentset do ---~ local ci = currentset[i] ---~ local operation = ci.operation ---~ if operation then ---~ if find(operation,"\\") then -- if o_has_tex then ---~ if not done then ---~ context(b) ---~ done = true ---~ end ---~ context(o,i,operation) ---~ end ---~ end ---~ local arguments = ci.arguments ---~ if arguments then ---~ if find(arguments,"\\") then -- if a_has_tex then ---~ if not done then ---~ context(b) ---~ done = true ---~ end ---~ context(a,i,arguments) ---~ end ---~ end ---~ end ---~ if done then ---~ context(e) ---~ end ---~ end ---~ end - function commands.setreferenceoperation(k,v) references.currentset[k].operation = v end @@ -971,281 +650,741 @@ function references.expandcurrent() -- todo: two booleans: o_has_tex& a_has_tex end end ---~ local uo = urls[outer] ---~ if uo then ---~ special, operation, argument = "url", uo[1], inner or uo[2] -- maybe more is needed ---~ else ---~ local fo = files[outer] ---~ if fo then ---~ special, operation, argument = "file", fo[1], inner -- maybe more is needed ---~ end ---~ end +local externals = { } -local prefixsplitter = lpegCs(lpegP((1-lpegP(":"))^1 * lpegP(":"))) * lpegCs(lpegP(1)^1) +-- we have prefixes but also components: +-- +-- : prefix +-- :: always external +-- ::: internal (for products) or external (for components) + +local function loadexternalreferences(name,utilitydata) + local struc = utilitydata.structures + if struc then + local external = struc.references.collected -- direct references + local lists = struc.lists.collected -- indirect references (derived) + local pages = struc.pages.collected -- pagenumber data + for prefix, set in next, external do + for reference, data in next, set do + if trace_importing then + report_importing("registering external reference: regular | %s | %s | %s",name,prefix,reference) + end + local section = reference.section + local realpage = reference.realpage + if section then + reference.sectiondata = lists[section] + end + if realpage then + reference.pagedata = pages[realpage] + end + end + end + for i=1,#lists do + local entry = lists[i] + local metadata = entry.metadata + local references = entry.references + if metadata and references then + local reference = references.reference + if reference and reference ~= "" then + local kind = metadata.kind + local realpage = references.realpage + if kind and realpage then + references.pagedata = pages[realpage] + local prefix = references.referenceprefix or "" + local target = external[prefix] + if not target then + target = { } + external[prefix] = target + end + for s in gmatch(reference,"%s*([^,]+)") do + if trace_importing then + report_importing("registering external reference: %s | %s | %s | %s",kind,name,prefix,s) + end + target[s] = target[s] or entry + end + end + end + end + end + externals[name] = external + return external + end +end --- todo: add lots of tracing here +table.setmetatableindex(externals,function(t,k) -- either or not automatically + local filename = files[k][1] -- filename + local fullname = file.replacesuffix(filename,"tuc") + if lfs.isfile(fullname) then -- todo: use other locator + local utilitydata = job.loadother(fullname) + if utilitydata then + local external = loadexternalreferences(k,utilitydata) + t[k] = external or false + return external + end + end + t[k] = false + return false +end) -local n = 0 +local productdata = { + productreferences = { }, + componentreferences = { }, + components = { }, +} -local function identify(prefix,reference) - local set = resolve(prefix,reference) - local bug = false - texcount.referencehastexstate = set.has_tex and 1 or 0 - n = n + 1 - set.n = n - for i=1,#set do - local var = set[i] - local special, inner, outer, arguments, operation = var.special, var.inner, var.outer, var.arguments, var.operation - if special then - local s = specials[special] - if s then - if outer then - if operation then - -- special(outer::operation) - var.kind = "special outer with operation" - else - -- special() - var.kind = "special outer" - end - var.f = outer - elseif operation then - if arguments then - -- special(operation{argument,argument}) - var.kind = "special operation with arguments" - else - -- special(operation) - var.kind = "special operation" - end - else - -- special() - var.kind = "special" +local function loadproductreferences(productname,componentname,utilitydata) + local struc = utilitydata.structures + if struc then + local productreferences = struc.references.collected -- direct references + local lists = struc.lists.collected -- indirect references (derived) + local pages = struc.pages.collected -- pagenumber data + -- we use indirect tables to save room but as they are eventually + -- just references we resolve them to data here (the mechanisms + -- that use this data check for indirectness) + for prefix, set in next, productreferences do + for reference, data in next, set do + if trace_importing then + report_importing("registering product reference: regular | %s | %s | %s",productname,prefix,reference) + end + local section = reference.section + local realpage = reference.realpage + if section then + reference.sectiondata = lists[section] + end + if realpage then + reference.pagedata = pages[realpage] end - else - var.error = "unknown special" end - elseif outer then - local e = references.import(outer) - if e then - if inner then - local r = e.references - if r then - r = r[prefix] - if r then - r = r[inner] - if r then - if arguments then - -- outer::inner{argument} - var.kind = "outer with inner with arguments" - else - -- outer::inner - var.kind = "outer with inner" - end - var.i = { "reference", r } - resolvers.reference(var) - var.f = outer - var.e = true -- external + end + -- + local componentreferences = { } + for i=1,#lists do + local entry = lists[i] + local metadata = entry.metadata + local references = entry.references + if metadata and references then + local reference = references.reference + if reference and reference ~= "" then + local kind = metadata.kind + local realpage = references.realpage + if kind and realpage then + references.pagedata = pages[realpage] + local prefix = references.referenceprefix or "" + local component = references.component + local ctarget, ptarget + if component and component == componentname then + -- skip + else + -- one level up + local external = componentreferences[component] + if not external then + external = { } + componentreferences[component] = external + end + if component == prefix then + prefix = "" + end + ctarget = external[prefix] + if not ctarget then + ctarget = { } + external[prefix] = ctarget end end - end - if not r then - r = e.derived - if r then - r = r[prefix] - if r then - r = r[inner] - if r then - -- outer::inner - if arguments then - -- outer::inner{argument} - var.kind = "outer with inner with arguments" - else - -- outer::inner - var.kind = "outer with inner" - end - var.i = r - resolvers[r[1]](var) - var.f = outer + ptarget = productreferences[prefix] + if not ptarget then + ptarget = { } + productreferences[prefix] = ptarget + end + for s in gmatch(reference,"%s*([^,]+)") do + if ptarget then + if trace_importing then + report_importing("registering product reference: %s | %s | %s | %s",kind,productname,prefix,s) end + ptarget[s] = ptarget[s] or entry end - end - end - if not r then - var.error = "unknown outer" - end - elseif special then - local s = specials[special] - if s then - if operation then - if arguments then - -- outer::special(operation{argument,argument}) - var.kind = "outer with special and operation and arguments" - else - -- outer::special(operation) - var.kind = "outer with special and operation" + if ctarget then + if trace_importing then + report_importing("registering component reference: %s | %s | %s | %s",kind,productname,prefix,s) + end + ctarget[s] = ctarget[s] or entry end - else - -- outer::special() - var.kind = "outer with special" end - var.f = outer - else - var.error = "unknown outer with special" end - else - -- outer:: - var.kind = "outer" - var.f = outer end - else - if inner then - if arguments then - -- outer::inner{argument} - var.kind = "outer with inner with arguments" - else - -- outer::inner - var.kind = "outer with inner" + end + end + productdata.productreferences = productreferences -- not yet used + productdata.componentreferences = componentreferences + end +end + +local function loadproductvariables(product,component,utilitydata) + local struc = utilitydata.structures + if struc then + local lists = struc.lists and struc.lists.collected + if lists then + local pages = struc.pages and struc.pages.collected + for i=1,#lists do + local li = lists[i] + if li.metadata.kind == "section" and li.references.component == component then + local firstsection = li + if firstsection.numberdata then + local numbers = firstsection.numberdata.numbers + if numbers then + if trace_importing then + report_importing("initializing section number to %s",concat(numbers,":")) + end + productdata.firstsection = firstsection + structures.documents.preset(numbers) + end end - var.i = { "reference", inner } - resolvers.reference(var) - var.f = outer - elseif special then - local s = specials[special] - if s then - if operation then - if arguments then - -- outer::special(operation{argument,argument}) - var.kind = "outer with special and operation and arguments" - else - -- outer::special(operation) - var.kind = "outer with special and operation" + if pages and firstsection.references then + local firstpage = pages[firstsection.references.realpage] + local number = firstpage and firstpage.number + if number then + if trace_importing then + report_importing("initializing page number to %s",number) end - else - -- outer::special() - var.kind = "outer with special" + productdata.firstpage = firstpage + counters.set("userpage",1,number) end - var.f = outer - else - var.error = "unknown outer with special" end + break + end + end + end + end +end + +local function componentlist(tree,target) + local branches = tree and tree.branches + if branches then + for i=1,#branches do + local branch = branches[i] + local type = branch.type + if type == "component" then + if target then + target[#target+1] = branch.name else - -- outer:: - var.kind = "outer" - var.f = outer + target = { branch.name } + end + elseif type == "product" or type == "component" then + target = componentlist(branch,target) + end + end + end + return target +end + +local function loadproductcomponents(product,component,utilitydata) + local job = utilitydata.job + productdata.components = componentlist(job and job.structure and job.structure.collected) or { } +end + +function structures.references.loadpresets(product,component) -- we can consider a special components hash + if product and component and product~= "" and component ~= "" and not productdata.product then -- maybe: productdata.filename ~= filename + productdata.product = product + productdata.component = component + local fullname = file.replacesuffix(product,"tuc") + if lfs.isfile(fullname) then -- todo: use other locator + local utilitydata = job.loadother(fullname) + if utilitydata then + if trace_importing then + report_importing("loading presets for component %s from product %s",component,product) end + loadproductvariables (product,component,utilitydata) + loadproductreferences(product,component,utilitydata) + loadproductcomponents(product,component,utilitydata) + -- inspect(productdata) end + end + end +end + +structures.references.productdata = productdata + +local useproduct = commands.useproduct + +if useproduct then + + function commands.useproduct(product) + useproduct(product) + if texconditionals.autocrossfilereferences then + local component = justacomponent() + if component then + if trace_referencing then + report_references("loading presets for component '%s' from product '%s'",component,product) + end + structures.references.loadpresets(product,component) + end + end + end + +end + +-- productdata.firstsection.numberdata.numbers +-- productdata.firstpage.number + +local function report_identify_special(set,var,i,type) + local reference = set.reference + local prefix = set.prefix or "" + local special = var.special + local error = var.error + local kind = var.kind + if error then + report_identifying("type %s: %s, n: %s, prefix: %s, special: %s, error: %s",type,reference,i,prefix,special,error) + else + report_identifying("type %s: %s, n: %s, prefix: %s, special: %s, kind: %s",type,reference,i,prefix,special,kind) + end +end + +local function report_identify_arguments(set,var,i,type) + local reference = set.reference + local prefix = set.prefix or "" + local arguments = var.arguments + local error = var.error + local kind = var.kind + if error then + report_identifying("type %s: %s, n: %s, prefix: %s, arguments: %s, error: %s",type,reference,i,prefix,arguments,error) + else + report_identifying("type %s: %s, n: %s, prefix: %s, arguments: %s, kind: %s",type,reference,i,prefix,arguments,kind) + end +end + +local function report_identify_outer(set,var,i,type) + local reference = set.reference + local prefix = set.prefix or "" + local outer = var.outer + local error = var.error + local kind = var.kind + if outer then + if error then + report_identifying("type %s: %s, n: %s, prefix: %s, outer: %s, error: %s",type,reference,i,prefix,outer,error) + else + report_identifying("type %s: %s, n: %s, prefix: %s, outer: %s, kind: %s",type,reference,i,prefix,outer,kind) + end + else + if error then + report_identifying("type %s: %s, n: %s, prefix: %s, error: %s",type,reference,i,prefix,error) else + report_identifying("type %s: %s, n: %s, prefix: %s, kind: %s",type,reference,i,prefix,kind) + end + end +end + +local function identify_special(set,var,i) + local special = var.special + local s = specials[special] + if s then + local outer = var.outer + local operation = var.operation + local arguments = var.arguments + if outer then + if operation then + -- special(outer::operation) + var.kind = "special outer with operation" + else + -- special() + var.kind = "special outer" + end + var.f = outer + elseif operation then if arguments then - local s = specials[inner] - if s then - -- inner{argument} - var.kind = "special with arguments" - else - var.error = "unknown inner or special" - end + -- special(operation{argument,argument}) + var.kind = "special operation with arguments" else - -- inner ... we could move the prefix logic into the parser so that we have 'm for each entry - -- foo:bar -> foo == prefix (first we try the global one) - -- -:bar -> ignore prefix - local p, i = prefix, nil - local splitprefix, splitinner = lpegmatch(prefixsplitter,inner) - -- these are taken from other anonymous references - if splitprefix and splitinner then - if splitprefix == "-" then - i = collected[""] - i = i and i[splitinner] - if i then - p = "" - end - else - i = collected[splitprefix] - i = i and i[splitinner] - if i then - p = splitprefix - end - end - end - -- todo: strict here - if not i then - i = collected[prefix] - i = i and i[inner] - if i then - p = prefix - end + -- special(operation) + var.kind = "special operation" + end + else + -- special() + var.kind = "special" + end + if trace_identifying then + report_identify_special(set,var,i,"1a") + end + else + var.error = "unknown special" + end + return var +end + +local function identify_arguments(set,var,i) + local s = specials[var.inner] + if s then + -- inner{argument} + var.kind = "special with arguments" + else + var.error = "unknown inner or special" + end + if trace_identifying then + report_identify_arguments(set,var,i,"3a") + end + return var +end + +local function identify_inner(set,var,prefix,collected,derived,tobesaved) + local inner = var.inner + local outer = var.outer + -- inner ... we could move the prefix logic into the parser so that we have 'm for each entry + -- foo:bar -> foo == prefix (first we try the global one) + -- -:bar -> ignore prefix + local p, i = prefix, nil + local splitprefix, splitinner = lpegmatch(prefixsplitter,inner) + -- these are taken from other anonymous references + if splitprefix and splitinner then + if splitprefix == "-" then + i = collected[""] + i = i and i[splitinner] + if i then + p = "" + end + else + i = collected[splitprefix] + i = i and i[splitinner] + if i then + p = splitprefix + end + end + end + -- todo: strict here + if not i then + i = collected[prefix] + i = i and i[inner] + if i then + p = prefix + end + end + if not i and prefix ~= "" then + i = collected[""] + i = i and i[inner] + if i then + p = "" + end + end + if i then + var.i = { "reference", i } + resolvers.reference(var) + var.kind = "inner" + var.p = p + elseif derived then + -- these are taken from other data structures (like lists) + if splitprefix and splitinner then + if splitprefix == "-" then + i = derived[""] + i = i and i[splitinner] + if i then + p = "" end - if not i and prefix ~= "" then - i = collected[""] - i = i and i[inner] - if i then - p = "" - end + else + i = derived[splitprefix] + i = i and i[splitinner] + if i then + p = splitprefix end + end + end + if not i then + i = derived[prefix] + i = i and i[inner] + if i then + p = prefix + end + end + if not i and prefix ~= "" then + i = derived[""] + i = i and i[inner] + if i then + p = "" + end + end + if i then + var.kind = "inner" + var.i = i + resolvers[i[1]](var) + var.p = p + else + -- no prefixes here + local s = specials[inner] + if s then + var.kind = "special" + else + i = (collected and collected[""] and collected[""][inner]) or + (derived and derived [""] and derived [""][inner]) or + (tobesaved and tobesaved[""] and tobesaved[""][inner]) if i then + var.kind = "inner" var.i = { "reference", i } resolvers.reference(var) - var.kind = "inner" - var.p = p + var.p = "" else - -- these are taken from other data structures (like lists) - if splitprefix and splitinner then - if splitprefix == "-" then - i = derived[""] - i = i and i[splitinner] - if i then - p = "" - end - else - i = derived[splitprefix] - i = i and i[splitinner] - if i then - p = splitprefix - end - end - end - if not i then - i = derived[prefix] - i = i and i[inner] - if i then - p = prefix + var.error = "unknown inner or special" + end + end + end + end + return var +end + +local function identify_outer(set,var,i) + local outer = var.outer + local inner = var.inner + local external = externals[outer] + if external then + local v = copytable(var) + v = identify_inner(set,v,nil,external) + if v.i and not v.error then + v.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,v,i,"2a") + end + return v + end + v = copytable(var) + local v = identify_inner(set,v,v.outer,external) + if v.i and not v.error then + v.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,v,i,"2b") + end + return v + end + end + local external = productdata.componentreferences[outer] + if external then + local v = identify_inner(set,copytable(var),nil,external) + if v.i and not v.error then + v.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,v,i,"2c") + end + return v + end + end + local external = productdata.productreferences[outer] + if external then + local vi = external[inner] + if vi then + var.kind = "outer with inner" + var.i = vi + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"2d") + end + return var + end + end + -- the rest + local special = var.special + local arguments = var.arguments + local operation = var.operation + if inner then + if arguments then + -- outer::inner{argument} + var.kind = "outer with inner with arguments" + else + -- outer::inner + var.kind = "outer with inner" + end + var.i = { "reference", inner } + resolvers.reference(var) + var.f = outer + if trace_identifying then + report_identify_outer(set,var,i,"2e") + end + elseif special then + local s = specials[special] + if s then + if operation then + if arguments then + -- outer::special(operation{argument,argument}) + var.kind = "outer with special and operation and arguments" + else + -- outer::special(operation) + var.kind = "outer with special and operation" + end + else + -- outer::special() + var.kind = "outer with special" + end + var.f = outer + else + var.error = "unknown outer with special" + end + if trace_identifying then + report_identify_outer(set,var,i,"2f") + end + else + -- outer:: + var.kind = "outer" + var.f = outer + if trace_identifying then + report_identify_outer(set,var,i,"2g") + end + end + return var +end + +local function identify_inner_or_outer(set,var,i) + -- here we fall back on product data + local inner = var.inner + if inner and inner ~= "" then + local v = identify_inner(set,copytable(var),prefix,collected,derived,tobesaved) + if v.i and not v.error then + v.kind = "inner" -- check this + if trace_identifying then + report_identify_outer(set,v,i,"4a") + end + return v + end + local componentreferences = productdata.componentreferences + local productreferences = productdata.productreferences + local components = productdata.components + if components and componentreferences then + -- for component, data in next, productdata.componentreferences do -- better do this in order of processing: + for i=1,#components do + local component = components[i] + local data = componentreferences[component] + if data then + local d = data[""] + local vi = d and d[inner] + if vi then + var.outer = component + var.i = vi + var.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"4b") end + return var end - if not i and prefix ~= "" then - i = derived[""] - i = i and i[inner] - if i then - p = "" - end + end + end + end + local component, inner = lpegmatch(componentsplitter,inner) + if component then + local data = componentreferences and componentreferences[component] + if data then + local d = data[""] + local vi = d and d[inner] + if vi then + var.inner = inner + var.outer = component + var.i = vi + var.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"4c") end - if i then - var.kind = "inner" - var.i = i - resolvers[i[1]](var) - var.p = p - else - -- no prefixes here - local s = specials[inner] - if s then - var.kind = "special" - else - i = (collected[""] and collected[""][inner]) or - (derived [""] and derived [""][inner]) or - (tobesaved[""] and tobesaved[""][inner]) - if i then - var.kind = "inner" - var.i = { "reference", i } - resolvers.reference(var) - var.p = "" - else - var.error = "unknown inner or special" - end - end + return var + end + end + local data = productreferences and productreferences[component] + if data then + local vi = data[inner] + if vi then + var.inner = inner + var.outer = component + var.i = vi + var.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"4d") end + return var end end end - bug = bug or var.error + var.error = "unknown inner" + else + var.error = "no inner" + end + if trace_identifying then + report_identify_outer(set,var,i,"4e") + end + return var +end + +local function identify_inner_component(set,var,i) + -- we're in a product (maybe ignore when same as component) + local component = var.component + identify_inner(set,var,component,collected,derived,tobesaved) + if trace_identifying then + report_identify_outer(set,var,i,"5a") + end + return var +end + +local function identify_outer_component(set,var,i) + local component = var.component + local inner = var.inner + local data = productdata.componentreferences[component] + if data then + local d = data[""] + local vi = d and d[inner] + if vi then + var.inner = inner + var.outer = component + var.i = vi + var.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"6a") + end + return var + end + end + local data = productdata.productreferences[component] + if data then + local vi = data[inner] + if vi then + var.inner = inner + var.outer = component + var.i = vi + var.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,var,i,"6b") + end + return var + end + end + var.error = "unknown component" + if trace_identifying then + report_identify_outer(set,var,i,"6c") + end + return var +end + +local nofidentified = 0 + +local function identify(prefix,reference) + local set = resolve(prefix,reference) + local bug = false + texcount.referencehastexstate = set.has_tex and 1 or 0 + nofidentified = nofidentified + 1 + set.n = nofidentified + for i=1,#set do + local var = set[i] + if var.special then + var = identify_special(set,var,i) + elseif var.outer then + var = identify_outer(set,var,i) + elseif var.arguments then + var = identify_arguments(set,var,i) + elseif not var.component then + var = identify_inner_or_outer(set,var,i) + elseif currentcomponent() then + var = identify_inner_component(set,var,i) + else + var = identify_outer_component(set,var,i) + end set[i] = var + bug = bug or var.error end ---~ references.analyze(set) references.currentset = mark(set) -- mark, else in api doc if trace_analyzing then report_references(table.serialize(set,reference)) @@ -1281,13 +1420,20 @@ end function references.reportproblems() -- might become local if nofunknowns > 0 then - interfaces.showmessage("references",5,nofunknowns) -- 5 = unknown, 6 = illegal - -- -- we need a proper logger specific for the log file - -- texio.write_nl("log",format("%s unknown references",nofunknowns)) - -- for k, v in table.sortedpairs(unknowns) do - -- texio.write_nl("log",format("%s (n=%s)",k,v)) - -- end - -- texio.write_nl("log","") + statistics.register("cross referencing", function() + return format("%s identified, %s unknown",nofidentified,nofunknowns) + end) + logspushtarget("logfile") + logsnewline() + report_references("start problematic references") + logsnewline() + for k, v in table.sortedpairs(unknowns) do + report_unknown("%4i: %s",v,k) + end + logsnewline() + report_references("stop problematic references") + logsnewline() + logspoptarget() end end @@ -1316,14 +1462,14 @@ directives.register("references.linkmethod", function(v) -- page mixed names references.setinnermethod(v) end) -function references.setinternalreference(prefix,tag,internal,view) +function references.setinternalreference(prefix,tag,internal,view) -- needs checking if innermethod == "page" then return unsetvalue else local t, tn = { }, 0 -- maybe add to current if tag then if prefix and prefix ~= "" then - prefix = prefix .. ":" + prefix = prefix .. ":" -- watch out, : here for ref in gmatch(tag,"[^,]+") do tn = tn + 1 t[tn] = prefix .. ref @@ -1377,8 +1523,8 @@ function references.filter(name,...) -- number page title ... if name == "realpage" then local cs = references.analyze() -- normally already analyzed but also sets state context(cs.realpage or 0) -- todo, return and in command namespace - else - local kind = data.metadata and data.metadata.kind + else -- assumes data is table + local kind = type(data) == "table" and data.metadata and data.metadata.kind if kind then local filter = filters[kind] or filters.generic filter = filter and (filter[name] or filter.unknown or filters.generic[name] or filters.generic.unknown) @@ -1423,7 +1569,6 @@ function filters.generic.number(data,what,prefixspec) -- todo: spec and then no if data then local numberdata = data.numberdata if numberdata then ---~ print(table.serialize(prefixspec)) helpers.prefix(data,prefixspec) sections.typesetnumber(numberdata,"number",numberdata) else @@ -1439,7 +1584,7 @@ filters.generic.default = filters.generic.text function filters.generic.page(data,prefixspec,pagespec) local pagedata = data.pagedata - if pagedata then -- imported + if pagedata then local number, conversion = pagedata.number, pagedata.conversion if not number then -- error @@ -1514,17 +1659,17 @@ filters.float = { default = filters.generic.number } filters.description = { default = filters.generic.number } filters.item = { default = filters.generic.number } -function references.sectiontitle(n) - helpers.sectiontitle(lists.collected[tonumber(n) or 0]) -end +-- function references.sectiontitle(n) +-- helpers.sectiontitle(lists.collected[tonumber(n) or 0]) +-- end -function references.sectionnumber(n) - helpers.sectionnumber(lists.collected[tonumber(n) or 0]) -end +-- function references.sectionnumber(n) +-- helpers.sectionnumber(lists.collected[tonumber(n) or 0]) +-- end -function references.sectionpage(n,prefixspec,pagespec) - helpers.prefixedpage(lists.collected[tonumber(n) or 0],prefixspec,pagespec) -end +-- function references.sectionpage(n,prefixspec,pagespec) +-- helpers.prefixedpage(lists.collected[tonumber(n) or 0],prefixspec,pagespec) +-- end -- analyze @@ -1543,11 +1688,11 @@ local function checkedpagestate(n,page) if not p then return 0 elseif p > r then - return 3 + return 3 -- after elseif p < r then - return 2 + return 2 -- before else - return 1 + return 1 -- same end end @@ -1593,6 +1738,8 @@ function references.analyze(actions) local realpage = actions.realpage or setreferencerealpage(actions) if realpage == 0 then actions.pagestate = 0 + elseif actions.external then + actions.pagestate = 0 else actions.pagestate = checkedpagestate(actions.n,realpage) end @@ -1753,3 +1900,9 @@ end -- needs a better split ^^^ commands.filterreference = references.filter + +-- done differently now: + +function references.export(usedname) end +function references.import(usedname) end +function references.load (usedname) end diff --git a/tex/context/base/strc-ref.mkiv b/tex/context/base/strc-ref.mkiv deleted file mode 100644 index 88ed25819..000000000 --- a/tex/context/base/strc-ref.mkiv +++ /dev/null @@ -1,1830 +0,0 @@ -%D \module -%D [ file=strc-ref, -%D version=2008.10.20, -%D title=\CONTEXT\ Structure Macros, -%D subtitle=Cross Referencing, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -% todo: (1) configure references, (2) rendering => with presets -% -% \definestructureconversionset[default][Character,number,Romannumerals,Character][number] -% \definestructureseparatorset [default][.,.,--][.] -% \setuphead[subsection][sectionstopper=),sectionsegments=4:4] -% \setupreferencestructureprefix[default][prefixsegments=2:4] -% \setupreferencestructureprefix[figure][default][prefixsegments=3:4] -% \chapter {One} -% \section {One} -% \subsection[sec:test]{Two} -% See \in[sec:test] and \in[fig:xx] and \in[fig:yy] -% \placefigure[here][fig:xx]{}{} -% \placefigure[here][fig:yy]{}{} - -\writestatus{loading}{ConTeXt Structure Macros / Cross Referencing} - -\registerctxluafile{strc-ref}{1.001} -\registerctxluafile{node-ref}{1.001} - -\unprotect - -%D This module is a (partial) rewrite of core-ref.tex for \MKIV. As -%D such it will be a moving target for a while. - -%D Later we will do a further cleanup and move much of the code to -%D \LUA\ (i.e.\ better backend integration). - -\let\mainreference\gobblefivearguments - -% this will go when we got rid of the tuo file - -\let\currentfolioreference \!!zerocount % only used in xml-fo -\let\resetreferences \relax -\let\setreferences \relax -\let\showcurrentreference \relax -\let\setexecutecommandcheck\gobbletwoarguments - -\def\s!full{full} -\def\s!user{user} -\def\s!text{text} -\def\s!page{page} - -% todo : unknown/illegal reference no arg -% todo : +n pages check on 'samepage' (contrastcolor) -% todo : multiple text in reference - -% Makes more sense to build action data first, especially now -% openaction etc are supported. -% -% \definespecial\doexecuteactionchain w h -% \definespecial\dosetgotolocation -% \definespecial\dosetexecuteJScode -% ... - -%D This module deals with referencing. In \CONTEXT\ referencing -%D is one of the core features, although at a first glance -%D probably nobody will notice. This is good, because -%D referencing should be as hidden as possible. -%D -%D In paper documents, referencing comes down to cross -%D referencing, but in their interactive counterparts, is also -%D involves navigation. Many features implemented here are -%D therefore closely related to navigation. -%D -%D Many \CONTEXT\ commands can optionally be fed with a -%D reference. Such a reference, when called upon, returns the -%D number of a figure, table, chapter etc, a piece of text, or -%D a pagenumber. -%D -%D There are three ways of defining a reference: -%D -%D \starttyping -%D \pagereference[here] -%D \textreference[here]{some text} -%D \stoptyping -%D -%D the third alternative combines them in: -%D -%D \starttyping -%D \reference[here]{some text} -%D \stoptyping - -\unexpanded\def\textreference {\dosingleargument\dotextreference} -\unexpanded\def\pagereference {\dosingleargument\dopagereference} -\unexpanded\def\reference {\dosingleargument\doreference } -\unexpanded\def\setreference {\dodoubleargument\dosetreference } - -%D These are implemented in a low level form as: - -\def\dotextreference [#1]{\dodosetreference\s!text{#1}{}} -\def\dopagereference [#1]{\dodosetreference\s!page{#1}{}{}} -\def\doreference [#1]{\dodosetreference\s!full{#1}{}} -\def\dosetreference[#1][#2]{\dodosetreference\s!user{#1}{#2}{}} - -%D Actually there is not much difference between a text and a -%D full reference, but it's the concept that counts. The low -%D level implementation is: - -\newcount\lastreferenceattribute -\newcount\lastdestinationattribute - -\def\dofinishfullreference#1#2{\normalexpanded{\ctxlatelua{structures.references.enhance("#1","#2")}}} -\def\dofinishtextreference#1#2{\normalexpanded{\ctxlatelua{structures.references.enhance("#1","#2",{})}}} - -\let\dofinishpagereference\dofinishfullreference -\let\dofinishuserreference\dofinishfullreference - -\def\dofinishsomereference#1{\executeifdefined{dofinish#1reference}\gobbletwoarguments} - -\def\dodosetreference - {\ifreferencing - \expandafter\dododosetreference - \else - \expandafter\gobblefourarguments - \fi} - -\def\dododosetreference#1#2#3#4% kind labels userdata text -> todo: userdata - {\ifreferencing - % we could have a more efficient one for page references but for the moment - % we don't care too much - \edef\currentreferencekind{#1}% - \edef\currentreferencelabels{#2}% - \edef\currentreferenceuserdata{#3}% - \edef\currentreferenceexpansion{\@@rfexpansion}% {\referenceparameter\c!expansion} - \ifx\currentreferencelabels\empty \else - \ifx\currentreferenceexpansion\s!xml - \xmlstartraw - \xdef\currentreferencedata{#4}% data, no text else conflict - \xmlstopraw - \globallet\currentreferencecoding\s!xml - \else - \ifx\currentreferenceexpansion\v!yes - \xdef\currentreferencedata{#4}% - \else - \xdef\currentreferencedata{\detokenize{#4}}% - \fi - \globallet\currentreferencecoding\s!tex - \fi - % beware, the structures.references.set writes a - % \setnextinternalreference - \ctxlua{structures.references.setandgetattribute("\currentreferencekind", "\referenceprefix","\currentreferencelabels", - { - references = { - % internal = \nextinternalreference, % no need for an internal as we have an explicit - block = "\currentsectionblock", - section = structures.sections.currentid(), - }, - metadata = { % we could assume page to have no metadata - kind = "#1", - \ifx\currentreferencekind\s!page\else - catcodes = \the\catcodetable, - xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument" \else nil \fi, % only useful when text - \fi - }, - \ifx\currentreferencedata\empty\else - entries = { - text = \!!bs\currentreferencedata\!!es - }, - \fi - \ifx\currentreferenceuserdata\empty\else - userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es) - \fi - },"\interactionparameter\c!focus") - }% - % todo: optional - \xdef\currentdestinationattribute{\number\lastdestinationattribute}% - \begingroup\attribute\destinationattribute\currentdestinationattribute\emptyhbox\endgroup % todo - \fi - \fi} - -\def\defaultreferencepage#1{[[[#1]]]} -\def\defaultreferencetext#1{[[[#1]]]} - -%D For internal usage: - -\def\dosetsimplepagereference#1% label - {\iflocation - \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","#1", - { - references = { - % block = "\currentsectionblock", - % section = structures.sections.currentid(), - }, - metadata = { % we could assume page to have no metadata - kind = "\s!page", - }, - },"\interactionparameter\c!focus") - }% - \xdef\currentdestinationattribute{\number\lastdestinationattribute}% - \else - \xdef\currentdestinationattribute{\number\attributeunsetvalue}% - \fi} - -\def\dogetsimplepagereference#1% - {\iflocation - \ctxlua{structures.references.inject("\referenceprefix","#1",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% - \xdef\currentreferenceattribute{\number\lastreferenceattribute}% - \else - \xdef\currentreferenceattribute{\number\attributeunsetvalue}% - \fi} - -%D These macros depend on three other ones, -%D \type {\makesectionformat}, that generated \type -%D {\sectionformat}, \type {\pagenumber}. The not yet used -%D argument \type{#1} is a tag that specifies the type of -%D reference. - -%D \macros -%D {everyreference} -%D -%D For rather tricky purposes, one can assign sanitizing -%D macros to \type{\everyreference} (no longer that relevant). - -\newevery \everyreference \relax - -%D This is really needed, since for instance Polish has a -%D different alphabet and needs accented entries in registers. - -\appendtoks - \cleanupfeatures -\to \everyreference - -%D We did not yet discuss prefixing. Especially in interactive -%D documents, it's not always easy to keep track of duplicate -%D references. The prefix mechanism, which we will describe -%D later on, solves this problem. By (automatically) adding a -%D prefix one keeps references local, but the global ones in -%D view. To enable this feature, we explictly split the prefix -%D from the reference. - -\let\referenceprefix\empty - -%D For a long time the only way to access an external file was -%D to use the file prefix (\type {somefile::}. However, when -%D you split up a document, redefining the references may be -%D such a pain, that another approach is feasible. By setting -%D the \type {autofile} variable to \type {yes} or \type -%D {page}, you can access the reference directly. -%D -%D \starttabulate[||||] -%D \NC filename::tag \NC page(filename::pnum) \NC tag \NC\NR -%D \NC $\star$ \NC \NC \NC\NR -%D \NC $\star$ \NC $\star$ \NC $\star$ \NC\NR -%D \NC \NC $\star$ \NC \NC\NR -%D \stoptabulate - -\def\usereferences[#1]% not yet - {\writestatus\m!system{references from other files are handled automatically}} - -%D As mentioned we will also use the cross reference mechanism -%D for navigational purposes. The main reason for this is that -%D we want to treat both categories alike: -%D -%D \starttyping -%D \goto{go back}[PreviousJump] -%D \goto{colofon}[colofon page] -%D \stoptyping -%D -%D Here \type{PreviousJump} is handled by the viewer, while the -%D \type{colofon page} reference is, apart from hyperlinking, a -%D rather normal reference. -%D -%D We already saw that cross refences are written to and read -%D from a file. The pure navigational ones don't need to be -%D written to file, but both for fast processing and -%D transparant integration, they are saved internally as a sort -%D of reference. We can easily distinguish such system -%D references from real cross reference ones by their tag. -%D -%D We also use the odd/even characteristic to determine the -%D page state. - -\let\currentrealreference \empty -\let\currentpagereference \empty -\let\currenttextreference \empty -\let\currentreferenceorder \empty -\let\currentsubtextreference \empty -\let\currentsubsubtextreference\empty - -\newcount\referencehastexstate % set in backend - -\def\referencepagestate{\ctxcommand{referencepagestate()}} -\def\referencerealpage {\ctxcommand{referencerealpage ()}} - -% referencepagestate: -% -% 0 = no page ref, 1=same page, 2=before, 3=after - -%D Cross references appear as numbers (figure~1.1, chapter~2) -%D or pagenumbers (page~2, page 3--2), and are called with -%D \type{\in} and \type{\at}. In interactive documents we also -%D have \type{\goto}, \type{\button} and alike. These are more -%D versatile and look like: -%D -%D \starttyping -%D \goto[reference] -%D \goto[outer reference::] -%D \goto[outer reference::inner reference] -%D \goto[operation(argument)] -%D \goto[operation(action{argument,argument})] -%D \goto[action] -%D \goto[action{argument}] -%D \stoptyping -%D -%D The first one is a normal reference, the second and third -%D are references to a file or \URL. The brace delimited -%D references for instance refer to a \JAVASCRIPT. The last -%D example shows that we can pass arguments to the actions. - -\newif\ifreferencefound - -%D Now we've come to the testing step. As we can see below, -%D this macro does bit more than testing: it also resolves -%D the reference. This means that whenever we test for the -%D existance of a reference at an outer level, we have all the -%D relevant properties of that reference avaliable inside the -%D true branche~(\type{#2}). -%D -%D The prefix has to do with localizing references. When a -%D prefix is set, looking for a reference comes to looking for -%D the prefixed one, and when not found, looking for the non -%D prefixed one. Consider for instance the prefix set to -%D \type{sidetrack}. -%D -%D \starttyping -%D \pagereference[important] -%D \pagereference[unimportant] -%D \setupreferencing[prefix=sidetrack] -%D \pagereference[important] -%D \stoptyping -%D -%D results in saving (writing) the references -%D -%D \starttyping -%D ...{}{important} -%D ...{}{unimportant} -%D ...{sidetrack}{important}... -%D \stoptyping -%D -%D Now when we call for \type{unimportant}, we will indeed get -%D the pagenumber associated to this reference. But when we -%D call for \type{important}, while the prefix is still set, we -%D will get the pagenumber bound to the prefixed one. -%D -%D {\em Some day, when processing time and memory are no longer -%D performance factors, we will introduce multi||level -%D prefixes.} -%D -%D Before we start analyzing, I introduce a general -%D definition macro. Consider: -%D -%D \starttyping -%D \goto{do}[JS(My_Script{"test",123}),titlepage] -%D \stoptyping -%D -%D This can also be achieved by: -%D -%D \starttyping -%D \definereference[startup][JS(My_Script{"test",123}),titlepage] -%D \goto{do}[startup] -%D \stoptyping -%D -%D Now is this is a handy feature or not? -%D -%D \showsetup{definereference} -%D -%D We can trace references by setting the next switch to -%D true. - -\unexpanded\def\definereference - {\dodoubleempty\dodefinereference} - -\def\dodefinereference[#1][#2]% - {\ctxlua{structures.references.define("\referenceprefix","#1",\!!bs\detokenize{#2}\!!es)}} - -\def\resetreference[#1]% - {\ctxlua{structures.references.reset("\referenceprefix","#1")}} - -\def\setpagereference#1#2% name, specification - {\ctxlua{structures.references.define("","#1",\!!bs\v!page(\luaescapestring{#2})\!!es)}} - -%D Chained references are defined as: -%D -%D \starttyping -%D \goto{somewhere}[JS(somescript),nextpage,JS(anotherscript)] -%D \stoptyping -%D -%D Actually supporting chains is up to the special driver. Here -%D we only provide the hooks. - -%D \macros -%D {highlighthyperlinks} -%D -%D The next switch can be used to make user hyperlinks are -%D not highlighted when clicked on. - -\newconditional\highlighthyperlinks \settrue\highlighthyperlinks - -%D \macros -%D {gotonewwindow} -%D -%D To make the {\em goto previous jump} feature more -%D convenient when using more than one file, it makes sense -%D to force the viewer to open a new window for each file -%D opened. - -\newconditional\gotonewwindow \setfalse\gotonewwindow - -\def\expandtexincurrentreference % will happen in lua some time - {\ifcase\referencehastexstate\else\ctxlua{structures.references.expandcurrent()}\fi} - -\def\expandreferenceoperation#1#2{\ctxcommand{setreferenceoperation(#1,\!!bs#2\!!es)}} -\def\expandreferencearguments#1#2{\ctxcommand{setreferencearguments(#1,\!!bs#2\!!es)}} - -\def\doifreferencefoundelse#1#2#3% - {\ctxlua{structures.references.doifelse("\referenceprefix","#1",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}% - {\expandtexincurrentreference#2}% - {#3}} - -%D The tester only splits the reference in components but does -%D not look into them. The following macro does a preroll and -%D determines for instance the current real reference pagenumber. -%D The \type {\currentrealreference} macro does the same so unless -%D one wants to use the pagestate the next macro seldom needs to -%D be called. - -% \def\analyzecurrentreference -% {\ctxlua{structures.references.analyze()}} - -%D The inner case is simple. Only two cases have to be taken -%D care of: -%D -%D \starttyping -%D \goto{some text}[reference] -%D \goto{some text}[prefix:reference] -%D \stoptyping -%D -%D References to other files however are treated strict or -%D tolerant, depending on their loading and availability: -%D -%D \starttyping -%D \useexternaldocument[somefile][filename][a nice description] -%D -%D \goto{checked reference}[somefile::reference] -%D \goto{unchecked reference}[somefile::] -%D \goto{unchecked reference}[anotherfile::reference] -%D \stoptyping -%D -%D An unknown reference is reported on the screen, in the log -%D file and, when enabled, in the left margin of the text. - -% \def\unknownreference#1% -% {\iftrialtypesetting \else -% \ifinpagebody \else -% \doifconcepttracing{\doifsomething{#1}{\inleft{\infofont\doboundtext{#1}{\dimexpr\leftmarginwidth-2em\relax}{..}->}}}% -% \fi -% \fi} - -\let\unknownreference\gobbleoneargument - -%D When a reference is not found, we typeset a placeholder -%D (two glyphs are often enough to represent the reference -%D text). - -\def\dummyreference{{\tttf ??}} - -%D To prevent repetitive messages concerning a reference -%D being defined, we set such an unknown reference to an empty -%D one after the first encounter. - -%D Apart from cross references supplied by the user, \CONTEXT\ -%D generates cross references itself. Most of them are not -%D saved as a reference, but stored with their source, for -%D instance a list or an index entry. Such automatically -%D generated, for the user invisible, references are called -%D {\em internal references}. The user supplied ones are -%D labeled as {\em external references}. -%D -%D A second important characteristic is that when we want to -%D support different backends (viewers), we need to support -%D named destinations as well as page numbers. I invite readers -%D to take a glance at the special driver modules to understand -%D the fine points of this. As a result we will deal with {\em -%D locations} as well as {\em real page numbers}. We explictly -%D call this pagenumber a real one, because it is independant -%D of the page numbering scheme used in the document. -%D -%D One of the reasons for \CONTEXT\ being the first \TEX\ base -%D macropackage to support sophisticated interactive \PDF\ -%D files, lays in the mere fact that real page numbers are -%D available in most two pass data, like references, list data -%D and index entries. -%D -%D We will speak of \type{thisis...} when we are marking a -%D location, and \type{goto...} when we point to such a -%D location. The latter one can be seen as a hyperlink to the -%D former one. In the next macros one we use constructs like: -%D -%D \starttyping -%D \dostart... -%D \dostop... -%D \stoptyping -%D -%D Such macros are used to invoke the relevant specials from -%D the special driver modules (see \type{spec-ini}). The flag -%D \type{\iflocation} signals if we're in interactive mode. - -\ifx\buttonheight\undefined \newdimen\buttonheight \fi -\ifx\buttonwidth \undefined \newdimen\buttonwidth \fi - -%D Internal references can best be set using the next few -%D macros. Setting such references to unique values is -%D completely up to the macros that call them. -%D -%D \starttyping -%D \thisissomeinternal{tag}{identifier} -%D \gotosomeinternal {tag}{identifier}{pagenumber}{text} -%D \stoptyping - -%D We could do this in lua ... - -\newif \iflocation -\newcount\locationcount -\newcount\locationorder -\newbox \locationbox - -\def\nextinternalreference {\the\locationcount} -\def\nextinternalorderreference{\the\locationorder} - -\def\setnextinternalreference - {\global\advance\locationcount\plusone} - -\def\setnextinternalreferences#1#2% plural - {\ctxlua{structures.references.setnextinternal("#1","#2")}} - -\def\getinternalorderreference#1#2% - {\ctxlua{structures.references.currentorder("#1","#2")}} - -\def\thisissomeinternal#1#2% tag reference (only for old time sake) - {\begingroup - \ctxlua{structures.references.setinternalreference("","#1:#2")}% - \hbox attr \destinationattribute\lastdestinationattribute{}% - \endgroup} - -\newconditional\preferpagereferences - -\def\gotosomeinternal#1#2#3#4% - {\ifconditional\preferpagereferences - \directgoto{#4}[page(#3)]% - \else - \directgoto{#4}[#1:#2]% - \fi} - -\def\gotonextinternal#1#2% - {\directgoto{#1}[internal(#2)]} - -%D In this module we define three system references: one for -%D handling navigational, viewer specific, commands, another -%D for jumping to special pages, like the first or last one, -%D and a third reference for linking tree like lists, like -%D tables of contents. The latter two adapt themselves to the -%D current state. -%D -%D An example of an action is: -%D -%D \starttyping -%D \goto{some action}[PreviousJump] -%D \stoptyping -%D -%D as well as: -%D -%D \starttyping -%D \goto{some text}[\v!action(PreviousJump] -%D \stoptyping - -% compatibility hack - -\def\setglobalsystemreference#1#2#3{\definereference[#2][\v!action(#3)]} - -\newif\ifreferencing \referencingtrue - -%D One can also activate an automatic prefix mechanism. By -%D setting the \type{\prefix} variable to \type{+}, the prefix -%D is incremented, when set to \type{-} or empty, the prefix is -%D reset. Other values become the prefix. - -\newcount\prefixcounter - -%D These settings are accomplished by: -%D -%D \showsetup{setupreferencing} -%D -%D In interactive documents verbose references don't always -%D make sense (what is a page number in an unnumbered -%D document). By setting the \type{interaction} variable, one -%D can influences the way interactive references are set. - -\newconstant\autocrossfilereferences % not yet supported in mkiv -\newconstant\referencefilecaseswap % not yet supported in mkiv - -\newtoks \everysetupreferencing - -\unexpanded\def\setupreferencing - {\dosingleargument\dosetupreferencing} - -\def\dosetupreferencing[#1]% - {\getparameters[\??rf][\c!prefix=\s!unknown,#1]% - \the\everysetupreferencing} - -\appendtoks - \processaction - [\@@rfstate] - [ \v!stop=>\referencingfalse, - \v!start=>\referencingtrue]% -\to \everysetupreferencing - -% \newconstant \referencecontentmode -% -% \appendtoks -% \processaction -% [\@@rfinteraction] -% [ \v!all=>\referencecontentmode\zerocount, -% \v!label=>\referencecontentmode\plusone, -% \v!text=>\referencecontentmode\plustwo, -% \v!symbol=>\referencecontentmode\plusthree]% -% \to \everysetupreferencing - -\appendtoks - \autocrossfilereferences\zerocount - \processaction - [\@@rfautofile] % not yet in mkiv - [ \v!yes=>\autocrossfilereferences\plusone, - \v!page=>\autocrossfilereferences\plustwo]% -\to \everysetupreferencing - -\appendtoks - \referencefilecaseswap\zerocount - \processaction[\@@rfconvertfile] % not yet in mkiv - [ \v!yes=>\referencefilecaseswap\plusone, - \v!big=>\referencefilecaseswap\plusone, - \v!small=>\referencefilecaseswap\plustwo]% -\to \everysetupreferencing - -\appendtoks - \setupreferenceprefix[\@@rfprefix]% - \doifelse\@@rfglobal\v!yes - {\settrue \autoglobalfilereferences}% - {\setfalse\autoglobalfilereferences}% -\to \everysetupreferencing - -% \appendtoks\ctxlua{structures.references.export("whatever")}\to\everystoptext -% \starttext -% \chapter[test]{test} -% test \in{IN}[more] and \in{IN}[test] or \at{AT}[more] and \at{AT}[test]\par -% test \in{IN}[whatever::more] and \in{IN}[whatever::test] or \at{AT}[whatever::more] and \at{AT}[whatever::test] \page -% reference\reference[more]{oeps} -% \stoptext - -\def\exportreferences - {\doif\@@rfexport\v!yes{\ctxlua{structures.references.export()}}} - -\appendtoks - \exportreferences -\to \everygoodbye - -\def\incrementreferenceprefix{+} -\def\decrementreferenceprefix{-} - -\unexpanded\def\setupreferenceprefix[#1]% - {\edef\@@rfprefix{#1}% - \ifx\@@rfprefix\empty - \let\referenceprefix\empty - \else\ifx\@@rfprefix\incrementreferenceprefix - \advance\prefixcounter \plusone % should be global - \edef\referenceprefix{\the\prefixcounter:}% - \let\@@rfprefix\s!unknown - \else\ifx\@@rfprefix\decrementreferenceprefix - \let\referenceprefix\empty - \let\@@rfprefix\s!unknown - \else\ifx\@@rfprefix\s!unknown - % forget about it - \else - \edef\referenceprefix{\@@rfprefix:}% - \fi\fi\fi\fi} - -\unexpanded\def\setupglobalreferenceprefix[#1]% - {\xdef\referenceprefix{#1:}} - -%D The most straightforward way of retrieving references is -%D using \type{\ref}. Consider the reference: -%D -%D \startbuffer -%D \reference[my ref]{{Look}{Here}{I am}} -%D \stopbuffer -%D -%D \typebuffer -%D -%D \getbuffer -%D -%D We can ask for upto five reference components: -%D -%D \startbuffer -%D user page reference: \ref[p][my ref] -%D text reference: \ref[t][my ref] -%D real page reference: \ref[r][my ref] -%D sub text reference: \ref[s][my ref] -%D extra text reference: \ref[e][my ref] -%D \stopbuffer -%D -%D \typebuffer -%D -%D And get back: -%D -%D \startlines -%D \getbuffer -%D \stoplines -%D -%D This is a cheap compatibility hack. Don't use this command -%D as there will be more advanced access to user data. - -\def\ref{\dodoubleargument\doref} - -\def\reftypep{\currentreferencepage} -\def\reftypet{\currentreferencetext} -\def\reftyper{\currentreferencepage} -\def\reftypes{\currentreferencetext} -\def\reftypee{\currentreferencetext} - -\def\doref[#1][#2]% - {\ifsecondargument - \doifreferencefoundelse{#2} - {\executeifdefined{reftype#1}\reftypep} - {\dummyreference}% - \else - \dummyreference - \fi} - -%D We can typeset a reference using \type{\in}, \type{\at} and -%D \type{\about} and goto specific locations using -%D \type{\goto}. The last one does not make that much sense in -%D a paper document. To complicate things, \PLAIN\ \TEX\ also -%D implements an \type {\in} but fortunately that one only -%D makes sense in math mode. -%D -%D Typesetting the reference is a bit more complicated than one -%D would at first sight expect. This is due to the fact that we -%D distinguish three (five) alternative calls: -%D -%D \placefigure -%D [here][three calls] -%D {Three alternatives reference calls.} -%D {\startcombination[1*3] -%D {\framed{\type{ \in }}} {a} -%D {\framed{\type{ \at }}} {b} -%D {\framed{\type{\goto}}} {c} -%D \stopcombination} -%D -%D \startbuffer -%D \in figure[fig:three calls] -%D \in{figure}[fig:three calls] -%D \in figure a[fig:three calls] -%D \in{figure}{a}[fig:three calls] -%D figure~\in[fig:three calls] -%D \stopbuffer -%D -%D \typebuffer -%D -%D This turns up as: -%D -%D \startlines -%D \getbuffer -%D \stoplines -%D -%D The dual \type{{}} results in a split reference. In a -%D document meant for paper, one is tempted to use the last -%D (most straightforward) alternative. When a document is also -%D meant voor electronic distribution, the former alternatives -%D have preference, because everything between the \type{\in} -%D and~\type{[} becomes active (and when asked for, typeset -%D in a different color and typeface). - -% \unexpanded\def\in {\mathortext\donormalmathin \dospecialin} -% \unexpanded\def\at {\mathortext\donormalmathat \dospecialat} -% \unexpanded\def\about{\mathortext\donormalmathabout\dospecialabout} -% \unexpanded\def\from {\mathortext\donormalmathfrom \dospecialfrom} -% \unexpanded\def\over {\mathortext\donormalmathover \dospecialabout} - -% \definecommand in {\dospecialin} -% \definecommand at {\dospecialat} -% \definecommand about {\dospecialabout} -% \definecommand from {\dospecialfrom} -% \definecommand over {\dospecialabout} % needed here, else math problems - - \def\filterreference #1{\ctxcommand{filterreference("#1")}} -\unexpanded\def\getreferenceentry#1{\ctxcommand{filterreference("#1")}} - -\def\currentreferencenumber {\filterreference{number}} -\def\currentreferencepage {\filterreference{page}} -\def\currentreferencetitle {\filterreference{title}} -\def\currentreferencetext {\filterreference{text}} -\def\currentreferencedefault {\filterreference{default}} -\def\currentreferencerealpage{\filterreference{realpage}} - -\unexpanded\def\dospecialabout[#1]% - {\dontleavehmode - \begingroup - \let\crlf\space - \let\\\space - \postponenotes - \@@rfleft - \doifreferencefoundelse{#1} - {\goto{\limitatetext\currentreferencetitle\@@rfwidth\unknown}[#1]}% not so efficient (dup lookup) - {}% todo - \@@rfright - \endgroup} - -%D The previously discussed setup macro lets us specify the -%D representation of references. A symbol reference does not -%D show the specific data, like the number of a figure, but -%D shows one of: \hbox {$^\goforwardcharacter$ -%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending -%D on the direction to go. - -% 1 = whatever -% 2 = forward, following page -% 3 = backward, preceding page -% 4 = forward, same page -% 5 = backward, same page - -% Yet untested: - -\unexpanded\def\somewhere#1#2#3[#4]% #3 gobbles space around #2 % todo - {\doifreferencefoundelse{#4}% kind of inefficient as \goto also analyzes - {\goto{\ifcase\referencepagestate\relax#1/#2\or#2\or#1\or#2\fi}[#4]} - {[#1/#2]}} - -\unexpanded\def\atpage[#1]% todo - {\doifreferencefoundelse{#1}% kind of inefficient as \goto also analyzes - {\goto{\ifcase\referencepagestate\relax - \labeltexts\v!page\dummyreference - \or - \labeltexts\v!atpage\currentreferencepage - \or - \labeltexts\v!atpage\currentreferencepage - \or - \labeltexts\v!atpage\currentreferencepage - \or - \labeltext\v!hereafter - \or - \labeltext\v!hencefore - \fi}[#1]} - {[?]}} - -\unexpanded\def\referencesymbol - {\hbox{\strut\high - {\setupsymbolset[\interactionparameter\c!symbolset]% - \symbol - [\ifcase\referencepagestate\relax - \v!somewhere - \or % same - \v!nowhere - \or % before - \v!previous - \or % after - \v!next% - \fi]}}} - -%D The other alternatives just conform their names: only the -%D label, only the text, or the label and the text. - -% \dounknownreference -> \dummyreference - -\def\symbolreference[#1]% for old times sake - {\goto{\referencesymbol}[#1]} - -% \referencecontentmode 0=all 1=label 2=text 3=symbol - -\newtoks\leftreferencetoks -\newtoks\rightreferencetoks -\newtoks\defaultleftreferencetoks -\newtoks\defaultrightreferencetoks - -\def\leftofreferencecontent {\nobreakspace} % we cannot do \definereferenceformat[at] .. so we need this -\let\rightofreferencecontent \empty -\let\leftofreference \empty -\let\rightofreference \empty - -% \setvalue{\??rf\c!interaction\v!all}% -% {\leftofreference -% \the\leftreferencetoks -% \doifsometokselse\leftreferencetoks \leftofreferencecontent \donothing -% \currentreferencecontent -% \doifsometokselse\rightreferencetoks\rightofreferencecontent\donothing -% \the\rightreferencetoks -% \rightofreference} - -\setvalue{\??rf\c!interaction\v!all}% - {\the\leftreferencetoks - \doifsometokselse\leftreferencetoks \leftofreferencecontent \donothing - \leftofreference - \currentreferencecontent - \rightofreference - \doifsometokselse\rightreferencetoks\rightofreferencecontent\donothing - \the\rightreferencetoks} - -\setvalue{\??rf\c!interaction\v!label}% - {\leftofreference - \the\leftreferencetoks - \the\rightreferencetoks - \rightofreference} - -\setvalue{\??rf\c!interaction\v!text}% - {\leftofreference - \currentreferencecontent - \rightofreference} - -\setvalue{\??rf\c!interaction\v!symbol}% - {\referencesymbol} - -\def\referencesequence - {\csname \??rf\c!interaction - \ifcsname\??rf\c!interaction\@@rfinteraction\endcsname - \@@rfinteraction - \else - \v!all - \fi - \endcsname} - -\newtoks\everyresetinatreference - -\appendtoks - \glet\leftofreference \relax - \glet\rightofreference\relax -\to \everyresetinatreference - -\def\dostartgotoreference - {\dontleavehmode - \begingroup} - -\def\dostopgotoreference - {\the\everyresetinatreference - \endgroup} - -\def\dopickupgotoreference - {\dodoublegroupempty\dodopickupgotoreference} - -\def\dodopickupgotoreference#1#2#3[#4]% #3 gobbles spaces (really needed) - {\leftreferencetoks - \iffirstargument - {#1}% - \else - \defaultleftreferencetoks - \let\leftofreferencecontent\empty - \fi - \rightreferencetoks - \ifsecondargument - {#2}% - \else - \defaultrightreferencetoks - \let\rightofreferencecontent\empty - \fi - % inefficient: double resolve - \doifreferencefoundelse{#4} % we need to resolve the text - {\goto{\referencesequence}[#4]} - {\let\currentreferencecontent\dummyreference - \goto{\referencesequence}[#4]}% - \dostopgotoreference} - -\unexpanded\def\dospecialin{\dostartgotoreference\let\currentreferencecontent\currentreferencedefault\dopickupgotoreference} -\unexpanded\def\dospecialat{\dostartgotoreference\let\currentreferencecontent\currentreferencepage \dopickupgotoreference} - -%D \macros -%D {definereferenceformat} -%D -%D The next few macros were made for for David Arnold and Taco -%D Hoekwater. They can be used for predefining reference -%D texts, and thereby stimulate efficiency. -%D -%D \starttyping -%D \definereferenceformat[informula] [left=(,right=),text=formula] -%D \definereferenceformat[informulas] [left=(,right=),text=formulas] -%D \definereferenceformat[andformula] [left=(,right=),text=and] -%D \definereferenceformat[andformulas][left=(,right=),text=and] -%D -%D \informula [b] and \informula [for:c] -%D the \informula {formulas}[b] \informula {and} [for:c] -%D the \informulas {formulas}[b] \informula {and} [for:c] -%D the \informulas [b] \informula {en} [for:c] -%D the \informulas [b] \andformula [for:c] -%D \stoptyping -%D -%D Instead of a text, one can specify a label, which should -%D be defined with \type {\setuplabeltext}. -%D -%D Watch out: the second argument is somewhat special and mostly -%D meant for a suffix to a number: -%D -%D \startbuffer -%D \definereferenceformat [intesta] [left=(,right=),text=Whatever~] -%D \definereferenceformat [intestb] [left=(,right=),label=figure] -%D -%D \placeformula[x]\startformula a \stopformula -%D -%D \starttabulate[|||||] -%D \NC \in [x] \NC \in {left}[x] \NC \in {}{right}[x] \NC \in {left}{right}[x] \NC \NR -%D \NC \intesta[x] \NC \intesta{left}[x] \NC \intesta{}{right}[x] \NC \intesta{left}{right}[x] \NC \NR -%D \NC \intestb[x] \NC \intestb{left}[x] \NC \intestb{}{right}[x] \NC \intestb{left}{right}[x] \NC \NR -%D \stoptabulate -%D \stopbuffer -%D -%D \typebuffer \getbuffer - -% to be done: interfaced - -\installcommandhandler \??re {referenceformat} \??re - -\appendtoks - \setuevalue\currentreferenceformat{\doexecutereferenceformat{\currentreferenceformat}}% -\to \everydefinereferenceformat - -\setupreferenceformat - [\c!left=, - \c!right=, - \c!text=, - \c!label=, - \c!autocase=\v!no, - \c!style=, - \c!type=default, % to be done: interfaced - \c!setups=, - \c!color=] - -\unexpanded\def\doexecutereferenceformat#1% - {\dostartgotoreference - \edef\currentreferenceformat{#1}% - \gdef\leftofreference {\referenceformatparameter\c!left }% - \gdef\rightofreference {\referenceformatparameter\c!right }% - \edef\currentreferenceformatlabel {\referenceformatparameter\c!label }% - \edef\currentreferenceformattype {\referenceformatparameter\c!type }% - \edef\currentreferenceformatsetups {\referenceformatparameter\c!setups }% - \edef\currentreferenceformatautocase{\referenceformatparameter\c!autocase}% - \dosetreferenceformatattributes \c!style \c!color - \ifx\fontattributehash\empty \else - \resetinteractionparameter\c!style - \fi - \ifx\colorattributehash\empty \else - \resetinteractionparameter\c!contrastcolor - \resetinteractionparameter\c!color - \fi - \ifx\currentreferenceformatlabel\autoreferencelabeltextflag - \edef\currentreferenceformatlabel{\autoreferencelabeltext}% - \fi - \ifx\currentreferenceformatautocase\v!yes - \setcharactercleaning[1]% - \fi - \ifx\currentreferenceformatlabel\empty - \defaultleftreferencetoks {\referenceformatparameter\c!text}% - \defaultrightreferencetoks\emptytoks - \else - \defaultleftreferencetoks {\leftlabeltext \currentreferenceformatlabel}% - \defaultrightreferencetoks{\rightlabeltext\currentreferenceformatlabel}% - \fi - \ifx\currentreferenceformattype\empty - \def\currentreferenceformattype{default}% - \fi - % - \ifx\currentreferenceformatsetups\empty - \def\currentreferencecontent{\filterreference\currentreferenceformattype}% - \else - \def\currentreferencecontent{\directsetup\currentreferenceformatsetups}% - \fi - % - \let\leftofreferencecontent \empty - \let\rightofreferencecontent\empty - \dopickupgotoreference} - -\def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key - -\unexpanded\def\autoreferencelabeltext - {\ctxlua{structures.references.getcurrentmetadata("name")}} - -% \starttext -% \definereferenceformat[inxx] [left=(,right=),text=txt] -% \setupinteraction[state=start] -% \chapter[one]{xx} -% [\goto{state}[file(mk-last-state)]] -% [\goto{state} [file(mk-last-state)]] -% [\at{page} [one]] -% [\at{page}[one]] -% [\at{page}{okay}[one]] -% [\inxx{a}{b}[one]] -% \stoptext - -% \startsetups referenceformat:numberplustext -% \filterreference{number}, \filterreference{title} -% \stopsetups -% -% \definereferenceformat[hellup][text=Hellup ,setups=referenceformat:numberplustext] - -%D In interactive documents going to a specific location is not -%D bound to cross references. The \type{\goto} commands can be -%D used to let users access another part of the document. In -%D this respect, interactive tables of contents and registers -%D can be considered goto's. Because in fact a \type{\goto} is -%D just a reference without reference specific data, the -%D previous macros are implemented using the goto -%D functionality. -%D -%D \showsetup{goto} -%D -%D One important characteristic is that the first argument of -%D \type{\goto} (and therefore \type{\at} and \type{\in} is -%D split at spaces. This means that, although hyphenation is -%D prevented, long references can cross line endings. - -% \starttext -% \setupinteraction[state=start] -% [\goto{state}[file(mk-last-state)]] -% [\goto{state} [file(mk-last-state)]] -% \stoptext - -\newconditional\uselocationstrut \settrue\uselocationstrut - -\def\extrareferencearguments{\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow,"\currentviewerlayer"} - -\unexpanded\def\directgoto{\ifconditional\uselocationstrut\expandafter\dodirectgoto\else\expandafter\dodirectgotohtdp\fi} -\unexpanded\def\goto {\ifconditional\uselocationstrut\expandafter\dogoto \else\expandafter\dogotohtdp \fi} - -% The unbox trick is needed in order to permit \par inside a reference. Otherwise -% the reference attribute migrates to the outer boxes. - -\newcount\lastsavedreferenceattribute - -\newbox\referencebox - -\def\revivesavedreferenceattribute % sometimes handy as no test etc needed - {\attribute\referenceattribute\lastsavedreferenceattribute} - -\def\dodirectgoto#1[#2]% no test for valid references - {\dontleavehmode - \begingroup - \attribute\referenceattribute\attributeunsetvalue - \global\lastsavedreferenceattribute\attributeunsetvalue - \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#2",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% - \setlocationattributes - \setstrut % can be option - \global\lastsavedreferenceattribute\lastreferenceattribute - \attribute\referenceattribute\lastreferenceattribute - \dostarttagged\t!link\empty % not here - #1% - \dostoptagged - \else - #1% - \fi - \endgroup} - -\def\dodirectgotohtdp#1[#2]% no test for valid references - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \attribute\referenceattribute\attributeunsetvalue - \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#2",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}% - \setlocationattributes - \attribute\referenceattribute\lastreferenceattribute - \global\lastsavedreferenceattribute\lastreferenceattribute - \dostarttagged\t!link\empty - #1% - \dostoptagged - \else - #1% - \fi - \endgroup} - -\def\dogoto#1#2[#3]% #2 gobbles spaces after #1 so that \goto{xx} [yy] works ok - {\dontleavehmode - \begingroup - %\setbox\referencebox\hbox\bgroup % experiment, might change again to non \par support - \global\lastsavedreferenceattribute\attributeunsetvalue - \attribute\referenceattribute\attributeunsetvalue - \iflocation - \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}% - {\expandtexincurrentreference - \ctxlua{structures.references.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}% - \setlocationattributes - \setstrut % can be option - \global\lastsavedreferenceattribute\lastreferenceattribute - \attribute\referenceattribute\lastreferenceattribute - \dostarttagged\t!link\empty - #1% - \dostoptagged}% - {#1}% - \else - #1% - \fi - %\egroup\unhbox\referencebox} - \endgroup} - -\def\dogotohtdp#1#2[#3]% #2 gobbles spaces after #1 so that \goto{xx} [yy] works ok - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \attribute\referenceattribute\attributeunsetvalue - \iflocation - \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}% - {\expandtexincurrentreference - \ctxlua{structures.references.injectcurrentset(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax)}% - \setlocationattributes - \global\lastsavedreferenceattribute\lastreferenceattribute - \attribute\referenceattribute\lastreferenceattribute - \dostarttagged\t!link\empty - #1% - \dostoptagged}% - {#1}% - \else - #1% - \fi - \endgroup} - -\unexpanded\def\directgotobox#1[#2]% no test for valid references - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \attribute\referenceattribute\attributeunsetvalue - \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% - \setlocationattributes - \global\lastsavedreferenceattribute\lastreferenceattribute - \dostarttagged\t!link\empty - \hbox attr \referenceattribute \lastreferenceattribute {#1}% - \dostoptagged - \else - #1% - \fi - \endgroup} - -\unexpanded\def\directgotospecbox#1#2[#3]% no test for valid references - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \attribute\referenceattribute\attributeunsetvalue - \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#3",nil,nil,\extrareferencearguments)}% - \setlocationcolorspec{#1}% #1=\resolver; no consequence for strut - \global\lastsavedreferenceattribute\lastreferenceattribute - \dostarttagged\t!link\empty - \hbox attr \referenceattribute \lastreferenceattribute {#2}% - \dostoptagged - \else - #2% - \fi - \endgroup} - -\unexpanded\def\directgotodumbbox#1[#2]% no test for valid references - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \attribute\referenceattribute\attributeunsetvalue - \iflocation - \ctxlua{structures.references.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% - \global\lastsavedreferenceattribute\lastreferenceattribute - \dostarttagged\t!link\empty - \hbox attr \referenceattribute \lastreferenceattribute {#1}% - \dostoptagged - \else - #1% - \fi - \endgroup} - -\unexpanded\def\gotobox#1[#2]% no test for valid references - {\dontleavehmode - \begingroup - \global\lastsavedreferenceattribute\attributeunsetvalue - \attribute\referenceattribute\attributeunsetvalue - \iflocation - \ctxlua{structures.references.doifelse("\referenceprefix","#2",\extrareferencearguments)}% - {\expandtexincurrentreference - \ctxlua{structures.references.injectcurrentset(nil,nil)}% - \setlocationattributes - \global\lastsavedreferenceattribute\lastreferenceattribute - \dostarttagged\t!link\empty - \hbox attr \referenceattribute \lastreferenceattribute {#1}% - \dostoptagged}% - {#1}% - \else - #1% - \fi - \endgroup} - -\unexpanded\def\gotowdhtbox#1#2[#3]% fast variant for overlays - {\dontleavehmode - \begingroup - \setbox\scratchbox\emptyhbox\wd\scratchbox#1\ht\scratchbox#2% - \global\lastsavedreferenceattribute\attributeunsetvalue - \attribute\referenceattribute\attributeunsetvalue - \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}% - {\ctxlua{structures.references.injectcurrentset(nil,nil)}% - \global\lastsavedreferenceattribute\lastreferenceattribute - \hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}} - {\box\scratchbox}% - \endgroup} - -%D An reference to another document can be specified as a file -%D or as an \URL. Both are handled by the same mechanism and -%D can be issued by saying something like: -%D -%D \starttyping -%D \goto[dictionary::the letter a] -%D \stoptyping -%D -%D One can imagine that many references to such a dictionary -%D are made, so in most cases such a document reference in an -%D indirect one. -%D -%D \showsetup{useexternaldocument} -%D -%D For example: -%D -%D \starttyping -%D \useexternaldocument -%D [dictionary][engldict] -%D [The Famous English Dictionary] -%D \stoptyping -%D -%D The next macro implements these relations, and also take -%D care of loading the document specific references. -%D -%D The \URL\ alternative takes four arguments: -%D -%D \showsetup{useURL} -%D -%D like: -%D -%D \starttyping -%D \useURL -%D [dictionary][http://www.publisher.com/public][engldict] -%D [The Famous English Dictionary] -%D \stoptyping -%D -%D Several specifications are possible: -%D -%D \starttyping -%D \useURL [id] [url] [file] [description] -%D \useURL [id] [url] [file] -%D \useURL [id] [url] -%D \stoptyping -%D -%D This time we don't load the references when no file is -%D specified. This is logical when one keeps in mind that a -%D valid \URL\ can also be a mail address. - -\unexpanded\def\usefile{\dotripleargument\dousefile} % so that they can be used in expanded arguments -\unexpanded\def\useurl {\doquadrupleempty\douseurl } % so that they can be used in expanded arguments - -\let\useURL \useurl -\let\useexternaldocument\usefile - -\def\douseurl[#1][#2][#3][#4]% - {\ctxlua{structures.references.urls.define("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es,\!!bs\detokenize{#4}\!!es)}} - -\def\dousefile[#1][#2][#3]% - {\ctxlua{structures.references.files.define("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es)}} - -\def\doifurldefinedelse #1{\ctxcommand{doifurldefinedelse ("#1")}} -\def\doiffiledefinedelse#1{\ctxcommand{doiffiledefinedelse("#1")}} - -%D \macros -%D {url,setupurl} -%D -%D We also have: \type{\url} for directly calling the -%D description. So we can say: -%D -%D \starttyping -%D \useURL [one] [http://www.test.nl] -%D \useURL [two] [http://www.test.nl] [] [Some Site] -%D -%D \url[one] or \from[two] or \goto{Whatever Site}[URL(two)] -%D \stoptyping -%D -%D An \URL\ can be set up with -%D -%D \showsetup{setupurl} - -\unexpanded\def\setupurl - {\dodoubleargument\getparameters[\??ur]} - -\unexpanded\def\url[#1]% - {\dontleavehmode - \begingroup - \dosetfontattribute\??ur\c!style - \dosetcolorattribute\??ur\c!color - \hyphenatedurl{\ctxlua{structures.references.urls.get("#1","\@@uralternative","\@@urspace")}}% - \endgroup} - -% # fails - -%D This macro is hooked into a support macro, and thereby -%D \URL's break ok, according to the setting of a switch, -%D -%D \startbuffer -%D \useURL -%D [test] -%D [sentence_sentence~sentence//sentence:sentence.sentence] -%D \stopbuffer -%D -%D \typebuffer -%D -%D Such an \URL\ is, depending on the settings, hyphenated as: -%D -%D \getbuffer -%D -%D \startlinecorrection -%D \hbox to \hsize -%D {\hss\en -%D \setupreferencing[urlalternative=both]% -%D \vbox{\hsize.25cm\hbox{\bf both}\prewordbreak\url[test]}% -%D \hss -%D \setupreferencing[urlalternative=before]% -%D \vbox{\hsize.25cm\hbox{\bf before}\prewordbreak\url[test]}% -%D \hss -%D \setupreferencing[urlalternative=after]% -%D \vbox{\hsize.25cm\hbox{\bf after}\prewordbreak\url[test]}% -%D \hss} -%D \stoplinecorrection -%D -%D By setting \type{urlspace=yes} one can get slightly better -%D spacing when using very long \URL's. -%D -%D When defining the external source of information, one can -%D also specify a suitable name (the last argument). This name -%D can be called upon with: -%D -%D \showsetup{from} - -%D We keep this for compatibility reasons, hence the hackery. - -\unexpanded\def\dospecialfrom - {\dosingleempty\dodospecialfrom} - -\def\dodospecialfrom[#1]% - {\dontleavehmode - \goto{\ctxlua{structures.references.from("#1")}}[fileorurl(#1)]} - -\def\dofromurldescription#1% - {#1} - -\def\dofromurlliteral#1% - {\dosetfontattribute \??ur\c!style - \dosetcolorattribute\??ur\c!color - \hyphenatedurl{#1}} - -\let\dofromfiledescription\dofromurldescription -\let\dofromfileliteral \dofromurlliteral % maybe some day setupfile that inherits from url - -%D We also support: -%D -%D \starttyping -%D \goto{some text}[file(identifier{location}] -%D \stoptyping -%D -%D which is completely equivalent with -%D -%D \starttyping -%D \goto{some text}[identifier::location] -%D \stoptyping - -%D A special case of references are those to programs. These, -%D very system dependant references are implemented by abusing -%D some of the previous macros. -%D -%D \showsetup{setupprograms} -%D \showsetup{defineprogram} -%D \showsetup{program} % changed functionality ! -%D -%D The latter gives access to the description of the program, -%D being the last argument to the definition command. - -% also lua, like urls and files - -\unexpanded\def\setupprograms - {\dodoubleargument\getparameters[\??pr]} - -\unexpanded\def\defineprogram - {\dotripleargument\dodefineprogram} - -\def\dodefineprogram[#1][#2][#3]% - {\ctxlua{structures.references.programs.define("#1","#2","#3")}} - -\def\program[#1]% incompatible, more consistent, hardy used anyway - {\dontleavehmode - \begingroup - \dosetfontattribute\??pr\c!style - \dosetcolorattribute\??pr\c!color - \ctxlua{structures.references.programs.get("#1","\@@pralternative","\@@prspace")}% - \endgroup} - -%D As we can see, we directly use the special reference -%D mechanism, which means that -%D -%D \starttyping -%D \goto{some text}[program(name{args})] -%D \stoptyping -%D -%D is valid. - -%D The next macro provides access to the actual pagenumbers. -%D When documenting and sanitizing the original reference -%D macros, I decided to keep the present meaning as well as to -%D make this meaning available as a special reference method. -%D So now one can use: -%D -%D \starttyping -%D \gotopage{some text}[location] -%D \gotopage{some text}[number] -%D \gotopage{some text}[file::number] -%D \stoptyping -%D -%D as well as: -%D -%D \starttyping -%D \goto{some text}[page(location)] -%D \goto{some text}[page(number)] -%D \goto{some text}[file::page(number)] -%D \stoptyping -%D -%D Here location is a keyword like \type{nextpage}. -%D -%D \showsetup{gotopage} - -\unexpanded\def\definepage - {\dodoubleargument\dodefinepage} - -\def\dodefinepage[#1][#2]% - {\definereference[#1][page(#1)]} - -\def\gotopage#1[#2]% - {\goto{#1}[\v!page(#2)]} - -%D The previous definitions are somewhat obsolete so we don't -%D use it here. - -%D A still very rudimentary|/|experimental forward|/|backward -%D reference mechanism is provided by the macro \type{\atpage}: -%D -%D \starttyping -%D ... \somewhere{backward text}{forward text}[someref] ... -%D ... \atpage[someref] ... -%D \stoptyping -%D -%D In future versions there will be more sophisticated - -% 0 = no page reference -% 1 = same page -% 2 = preceding page -% 3 = following page -% 4 = backward, same page (todo) -% 5 = forward, same page (todo) - -%D We can cross link documents by using: -%D -%D \showsetup{coupledocument} -%D -%D like: -%D -%D \starttyping -%D \coupledocument[print][somefile][chapter,section] -%D \stoptyping -%D -%D After which when applicable, we have available the -%D references: -%D -%D \starttyping -%D \goto{print version}[print::chapter] -%D \stoptyping -%D -%D and alike. The title placement definition macros have a -%D key \type{file}, which is interpreted as the file to jump -%D to, that is, when one clicks on the title. - -\def\coupledocument - {\doquadrupleempty\docoupledocument} - -\def\docoupledocument[#1][#2][#3][#4]% [name] [file] [sections] [description] - {\ifthirdargument - % this will be done differently (when it's needed) - \fi} - -%D \macros -%D {dotextprefix} -%D -%D In previous macros we used \type {\dotextprefix} to -%D generate a space between a label and a number. -%D -%D \starttyping -%D \dotextprefix{text} -%D \stoptyping -%D -%D Only when \type {text} is not empty, a space is inserted. - -\def\dotextprefix#1% - {\begingroup - \setbox\scratchbox\hbox{#1}% to be solved some day - \ifdim\wd\scratchbox>\zeropoint - \unhbox\scratchbox - \doifsomething\@@rfseparator{\removeunwantedspaces\@@rfseparator}% remove is new - \else - \unhbox\scratchbox - \fi - \endgroup} - -%D In the next settings we see some variables that were not -%D used here and that concern the way the pagenumbers refered -%D to are typeset. - -\setupreferencing - [\c!state=\v!start, - \c!autofile=\v!no, - \v!part\c!number=\v!yes, - \v!chapter\c!number=\v!no, - \c!interaction=\v!all, - \c!convertfile=\v!no, - %\c!strut=\v!no, % some day an option - \c!prefix=, - \c!width=.75\makeupwidth, - \c!left=\quotation\bgroup, - \c!right=\egroup, - \c!global=\v!no, - \c!expansion=\v!no, - \c!separator=\nonbreakablespace, - \c!export=\v!no] - -\setupurl - [\c!alternative=\v!both, - \c!space=\v!no, - \c!style=\v!type, - \c!color=] - -\setupprograms - [\c!directory=, - \c!alternative=\v!both, - \c!space=\v!no, - \c!style=\v!type, - \c!color=] - -\definereference [\v!CloseDocument ] [action(close)] -\definereference [\v!ExitViewer ] [action(exit)] -\definereference [\v!FirstPage ] [action(first)] -\definereference [\v!LastPage ] [action(last)] -\definereference [\v!NextJump ] [action(forward)] -\definereference [\v!NextPage ] [action(next)] -\definereference [\v!PauseMovie ] [action(pausemovie)] -\definereference [\v!PauseSound ] [action(pausesound)] -\definereference [\v!PauseRendering ] [action(pauserendering)] -\definereference [\v!PreviousJump ] [action(backward)] -\definereference [\v!PreviousPage ] [action(previous)] -\definereference [\v!PrintDocument ] [action(print)] -\definereference [\v!SaveForm ] [action(exportform)] -\definereference [\v!LoadForm ] [action(importform)] -\definereference [\v!ResetForm ] [action(resetform)] -\definereference [\v!ResumeMovie ] [action(resumemovie)] -\definereference [\v!ResumeSound ] [action(resumesound)] -\definereference [\v!ResumeRendering ] [action(resumerendering)] -\definereference [\v!SaveDocument ] [action(save)] -\definereference [\v!SaveNamedDocument] [action(savenamed)] -\definereference [\v!OpenNamedDocument] [action(opennamed)] -\definereference [\v!SearchDocument ] [action(search)] -\definereference [\v!SearchAgain ] [action(searchagain)] -\definereference [\v!StartMovie ] [action(startmovie)] -\definereference [\v!StartSound ] [action(startsound)] -\definereference [\v!StartRendering ] [action(startrendering)] -\definereference [\v!StopMovie ] [action(stopmovie)] -\definereference [\v!StopSound ] [action(stopsound)] -\definereference [\v!StopRendering ] [action(stoprendering)] -\definereference [\v!SubmitForm ] [action(submitform)] -\definereference [\v!ToggleViewer ] [action(toggle)] -\definereference [\v!ViewerHelp ] [action(help)] -\definereference [\v!HideField ] [action(hide)] -\definereference [\v!ShowField ] [action(show)] -\definereference [\v!GotoPage ] [action(gotopage)] -\definereference [\v!Query ] [action(query)] -\definereference [\v!QueryAgain ] [action(queryagain)] -\definereference [\v!FitWidth ] [action(fitwidth)] -\definereference [\v!FitHeight ] [action(fitheight)] -\definereference [\v!ShowThumbs ] [action(thumbnails)] -\definereference [\v!ShowBookmarks ] [action(bookmarks)] - -\definereference [\v!HideLayer ] [action(hidelayer)] -\definereference [\v!VideLayer ] [action(videlayer)] -\definereference [\v!ToggleLayer ] [action(togglelayer)] - -\definereference [\v!firstpage] [page(firstpage)] -\definereference [\v!previouspage] [page(previouspage)] -\definereference [\v!nextpage] [page(nextpage)] -\definereference [\v!lastpage] [page(lastpage)] -\definereference [\v!forward] [page(forward)] -\definereference [\v!backward] [page(backward)] -\definereference [\v!firstsubpage] [page(firstsubpage)] -\definereference [\v!previoussubpage] [page(previoussubpage)] -\definereference [\v!nextsubpage] [page(nextsubpage)] -\definereference [\v!lastsubpage] [page(lastsubpage)] - -% we can do this but only when later in resolve (else problems with \chapter[first]{...} -% -% \definereference [\v!first] [page(firstpage)] -% \definereference [\v!previous] [page(prevpage)] -% \definereference [\v!next] [page(nextpage)] -% \definereference [\v!last] [page(lastpage)] -% \definereference [\v!first\v!sub] [page(firstsubpage)] -% \definereference [\v!previous\v!sub] [page(prevsubpage)] -% \definereference [\v!next\v!sub] [page(nextsubpage)] -% \definereference [\v!last\v!sub] [page(lastsubpage)] - -%D We cannot set up buttons (not yet, this one calls a menu macro): - -%D New (and experimental): - -% \starttext -% \chapter{test} -% \placefigure[here][xx:1]{}{\framed{one}} \placefigure[here][xx:2]{}{\framed{three}} -% \placetable [here][xx:3]{}{\framed{two}} \placetable [here][xx:4]{}{\framed{four}} -% \start -% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4] -% \stop \blank \start -% \setupreferencestructureprefix[default][prefix=no] -% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4] -% \stop \blank \start -% \setupreferencestructureprefix[float][default][prefix=no] -% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4] -% \stop \blank \start -% \setupreferencestructureprefix[figure][default][prefix=no] -% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4] -% \stop \blank -% \stoptext - -\unexpanded\def\setupreferencestructureprefix - {\dotripleargument\dosetupreferencestructureprefix} - -\def\getreferencestructureprefix#1#2#3% - {{ - prefix = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefix", - separatorset = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixseparatorset", - conversion = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconversion", - conversionset = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconversionset", - set = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixset", - segments = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixsegments", - connector = \!!bs\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconnector\!!es, - }} - -\unexpanded\def\setupreferencestructureprefix - {\dotripleempty\dosetupreferencestructureprefix} - -\def\dosetupreferencestructureprefix[#1][#2][#3]% - {\ifthirdargument - \getparameters[\??rf:\c!prefix:#1:#2][#3]% - \else\ifsecondargument - \getparameters[\??rf:\c!prefix::#1][#2]% - \fi\fi} - -\def\referencestructureprefixparameter#1#2#3#4% kind name category parameter - {\ifcsname\??rf:\c!prefix:#2:#3#4\endcsname - \csname\??rf:\c!prefix:#2:#3#4\endcsname - \else\ifcsname\??rf:\c!prefix:#1:#3#4\endcsname - \csname\??rf:\c!prefix:#1:#3#4\endcsname - \else\ifcsname\??rf:\c!prefix::#3#4\endcsname - \csname\??rf:\c!prefix::#3#4\endcsname - \fi\fi\fi} - -% \def\getreferencestructureprefixspec#1% we can save one call by moving this to the lua end -% {\getreferencestructureprefix -% {\ctxlua{structures.references.getcurrentmetadata("kind")}} -% {\ctxlua{structures.references.getcurrentmetadata("name")}} -% {#1}} -% \def\currentreferencedefault -% {\ctxlua{structures.references.filter("default",\getreferencestructureprefixspec\v!default)}} -% -% this is shortcut for: - -\def\currentreferencedefault - {\ctxlua{structures.references.filter("default",\ctxlua{structures.references.getcurrentprefixspec("\v!default")})}} - -%D Not all support is visible by looking at the \TEX\ code; here is one of those:^ -%D -%D \starttyping -%D \startinteractionmenu[right] -%D \startbut [section(first {chapter})] first chapter \stopbut -%D \startbut [section(previous{chapter})] previous chapter \stopbut -%D \startbut [section(next {chapter})] next chapter \stopbut -%D \startbut [section(last {chapter})] last chapter \stopbut -%D \blank[2*big] -%D \startbut [section(first {section})] first section \stopbut -%D \startbut [section(previous{section})] previous section \stopbut -%D \startbut [section(next {section})] next section \stopbut -%D \startbut [section(last {section})] last section \stopbut -%D \stopinteractionmenu -%D \stoptyping - -\protect \endinput - -% tricky: -% -% \enabletrackers[nodes.references] -% \setupinteraction[state=start] -% \def\KnuthTest{\input knuth } -% \def\KnuthTest{\input tufte } -% \def\TufteTest{\input tufte } -% \defineoverlay[xxx][\overlaybutton{page(3)}] -% \setupbackgrounds[text][background=xxx] -% \starttext -% test {\red \KnuthTest} test \par -% \button{test}[page(1)] \par -% \goto{page 2 \TeX}[page(2)] \goto{page 2 \TeX}[page(2)] \goto{\TufteTest}[page(2)] test \page -% test \goto{page 3}[page(3)] \goto{\TufteTest\space\par\TufteTest}[page(4)] test \page -% \goto{page 1}[page(1)] \goto{\TufteTest\space test}[page(1)] \page -% \goto{page 1}[page(1)] \goto{\KnuthTest\space test}[page(1)] \page -% test \goto{page 1}[page(1)] {\goto{\KnuthTest\space test}[page(1)]} test -% \goto{page 1}[page(1)] \goto{\TufteTest}[page(1)] test \page -% \stoptext diff --git a/tex/context/base/strc-ref.mkvi b/tex/context/base/strc-ref.mkvi new file mode 100644 index 000000000..40f03a6d6 --- /dev/null +++ b/tex/context/base/strc-ref.mkvi @@ -0,0 +1,1732 @@ +%D \module +%D [ file=strc-ref, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Cross Referencing, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +% todo: (1) configure references, (2) rendering => with presets +% +% \definestructureconversionset[default][Character,number,Romannumerals,Character][number] +% \definestructureseparatorset [default][.,.,--][.] +% \setuphead[subsection][sectionstopper=),sectionsegments=4:4] +% \setupreferencestructureprefix[default][prefixsegments=2:4] +% \setupreferencestructureprefix[figure][default][prefixsegments=3:4] +% \chapter {One} +% \section {One} +% \subsection[sec:test]{Two} +% See \in[sec:test] and \in[fig:xx] and \in[fig:yy] +% \placefigure[here][fig:xx]{}{} +% \placefigure[here][fig:yy]{}{} + +\writestatus{loading}{ConTeXt Structure Macros / Cross Referencing} + +\registerctxluafile{strc-rsc}{1.001} +\registerctxluafile{strc-ref}{1.001} +\registerctxluafile{node-ref}{1.001} + +\unprotect + +%D This module is a (partial) rewrite of core-ref.tex for \MKIV. As +%D such it will be a moving target for a while. + +%D Later we will do a further cleanup and move much of the code to +%D \LUA\ (i.e.\ better backend integration). + +\let\mainreference\gobblefivearguments + +% this will go when we got rid of the tuo file + +\let\currentfolioreference \!!zerocount % only used in xml-fo +\let\resetreferences \relax +\let\setreferences \relax +\let\showcurrentreference \relax +\let\setexecutecommandcheck\gobbletwoarguments + +\def\s!full{full} +\def\s!user{user} +\def\s!text{text} +\def\s!page{page} + +% todo : unknown/illegal reference no arg +% todo : +n pages check on 'samepage' (contrastcolor) +% todo : multiple text in reference + +% Makes more sense to build action data first, especially now +% openaction etc are supported. +% +% \definespecial\doexecuteactionchain w h +% \definespecial\dosetgotolocation +% \definespecial\dosetexecuteJScode +% ... + +%D This module deals with referencing. In \CONTEXT\ referencing +%D is one of the core features, although at a first glance +%D probably nobody will notice. This is good, because +%D referencing should be as hidden as possible. +%D +%D In paper documents, referencing comes down to cross +%D referencing, but in their interactive counterparts, is also +%D involves navigation. Many features implemented here are +%D therefore closely related to navigation. +%D +%D Many \CONTEXT\ commands can optionally be fed with a +%D reference. Such a reference, when called upon, returns the +%D number of a figure, table, chapter etc, a piece of text, or +%D a pagenumber. +%D +%D There are three ways of defining a reference: +%D +%D \starttyping +%D \pagereference[here] +%D \textreference[here]{some text} +%D \stoptyping +%D +%D the third alternative combines them in: +%D +%D \starttyping +%D \reference[here]{some text} +%D \stoptyping + +\unexpanded\def\textreference {\dosingleargument\do_text_reference} +\unexpanded\def\pagereference {\dosingleargument\do_page_reference} +\unexpanded\def\reference {\dosingleargument\do_full_reference} +\unexpanded\def\setreference {\dodoubleargument\do_set_reference } + +%D These are implemented in a low level form as: + +\def\do_text_reference [#labels]{\do_do_set_reference\s!text{#labels}{}} +\def\do_page_reference [#labels]{\do_do_set_reference\s!page{#labels}{}{}} +\def\do_full_reference [#labels]{\do_do_set_reference\s!full{#labels}{}} +\def\do_set_reference[#labels][#settings]{\do_do_set_reference\s!user{#labels}{#settings}{}} + +%D Actually there is not much difference between a text and a +%D full reference, but it's the concept that counts. The low +%D level implementation is: + +\newcount\lastreferenceattribute +\newcount\lastdestinationattribute + +\def\dofinishfullreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label")}}} +\def\dofinishtextreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label",{})}}} + +\let\dofinishpagereference\dofinishfullreference +\let\dofinishuserreference\dofinishfullreference + +\def\dofinishsomereference#kind{\executeifdefined{dofinish#{kind}reference}\gobbletwoarguments} + +\def\do_do_set_reference + {\ifreferencing + \expandafter\do_do_do_set_reference + \else + \expandafter\gobblefourarguments + \fi} + +\def\do_do_do_set_reference#kind#labels#userdata#text% labels userdata text -> todo: userdata + {\ifreferencing + % we could have a more efficient one for page references but for the moment + % we don't care too much + \edef\currentreferencekind {#kind}% + \edef\currentreferencelabels {#labels}% + \edef\currentreferenceuserdata {#userdata}% + \edef\currentreferenceexpansion{\@@rfexpansion}% {\referenceparameter\c!expansion} + \ifx\currentreferencelabels\empty \else + \ifx\currentreferenceexpansion\s!xml + \xmlstartraw + \xdef\currentreferencedata{#text}% data, no text else conflict + \xmlstopraw + \globallet\currentreferencecoding\s!xml + \else + \ifx\currentreferenceexpansion\v!yes + \xdef\currentreferencedata{#text}% + \else + \xdef\currentreferencedata{\detokenize{#text}}% + \fi + \globallet\currentreferencecoding\s!tex + \fi + % beware, the structures.references.set writes a + % \setnextinternalreference + \ctxlua{structures.references.setandgetattribute("\currentreferencekind", "\referenceprefix","\currentreferencelabels", + { + references = { + % internal = \nextinternalreference, % no need for an internal as we have an explicit + block = "\currentsectionblock", + section = structures.sections.currentid(), + }, + metadata = { % we could assume page to have no metadata + kind = "#kind", + \ifx\currentreferencekind\s!page\else + catcodes = \the\catcodetable, + xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument"\else nil\fi, % only useful when text + \fi + }, + \ifx\currentreferencedata\empty\else + entries = { + text = \!!bs\currentreferencedata\!!es + }, + \fi + \ifx\currentreferenceuserdata\empty\else + userdata = structures.helpers.touserdata(\!!bs\detokenize{#userdata}\!!es) + \fi + },"\interactionparameter\c!focus") + }% + % todo: optional + \xdef\currentdestinationattribute{\number\lastdestinationattribute}% + \begingroup\attribute\destinationattribute\currentdestinationattribute\emptyhbox\endgroup % todo + \fi + \fi} + +\def\defaultreferencepage#text{[[[#text]]]} +\def\defaultreferencetext#text{[[[#text]]]} + +%D For internal usage: + +\def\dosetsimplepagereference#label% + {\iflocation + \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","#label", + { + references = { + % block = "\currentsectionblock", + % section = structures.sections.currentid(), + }, + metadata = { % we could assume page to have no metadata + kind = "\s!page", + }, + },"\interactionparameter\c!focus") + }% + \xdef\currentdestinationattribute{\number\lastdestinationattribute}% + \else + \xdef\currentdestinationattribute{\number\attributeunsetvalue}% + \fi} + +\def\dogetsimplepagereference#label% + {\iflocation + \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% + \xdef\currentreferenceattribute{\number\lastreferenceattribute}% + \else + \xdef\currentreferenceattribute{\number\attributeunsetvalue}% + \fi} + +%D \macros +%D {everyreference} +%D +%D For rather tricky purposes, one can assign sanitizing +%D macros to \type{\everyreference} (no longer that relevant). + +\newevery \everyreference \relax + +%D This is really needed, since for instance Polish has a +%D different alphabet and needs accented entries in registers. + +\appendtoks + \cleanupfeatures +\to \everyreference + +%D We did not yet discuss prefixing. Especially in interactive +%D documents, it's not always easy to keep track of duplicate +%D references. The prefix mechanism, which we will describe +%D later on, solves this problem. By (automatically) adding a +%D prefix one keeps references local, but the global ones in +%D view. To enable this feature, we explictly split the prefix +%D from the reference. + +\let\referenceprefix\empty + +%D For a long time the only way to access an external file was +%D to use the file prefix (\type {somefile::}. However, when +%D you split up a document, redefining the references may be +%D such a pain, that another approach is feasible. By setting +%D the \type {autofile} variable to \type {yes} or \type +%D {page}, you can access the reference directly. +%D +%D \starttabulate[||||] +%D \NC filename::tag \NC page(filename::pnum) \NC tag \NC\NR +%D \NC $\star$ \NC \NC \NC\NR +%D \NC $\star$ \NC $\star$ \NC $\star$ \NC\NR +%D \NC \NC $\star$ \NC \NC\NR +%D \stoptabulate + +\unexpanded\def\usereferences[#filename]{} % obsolete + +%D As mentioned we will also use the cross reference mechanism +%D for navigational purposes. The main reason for this is that +%D we want to treat both categories alike: +%D +%D \starttyping +%D \goto{go back}[PreviousJump] +%D \goto{colofon}[colofon page] +%D \stoptyping +%D +%D Here \type{PreviousJump} is handled by the viewer, while the +%D \type{colofon page} reference is, apart from hyperlinking, a +%D rather normal reference. +%D +%D We already saw that cross refences are written to and read +%D from a file. The pure navigational ones don't need to be +%D written to file, but both for fast processing and +%D transparant integration, they are saved internally as a sort +%D of reference. We can easily distinguish such system +%D references from real cross reference ones by their tag. +%D +%D We also use the odd/even characteristic to determine the +%D page state. + +\let\currentrealreference \empty +\let\currentpagereference \empty +\let\currenttextreference \empty +\let\currentreferenceorder \empty +\let\currentsubtextreference \empty +\let\currentsubsubtextreference\empty + +\newcount\referencehastexstate % set in backend + +\def\referencepagestate{\ctxcommand{referencepagestate()}} +\def\referencerealpage {\ctxcommand{referencerealpage ()}} + +% referencepagestate: +% +% 0 = no page ref, 1=same page, 2=before, 3=after + +%D Cross references appear as numbers (figure~1.1, chapter~2) +%D or pagenumbers (page~2, page 3--2), and are called with +%D \type{\in} and \type{\at}. In interactive documents we also +%D have \type{\goto}, \type{\button} and alike. These are more +%D versatile and look like: +%D +%D \starttyping +%D \goto[reference] +%D \goto[outer reference::] +%D \goto[outer reference::inner reference] +%D \goto[operation(argument)] +%D \goto[operation(action{argument,argument})] +%D \goto[action] +%D \goto[action{argument}] +%D \stoptyping +%D +%D The first one is a normal reference, the second and third +%D are references to a file or \URL. The brace delimited +%D references for instance refer to a \JAVASCRIPT. The last +%D example shows that we can pass arguments to the actions. +%D +%D Now we've come to the testing step. As we can see below, +%D this macro does bit more than testing: it also resolves +%D the reference. This means that whenever we test for the +%D existance of a reference at an outer level, we have all the +%D relevant properties of that reference avaliable inside the +%D true branche~(\type{#2}). +%D +%D The prefix has to do with localizing references. When a +%D prefix is set, looking for a reference comes to looking for +%D the prefixed one, and when not found, looking for the non +%D prefixed one. Consider for instance the prefix set to +%D \type{sidetrack}. +%D +%D \starttyping +%D \pagereference[important] +%D \pagereference[unimportant] +%D \setupreferencing[prefix=sidetrack] +%D \pagereference[important] +%D \stoptyping +%D +%D results in saving (writing) the references +%D +%D \starttyping +%D ...{}{important} +%D ...{}{unimportant} +%D ...{sidetrack}{important}... +%D \stoptyping +%D +%D Now when we call for \type{unimportant}, we will indeed get +%D the pagenumber associated to this reference. But when we +%D call for \type{important}, while the prefix is still set, we +%D will get the pagenumber bound to the prefixed one. +%D +%D {\em Some day, when processing time and memory are no longer +%D performance factors, we will introduce multi||level +%D prefixes.} +%D +%D Before we start analyzing, I introduce a general +%D definition macro. Consider: +%D +%D \starttyping +%D \goto{do}[JS(My_Script{"test",123}),titlepage] +%D \stoptyping +%D +%D This can also be achieved by: +%D +%D \starttyping +%D \definereference[startup][JS(My_Script{"test",123}),titlepage] +%D \goto{do}[startup] +%D \stoptyping +%D +%D Now is this is a handy feature or not? +%D +%D \showsetup{definereference} +%D +%D We can trace references by setting the next switch to +%D true. + +\unexpanded\def\definereference + {\dodoubleempty\do_define_reference} + +\def\do_define_reference[#name][#specification]% + {\ctxlua{structures.references.define("\referenceprefix","#name",\!!bs\detokenize{#specification}\!!es)}} + +\unexpanded\def\resetreference[#name]% + {\ctxlua{structures.references.reset("\referenceprefix","#name")}} + +\def\setpagereference#name#specification% hm,. low level ? + {\ctxlua{structures.references.define("","#name",\!!bs\v!page(\luaescapestring{#specification})\!!es)}} + +%D Chained references are defined as: +%D +%D \starttyping +%D \goto{somewhere}[JS(somescript),nextpage,JS(anotherscript)] +%D \stoptyping +%D +%D Actually supporting chains is up to the special driver. Here +%D we only provide the hooks. + +%D \macros +%D {highlighthyperlinks} +%D +%D The next switch can be used to make user hyperlinks are +%D not highlighted when clicked on. + +\newconditional\highlighthyperlinks \settrue\highlighthyperlinks + +%D \macros +%D {gotonewwindow} +%D +%D To make the {\em goto previous jump} feature more +%D convenient when using more than one file, it makes sense +%D to force the viewer to open a new window for each file +%D opened. + +\newconditional\gotonewwindow \setfalse\gotonewwindow + +\def\expandtexincurrentreference % will happen in lua some time + {\ifcase\referencehastexstate\else\ctxlua{structures.references.expandcurrent()}\fi} + +\def\expandreferenceoperation#tag#content{\ctxcommand{setreferenceoperation(#tag,\!!bs#content\!!es)}} +\def\expandreferencearguments#tag#content{\ctxcommand{setreferencearguments(#tag,\!!bs#content\!!es)}} + +\def\doifreferencefoundelse#labels#yes#nop% + {\ctxlua{structures.references.doifelse("\referenceprefix","#labels",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}% + {\expandtexincurrentreference + #yes}% + {#nop}} + +%D The tester only splits the reference in components but does +%D not look into them. The following macro does a preroll and +%D determines for instance the current real reference pagenumber. +%D The \type {\currentrealreference} macro does the same so unless +%D one wants to use the pagestate the next macro seldom needs to +%D be called. + +%D The inner case is simple. Only two cases have to be taken +%D care of: +%D +%D \starttyping +%D \goto{some text}[reference] +%D \goto{some text}[prefix:reference] +%D \stoptyping +%D +%D References to other files however are treated strict or +%D tolerant, depending on their loading and availability: +%D +%D \starttyping +%D \useexternaldocument[somefile][filename][a nice description] +%D +%D \goto{checked reference}[somefile::reference] +%D \goto{unchecked reference}[somefile::] +%D \goto{unchecked reference}[anotherfile::reference] +%D \stoptyping +%D +%D An unknown reference is reported on the screen, in the log +%D file and, when enabled, in the left margin of the text. + +\let\unknownreference\gobbleoneargument + +%D When a reference is not found, we typeset a placeholder +%D (two glyphs are often enough to represent the reference +%D text). + +\def\dummyreference{{\tttf ??}} + +%D To prevent repetitive messages concerning a reference +%D being defined, we set such an unknown reference to an empty +%D one after the first encounter. + +%D Apart from cross references supplied by the user, \CONTEXT\ +%D generates cross references itself. Most of them are not +%D saved as a reference, but stored with their source, for +%D instance a list or an index entry. Such automatically +%D generated, for the user invisible, references are called +%D {\em internal references}. The user supplied ones are +%D labeled as {\em external references}. +%D +%D A second important characteristic is that when we want to +%D support different backends (viewers), we need to support +%D named destinations as well as page numbers. I invite readers +%D to take a glance at the special driver modules to understand +%D the fine points of this. As a result we will deal with {\em +%D locations} as well as {\em real page numbers}. We explictly +%D call this pagenumber a real one, because it is independant +%D of the page numbering scheme used in the document. +%D +%D One of the reasons for \CONTEXT\ being the first \TEX\ base +%D macropackage to support sophisticated interactive \PDF\ +%D files, lays in the mere fact that real page numbers are +%D available in most two pass data, like references, list data +%D and index entries. +%D +%D We will speak of \type{thisis...} when we are marking a +%D location, and \type{goto...} when we point to such a +%D location. The latter one can be seen as a hyperlink to the +%D former one. In the next macros one we use constructs like: +%D +%D \starttyping +%D \dostart... +%D \dostop... +%D \stoptyping +%D +%D Such macros are used to invoke the relevant specials from +%D the special driver modules (see \type{spec-ini}). The flag +%D \type{\iflocation} signals if we're in interactive mode. + +\ifx\buttonheight\undefined \newdimen\buttonheight \fi +\ifx\buttonwidth \undefined \newdimen\buttonwidth \fi + +%D Internal references can best be set using the next few +%D macros. Setting such references to unique values is +%D completely up to the macros that call them. +%D +%D \starttyping +%D \thisissomeinternal{tag}{identifier} +%D \gotosomeinternal {tag}{identifier}{pagenumber}{text} +%D \stoptyping + +%D We could do this in lua ... + +\newif \iflocation +\newcount\locationcount +\newcount\locationorder +\newbox \locationbox + +\def\nextinternalreference {\the\locationcount} +\def\nextinternalorderreference{\the\locationorder} + +\def\setnextinternalreference + {\global\advance\locationcount\plusone} + +\def\setnextinternalreferences#kind#name% plural + {\ctxlua{structures.references.setnextinternal("#kind","#name")}} + +\def\getinternalorderreference#kind#name% + {\ctxlua{structures.references.currentorder("#kind","#name")}} + +\def\thisissomeinternal#kind#name% only for old time sake + {\begingroup + \ctxlua{structures.references.setinternalreference("","#kind:#name")}% + \hbox attr \destinationattribute\lastdestinationattribute{}% + \endgroup} + +\newconditional\preferpagereferences + +\def\gotosomeinternal#kind#name#target#text% + {\ifconditional\preferpagereferences + \directgoto{#text}[page(#target)]% + \else + \directgoto{#text}[#kind:#name]% + \fi} + +\def\gotonextinternal#text#target% + {\directgoto{#text}[internal(#target)]} + +%D In this module we define three system references: one for +%D handling navigational, viewer specific, commands, another +%D for jumping to special pages, like the first or last one, +%D and a third reference for linking tree like lists, like +%D tables of contents. The latter two adapt themselves to the +%D current state. +%D +%D An example of an action is: +%D +%D \starttyping +%D \goto{some action}[PreviousJump] +%D \stoptyping +%D +%D as well as: +%D +%D \starttyping +%D \goto{some text}[\v!action(PreviousJump] +%D \stoptyping + +\newif\ifreferencing \referencingtrue + +%D One can also activate an automatic prefix mechanism. By +%D setting the \type{\prefix} variable to \type{+}, the prefix +%D is incremented, when set to \type{-} or empty, the prefix is +%D reset. Other values become the prefix. + +\newcount\prefixcounter + +%D These settings are accomplished by: +%D +%D \showsetup{setupreferencing} +%D +%D In interactive documents verbose references don't always +%D make sense (what is a page number in an unnumbered +%D document). By setting the \type{interaction} variable, one +%D can influences the way interactive references are set. + +\newtoks \everysetupreferencing + +\unexpanded\def\setupreferencing + {\dosingleargument\do_setup_referencing} + +\def\do_setup_referencing[#settings]% + {\getparameters[\??rf][\c!prefix=\s!unknown,#settings]% + \the\everysetupreferencing} + +\appendtoks + \processaction + [\@@rfstate] + [ \v!stop=>\referencingfalse, + \v!start=>\referencingtrue]% +\to \everysetupreferencing + +\newconditional\autocrossfilereferences + +\appendtoks + \doifelse\@@rfautofile\v!yes\settrue\setfalse\autocrossfilereferences +\to \everysetupreferencing + +\def\exportreferences + {\doif\@@rfexport\v!yes{\ctxlua{structures.references.export()}}} + +\appendtoks + \exportreferences +\to \everygoodbye + +\def\incrementreferenceprefix{+} +\def\decrementreferenceprefix{-} + +\unexpanded\def\setupreferenceprefix[#prefix]% + {\edef\@@rfprefix{#prefix}% + \ifx\@@rfprefix\empty + \let\referenceprefix\empty + \else\ifx\@@rfprefix\incrementreferenceprefix + \advance\prefixcounter \plusone % should be global + \edef\referenceprefix{\the\prefixcounter}% + \let\@@rfprefix\s!unknown + \else\ifx\@@rfprefix\decrementreferenceprefix + \let\referenceprefix\empty + \let\@@rfprefix\s!unknown + \else\ifx\@@rfprefix\s!unknown + % forget about it + \else + \edef\referenceprefix{\@@rfprefix}% expanded ! + \fi\fi\fi\fi} + +\unexpanded\def\setupglobalreferenceprefix[#prefix]% + {\xdef\referenceprefix{#prefix}} + +\unexpanded\def\pushreferenceprefix#prefix% + {\pushmacro\referenceprefix + \xdef\referenceprefix{#prefix}} + +\unexpanded\def\popreferenceprefix + {\popmacro\referenceprefix} + +%D We can typeset a reference using \type{\in}, \type{\at} and +%D \type{\about} and goto specific locations using +%D \type{\goto}. The last one does not make that much sense in +%D a paper document. To complicate things, \PLAIN\ \TEX\ also +%D implements an \type {\in} but fortunately that one only +%D makes sense in math mode. +%D +%D Typesetting the reference is a bit more complicated than one +%D would at first sight expect. This is due to the fact that we +%D distinguish three (five) alternative calls: +%D +%D \placefigure +%D [here][three calls] +%D {Three alternatives reference calls.} +%D {\startcombination[1*3] +%D {\framed{\type{ \in }}} {a} +%D {\framed{\type{ \at }}} {b} +%D {\framed{\type{\goto}}} {c} +%D \stopcombination} +%D +%D \startbuffer +%D \in figure[fig:three calls] +%D \in{figure}[fig:three calls] +%D \in figure a[fig:three calls] +%D \in{figure}{a}[fig:three calls] +%D figure~\in[fig:three calls] +%D \stopbuffer +%D +%D \typebuffer +%D +%D This turns up as: +%D +%D \startlines +%D \getbuffer +%D \stoplines +%D +%D The dual \type{{}} results in a split reference. In a +%D document meant for paper, one is tempted to use the last +%D (most straightforward) alternative. When a document is also +%D meant voor electronic distribution, the former alternatives +%D have preference, because everything between the \type{\in} +%D and~\type{[} becomes active (and when asked for, typeset +%D in a different color and typeface). + +% \unexpanded\def\in {\mathortext\donormalmathin \reference_in} +% \unexpanded\def\at {\mathortext\donormalmathat \reference_at} +% \unexpanded\def\about{\mathortext\donormalmathabout\reference_about} +% \unexpanded\def\from {\mathortext\donormalmathfrom \reference_from} +% \unexpanded\def\over {\mathortext\donormalmathover \reference_about} + +% \definecommand in {\reference_in} +% \definecommand at {\reference_at} +% \definecommand about {\reference_about} +% \definecommand from {\reference_from} +% \definecommand over {\reference_about} % needed here, else math problems + +\appendtoks + \ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \reference_in } \else \let\in \reference_in \fi + \ifdefined\at \let\normalmathat \at \unexpanded\def\at {\mathortext\normalmathat \reference_at } \else \let\at \reference_at \fi + \ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\reference_about} \else \let\about\reference_about \fi + \ifdefined\from \let\normalmathfrom \from \unexpanded\def\from {\mathortext\normalmathfrom \reference_from } \else \let\from \reference_from \fi + \ifdefined\over \let\normalmathover \over \unexpanded\def\over {\mathortext\normalmathover \reference_about} \else \let\over \reference_about \fi +\to \everydump + + \def\filterreference #key{\ctxcommand{filterreference("#key")}} % no checking, expanded +\unexpanded\def\getreferenceentry#key{\ctxcommand{filterreference("#key")}} % no checking, unexpanded + +\def\currentreferencenumber {\filterreference{number}} +\def\currentreferencepage {\filterreference{page}} +\def\currentreferencetitle {\filterreference{title}} +\def\currentreferencetext {\filterreference{text}} +\def\currentreferencedefault {\filterreference{default}} +\def\currentreferencerealpage{\filterreference{realpage}} + +%D The most straightforward way of retrieving references is +%D using \type{\ref}. + +\unexpanded\def\getreference % checking, unexpanded + {\dodoubleargument\do_get_reference} + +\def\do_get_reference[#key][#label]% #key = number page title text default realpage ... + {\ifsecondargument + \doifreferencefoundelse{#label}{\ctxcommand{filterreference("#key")}}\dummyreference + \else + \dummyreference + \fi} + +\let\ref\getreference + +%D Special cases: + +\unexpanded\def\reference_about[#label]% + {\dontleavehmode + \begingroup + \let\crlf\space + \let\\\space + \postponenotes + \@@rfleft + \doifreferencefoundelse{#label} + {\goto{\limitatetext\currentreferencetitle\@@rfwidth\unknown}[#label]}% not so efficient (dup lookup) + {}% todo + \@@rfright + \endgroup} + +%D The previously discussed setup macro lets us specify the +%D representation of references. A symbol reference does not +%D show the specific data, like the number of a figure, but +%D shows one of: \hbox {$^\goforwardcharacter$ +%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending +%D on the direction to go. + +% 0 = unknown +% 1 = same +% 2 = before +% 3 = after + +\def\do_by_reference_page_state#unknown#before#current#after% + {\ifcase\referencepagestate\relax#unknown\or#current\or#before\or#after\fi} + +\unexpanded\def\somewhere#backward#foreward#dummy[#label]% #dummy gobbles space around #foreward + {\doifreferencefoundelse{#label}% usage needs checking (useless) + {\goto{\do_by_reference_page_state{#label}{#backward}{}{#foreward}}[#label]} + {[#label]}} + +\unexpanded\def\atpage[#label]% todo + {\doifreferencefoundelse{#label}% kind of inefficient as \goto also analyzes + {\goto + {\do_by_reference_page_state + {\labeltexts\v!page\dummyreference}% + {\labeltext\v!hencefore}% + {\labeltexts\v!atpage\currentreferencepage}% + {\labeltext\v!hereafter}}% + [#label]} + {[#label]}} + +\unexpanded\def\referencesymbol + {\hbox{\strut\high + {\setupsymbolset[\interactionparameter\c!symbolset]% + \symbol[\do_by_reference_page_state\v!somewhere\v!nowhere\v!previous\v!next]}}} + +%D The other alternatives just conform their names: only the +%D label, only the text, or the label and the text. + +% \dounknownreference -> \dummyreference + +\def\symbolreference[#label]% for old times sake + {\goto{\referencesymbol}[#label]} + +% \referencecontentmode 0=all 1=label 2=text 3=symbol + +\newtoks\leftreferencetoks +\newtoks\rightreferencetoks +\newtoks\defaultleftreferencetoks +\newtoks\defaultrightreferencetoks + +\def\leftofreferencecontent {\nobreakspace} % we cannot do \definereferenceformat[at] .. so we need this +\let\rightofreferencecontent \empty +\let\leftofreference \empty +\let\rightofreference \empty + +\setvalue{\??rf\c!interaction\v!all}% + {\the\leftreferencetoks + \doifsometokselse\leftreferencetoks \leftofreferencecontent \donothing + \leftofreference + \currentreferencecontent + \rightofreference + \doifsometokselse\rightreferencetoks\rightofreferencecontent\donothing + \the\rightreferencetoks} + +\setvalue{\??rf\c!interaction\v!label}% + {\leftofreference + \the\leftreferencetoks + \the\rightreferencetoks + \rightofreference} + +\setvalue{\??rf\c!interaction\v!text}% + {\leftofreference + \currentreferencecontent + \rightofreference} + +\setvalue{\??rf\c!interaction\v!symbol}% + {\referencesymbol} + +\def\referencesequence + {\csname \??rf\c!interaction + \ifcsname\??rf\c!interaction\@@rfinteraction\endcsname + \@@rfinteraction + \else + \v!all + \fi + \endcsname} + +\newtoks\everyresetinatreference + +\appendtoks + \glet\leftofreference \relax + \glet\rightofreference\relax +\to \everyresetinatreference + +\def\start_goto_reference + {\dontleavehmode + \begingroup} + +\def\stop_goto_reference + {\the\everyresetinatreference + \endgroup} + +\def\pickup_goto_reference + {\dodoublegroupempty\do_pickup_goto_reference} + +\def\do_pickup_goto_reference#left#right#dummy[#label]% #dummy gobbles spaces (really needed) + {\leftreferencetoks + \iffirstargument + {#left}% + \else + \defaultleftreferencetoks + \let\leftofreferencecontent\empty + \fi + \rightreferencetoks + \ifsecondargument + {#right}% + \else + \defaultrightreferencetoks + \let\rightofreferencecontent\empty + \fi + % inefficient: double resolve + \doifreferencefoundelse{#label} % we need to resolve the text + {\goto{\referencesequence}[#label]} + {\let\currentreferencecontent\dummyreference + \goto{\referencesequence}[#label]}% + \stop_goto_reference} + +\unexpanded\def\reference_in{\start_goto_reference\let\currentreferencecontent\currentreferencedefault\pickup_goto_reference} +\unexpanded\def\reference_at{\start_goto_reference\let\currentreferencecontent\currentreferencepage \pickup_goto_reference} + +%D \macros +%D {definereferenceformat} +%D +%D The next few macros were made for for David Arnold and Taco +%D Hoekwater. They can be used for predefining reference +%D texts, and thereby stimulate efficiency. +%D +%D \starttyping +%D \definereferenceformat[informula] [left=(,right=),text=formula] +%D \definereferenceformat[informulas] [left=(,right=),text=formulas] +%D \definereferenceformat[andformula] [left=(,right=),text=and] +%D \definereferenceformat[andformulas][left=(,right=),text=and] +%D +%D \informula [b] and \informula [for:c] +%D the \informula {formulas}[b] \informula {and} [for:c] +%D the \informulas {formulas}[b] \informula {and} [for:c] +%D the \informulas [b] \informula {en} [for:c] +%D the \informulas [b] \andformula [for:c] +%D \stoptyping +%D +%D Instead of a text, one can specify a label, which should +%D be defined with \type {\setuplabeltext}. +%D +%D Watch out: the second argument is somewhat special and mostly +%D meant for a suffix to a number: +%D +%D \startbuffer +%D \definereferenceformat [intesta] [left=(,right=),text=Whatever~] +%D \definereferenceformat [intestb] [left=(,right=),label=figure] +%D +%D \placeformula[x]\startformula a \stopformula +%D +%D \starttabulate[|||||] +%D \NC \in [x] \NC \in {left}[x] \NC \in {}{right}[x] \NC \in {left}{right}[x] \NC \NR +%D \NC \intesta[x] \NC \intesta{left}[x] \NC \intesta{}{right}[x] \NC \intesta{left}{right}[x] \NC \NR +%D \NC \intestb[x] \NC \intestb{left}[x] \NC \intestb{}{right}[x] \NC \intestb{left}{right}[x] \NC \NR +%D \stoptabulate +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +% to be done: interfaced + +\installcommandhandler \??re {referenceformat} \??re + +\appendtoks + \setuevalue\currentreferenceformat{\execute_reference_format{\currentreferenceformat}}% +\to \everydefinereferenceformat + +\setupreferenceformat + [\c!left=, + \c!right=, + \c!text=, + \c!label=, + \c!autocase=\v!no, + \c!style=, + \c!type=default, % to be done: interfaced + \c!setups=, + \c!color=] + +\unexpanded\def\execute_reference_format#name% + {\start_goto_reference + \edef\currentreferenceformat{#name}% + \gdef\leftofreference {\referenceformatparameter\c!left }% + \gdef\rightofreference {\referenceformatparameter\c!right }% + \edef\currentreferenceformatlabel {\referenceformatparameter\c!label }% + \edef\currentreferenceformattype {\referenceformatparameter\c!type }% + \edef\currentreferenceformatsetups {\referenceformatparameter\c!setups }% + \edef\currentreferenceformatautocase{\referenceformatparameter\c!autocase}% + \dosetreferenceformatattributes \c!style \c!color + \ifx\fontattributehash\empty \else + \resetinteractionparameter\c!style + \fi + \ifx\colorattributehash\empty \else + \resetinteractionparameter\c!contrastcolor + \resetinteractionparameter\c!color + \fi + \ifx\currentreferenceformatlabel\autoreferencelabeltextflag + \edef\currentreferenceformatlabel{\autoreferencelabeltext}% + \fi + \ifx\currentreferenceformatautocase\v!yes + \setcharactercleaning[1]% + \fi + \ifx\currentreferenceformatlabel\empty + \defaultleftreferencetoks {\referenceformatparameter\c!text}% + \defaultrightreferencetoks\emptytoks + \else + \defaultleftreferencetoks {\leftlabeltext \currentreferenceformatlabel}% + \defaultrightreferencetoks{\rightlabeltext\currentreferenceformatlabel}% + \fi + \ifx\currentreferenceformattype\empty + \def\currentreferenceformattype{default}% + \fi + % + \ifx\currentreferenceformatsetups\empty + \def\currentreferencecontent{\filterreference\currentreferenceformattype}% + \else + \def\currentreferencecontent{\directsetup\currentreferenceformatsetups}% + \fi + % + \let\leftofreferencecontent \empty + \let\rightofreferencecontent\empty + \pickup_goto_reference} + +\def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key + +\unexpanded\def\autoreferencelabeltext + {\ctxlua{structures.references.getcurrentmetadata("name")}} + +% \starttext +% \definereferenceformat[inxx] [left=(,right=),text=txt] +% \setupinteraction[state=start] +% \chapter[one]{xx} +% [\goto{state}[file(mk-last-state)]] +% [\goto{state} [file(mk-last-state)]] +% [\at{page} [one]] +% [\at{page}[one]] +% [\at{page}{okay}[one]] +% [\inxx{a}{b}[one]] +% \stoptext + +% \startsetups referenceformat:numberplustext +% \filterreference{number}, \filterreference{title} +% \stopsetups +% +% \definereferenceformat[hellup][text=Hellup ,setups=referenceformat:numberplustext] + +%D In interactive documents going to a specific location is not +%D bound to cross references. The \type{\goto} commands can be +%D used to let users access another part of the document. In +%D this respect, interactive tables of contents and registers +%D can be considered goto's. Because in fact a \type{\goto} is +%D just a reference without reference specific data, the +%D previous macros are implemented using the goto +%D functionality. +%D +%D \showsetup{goto} +%D +%D One important characteristic is that the first argument of +%D \type{\goto} (and therefore \type{\at} and \type{\in} is +%D split at spaces. This means that, although hyphenation is +%D prevented, long references can cross line endings. + +% \starttext +% \setupinteraction[state=start] +% [\goto{state}[file(mk-last-state)]] +% [\goto{state} [file(mk-last-state)]] +% \stoptext + +\newconditional\uselocationstrut \settrue\uselocationstrut + +\def\extrareferencearguments + {\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow,"\currentviewerlayer"} + +\unexpanded\def\directgoto + {\ifconditional\uselocationstrut + \expandafter\dodirectgoto + \else + \expandafter\dodirectgotohtdp + \fi} + +\unexpanded\def\goto + {\ifconditional\uselocationstrut + \expandafter\dogoto + \else + \expandafter\dogotohtdp + \fi} + +% The unbox trick is needed in order to permit \par inside a reference. Otherwise +% the reference attribute migrates to the outer boxes. + +\newcount\lastsavedreferenceattribute + +\newbox\referencebox + +\def\revivesavedreferenceattribute % sometimes handy as no test etc needed + {\attribute\referenceattribute\lastsavedreferenceattribute} + +\def\dodirectgoto#content[#label]% no test for valid references + {\dontleavehmode + \begingroup + \attribute\referenceattribute\attributeunsetvalue + \global\lastsavedreferenceattribute\attributeunsetvalue + \iflocation + \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% + \setlocationattributes + \setstrut % can be option + \global\lastsavedreferenceattribute\lastreferenceattribute + \attribute\referenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty % not here + #content% + \dostoptagged + \else + #content% + \fi + \endgroup} + +\def\dodirectgotohtdp#content[#label]% no test for valid references + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \attribute\referenceattribute\attributeunsetvalue + \iflocation + \ctxlua{structures.references.inject("\referenceprefix","#label",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}% + \setlocationattributes + \attribute\referenceattribute\lastreferenceattribute + \global\lastsavedreferenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty + #content% + \dostoptagged + \else + #content% + \fi + \endgroup} + +\def\dogoto#content#dummy[#label]% #dummy gobbles spaces + {\dontleavehmode + \begingroup + %\setbox\referencebox\hbox\bgroup % experiment, might change again to non \par support + \global\lastsavedreferenceattribute\attributeunsetvalue + \attribute\referenceattribute\attributeunsetvalue + \iflocation + \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% + {\expandtexincurrentreference + \ctxlua{structures.references.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}% + \setlocationattributes + \setstrut % can be option + \global\lastsavedreferenceattribute\lastreferenceattribute + \attribute\referenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty + #content% + \dostoptagged}% + {#content}% + \else + #content% + \fi + %\egroup\unhbox\referencebox} + \endgroup} + +\def\dogotohtdp#content#dummy[#label]% dummy gobbles spaces + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \attribute\referenceattribute\attributeunsetvalue + \iflocation + \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% + {\expandtexincurrentreference + \ctxlua{structures.references.injectcurrentset(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax)}% + \setlocationattributes + \global\lastsavedreferenceattribute\lastreferenceattribute + \attribute\referenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty + #content% + \dostoptagged}% + {#content}% + \else + #content% + \fi + \endgroup} + +\unexpanded\def\directgotobox#content[#label]% no test for valid references + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \attribute\referenceattribute\attributeunsetvalue + \iflocation + \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% + \setlocationattributes + \global\lastsavedreferenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty + \hbox attr \referenceattribute \lastreferenceattribute {#content}% + \dostoptagged + \else + #content% + \fi + \endgroup} + +\unexpanded\def\directgotospecbox#resolver#content[#label]% no test for valid references + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \attribute\referenceattribute\attributeunsetvalue + \iflocation + \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% + \setlocationcolorspec{#resolver}% no consequence for strut + \global\lastsavedreferenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty + \hbox attr \referenceattribute \lastreferenceattribute {#content}% + \dostoptagged + \else + #content% + \fi + \endgroup} + +\unexpanded\def\directgotodumbbox#content[#label]% no test for valid references + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \attribute\referenceattribute\attributeunsetvalue + \iflocation + \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}% + \global\lastsavedreferenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty + \hbox attr \referenceattribute \lastreferenceattribute {#content}% + \dostoptagged + \else + #content% + \fi + \endgroup} + +\unexpanded\def\gotobox#content[#label]% no test for valid references + {\dontleavehmode + \begingroup + \global\lastsavedreferenceattribute\attributeunsetvalue + \attribute\referenceattribute\attributeunsetvalue + \iflocation + \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% + {\expandtexincurrentreference + \ctxlua{structures.references.injectcurrentset(nil,nil)}% + \setlocationattributes + \global\lastsavedreferenceattribute\lastreferenceattribute + \dostarttagged\t!link\empty + \hbox attr \referenceattribute \lastreferenceattribute {#content}% + \dostoptagged}% + {#content}% + \else + #content% + \fi + \endgroup} + +\unexpanded\def\gotowdhtbox#width#height[#label]% fast variant for overlays + {\dontleavehmode + \begingroup + \setbox\scratchbox\emptyhbox + \wd\scratchbox#width% + \ht\scratchbox#height% + \global\lastsavedreferenceattribute\attributeunsetvalue + \attribute\referenceattribute\attributeunsetvalue + \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}% + {\ctxlua{structures.references.injectcurrentset(nil,nil)}% + \global\lastsavedreferenceattribute\lastreferenceattribute + \hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}} + {\box\scratchbox}% + \endgroup} + +%D An reference to another document can be specified as a file +%D or as an \URL. Both are handled by the same mechanism and +%D can be issued by saying something like: +%D +%D \starttyping +%D \goto[dictionary::the letter a] +%D \stoptyping +%D +%D One can imagine that many references to such a dictionary +%D are made, so in most cases such a document reference in an +%D indirect one. +%D +%D \showsetup{useexternaldocument} +%D +%D For example: +%D +%D \starttyping +%D \useexternaldocument +%D [dictionary][engldict] +%D [The Famous English Dictionary] +%D \stoptyping +%D +%D The next macro implements these relations, and also take +%D care of loading the document specific references. +%D +%D The \URL\ alternative takes four arguments: +%D +%D \showsetup{useURL} +%D +%D like: +%D +%D \starttyping +%D \useURL +%D [dictionary][http://www.publisher.com/public][engldict] +%D [The Famous English Dictionary] +%D \stoptyping +%D +%D Several specifications are possible: +%D +%D \starttyping +%D \useURL [id] [url] [file] [description] +%D \useURL [id] [url] [file] +%D \useURL [id] [url] +%D \stoptyping +%D +%D This time we don't load the references when no file is +%D specified. This is logical when one keeps in mind that a +%D valid \URL\ can also be a mail address. + +\unexpanded\def\useurl {\doquadrupleempty\do_use_url } % so that they can be used in expanded arguments +\unexpanded\def\usefile{\dotripleargument\do_use_file} % so that they can be used in expanded arguments + +\let\useURL \useurl +\let\useexternaldocument\usefile + +\def\do_use_url[#label][#url][#file][#description]% + {\ctxlua{structures.references.urls.define("#label",\!!bs\detokenize{#url}\!!es,\!!bs\detokenize{#file}\!!es,\!!bs\detokenize{#description}\!!es)}} + +\def\do_use_file[#label][#file][#description]% + {\ctxlua{structures.references.files.define("#label",\!!bs\detokenize{#file}\!!es,\!!bs\detokenize{#description}\!!es)}} + +\def\doifurldefinedelse #label{\ctxcommand{doifurldefinedelse ("#label")}} +\def\doiffiledefinedelse#label{\ctxcommand{doiffiledefinedelse("#label")}} + +%D \macros +%D {url,setupurl} +%D +%D We also have: \type{\url} for directly calling the +%D description. So we can say: +%D +%D \starttyping +%D \useURL [one] [http://www.test.nl] +%D \useURL [two] [http://www.test.nl] [] [Some Site] +%D +%D \url[one] or \from[two] or \goto{Whatever Site}[URL(two)] +%D \stoptyping +%D +%D An \URL\ can be set up with +%D +%D \showsetup{setupurl} + +\unexpanded\def\setupurl + {\dodoubleargument\getparameters[\??ur]} + +\unexpanded\def\url[#label]% move \hyphenatedurl to lua end (is already lua) + {\dontleavehmode + \begingroup + \dosetfontattribute\??ur\c!style + \dosetcolorattribute\??ur\c!color + \hyphenatedurl{\ctxlua{structures.references.urls.get("#label","\@@uralternative","\@@urspace")}}% + \endgroup} + +% # fails + +%D This macro is hooked into a support macro, and thereby +%D \URL's break ok, according to the setting of a switch, +%D +%D \startbuffer +%D \useURL +%D [test] +%D [sentence_sentence~sentence//sentence:sentence.sentence] +%D \stopbuffer +%D +%D \typebuffer +%D +%D Such an \URL\ is, depending on the settings, hyphenated as: +%D +%D \getbuffer +%D +%D \startlinecorrection +%D \hbox to \hsize +%D {\hss\en +%D \setupreferencing[urlalternative=both]% +%D \vbox{\hsize.25cm\hbox{\bf both}\prewordbreak\url[test]}% +%D \hss +%D \setupreferencing[urlalternative=before]% +%D \vbox{\hsize.25cm\hbox{\bf before}\prewordbreak\url[test]}% +%D \hss +%D \setupreferencing[urlalternative=after]% +%D \vbox{\hsize.25cm\hbox{\bf after}\prewordbreak\url[test]}% +%D \hss} +%D \stoplinecorrection +%D +%D By setting \type{urlspace=yes} one can get slightly better +%D spacing when using very long \URL's. +%D +%D When defining the external source of information, one can +%D also specify a suitable name (the last argument). This name +%D can be called upon with: +%D +%D \showsetup{from} + +%D We keep this for compatibility reasons, hence the hackery. + +\unexpanded\def\reference_from + {\dosingleempty\do_do_special_from} + +\def\do_do_special_from[#label]% + {\dontleavehmode + \goto{\ctxlua{structures.references.from("#label")}}[fileorurl(#label)]} + +\def\dofromurldescription#content% called at the lua end + {#content} + +\def\dofromurlliteral#content% called at the lua end + {\dosetfontattribute \??ur\c!style + \dosetcolorattribute\??ur\c!color + \hyphenatedurl{#content}} + +\let\dofromfiledescription\dofromurldescription +\let\dofromfileliteral \dofromurlliteral % maybe some day setupfile that inherits from url + +%D We also support: +%D +%D \starttyping +%D \goto{some text}[file(identifier{location}] +%D \stoptyping +%D +%D which is completely equivalent with +%D +%D \starttyping +%D \goto{some text}[identifier::location] +%D \stoptyping + +%D A special case of references are those to programs. These, +%D very system dependant references are implemented by abusing +%D some of the previous macros. +%D +%D \showsetup{setupprograms} +%D \showsetup{defineprogram} +%D \showsetup{program} % changed functionality ! +%D +%D The latter gives access to the description of the program, +%D being the last argument to the definition command. + +% also lua, like urls and files + +\unexpanded\def\setupprograms + {\dodoubleargument\getparameters[\??pr]} + +\unexpanded\def\defineprogram + {\dotripleargument\do_define_program} + +\def\do_define_program[#name][#program][#description]% + {\ctxlua{structures.references.programs.define("#name","#program","#description")}} + +\def\program[#name]% incompatible, more consistent, hardy used anyway + {\dontleavehmode + \begingroup + \dosetfontattribute\??pr\c!style + \dosetcolorattribute\??pr\c!color + \ctxlua{structures.references.programs.get("#name","\@@pralternative","\@@prspace")}% + \endgroup} + +%D As we can see, we directly use the special reference +%D mechanism, which means that +%D +%D \starttyping +%D \goto{some text}[program(name{args})] +%D \stoptyping +%D +%D is valid. + +%D The next macro provides access to the actual pagenumbers. +%D When documenting and sanitizing the original reference +%D macros, I decided to keep the present meaning as well as to +%D make this meaning available as a special reference method. +%D So now one can use: +%D +%D \starttyping +%D \gotopage{some text}[location] +%D \gotopage{some text}[number] +%D \gotopage{some text}[file::number] +%D \stoptyping +%D +%D as well as: +%D +%D \starttyping +%D \goto{some text}[page(location)] +%D \goto{some text}[page(number)] +%D \goto{some text}[file::page(number)] +%D \stoptyping +%D +%D Here location is a keyword like \type{nextpage}. +%D +%D \showsetup{gotopage} + +\unexpanded\def\definepage + {\dodoubleargument\do_define_page} + +\def\do_define_page[#name][#target]% + {\definereference[#name][page(#target)]} + +\def\gotopage#text[#target]% + {\goto{#text}[\v!page(#target)]} + +%D The previous definitions are somewhat obsolete so we don't +%D use it here. + +%D A still very rudimentary|/|experimental forward|/|backward +%D reference mechanism is provided by the macro \type{\atpage}: +%D +%D \starttyping +%D ... \somewhere{backward text}{forward text}[someref] ... +%D ... \atpage[someref] ... +%D \stoptyping +%D +%D In future versions there will be more sophisticated + +% 0 = no page reference +% 1 = same page +% 2 = preceding page +% 3 = following page +% 4 = backward, same page (todo) +% 5 = forward, same page (todo) + +%D We can cross link documents by using: +%D +%D \showsetup{coupledocument} +%D +%D like: +%D +%D \starttyping +%D \coupledocument[print][somefile][chapter,section] +%D \stoptyping +%D +%D After which when applicable, we have available the +%D references: +%D +%D \starttyping +%D \goto{print version}[print::chapter] +%D \stoptyping +%D +%D and alike. The title placement definition macros have a +%D key \type{file}, which is interpreted as the file to jump +%D to, that is, when one clicks on the title. + +\def\coupledocument + {\doquadrupleempty\do_couple_document} + +\def\do_couple_document[#name][#file][#sections][#description]% + {\ifthirdargument + % this will be done differently (when it's needed) + \fi} + +%D \macros +%D {dotextprefix} +%D +%D In previous macros we used \type {\dotextprefix} to +%D generate a space between a label and a number. +%D +%D \starttyping +%D \dotextprefix{text} +%D \stoptyping +%D +%D Only when \type {text} is not empty, a space is inserted. + +\def\dotextprefix#text% + {\begingroup + \setbox\scratchbox\hbox{#text}% to be solved some day + \ifdim\wd\scratchbox>\zeropoint + \unhbox\scratchbox + \doifsomething\@@rfseparator{\removeunwantedspaces\@@rfseparator}% remove is new + \else + \unhbox\scratchbox + \fi + \endgroup} + +%D In the next settings we see some variables that were not +%D used here and that concern the way the pagenumbers refered +%D to are typeset. + +\setupreferencing + [\c!state=\v!start, + \c!autofile=\v!no, + \v!part\c!number=\v!yes, + \v!chapter\c!number=\v!no, + \c!interaction=\v!all, + \c!convertfile=\v!no, + %\c!strut=\v!no, % some day an option + \c!prefix=, + \c!width=.75\makeupwidth, + \c!left=\quotation\bgroup, + \c!right=\egroup, + \c!global=\v!no, + \c!expansion=\v!no, + \c!separator=\nonbreakablespace, + \c!export=\v!no] + +\setupurl + [\c!alternative=\v!both, + \c!space=\v!no, + \c!style=\v!type, + \c!color=] + +\setupprograms + [\c!directory=, + \c!alternative=\v!both, + \c!space=\v!no, + \c!style=\v!type, + \c!color=] + +\definereference [\v!CloseDocument ] [action(close)] +\definereference [\v!ExitViewer ] [action(exit)] +\definereference [\v!FirstPage ] [action(first)] +\definereference [\v!LastPage ] [action(last)] +\definereference [\v!NextJump ] [action(forward)] +\definereference [\v!NextPage ] [action(next)] +\definereference [\v!PauseMovie ] [action(pausemovie)] +\definereference [\v!PauseSound ] [action(pausesound)] +\definereference [\v!PauseRendering ] [action(pauserendering)] +\definereference [\v!PreviousJump ] [action(backward)] +\definereference [\v!PreviousPage ] [action(previous)] +\definereference [\v!PrintDocument ] [action(print)] +\definereference [\v!SaveForm ] [action(exportform)] +\definereference [\v!LoadForm ] [action(importform)] +\definereference [\v!ResetForm ] [action(resetform)] +\definereference [\v!ResumeMovie ] [action(resumemovie)] +\definereference [\v!ResumeSound ] [action(resumesound)] +\definereference [\v!ResumeRendering ] [action(resumerendering)] +\definereference [\v!SaveDocument ] [action(save)] +\definereference [\v!SaveNamedDocument] [action(savenamed)] +\definereference [\v!OpenNamedDocument] [action(opennamed)] +\definereference [\v!SearchDocument ] [action(search)] +\definereference [\v!SearchAgain ] [action(searchagain)] +\definereference [\v!StartMovie ] [action(startmovie)] +\definereference [\v!StartSound ] [action(startsound)] +\definereference [\v!StartRendering ] [action(startrendering)] +\definereference [\v!StopMovie ] [action(stopmovie)] +\definereference [\v!StopSound ] [action(stopsound)] +\definereference [\v!StopRendering ] [action(stoprendering)] +\definereference [\v!SubmitForm ] [action(submitform)] +\definereference [\v!ToggleViewer ] [action(toggle)] +\definereference [\v!ViewerHelp ] [action(help)] +\definereference [\v!HideField ] [action(hide)] +\definereference [\v!ShowField ] [action(show)] +\definereference [\v!GotoPage ] [action(gotopage)] +\definereference [\v!Query ] [action(query)] +\definereference [\v!QueryAgain ] [action(queryagain)] +\definereference [\v!FitWidth ] [action(fitwidth)] +\definereference [\v!FitHeight ] [action(fitheight)] +\definereference [\v!ShowThumbs ] [action(thumbnails)] +\definereference [\v!ShowBookmarks ] [action(bookmarks)] + +\definereference [\v!HideLayer ] [action(hidelayer)] +\definereference [\v!VideLayer ] [action(videlayer)] +\definereference [\v!ToggleLayer ] [action(togglelayer)] + +\definereference [\v!firstpage] [page(firstpage)] +\definereference [\v!previouspage] [page(previouspage)] +\definereference [\v!nextpage] [page(nextpage)] +\definereference [\v!lastpage] [page(lastpage)] +\definereference [\v!forward] [page(forward)] +\definereference [\v!backward] [page(backward)] +\definereference [\v!firstsubpage] [page(firstsubpage)] +\definereference [\v!previoussubpage] [page(previoussubpage)] +\definereference [\v!nextsubpage] [page(nextsubpage)] +\definereference [\v!lastsubpage] [page(lastsubpage)] + +% we can do this but only when later in resolve (else problems with \chapter[first]{...} +% +% \definereference [\v!first] [page(firstpage)] +% \definereference [\v!previous] [page(prevpage)] +% \definereference [\v!next] [page(nextpage)] +% \definereference [\v!last] [page(lastpage)] +% \definereference [\v!first\v!sub] [page(firstsubpage)] +% \definereference [\v!previous\v!sub] [page(prevsubpage)] +% \definereference [\v!next\v!sub] [page(nextsubpage)] +% \definereference [\v!last\v!sub] [page(lastsubpage)] + +%D We cannot set up buttons (not yet, this one calls a menu macro): + +%D New (and experimental): + +% \starttext +% \chapter{test} +% \placefigure[here][xx:1]{}{\framed{one}} \placefigure[here][xx:2]{}{\framed{three}} +% \placetable [here][xx:3]{}{\framed{two}} \placetable [here][xx:4]{}{\framed{four}} +% \start +% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4] +% \stop \blank \start +% \setupreferencestructureprefix[default][prefix=no] +% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4] +% \stop \blank \start +% \setupreferencestructureprefix[float][default][prefix=no] +% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4] +% \stop \blank \start +% \setupreferencestructureprefix[figure][default][prefix=no] +% \in{fig}[xx:1] and \in{fig}[xx:2] \in{tab}[xx:3] and \in{tab}[xx:4] +% \stop \blank +% \stoptext + +% todo: parameterhandler + +\def\getreferencestructureprefix#kind#name#category% + {{ + prefix = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefix", + separatorset = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixseparatorset", + conversion = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversion", + conversionset = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversionset", + set = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixset", + segments = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixsegments", + connector = \!!bs\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconnector\!!es, + }} + +\unexpanded\def\setupreferencestructureprefix + {\dotripleempty\do_setup_reference_structure_prefix} + +\def\do_setup_reference_structure_prefix[#kind][#category][#settings]% + {\ifthirdargument + \getparameters[\??rf:\c!prefix:#kind:#category][#settings]% + \else\ifsecondargument + \getparameters[\??rf:\c!prefix::#kind][#category]% + \fi\fi} + +\def\referencestructureprefixparameter#kind#name#category#parameter% + {\ifcsname\??rf:\c!prefix:#name:#category#parameter\endcsname + \csname\??rf:\c!prefix:#name:#category#parameter\endcsname + \else\ifcsname\??rf:\c!prefix:#kind:#category#parameter\endcsname + \csname \??rf:\c!prefix:#kind:#category#parameter\endcsname + \else\ifcsname\??rf:\c!prefix::#category#parameter\endcsname + \csname \??rf:\c!prefix::#category#parameter\endcsname + \fi\fi\fi} + +\def\currentreferencedefault + {\ctxlua{structures.references.filter("default",\ctxlua{structures.references.getcurrentprefixspec("\v!default")})}} + +%D Not all support is visible by looking at the \TEX\ code; here is one of those:^ +%D +%D \starttyping +%D \startinteractionmenu[right] +%D \startbut [section(first {chapter})] first chapter \stopbut +%D \startbut [section(previous{chapter})] previous chapter \stopbut +%D \startbut [section(next {chapter})] next chapter \stopbut +%D \startbut [section(last {chapter})] last chapter \stopbut +%D \blank[2*big] +%D \startbut [section(first {section})] first section \stopbut +%D \startbut [section(previous{section})] previous section \stopbut +%D \startbut [section(next {section})] next section \stopbut +%D \startbut [section(last {section})] last section \stopbut +%D \stopinteractionmenu +%D \stoptyping + +\protect \endinput + +% tricky: +% +% \enabletrackers[nodes.references] +% \setupinteraction[state=start] +% \def\KnuthTest{\input knuth } +% \def\KnuthTest{\input tufte } +% \def\TufteTest{\input tufte } +% \defineoverlay[xxx][\overlaybutton{page(3)}] +% \setupbackgrounds[text][background=xxx] +% \starttext +% test {\red \KnuthTest} test \par +% \button{test}[page(1)] \par +% \goto{page 2 \TeX}[page(2)] \goto{page 2 \TeX}[page(2)] \goto{\TufteTest}[page(2)] test \page +% test \goto{page 3}[page(3)] \goto{\TufteTest\space\par\TufteTest}[page(4)] test \page +% \goto{page 1}[page(1)] \goto{\TufteTest\space test}[page(1)] \page +% \goto{page 1}[page(1)] \goto{\KnuthTest\space test}[page(1)] \page +% test \goto{page 1}[page(1)] {\goto{\KnuthTest\space test}[page(1)]} test +% \goto{page 1}[page(1)] \goto{\TufteTest}[page(1)] test \page +% \stoptext diff --git a/tex/context/base/strc-rsc.lua b/tex/context/base/strc-rsc.lua new file mode 100644 index 000000000..aa969569a --- /dev/null +++ b/tex/context/base/strc-rsc.lua @@ -0,0 +1,154 @@ +if not modules then modules = { } end modules ['strc-rsc'] = { + version = 1.001, + comment = "companion to strc-ref.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- The scanner is in a separate module so that we can test without too +-- many dependencies. + +-- The scanner accepts nested outer, but we don't care too much, maybe +-- some day we will have both but currently the innermost wins. + +local lpegmatch, lpegP, lpegS, lpegCs, lpegCt, lpegCf, lpegCc, lpegC, lpegCg = lpeg.match, lpeg.P, lpeg.S, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cc, lpeg.C, lpeg.Cg +local find = string.find + +local spaces = lpegP(" ")^0 +local lparent = lpegP("(") +local rparent = lpegP(")") +local lbrace = lpegP("{") +local rbrace = lpegP("}") +local tcolon = lpegP(":::") -- component or outer +local dcolon = lpegP("::") -- outer +local scolon = lpegP(":") -- prefix +local backslash = lpegP("\\") + + lparent = spaces * lparent * spaces + rparent = spaces * rparent * spaces + lbrace = spaces * lbrace * spaces + rbrace = spaces * rbrace * spaces + tcolon = spaces * tcolon * spaces + dcolon = spaces * dcolon * spaces + +local endofall = spaces * lpegP(-1) + +local o_token = 1 - rparent - rbrace - lparent - lbrace -- can be made more efficient +local a_token = 1 - rbrace +local s_token = 1 - lparent - lbrace +local i_token = 1 - lparent - lbrace - endofall +local f_token = 1 - lparent - lbrace - dcolon +local c_token = 1 - lparent - lbrace - tcolon + +local hastexcode = lpegCg(lpegCc("has_tex") * lpegCc(true)) -- cannot be made to work +local component = lpegCg(lpegCc("component") * lpegCs(c_token^1)) +local outer = lpegCg(lpegCc("outer") * lpegCs(f_token^1)) +local operation = lpegCg(lpegCc("operation") * lpegCs(o_token^1)) +local arguments = lpegCg(lpegCc("arguments") * lpegCs(a_token^0)) +local special = lpegCg(lpegCc("special") * lpegCs(s_token^1)) +local inner = lpegCg(lpegCc("inner") * lpegCs(i_token^1)) + + arguments = (lbrace * arguments * rbrace)^-1 + component = component * tcolon + outer = outer * dcolon + operation = outer^-1 * operation -- special case: page(file::1) and file::page(1) + inner = inner * arguments + special = special * lparent * (operation * arguments)^-1 * rparent + +local referencesplitter = spaces * lpegCf (lpegCt("") * (component + outer)^-1 * (special + inner)^-1 * endofall, rawset) +local prefixsplitter = lpegCs(lpegP((1-scolon)^1 * scolon)) * #-scolon * lpegCs(lpegP(1)^1) +local componentsplitter = lpegCs(lpegP((1-scolon)^1)) * scolon * #-scolon * lpegCs(lpegP(1)^1) + +prefixsplitter = componentsplitter + +local function splitreference(str) + if str and str ~= "" then + local t = lpegmatch(referencesplitter,str) + if t then + local a = t.arguments + if a and find(a,"\\") then + t.has_tex = true + else + local o = t.arguments + if o and find(o,"\\") then + t.has_tex = true + end + end + return t + end + end +end + +local function splitprefix(str) + return lpegmatch(prefixsplitter,str) +end + +local function splitcomponent(str) + return lpegmatch(componentsplitter,str) +end + +-- register in the right namespace + +structures = structures or { } +structures.references = structures.references or { } +local references = structures.references + +references.referencesplitter = referencesplitter +references.splitreference = splitreference +references.prefixsplitter = prefixsplitter +references.splitprefix = splitprefix +references.componentsplitter = componentsplitter +references.splitcomponent = splitcomponent + +-- test code: + +-- inspect(splitreference([[component:::inner]])) +-- print(splitprefix([[component:::inner]])) +-- print(splitprefix([[component:inner]])) + +-- inspect(splitreference([[ ]])) +-- inspect(splitreference([[ inner ]])) +-- inspect(splitreference([[ special ( operation { argument, argument } ) ]])) +-- inspect(splitreference([[ special ( operation { argument } ) ]])) +-- inspect(splitreference([[ special ( operation { argument, \argument } ) ]])) +-- inspect(splitreference([[ special ( operation { \argument } ) ]])) +-- inspect(splitreference([[ special ( operation ) ]])) +-- inspect(splitreference([[ special ( \operation ) ]])) +-- inspect(splitreference([[ special ( o\peration ) ]])) +-- inspect(splitreference([[ special ( ) ]])) +-- inspect(splitreference([[ inner { argument } ]])) +-- inspect(splitreference([[ inner { \argument } ]])) +-- inspect(splitreference([[ inner { ar\gument } ]])) +-- inspect(splitreference([[inner{a\rgument}]])) +-- inspect(splitreference([[ inner { argument, argument } ]])) +-- inspect(splitreference([[ inner { argument, \argument } ]])) -- fails: bug in lpeg? +-- inspect(splitreference([[ inner { \argument, \argument } ]])) +-- inspect(splitreference([[ outer :: ]])) +-- inspect(splitreference([[ outer :: inner]])) +-- inspect(splitreference([[ outer :: special (operation { argument,argument } ) ]])) +-- inspect(splitreference([[ outer :: special (operation { } )]])) +-- inspect(splitreference([[ outer :: special ( operation { argument, \argument } ) ]])) +-- inspect(splitreference([[ outer :: special ( operation ) ]])) +-- inspect(splitreference([[ outer :: special ( \operation ) ]])) +-- inspect(splitreference([[ outer :: special ( ) ]])) +-- inspect(splitreference([[ outer :: inner { argument } ]])) +-- inspect(splitreference([[ special ( outer :: operation ) ]])) + +-- inspect(splitreference([[]])) +-- inspect(splitreference([[inner]])) +-- inspect(splitreference([[special(operation{argument,argument})]])) +-- inspect(splitreference([[special(operation)]])) +-- inspect(splitreference([[special(\operation)]])) +-- inspect(splitreference([[special()]])) +-- inspect(splitreference([[inner{argument}]])) +-- inspect(splitreference([[inner{\argument}]])) +-- inspect(splitreference([[outer::]])) +-- inspect(splitreference([[outer::inner]])) +-- inspect(splitreference([[outer::special(operation{argument,argument})]])) +-- inspect(splitreference([[outer::special(operation{argument,\argument})]])) +-- inspect(splitreference([[outer::special(operation)]])) +-- inspect(splitreference([[outer::special(\operation)]])) +-- inspect(splitreference([[outer::special()]])) +-- inspect(splitreference([[outer::inner{argument}]])) +-- inspect(splitreference([[special(outer::operation)]])) diff --git a/tex/context/base/tabl-tsp.mkiv b/tex/context/base/tabl-tsp.mkiv index 47984a8be..f43ff8138 100644 --- a/tex/context/base/tabl-tsp.mkiv +++ b/tex/context/base/tabl-tsp.mkiv @@ -148,7 +148,8 @@ \def\dochecksplitofffloat#1% box {\ifinsidesplitfloat - \ifdim\ht#1=\zeropoint + % \ifdim\ht#1=\zeropoint % funny: \ifcase does not check for overflow + \ifcase\ht#1\relax \global\setfalse\somenextplitofffloat \else \global\settrue \somenextplitofffloat diff --git a/tex/context/base/type-one.mkii b/tex/context/base/type-one.mkii index b8a582d83..e98f6864a 100644 --- a/tex/context/base/type-one.mkii +++ b/tex/context/base/type-one.mkii @@ -2748,4 +2748,128 @@ \stoptypescriptcollection +\starttypescriptcollection[dejavu] + + \definetypescriptprefix [e:ec] [t1] + \definetypescriptprefix [e:qx] [qx] + \definetypescriptprefix [e:t2a] [t2a] + + \starttypescript [serif] [dejavu] [ec,qx,t2a] + \definefontsynonym [DejaVuSerif] [DejaVuSerif-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerif-Italic] [DejaVuSerif-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerif-Bold] [DejaVuSerif-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerif-BoldItalic] [DejaVuSerif-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + + \loadmapfile[dejavu-truetype.map] + \stoptypescript + + \starttypescript [serif] [dejavu-condensed] [ec,qx,t2a] + \definefontsynonym [DejaVuSerifCondensed] [DejaVuSerifCondensed-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerifCondensed-Italic] [DejaVuSerifCondensed-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerifCondensed-Bold] [DejaVuSerifCondensed-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSerifCondensed-BoldItalic] [DejaVuSerifCondensed-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + + \loadmapfile[dejavu-truetype.map] + \stoptypescript + + \starttypescript [sans] [dejavu] [ec,qx,t2a] + \definefontsynonym [DejaVuSans] [DejaVuSans-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSans-Italic] [DejaVuSans-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSans-Bold] [DejaVuSans-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSans-BoldItalic] [DejaVuSans-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + + \loadmapfile[dejavu-truetype.map] + \stoptypescript + + \starttypescript [sans] [dejavu-condensed] [ec,qx,t2a] + \definefontsynonym [DejaVuSansCondensed] [DejaVuSansCondensed-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansCondensed-Italic] [DejaVuSansCondensed-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansCondensed-Bold] [DejaVuSansCondensed-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansCondensed-BoldItalic] [DejaVuSansCondensed-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + + \loadmapfile[dejavu-truetype.map] + \stoptypescript + + \starttypescript [mono] [dejavu,dejavu-condensed] [ec,qx,t2a] + \definefontsynonym [DejaVuSansMono] [DejaVuSansMono-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansMono-Italic] [DejaVuSansMono-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansMono-Bold] [DejaVuSansMono-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + \definefontsynonym [DejaVuSansMono-BoldItalic] [DejaVuSansMono-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree] + + \loadmapfile[dejavu-truetype.map] + \stoptypescript + + \starttypescript [serif] [dejavu] [name] + \definefontsynonym [Serif] [DejaVuSerif] + \definefontsynonym [SerifItalic] [DejaVuSerif-Italic] + \definefontsynonym [SerifBold] [DejaVuSerif-Bold] + \definefontsynonym [SerifBoldItalic] [DejaVuSerif-BoldItalic] + + \definefontsynonym [SerifSlanted] [SerifItalic] + \definefontsynonym [SerifBoldSlanted] [SerifBoldItalic] + \definefontsynonym [SerifCaps] [Serif] + \stoptypescript + + \starttypescript [serif] [dejavu-condensed] [name] + \definefontsynonym [Serif] [DejaVuSerifCondensed] + \definefontsynonym [SerifItalic] [DejaVuSerifCondensed-Italic] + \definefontsynonym [SerifBold] [DejaVuSerifCondensed-Bold] + \definefontsynonym [SerifBoldItalic] [DejaVuSerifCondensed-BoldItalic] + + \definefontsynonym [SerifSlanted] [SerifItalic] + \definefontsynonym [SerifBoldSlanted] [SerifBoldItalic] + \definefontsynonym [SerifCaps] [Serif] + \stoptypescript + + \starttypescript [sans] [dejavu] [name] + \definefontsynonym [Sans] [DejaVuSans] + \definefontsynonym [SansItalic] [DejaVuSans-Italic] + \definefontsynonym [SansBold] [DejaVuSans-Bold] + \definefontsynonym [SansBoldItalic] [DejaVuSans-BoldItalic] + + \definefontsynonym [SansSlanted] [SansItalic] + \definefontsynonym [SansBoldSlanted] [SansBoldItalic] + \definefontsynonym [SansCaps] [Sans] + \stoptypescript + + \starttypescript [sans] [dejavu-condensed] [name] + \definefontsynonym [Sans] [DejaVuSansCondensed] + \definefontsynonym [SansItalic] [DejaVuSansCondensed-Italic] + \definefontsynonym [SansBold] [DejaVuSansCondensed-Bold] + \definefontsynonym [SansBoldItalic] [DejaVuSansCondensed-BoldItalic] + + \definefontsynonym [SansSlanted] [SansItalic] + \definefontsynonym [SansBoldSlanted] [SansBoldItalic] + \definefontsynonym [SansCaps] [Sans] + \stoptypescript + + \starttypescript [mono] [dejavu,dejavu-condensed] [name] + \definefontsynonym [Mono] [DejaVuSansMono] + \definefontsynonym [MonoItalic] [DejaVuSansMono-Italic] + \definefontsynonym [MonoBold] [DejaVuSansMono-Bold] + \definefontsynonym [MonoBoldItalic] [DejaVuSansMono-BoldItalic] + + \definefontsynonym [MonoSlanted] [MonoItalic] + \definefontsynonym [MonoBoldSlanted] [MonoBoldItalic] + \definefontsynonym [MonoCaps] [Mono] + \stoptypescript + + \starttypescript [dejavu] [ec,qx,t2a] + \definetypeface [dejavu] [rm] [serif] [dejavu] [default] [encoding=\typescripttwo] + \definetypeface [dejavu] [ss] [sans] [dejavu] [default] [encoding=\typescripttwo] + \definetypeface [dejavu] [tt] [mono] [dejavu] [default] [encoding=\typescripttwo] + \definetypeface [dejavu] [mm] [math] [xits] [default] [rscale=auto] + \loadmapfile [dejavu-truetype.map] + \stoptypescript + + \starttypescript [dejavu-condensed] [ec,qx,t2a] + \definetypeface [dejavu-condensed] [rm] [serif] [dejavu-condensed] [default] [encoding=\typescripttwo] + \definetypeface [dejavu-condensed] [ss] [sans] [dejavu-condensed] [default] [encoding=\typescripttwo] + \definetypeface [dejavu-condensed] [tt] [mono] [dejavu-condensed] [default] [encoding=\typescripttwo] + \definetypeface [dejavu-condensed] [mm] [math] [xits] [default] [rscale=auto] + \loadmapfile [dejavu-truetype.map] + \stoptypescript + +\stoptypescriptcollection + \endinput diff --git a/tex/context/base/util-pck.lua b/tex/context/base/util-pck.lua index c802a09ed..d964c7a23 100644 --- a/tex/context/base/util-pck.lua +++ b/tex/context/base/util-pck.lua @@ -62,34 +62,38 @@ packers.simplehashed = simplehashed --~ end local function pack(t,keys,hash,index) - for k,v in next, t do - if type(v) == "table" then - pack(v,keys,hash,index) - if keys[k] then - local h = hashed(v) - local i = hash[h] - if not i then - i = #index + 1 - index[i] = v - hash[h] = i + if t then + for k,v in next, t do + if type(v) == "table" then + pack(v,keys,hash,index) + if keys[k] then + local h = hashed(v) + local i = hash[h] + if not i then + i = #index + 1 + index[i] = v + hash[h] = i + end + t[k] = i end - t[k] = i end end end end local function unpack(t,keys,index) - for k,v in next, t do - if keys[k] and type(v) == "number" then - local iv = index[v] - if iv then - v = iv - t[k] = v + if t then + for k, v in next, t do + if keys[k] and type(v) == "number" then + local iv = index[v] + if iv then + v = iv + t[k] = v + end + end + if type(v) == "table" then + unpack(v,keys,index) end - end - if type(v) == "table" then - unpack(v,keys,index) end end end diff --git a/tex/context/base/util-sto.lua b/tex/context/base/util-sto.lua index 8710f78af..4c0052f0e 100644 --- a/tex/context/base/util-sto.lua +++ b/tex/context/base/util-sto.lua @@ -14,8 +14,8 @@ local storage = utilities.storage function storage.mark(t) if not t then - texio.write_nl("fatal error: storage '%s' cannot be marked",t) - os.exit() + texio.write_nl("fatal error: storage cannot be marked") + return -- os.exit() end local m = getmetatable(t) if not m then @@ -44,8 +44,8 @@ end function storage.checked(t) if not t then - texio.write_nl("fatal error: storage '%s' has not been allocated",t) - os.exit() + texio.write_nl("fatal error: storage has not been allocated") + return -- os.exit() end return t end diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua index 3610c24dd..28a6b8cc5 100644 --- a/tex/context/base/util-tab.lua +++ b/tex/context/base/util-tab.lua @@ -29,14 +29,31 @@ function tables.definetable(target) -- defines undefined tables return concat(t,"\n") end -function tables.accesstable(target) - local t = _G +function tables.accesstable(target,root) + local t = root or _G for name in gmatch(target,"([^%.]+)") do t = t[name] + if not t then + return + end end return t end +function tables.migratetable(target,v,root) + local t = root or _G + local names = string.split(target,".") + for i=1,#names-1 do + local name = names[i] + t[name] = t[name] or { } + t = t[name] + if not t then + return + end + end + t[names[#names]] = v +end + function tables.removevalue(t,value) -- todo: n if value then for i=1,#t do diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index b60a0b79b..ab366de23 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 09/27/11 20:05:02 +-- merge date : 10/01/11 10:48:20 do -- begin closure to overcome local limits and interference -- cgit v1.2.3