diff options
Diffstat (limited to 'tex/context/base/strc-not.lua')
-rw-r--r-- | tex/context/base/strc-not.lua | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/tex/context/base/strc-not.lua b/tex/context/base/strc-not.lua new file mode 100644 index 000000000..be883af57 --- /dev/null +++ b/tex/context/base/strc-not.lua @@ -0,0 +1,338 @@ +if not modules then modules = { } end modules ['strc-not'] = { + version = 1.001, + comment = "companion to strc-not.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local format = string.format +local next = next +local texsprint, texwrite, texcount = tex.sprint, tex.write, tex.count + +local ctxcatcodes = tex.ctxcatcodes + +local trace_notes = false trackers.register("structure.notes", function(v) trace_notes = v end) + +structure = structure or { } +structure.helpers = structure.helpers or { } +structure.lists = structure.lists or { } +structure.sections = structure.sections or { } +structure.counters = structure.counters or { } +structure.notes = structure.notes or { } + +structure.notes.states = structure.notes.states or { } +structure.lists.enhancers = structure.lists.enhancers or { } + +storage.register("structure/notes/states", structure.notes.states, "structure.notes.states") + +local helpers = structure.helpers +local lists = structure.lists +local sections = structure.sections +local counters = structure.counters +local notes = structure.notes + +local notestates = structure.notes.states +local notedata = { } + +-- state: store, insert, postpone + +function notes.store(tag,n) + local nd = notedata[tag] + if not nd then + nd = { } + notedata[tag] = nd + end + local nnd = #nd+1 + nd[nnd] = n + local state = notestates[tag] + if state.kind ~= "insert" then + if trace_notes then + logs.report("notes","storing %s with state %s as %s",tag,state.kind,nnd) + end + state.start = state.start or nnd + end + texwrite(#nd) +end + +local function get(tag,n) + local nd = notedata[tag] + if nd then + n = n or #nd + nd = nd[n] + if nd then + if trace_notes then + logs.report("notes","getting %s of %s",n,tag) + end + return structure.lists.collected[nd] + end + end +end + +local function getn(tag) + local nd = notedata[tag] + return (nd and #nd) or 0 +end + +nodes.get = get +nodes.getn = getn + +-- we could make a special enhancer + +function notes.listindex(tag,n) + return notedata[tag][n] +end + +function notes.define(tag,kind,number) + local state = notes.setstate(tag,kind) + state.number = number +end + +function notes.save(tag,newkind) + local state = notestates[tag] + if state and not state.saved then + if trace_notes then + logs.report("notes","saving state of %s: %s -> %s",tag,state.kind,newkind or state.kind) + end + state.saved = notedata[tag] + state.savedkind = state.kind + state.kind = newkind or state.kind + notedata[tag] = { } + end +end + +function notes.restore(tag,forcedstate) + local state = notestates[tag] + if state and state.saved then + if trace_notes then + logs.report("notes","restoring state of %s: %s -> %s",tag,state.kind,state.savedkind) + end + state.saved = nil + state.kind = forcedstate or state.savedkind + notedata[tag] = state.saved + end +end + +function notes.setstate(tag,newkind) + local state = notestates[tag] + if trace_notes then + logs.report("notes","setting state of %s from %s to %s",tag,(state and state.kind) or "unset",newkind) + end + if not state then + state = { + kind = newkind + } + notestates[tag] = state + elseif newkind == "insert" then + if not state.start then + state.kind = newkind + end + else + state.kind = newkind + end + -- state.start can already be set and will be set when an entry is added or flushed + return state +end + +function notes.getstate(tag) + local state = notestates[tag] + texsprint(ctxcatcodes,(state and state.kind ) or "unknown") +end + +function notes.doifcontent(tag) + local ok = notestates[tag] + if ok then + if ok.kind == "insert" then + ok = tex.box[ok.number] + if ok then + ok = tbs.list + ok = lst and lst.next + end + else + ok = ok.start + end + end + commands.doif(ok) +end + +local function internal(tag,n) + local nd = get(tag,n) + if nd then + local r = nd.references + if r then + local i = r.internal +--~ return i and lists.internals[i] + return i and jobreferences.internals[i] + end + end + return nil +end + +local function ordered(kind,name,n) + local o = lists.ordered[kind] + o = o and o[name] + return o and o[n] +end + +notes.internal = internal +notes.ordered = ordered + +function notes.doifonsamepageasprevious(tag) + local same = false + local n = getn(tag,n) + local current, previous = get(tag,n), get(tag,n-1) + if current and previous then + local cr, pr = current.references, previous.references + same = cr and pr and cr.realpage == pr.realpage + end + commands.doifelse(same) +end + +function notes.checkpagechange(tag) -- called before increment ! + local nd = notedata[tag] -- can be unset at first entry + if nd then + local current = ordered("note",tag,#nd) + local nextone = ordered("note",tag,#nd+1) + if nextone then + -- we can use data from the previous pass + if nextone.pagenumber.number > current.pagenumber.number then + counters.reset(tag) + end + elseif current then + -- we need to locate the next one, best guess + if texcount.realpageno > current.pagenumber.number then + counters.reset(tag) + end + end + end +end + +function notes.deltapage(tag,n) + -- 0:unknown 1:textbefore, 2:textafter, 3:samepage + local what = 0 + local li = internal(tag,n) + if li then + local metadata, pagenumber = li.metadata, li.pagenumber + if metadata and pagenumber then + local symbolpage = metadata.symbolpage or 0 + local notepage = pagenumber.number or 0 + if notepage > 0 and symbolpage > 0 then + if notepage < symbolpage then + what = 1 + elseif notepage > symbolpage then + what = 2 + else + what = 3 + end + end + else + -- might be a note that is not flushed due to to deep + -- nesting in a vbox + what = 3 + end + end + texwrite(what) +end + +function notes.postpone() + if trace_notes then + logs.report("notes","postponing all insert notes") + end + for tag, state in next, notestates do + if state.kind ~= "store" then + notes.setstate(tag,"postpone") + end + end +end + +function notes.setsymbolpage(tag,n) + local nd = get(tag,n) + if nd then + nd.metadata.symbolpage = texcount.realpageno + end +end + +function notes.getsymbolpage(tag,n) + local nd = get(tag,n) + nd = nd and nd.metadata.symbolpage + texwrite(nd or 0) +end + +function notes.getnumberpage(tag,n) + local li = internal(tag,n) + li = li and li.pagenumber + li = li and li.numbers + li = li and li[1] + texwrite(li or 0) +end + +function notes.flush(tag,whatkind) -- store and postpone + local state = notestates[tag] + local kind = state.kind + if kind == whatkind then + local nd = notedata[tag] + local ns = state.start -- first index + if kind == "postpone" then + if nd and ns then + if trace_notes then + logs.report("notes","flushing state %s of %s from %s to %s",whatkind,tag,ns,#nd) + end + for i=ns,#nd do + texsprint(ctxcatcodes,format("\\handlenoteinsert{%s}{%s}",tag,i)) + end + end + state.start = nil + state.kind = "insert" + elseif kind == "store" then + if nd and ns then + if trace_notes then + logs.report("notes","flushing state %s of %s from %s to %s",whatkind,tag,ns,#nd) + end + for i=ns,#nd do + texsprint(ctxcatcodes,format("\\handlenoteitself{%s}{%s}",tag,i)) + end + end + state.start = nil + elseif kind == "reset" then + if nd and ns then + if trace_notes then + logs.report("notes","flushing state %s of %s from %s to %s",whatkind,tag,ns,#nd) + end + end + state.start = nil + elseif trace_notes then + logs.report("notes","not flushing state %s of %s",whatkind,tag) + end + elseif trace_notes then + logs.report("notes","not flushing state %s of %s",whatkind,tag) + end +end + +function notes.flushpostponed() + if trace_notes then + logs.report("notes","flushing all postponed notes") + end + for tag, _ in next, notestates do + notes.flush(tag,"postpone") + end +end + +function notes.resetpostponed() + if trace_notes then + logs.report("notes","resetting all postponed notes") + end + for tag, state in next, notestates do + if state.kind == "postpone" then + state.start = nil + state.kind = "insert" + end + end +end + +function notes.title(tag,n) + structure.lists.savedtitle(tag,notedata[tag][n]) +end + +function notes.number(tag,n,spec) + structure.lists.savedprefixednumber(tag,notedata[tag][n]) +end |