diff options
Diffstat (limited to 'tex/context/base/page-flt.lua')
-rw-r--r-- | tex/context/base/page-flt.lua | 578 |
1 files changed, 289 insertions, 289 deletions
diff --git a/tex/context/base/page-flt.lua b/tex/context/base/page-flt.lua index cd78b9356..ab7a534eb 100644 --- a/tex/context/base/page-flt.lua +++ b/tex/context/base/page-flt.lua @@ -1,289 +1,289 @@ -if not modules then modules = { } end modules ['page-flt'] = {
- version = 1.001,
- comment = "companion to page-flt.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- floats -> managers.floats
--- some functions are a tex/lua mix so we need a separation
-
-local insert, remove = table.insert, table.remove
-local find = string.find
-local setdimen, setcount, texbox = tex.setdimen, tex.setcount, tex.box
-
-local copy_node_list = node.copy_list
-
-local trace_floats = false trackers.register("graphics.floats", function(v) trace_floats = v end) -- name might change
-
-local report_floats = logs.reporter("structure","floats")
-
-local C, S, P, lpegmatch = lpeg.C, lpeg.S, lpeg.P, lpeg.match
-
--- we use floatbox, floatwidth, floatheight
--- text page leftpage rightpage (todo: top, bottom, margin, order)
-
-floats = floats or { }
-local floats = floats
-
-local noffloats, last, default, pushed = 0, nil, "text", { }
-
-local function initialize()
- return {
- text = { },
- page = { },
- leftpage = { },
- rightpage = { },
- somewhere = { },
- }
-end
-
-local stacks = initialize()
-
--- list location
-
-function floats.stacked(which) -- floats.thenofstacked
- return #stacks[which or default]
-end
-
-function floats.push()
- insert(pushed,stacks)
- stacks = initialize()
- setcount("global","savednoffloats",0)
-end
-
-function floats.pop()
- local popped = remove(pushed)
- if popped then
- for which, stack in next, stacks do
- for i=1,#stack do
- insert(popped[which],stack[i])
- end
- end
- stacks = popped
- setcount("global","savednoffloats",#stacks[default])
- end
-end
-
-local function setdimensions(b)
- local w, h, d = 0, 0, 0
- if b then
- w, h, d = b.width, b.height, b.depth
- end
- setdimen("global","floatwidth", w)
- setdimen("global","floatheight", h+d)
- return w, h, d
-end
-
-local function get(stack,n,bylabel)
- if bylabel then
- for i=1,#stack do
- local s = stack[i]
- local n = string.topattern(tostring(n)) -- to be sure
- if find(s.data.label,n) then
- return s, s.box, i
- end
- end
- else
- n = n or #stack
- if n > 0 then
- local t = stack[n]
- if t then
- return t, t.box, n
- end
- end
- end
-end
-
-function floats.save(which,data)
- which = which or default
- local b = texbox.floatbox
- if b then
- local stack = stacks[which]
- noffloats = noffloats + 1
- local w, h, d = b.width, b.height, b.depth
- local t = {
- n = noffloats,
- data = data or { },
- box = copy_node_list(b),
- }
- texbox.floatbox = nil
- insert(stack,t)
- setcount("global","savednoffloats",#stacks[default])
- if trace_floats then
- report_floats("%s, category %a, number %a, slot %a, width %p, height %p, depth %p","saving",which,noffloats,#stack,w,h,d)
- else
- interfaces.showmessage("floatblocks",2,noffloats)
- end
- else
- report_floats("ignoring empty, category %a, number %a",which,noffloats)
- end
-end
-
-function floats.resave(which)
- if last then
- which = which or default
- local stack = stacks[which]
- local b = texbox.floatbox
- local w, h, d = b.width, b.height, b.depth
- last.box = copy_node_list(b)
- texbox.floatbox = nil
- insert(stack,1,last)
- setcount("global","savednoffloats",#stacks[default])
- if trace_floats then
- report_floats("%s, category %a, number %a, slot %a width %p, height %p, depth %p","resaving",which,noffloats,#stack,w,h,d)
- else
- interfaces.showmessage("floatblocks",2,noffloats)
- end
- else
- report_floats("unable to resave float")
- end
-end
-
-function floats.flush(which,n,bylabel)
- which = which or default
- local stack = stacks[which]
- local t, b, n = get(stack,n or 1,bylabel)
- if t then
- local w, h, d = setdimensions(b)
- if trace_floats then
- report_floats("%s, category %a, number %a, slot %a width %p, height %p, depth %p","flushing",which,t.n,n,w,h,d)
- else
- interfaces.showmessage("floatblocks",3,t.n)
- end
- texbox.floatbox = b
- last = remove(stack,n)
- last.box = nil
- setcount("global","savednoffloats",#stacks[default]) -- default?
- else
- setdimensions()
- end
-end
-
-function floats.consult(which,n)
- which = which or default
- local stack = stacks[which]
- local t, b, n = get(stack,n)
- if t then
- local w, h, d = setdimensions(b)
- if trace_floats then
- report_floats("%s, category %a, number %a, slot %a width %p, height %p, depth %p","consulting",which,t.n,n,w,h,d)
- end
- return t, b, n
- else
- if trace_floats then
- report_floats("nothing to consult")
- end
- setdimensions()
- end
-end
-
-function floats.collect(which,maxwidth,distance)
- which = which or default
- local stack = stacks[which]
- local n, m = #stack, 0
- for i=1,n do
- local t, b, n = get(stack,i)
- if t then
- local w, h, d = setdimensions(b)
- if w + distance < maxwidth then
- m = m + 1
- maxwidth = maxwidth - w - distance
- else
- break
- end
- else
- break
- end
- end
- if m == 0 then
- m = 1
- end
- setcount("global","nofcollectedfloats",m)
-end
-
-function floats.getvariable(name,default)
- local value = last and last.data[name] or default
- return value ~= "" and value
-end
-
-function floats.checkedpagefloat(packed)
- if structures.pages.is_odd() then
- if #stacks.rightpage > 0 then
- return "rightpage"
- elseif #stacks.page > 0 then
- return "page"
- elseif #stacks.leftpage > 0 then
- if packed then
- return "leftpage"
- end
- end
- else
- if #stacks.leftpage > 0 then
- return "leftpage"
- elseif #stacks.page > 0 then
- return "page"
- elseif #stacks.rightpage > 0 then
- if packed then
- return "rightpage"
- end
- end
- end
-end
-
-function floats.nofstacked()
- return #stacks[which or default] or 0
-end
-
--- todo: check for digits !
-
-local method = C((1-S(", :"))^1)
-local position = P(":") * C((1-S("*,"))^1) * (P("*") * C((1-S(","))^1))^0
-local label = P(":") * C((1-S(",*: "))^0)
-
-local pattern = method * (
- label * position * C("")
- + C("") * position * C("")
- + label * C("") * C("")
- + C("") * C("") * C("")
-) + C("") * C("") * C("") * C("")
-
--- inspect { lpegmatch(pattern,"somewhere:blabla,crap") }
--- inspect { lpegmatch(pattern,"somewhere:1*2") }
--- inspect { lpegmatch(pattern,"somewhere:blabla:1*2") }
--- inspect { lpegmatch(pattern,"somewhere::1*2") }
--- inspect { lpegmatch(pattern,"somewhere,") }
--- inspect { lpegmatch(pattern,"somewhere") }
--- inspect { lpegmatch(pattern,"") }
-
-function floats.analysemethod(str) -- will become a more extensive parser
- return lpegmatch(pattern,str or "")
-end
-
--- interface
-
-local context = context
-local setvalue = context.setvalue
-
-commands.flushfloat = floats.flush
-commands.savefloat = floats.save
-commands.resavefloat = floats.resave
-commands.pushfloat = floats.push
-commands.popfloat = floats.pop
-commands.consultfloat = floats.consult
-commands.collectfloat = floats.collect
-
-function commands.getfloatvariable (...) local v = floats.getvariable(...) if v then context(v) end end
-function commands.checkedpagefloat (...) local v = floats.checkedpagefloat(...) if v then context(v) end end
-
-function commands.nofstackedfloats (...) context(floats.nofstacked(...)) end
-function commands.doifelsesavedfloat(...) commands.doifelse(floats.nofstacked(...)>0) end
-
-function commands.analysefloatmethod(str) -- currently only one method
- local method, label, row, column = floats.analysemethod(str)
- setvalue("floatmethod",method or "")
- setvalue("floatlabel", label or "")
- setvalue("floatrow", row or "")
- setvalue("floatcolumn",column or "")
-end
+if not modules then modules = { } end modules ['page-flt'] = { + version = 1.001, + comment = "companion to page-flt.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- floats -> managers.floats +-- some functions are a tex/lua mix so we need a separation + +local insert, remove = table.insert, table.remove +local find = string.find +local setdimen, setcount, texbox = tex.setdimen, tex.setcount, tex.box + +local copy_node_list = node.copy_list + +local trace_floats = false trackers.register("graphics.floats", function(v) trace_floats = v end) -- name might change + +local report_floats = logs.reporter("structure","floats") + +local C, S, P, lpegmatch = lpeg.C, lpeg.S, lpeg.P, lpeg.match + +-- we use floatbox, floatwidth, floatheight +-- text page leftpage rightpage (todo: top, bottom, margin, order) + +floats = floats or { } +local floats = floats + +local noffloats, last, default, pushed = 0, nil, "text", { } + +local function initialize() + return { + text = { }, + page = { }, + leftpage = { }, + rightpage = { }, + somewhere = { }, + } +end + +local stacks = initialize() + +-- list location + +function floats.stacked(which) -- floats.thenofstacked + return #stacks[which or default] +end + +function floats.push() + insert(pushed,stacks) + stacks = initialize() + setcount("global","savednoffloats",0) +end + +function floats.pop() + local popped = remove(pushed) + if popped then + for which, stack in next, stacks do + for i=1,#stack do + insert(popped[which],stack[i]) + end + end + stacks = popped + setcount("global","savednoffloats",#stacks[default]) + end +end + +local function setdimensions(b) + local w, h, d = 0, 0, 0 + if b then + w, h, d = b.width, b.height, b.depth + end + setdimen("global","floatwidth", w) + setdimen("global","floatheight", h+d) + return w, h, d +end + +local function get(stack,n,bylabel) + if bylabel then + for i=1,#stack do + local s = stack[i] + local n = string.topattern(tostring(n)) -- to be sure + if find(s.data.label,n) then + return s, s.box, i + end + end + else + n = n or #stack + if n > 0 then + local t = stack[n] + if t then + return t, t.box, n + end + end + end +end + +function floats.save(which,data) + which = which or default + local b = texbox.floatbox + if b then + local stack = stacks[which] + noffloats = noffloats + 1 + local w, h, d = b.width, b.height, b.depth + local t = { + n = noffloats, + data = data or { }, + box = copy_node_list(b), + } + texbox.floatbox = nil + insert(stack,t) + setcount("global","savednoffloats",#stacks[default]) + if trace_floats then + report_floats("%s, category %a, number %a, slot %a, width %p, height %p, depth %p","saving",which,noffloats,#stack,w,h,d) + else + interfaces.showmessage("floatblocks",2,noffloats) + end + else + report_floats("ignoring empty, category %a, number %a",which,noffloats) + end +end + +function floats.resave(which) + if last then + which = which or default + local stack = stacks[which] + local b = texbox.floatbox + local w, h, d = b.width, b.height, b.depth + last.box = copy_node_list(b) + texbox.floatbox = nil + insert(stack,1,last) + setcount("global","savednoffloats",#stacks[default]) + if trace_floats then + report_floats("%s, category %a, number %a, slot %a width %p, height %p, depth %p","resaving",which,noffloats,#stack,w,h,d) + else + interfaces.showmessage("floatblocks",2,noffloats) + end + else + report_floats("unable to resave float") + end +end + +function floats.flush(which,n,bylabel) + which = which or default + local stack = stacks[which] + local t, b, n = get(stack,n or 1,bylabel) + if t then + local w, h, d = setdimensions(b) + if trace_floats then + report_floats("%s, category %a, number %a, slot %a width %p, height %p, depth %p","flushing",which,t.n,n,w,h,d) + else + interfaces.showmessage("floatblocks",3,t.n) + end + texbox.floatbox = b + last = remove(stack,n) + last.box = nil + setcount("global","savednoffloats",#stacks[default]) -- default? + else + setdimensions() + end +end + +function floats.consult(which,n) + which = which or default + local stack = stacks[which] + local t, b, n = get(stack,n) + if t then + local w, h, d = setdimensions(b) + if trace_floats then + report_floats("%s, category %a, number %a, slot %a width %p, height %p, depth %p","consulting",which,t.n,n,w,h,d) + end + return t, b, n + else + if trace_floats then + report_floats("nothing to consult") + end + setdimensions() + end +end + +function floats.collect(which,maxwidth,distance) + which = which or default + local stack = stacks[which] + local n, m = #stack, 0 + for i=1,n do + local t, b, n = get(stack,i) + if t then + local w, h, d = setdimensions(b) + if w + distance < maxwidth then + m = m + 1 + maxwidth = maxwidth - w - distance + else + break + end + else + break + end + end + if m == 0 then + m = 1 + end + setcount("global","nofcollectedfloats",m) +end + +function floats.getvariable(name,default) + local value = last and last.data[name] or default + return value ~= "" and value +end + +function floats.checkedpagefloat(packed) + if structures.pages.is_odd() then + if #stacks.rightpage > 0 then + return "rightpage" + elseif #stacks.page > 0 then + return "page" + elseif #stacks.leftpage > 0 then + if packed then + return "leftpage" + end + end + else + if #stacks.leftpage > 0 then + return "leftpage" + elseif #stacks.page > 0 then + return "page" + elseif #stacks.rightpage > 0 then + if packed then + return "rightpage" + end + end + end +end + +function floats.nofstacked() + return #stacks[which or default] or 0 +end + +-- todo: check for digits ! + +local method = C((1-S(", :"))^1) +local position = P(":") * C((1-S("*,"))^1) * (P("*") * C((1-S(","))^1))^0 +local label = P(":") * C((1-S(",*: "))^0) + +local pattern = method * ( + label * position * C("") + + C("") * position * C("") + + label * C("") * C("") + + C("") * C("") * C("") +) + C("") * C("") * C("") * C("") + +-- inspect { lpegmatch(pattern,"somewhere:blabla,crap") } +-- inspect { lpegmatch(pattern,"somewhere:1*2") } +-- inspect { lpegmatch(pattern,"somewhere:blabla:1*2") } +-- inspect { lpegmatch(pattern,"somewhere::1*2") } +-- inspect { lpegmatch(pattern,"somewhere,") } +-- inspect { lpegmatch(pattern,"somewhere") } +-- inspect { lpegmatch(pattern,"") } + +function floats.analysemethod(str) -- will become a more extensive parser + return lpegmatch(pattern,str or "") +end + +-- interface + +local context = context +local setvalue = context.setvalue + +commands.flushfloat = floats.flush +commands.savefloat = floats.save +commands.resavefloat = floats.resave +commands.pushfloat = floats.push +commands.popfloat = floats.pop +commands.consultfloat = floats.consult +commands.collectfloat = floats.collect + +function commands.getfloatvariable (...) local v = floats.getvariable(...) if v then context(v) end end +function commands.checkedpagefloat (...) local v = floats.checkedpagefloat(...) if v then context(v) end end + +function commands.nofstackedfloats (...) context(floats.nofstacked(...)) end +function commands.doifelsesavedfloat(...) commands.doifelse(floats.nofstacked(...)>0) end + +function commands.analysefloatmethod(str) -- currently only one method + local method, label, row, column = floats.analysemethod(str) + setvalue("floatmethod",method or "") + setvalue("floatlabel", label or "") + setvalue("floatrow", row or "") + setvalue("floatcolumn",column or "") +end |