From deecfe09c774d4c2835f6999b2cdd9ca07e9bdae Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 20 Aug 2007 10:21:00 +0200 Subject: stable 2007.08.20 10:21 --- tex/context/base/attr-ini.lua | 697 +++++++++++++++--------------- tex/context/base/attr-ini.tex | 122 +++--- tex/context/base/char-ini.lua | 11 +- tex/context/base/char-utf.lua | 10 +- tex/context/base/colo-hex.tex | 4 + tex/context/base/colo-ini.tex | 182 ++++---- tex/context/base/colo-run.tex | 67 +-- tex/context/base/cont-new.mkiv | 37 +- tex/context/base/cont-new.tex | 53 ++- tex/context/base/context.tex | 11 +- tex/context/base/core-con.lua | 96 +++-- tex/context/base/core-con.mkiv | 60 +-- tex/context/base/core-mat.tex | 2 +- tex/context/base/core-obj.tex | 10 + tex/context/base/core-rul.tex | 49 ++- tex/context/base/core-sec.tex | 39 +- tex/context/base/core-spa.lua | 26 +- tex/context/base/core-spa.tex | 130 +++--- tex/context/base/core-tab.tex | 41 +- tex/context/base/core-uti.mkiv | 12 +- tex/context/base/core-var.tex | 3 + tex/context/base/font-afm.lua | 158 ++++--- tex/context/base/font-def.lua | 75 ++-- tex/context/base/font-enc.lua | 21 +- tex/context/base/font-ini.lua | 3 +- tex/context/base/font-ini.mkiv | 22 +- tex/context/base/font-map.lua | 185 +++----- tex/context/base/font-otf.lua | 484 ++++++++++++++++++--- tex/context/base/font-syn.lua | 6 +- tex/context/base/font-tfm.lua | 90 ++-- tex/context/base/l-aux.lua | 48 ++- tex/context/base/l-boolean.lua | 2 + tex/context/base/l-file.lua | 2 +- tex/context/base/l-string.lua | 12 + tex/context/base/l-table.lua | 36 ++ tex/context/base/l-tex.lua | 2 +- tex/context/base/l-utils.lua | 7 +- tex/context/base/l-xml.lua | 887 ++++++++++++++++++++++++++++++++++++++ tex/context/base/lang-ini.lua | 2 +- tex/context/base/lang-sla.mkiv | 4 +- tex/context/base/luat-cbk.lua | 2 +- tex/context/base/luat-crl.lua | 6 +- tex/context/base/luat-ini.lua | 17 +- tex/context/base/luat-ini.tex | 22 +- tex/context/base/luat-inp.lua | 82 +++- tex/context/base/luat-lib.tex | 2 +- tex/context/base/luat-tex.lua | 34 +- tex/context/base/luat-tmp.lua | 106 ++--- tex/context/base/luat-tra.lua | 104 +++-- tex/context/base/lxml-ini.lua | 33 ++ tex/context/base/lxml-ini.tex | 23 + tex/context/base/meta-mis.tex | 2 +- tex/context/base/meta-pdf.lua | 67 ++- tex/context/base/meta-pdf.mkiv | 2 - tex/context/base/meta-pdf.tex | 49 ++- tex/context/base/mult-con.tex | 12 + tex/context/base/mult-sys.tex | 2 + tex/context/base/node-ini.lua | 578 +++++++++++++------------ tex/context/base/page-flt.tex | 497 ++++++++++----------- tex/context/base/page-imp.tex | 4 +- tex/context/base/page-ini.tex | 3 - tex/context/base/prop-ini.tex | 27 +- tex/context/base/prop-lay.tex | 8 - tex/context/base/prop-mis.mkii | 155 +++++++ tex/context/base/prop-mis.mkiv | 46 ++ tex/context/base/prop-mis.tex | 177 +------- tex/context/base/s-abr-01.tex | 1 + tex/context/base/spec-dpx.tex | 2 + tex/context/base/spec-fdf.tex | 15 +- tex/context/base/spec-tpd.tex | 2 + tex/context/base/syst-con.lua | 44 +- tex/context/base/syst-con.mkiv | 16 +- tex/context/base/toks-ini.lua | 58 +-- tex/context/base/toks-ini.tex | 10 +- tex/context/interface/keys-cz.xml | 5 +- tex/context/interface/keys-de.xml | 5 +- tex/context/interface/keys-en.xml | 5 +- tex/context/interface/keys-fr.xml | 5 +- tex/context/interface/keys-it.xml | 5 +- tex/context/interface/keys-nl.xml | 5 +- tex/context/interface/keys-ro.xml | 5 +- 81 files changed, 3844 insertions(+), 2107 deletions(-) create mode 100644 tex/context/base/l-xml.lua create mode 100644 tex/context/base/lxml-ini.lua create mode 100644 tex/context/base/lxml-ini.tex create mode 100644 tex/context/base/prop-mis.mkii create mode 100644 tex/context/base/prop-mis.mkiv (limited to 'tex') diff --git a/tex/context/base/attr-ini.lua b/tex/context/base/attr-ini.lua index 4469608c4..81ca873d9 100644 --- a/tex/context/base/attr-ini.lua +++ b/tex/context/base/attr-ini.lua @@ -29,11 +29,17 @@ function totokens(str) return t end -function pdfliteral(str) - local t = node.new('whatsit',8) - t.mode = 1 -- direct - t.data = str -- totokens(str) - return t +-- temp hack, will be proper driver stuff + +backends = backends or { } +backends.pdf = backends.pdf or { } +backend = backend or backends.pdf + +function backends.pdf.literal(str) + local t = node.new('whatsit',8) + t.mode = 1 -- direct + t.data = str -- totokens(str) + return t end -- shipouts @@ -45,44 +51,44 @@ do local hlist, vlist = node.id('hlist'), node.id('vlist') - local function do_process_page(attribute,processor,head) -- maybe work with ranges - local previous, stack = nil, head - while stack do - local id = stack.id - if id == hlist or id == vlist then - local content = stack.list - if content then - stack.list = do_process_page(attribute,processor,content) - end - else - stack, previous, head = processor(attribute,stack,previous,head) - end - previous = stack - stack = stack.next - end - return head - end + local contains = node.has_attribute + + nodes.trigger = false + nodes.triggering = false + + -- we used to do the main processor loop here and call processor for each node + -- but eventually this was too much a slow down (1 sec on 23 for 120 pages mk) + -- so that we moved looping to teh processor itself; this may lead to a bit of + -- duplicate code once that we have more state handlers function nodes.process_page(head) + local trigger = nodes.trigger if head then - input.start_timing(nodes) + input.start_timing(attributes) local done, used = false, { } for name, plugin in pairs(shipouts.plugins) do local attribute = attributes.numbers[name] if attribute then - local initializer = plugin.initializer - local processor = plugin.processor - local finalizer = plugin.finalizer - if initializer then - initializer(attribute,head) - end - if processor then - head = do_process_page(attribute,processor,head) - end - if finalizer then - local ok - ok, head, used[attribute] = finalizer(attribute,head) - done = done or ok + local namespace = plugin.namespace + if namespace.enabled then + local initializer = plugin.initializer + local processor = plugin.processor + local finalizer = plugin.finalizer + local resolver = plugin.resolver + if initializer then + initializer(namespace,attribute,head) + end + if processor then + local inheritance = (resolver and resolver()) or -1 + local ok + ok, head = processor(namespace,attribute,head,inheritance) + done = done or ok + end + if finalizer then -- no need when not ok + local ok + ok, head, used[attribute] = finalizer(namespace,attribute,head) + done = done or ok + end end else texio.write_nl(string.format("undefined attribute %s",name)) @@ -92,14 +98,17 @@ do for name, plugin in pairs(shipouts.plugins) do local attribute = attributes.numbers[name] if used[attribute] then - local flusher = plugin.flusher - if flusher then - head = flusher(attribute,head,used[attribute]) + local namespace = plugin.namespace + if namespace.enabled then + local flusher = plugin.flusher + if flusher then + head = flusher(namespace,attribute,head,used[attribute]) + end end end end end - input.stop_timing(nodes) + input.stop_timing(attributes) end return head end @@ -132,7 +141,7 @@ states = { } do - local glyph, rule, whatsit = node.id('glyph'), node.id('rule'), node.id('whatsit') + local glyph, rule, whatsit, hlist, vlist = node.id('glyph'), node.id('rule'), node.id('whatsit'), node.id('hlist'), node.id('vlist') local current, used, done = 0, { }, false @@ -140,11 +149,11 @@ do current, used, done = 0, { }, false end - local contains = node.has_attribute + local contains, copy = node.has_attribute, node.copy - function insert(n,stack,previous,head) + local function insert(n,stack,previous,head) if n then - n = node.copy(n) + n = copy(n) n.next = stack if previous then previous.next = n @@ -156,94 +165,128 @@ do return stack, previous, head end - function states.finalize(what,attribute,head) - if what.enabled and what.none and current > 0 and head.list then - local head = head.list - stack, previous, head = insert(what.none,list,nil,list) + function states.finalize(namespace,attribute,head) + if current > 0 and namespace.none then + if head.id == hlist or head.id == vlist then + local stack, previous, head = insert(namespace.none,head.list,nil,head.list) + else + local stack, previous, head = insert(namespace.none,head,nil,head) + end + return true, head, true + else + return false, head, false end - return done, head, used end ---~ function states.process(what,attribute,stack,previous,head) -- one attribute ---~ if what.enabled then ---~ local c = contains(stack,attribute) ---~ if c then ---~ if current ~= c then ---~ local id = stack.id ---~ if id == glyph or id == rule or id == whatsit then ---~ stack, previous, head = insert(what.data[c],stack,previous,head) ---~ current, done, used[c] = c, true, true ---~ end ---~ end ---~ elseif current > 0 then ---~ stack, previous, head = insert(what.none,stack,previous,head) ---~ current, done, used[0] = 0, true, true ---~ end ---~ end ---~ return stack, previous, head ---~ end - - function states.process(what,attribute,stack,previous,head) -- one attribute - if what.enabled then + function states.process(namespace,attribute,head,inheritance,default) -- one attribute + local trigger = nodes.triggering and nodes.trigger + local stack, previous, done, process = head, nil, false, states.process + while stack do local id = stack.id - if id == glyph or id == rule then -- or id == whatsit then + if id == hlist or id == vlist then + local content = stack.list + if content then + local ok = false + if trigger and contains(stack,trigger) then + local outer = contains(stack,attribute) + if outer ~= inheritance then + ok, stack.list = process(namespace,attribute,content,inheritance,outer) + else + ok, stack.list = process(namespace,attribute,content,inheritance,default) + end + else + ok, stack.list = process(namespace,attribute,content,inheritance,default) + end + done = done or ok + end + elseif id == glyph or id == rule or id == whatsit then -- special local c = contains(stack,attribute) if c then - if current ~= c then - stack, previous, head = insert(what.data[c],stack,previous,head) + if default and c == inheritance then + if current ~= default then + local data = namespace.data[default] or namespace.reviver(default) + stack, previous, head = insert(data,stack,previous,head) + current, done, used[default] = default, true, true + end + elseif current ~= c then + local data = namespace.data[c] or namespace.reviver(c) + stack, previous, head = insert(data,stack,previous,head) current, done, used[c] = c, true, true end + elseif default and inheritance then + if current ~= default then + local data = namespace.data[default] or namespace.reviver(default) + stack, previous, head = insert(data,stack,previous,head) + current, done, used[default] = default, true, true + end elseif current > 0 then - stack, previous, head = insert(what.none,stack,previous,head) + stack, previous, head = insert(namespace.none,stack,previous,head) current, done, used[0] = 0, true, true end end + previous = stack + stack = stack.next end - return stack, previous, head + return done, head end ---~ function states.selective(what,attribute,stack,previous,head) -- two attributes ---~ if what.enabled then ---~ local c = contains(stack,attribute) ---~ if c then ---~ if current ~= c then ---~ local id = stack.id ---~ if id == glyph or id == rule then -- or id == whatsit then ---~ stack, previous, head = insert(what.data[c][contains(stack,what.selector) or what.default],stack,previous,head) ---~ current, done, used[c] = c, true, true ---~ end ---~ end ---~ elseif current > 0 then ---~ local id = stack.id ---~ if id == glyph or id == rule then -- or id == whatsit then ---~ stack, previous, head = insert(what.none,stack,previous,head) ---~ current, done, used[0] = 0, true, true ---~ end ---~ end ---~ end ---~ return stack, previous, head ---~ end + -- we can force a selector, e.g. document wide color spaces, saves a little - function states.selective(what,attribute,stack,previous,head) -- two attributes - if what.enabled then + function states.selective(namespace,attribute,head,inheritance,default) -- two attributes + local trigger = nodes.triggering and nodes.trigger + local stack, previous, done, selective = head, nil, false, states.selective + local defaultselector, forcedselector, selector, reviver = namespace.default, namespace.forced, namespace.selector, namespace.reviver + local none = namespace.none + while stack do local id = stack.id - if id == glyph or id == rule then -- or id == whatsit then + if id == hlist or id == vlist then + local content = stack.list + if content then + local ok = false + if trigger and contains(stack,trigger) then + local outer = contains(stack,attribute) + if outer ~= inheritance then + ok, stack.list = selective(namespace,attribute,content,inheritance,outer) + else + ok, stack.list = selective(namespace,attribute,content,inheritance,default) + end + else + ok, stack.list = selective(namespace,attribute,content,inheritance,default) + end + done = done or ok + end + elseif id == glyph or id == rule or id == whatsit then -- special local c = contains(stack,attribute) if c then - if current ~= c then - stack, previous, head = insert(what.data[c][contains(stack,what.selector) or what.default],stack,previous,head) + if default and c == inheritance then + if current ~= default then + local data = namespace.data[default] or reviver(default) + stack, previous, head = insert(data[forcedselector or contains(stack,selector) or defaultselector],stack,previous,head) + current, done, used[default] = default, true, true + end + elseif current ~= c then + local data = namespace.data[c] or reviver(c) + stack, previous, head = insert(data[forcedselector or contains(stack,selector) or defaultselector],stack,previous,head) current, done, used[c] = c, true, true end + elseif default and inheritance then + if current ~= default then + local data = namespace.data[default] or reviver(default) + stack, previous, head = insert(data[forcedselector or contains(stack,selector) or defaultselector],stack,previous,head) + current, done, used[default] = default, true, true + end elseif current > 0 then - stack, previous, head = insert(what.none,stack,previous,head) + stack, previous, head = insert(none,stack,previous,head) current, done, used[0] = 0, true, true end end + previous = stack + stack = stack.next end - return stack, previous, head + return done, head end - collected = { } + local collected = { } function states.collect(str) collected[#collected+1] = str @@ -269,24 +312,40 @@ end -- we also need to store the colorvalues because we need then in mp -colors = colors or { } -colors.enabled = true -colors.data = colors.data or { } -colors.strings = colors.strings or { } +colors = colors or { } +colors.data = colors.data or { } +colors.values = colors.values or { } colors.registered = colors.registered or { } +colors.enabled = true colors.weightgray = true colors.attribute = 0 colors.selector = 0 colors.default = 1 +colors.main = nil -input.storage.register(true,"colors/data", colors.strings, "colors.data") +-- This is a compromis between speed and simplicity. We used to store the +-- values and data in one array, which made in neccessary to store the +-- converters that need node constructor into strings and evaluate them +-- at runtime (after reading from storage). Think of: +-- +-- colors.strings = colors.strings or { } +-- +-- if environment.initex then +-- colors.strings[color] = "return colors." .. colorspace .. "(" .. table.concat({...},",") .. ")" +-- end +-- +-- input.storage.register(true,"colors/data", colors.strings, "colors.data") -- evaluated +-- +-- We assume that only processcolors are defined in the format. + +input.storage.register(false,"colors/values", colors.values, "colors.values") input.storage.register(false,"colors/registered", colors.registered, "colors.registered") colors.stamps = { rgb = "r:%s:%s:%s", cmyk = "c:%s:%s:%s:%s", gray = "s:%s", - spot = "p:%s:%s" + spot = "p:%s:%s:%s:%s" } colors.models = { @@ -303,23 +362,23 @@ do local format = string.format local concat = table.concat - local function rgbdata(r,g,b) - return pdfliteral(format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b)) + local function rgbdata(r,g,b) -- dodo: backends.pdf.rgbdata + return backends.pdf.literal(format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b)) end local function cmykdata(c,m,y,k) - return pdfliteral(format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k)) + return backends.pdf.literal(format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k)) end local function graydata(s) - return pdfliteral(format("%s g %s G",s,s)) + return backends.pdf.literal(format("%s g %s G",s,s)) end - local function spotdata(n,p) -- name, parent, ratio + local function spotdata(n,f,d,p) if type(p) == "string" then p = p:gsub(","," ") -- brr misuse of spot end - return pdfliteral(format("/%s cs /%s CS %s SCN %s scn",n,n,p,p)) + return backends.pdf.literal(format("/%s cs /%s CS %s SCN %s scn",n,n,p,p)) end local function rgbtocmyk(r,g,b) @@ -349,33 +408,54 @@ do -- default color space function colors.gray(s) - local gray = graydata(s) - return { gray, gray, gray, gray, 2, s, 0, 0, 0, 0, 0, 0, 1 } + return { 2, s, 0, 0, 0, 0, 0, 0, 1 } end function colors.rgb(r,g,b) local s = rgbtogray(r,g,b) local c, m, y, k = rgbtocmyk(r,g,b) - local gray, rgb, cmyk = graydata(s), rgbdata(r,g,b), cmykdata(c,m,y,k) - return { rgb, gray, rgb, cmyk, 3, s, r, g, b, c, m, y, k } + return { 3, s, r, g, b, c, m, y, k } end function colors.cmyk(c,m,y,k) local s = cmyktogray(c,m,y,k) local r, g, b = cmyktorgb(c,m,y,k) - local gray, rgb, cmyk = graydata(s), rgbdata(r,g,b), cmykdata(c,m,y,k) - return { cmyk, gray, rgb, cmyk, 4, s, r, g, b, c, m, y, k } + return { 4, s, r, g, b, c, m, y, k } end - function colors.spot(parent,p) -- parent, ratio - local spot = spotdata(parent,p) - if type(p) == "string" and p:find(",") then - -- use converted replacement (combination color) - else - -- todo: map gray, rgb, cmyk onto fraction*parent + function colors.spot(parent,f,d,p) +--~ if type(p) == "string" and p:find(",") then +--~ -- use converted replacement (combination color) +--~ else +--~ -- todo: map gray, rgb, cmyk onto fraction*parent +--~ end + return { 5, .5, .5, .5, .5, 0, 0, 0, .5, parent, f, d, p } + end + + function colors.reviver(n) + local d = colors.data[n] + if not d then + local v = colors.values[n] + if not v then + local gray = graydata(0) + d = { gray, gray, gray, gray } + logs.report("attributes",string.format("unable to revive color %s",n or "?")) + else + local kind, gray, rgb, cmyk = v[1], graydata(v[2]), rgbdata(v[3],v[4],v[5]), cmykdata(v[6],v[7],v[8],v[9]) + if kind == 2 then + d = { gray, gray, gray, gray } + elseif kind == 3 then + d = { rgb, gray, rgb, cmyk } + elseif kind == 4 then + d = { cmyk, gray, rgb, cmyk } + elseif kind == 5 then + local spot = spotdata(v[10],v[11],v[12],v[13]) + d = { spot, gray, rgb, cmyk } + end + end + colors.data[n] = d end - local gray, rgb, cmyk = graydata(.5), rgbdata(.5,.5,.5), cmykdata(0,0,0,.5) - return { spot, gray, rgb, cmyk, 5 } + return d end function colors.filter(n) @@ -386,284 +466,197 @@ do end --- conversion models - function colors.setmodel(attribute,name) colors.selector = attributes.numbers[attribute] colors.default = colors.models[name] or 1 return colors.default end -function colors.register(attribute, name, colorspace, ...) +function colors.register(attribute, name, colorspace, ...) -- passing 9 vars is faster local stamp = string.format(colors.stamps[colorspace], ...) local color = colors.registered[stamp] if not color then - local cd = colors.data - color = #cd+1 - cd[color] = colors[colorspace](...) - if environment.initex then - colors.strings[color] = "return colors." .. colorspace .. "(" .. table.concat({...},",") .. ")" - end + color = #colors.values+1 + colors.values[color] = colors[colorspace](...) colors.registered[stamp] = color + colors.reviver(color) + end + if name then + attributes.list[attributes.numbers[attribute]][name] = color -- not grouped, so only global colors end - attributes.list[attributes.numbers[attribute]][name] = color return colors.registered[stamp] end +function colors.value(id) + return colors.values[id] +end + shipouts.plugins.color = { - initializer = function(...) return states.initialize(colors,...) end, - finalizer = function(...) return states.finalize (colors,...) end, - processor = function(...) return states.selective (colors,...) end, + namespace = colors, + initializer = states.initialize, + finalizer = states.finalize , + processor = states.selective , + resolver = function(...) return colors.main end, +} + +-- transparencies + +-- for the moment we manage transparencies in the pdf driver because +-- first we need a nice interface to some pdf things + +transparencies = transparencies or { } +transparencies.registered = transparencies.registered or { } +transparencies.data = transparencies.data or { } +transparencies.values = transparencies.values or { } +transparencies.enabled = true +transparencies.template = "%s:%s" + +input.storage.register(false, "transparencies/registered", transparencies.registered, "transparencies.registered") +input.storage.register(false, "transparencies/data", transparencies.data, "transparencies.data") +input.storage.register(false, "transparencies/values", transparencies.values, "transparencies.values") + +function transparencies.reference(n) + return backends.pdf.literal(string.format("/Tr%s gs",n)) +end + +transparencies.none = transparencies.reference(0) + +function transparencies.register(name,...) + local stamp = string.format(transparencies.template, ...) + local n = transparencies.registered[stamp] + if not n then + n = #transparencies.data+1 + transparencies.data[n] = transparencies.reference(n) + transparencies.values[n] = { ... } + transparencies.registered[stamp] = n + states.collect(string.format("\\presetPDFtransparency{%s}{%s}",...)) -- too many, but experimental anyway + end + return transparencies.registered[stamp] +end + +function transparencies.value(id) + return transparencies.values[id] +end + +shipouts.plugins.transparency = { + namespace = transparencies, + initializer = states.initialize, + finalizer = states.finalize , + processor = states.process , } --- overprint / knockout -overprints = { enabled = true , data = { } } +overprints = overprints or { } +overprints.data = overprints.data or { } +overprints.enabled = true + +overprints.data[1] = backends.pdf.literal(string.format("/GSoverprint gs")) +overprints.data[2] = backends.pdf.literal(string.format("/GSknockout gs")) -overprints.none = pdfliteral(string.format("/GSoverprint gs")) -overprints.data[1] = pdfliteral(string.format("/GSknockout gs")) +overprints.none = overprints.data[1] overprints.registered = { - overprint = 0, - knockout = 1, + overprint = 1, + knockout = 2, } function overprints.register(stamp) +-- states.collect(tex.sprint(tex.ctxcatcodes,"\\initializePDFoverprint")) -- to be testd return overprints.registered[stamp] or overprints.registered.overprint end shipouts.plugins.overprint = { - initializer = function(...) return states.initialize(overprints,...) end, - finalizer = function(...) return states.finalize (overprints,...) end, - processor = function(...) return states.process (overprints,...) end, + namespace = overprints, + initializer = states.initialize, + finalizer = states.finalize , + processor = states.process , } --- negative / positive -negatives = { enabled = true, data = { } } +negatives = netatives or { } +negatives.data = negatives.data or { } +negatives.enabled = true -negatives.none = pdfliteral(string.format("/GSpositive gs")) -negatives.data[1] = pdfliteral(string.format("/GSnegative gs")) +negatives.data[1] = backends.pdf.literal(string.format("/GSpositive gs")) +negatives.data[2] = backends.pdf.literal(string.format("/GSnegative gs")) + +negatives.none = negatives.data[1] negatives.registered = { - positive = 0, - negative = 1, + positive = 1, + negative = 2, } function negatives.register(stamp) +-- states.collect(tex.sprint(tex.ctxcatcodes,"\\initializePDFnegative")) -- to be testd return negatives.registered[stamp] or negatives.registered.positive end shipouts.plugins.negative = { - initializer = function(...) return states.initialize(negatives,...) end, - finalizer = function(...) return states.finalize (negatives,...) end, - processor = function(...) return states.process (negatives,...) end, + namespace = negatives, + initializer = states.initialize, + finalizer = states.finalize, + processor = states.process, } -- effects -effects = { enabled = true, data = { } } - -effects.none = pdfliteral(string.format("0 Tr")) -effects.data[1] = pdfliteral(string.format("1 Tr")) -effects.data[2] = pdfliteral(string.format("2 Tr")) -effects.data[3] = pdfliteral(string.format("3 Tr")) +effects = effects or { } +effects.data = effects.data or { } +effects.registered = effects.registered or { } +effects.enabled = true +effects.stamp = "%s:%s:%s" + +input.storage.register(false, "effects/registered", effects.registered, "effects.registered") +input.storage.register(false, "effects/data", effects.data, "effects.data") + +function effects.register(effect,stretch,rulethickness) + local stamp = string.format(effects.stamp,effect,stretch,rulethickness) + local n = effects.registered[stamp] + if not n then + n = #effects.data+1 + effects.data[n] = effects.reference(effect,stretch,rulethickness) + effects.registered[stamp] = n + -- states.collect("") -- nothing + end + return effects.registered[stamp] +end -effects.registered = { - normal = 0, - inner = 0, - outer = 1, - both = 2, - hidden = 3, +backends.pdf.effects = { + normal = 1, + inner = 1, + outer = 2, + both = 3, + hidden = 4, } -function effects.register(stamp) - return effects.registered[stamp] or effects.registered.normal +function effects.reference(effect,stretch,rulethickness) -- will move, test code, we will develop a proper model for that + effect = backends.pdf.effects[effects] or backends.pdf.effects['normal'] + if stretch > 0 then + stretch = stretch .. " w " + else + stretch = "" + end + if rulethickness > 0 then + rulethickness = number.dimenfactors["bp"]*rulethickness.. " Tc " + else + rulethickness = "" + end + return backends.pdf.literal(string.format("%s%s%s Tr",stretch,rulethickness,effect)) -- watch order end +effects.none = effects.reference(effect,0,0) + shipouts.plugins.effect = { - initializer = function(...) return states.initialize(effects,...) end, - finalizer = function(...) return states.finalize (effects,...) end, - processor = function(...) return states.process (effects,...) end, + namespace = effects, + initializer = states.initialize, + finalizer = states.finalize , + processor = states.process , } -- layers --~ /OC /somename BDC --~ EMC - --- transparencies - --- for the moment we manage transparencies in the pdf driver because --- first we need a nice interface to some pdf things - -transparencies = { - enabled = true, - data = { }, - registered = { }, - hack = { } -} - -input.storage.register(false, "transparencies/registed", transparencies.registered, "transparencies.registered") -input.storage.register(false, "transparencies/data", transparencies.data, "transparencies.data") -input.storage.register(false, "transparencies/hack", transparencies.hack, "transparencies.hack") - -function transparencies.reference(n) - return pdfliteral(string.format("/Tr%s gs",n)) -end - -transparencies.none = transparencies.reference(0) - -transparencies.stamp = "%s:%s" - -function transparencies.register(...) - local stamp = string.format(transparencies.stamp, ...) - if not transparencies.registered[stamp] then - local n = #transparencies.data+1 - transparencies.data[n] = transparencies.reference(n) - transparencies.registered[stamp] = n - states.collect(string.format("\\presetPDFtransparency{%s}{%s}",...)) -- too many, but experimental anyway - end - return transparencies.registered[stamp] -end - -shipouts.plugins.transparency = { - initializer = function(...) return states.initialize(transparencies,...) end, - finalizer = function(...) return states.finalize (transparencies,...) end, - processor = function(...) return states.process (transparencies,...) end, -} - ---~ shipouts.plugins.transparency.flusher = function(attribute,head,used) ---~ local max = 0 ---~ for k,v in pairs(used) do ---~ end ---~ return head ---~ end - ---~ from the time that node lists were tables and not userdata ... ---~ ---~ local function do_collapse_page(stack,existing_t) ---~ if stack then ---~ local t = existing_t or { } ---~ for _, node in ipairs(stack) do ---~ if node then ---~ local kind = node[1] ---~ node[3] = nil ---~ if kind == 'hlist' or kind == 'vlist' then ---~ node[8] = do_collapse_page(node[8]) -- maybe here check for nil ---~ t[#t+1] = node ---~ elseif kind == 'inline' then -- appending literals cost too much time ---~ local nodes = node[4] ---~ if #nodes == 1 then ---~ t[#t+1] = nodes[1] ---~ else ---~ do_collapse_page(nodes,t) ---~ end ---~ else ---~ t[#t+1] = node ---~ end ---~ end ---~ end ---~ return t ---~ else ---~ return nil ---~ end ---~ end ---~ ---~ local function do_process_page(attribute,processor,stack) ---~ if stack then ---~ for i, node in ipairs(stack) do ---~ if node then ---~ local kind = node[1] ---~ if kind == 'hlist' or kind == "vlist" then ---~ local content = node[8] ---~ if not content then ---~ -- nil node ---~ elseif type(content) == "table" then ---~ node[8] = do_process_page(attribute,processor,content) ---~ else ---~ node[8] = do_process_page(attribute,processor,tex.get_node_list(content)) ---~ end ---~ elseif kind == 'inline' then ---~ node[4] = do_process_page(attribute,processor,node[4]) ---~ else ---~ processor(attribute,stack,i,node,kind) ---~ end ---~ end ---~ end ---~ end ---~ return stack ---~ end ---~ ---~ function nodes.process_page(stack,...) ---~ if stack then ---~ input.start_timing(nodes) ---~ local done, used = false, { } ---~ for name, plugin in pairs(shipouts.plugins) do ---~ local attribute = attributes.numbers[name] ---~ if attribute then ---~ local initializer = plugin.initializer ---~ local processor = plugin.processor ---~ local finalizer = plugin.finalizer ---~ if initializer then ---~ initializer(attribute,stack) ---~ end ---~ if processor then ---~ do_process_page(attribute,processor,stack) ---~ end ---~ if finalizer then ---~ local ok ---~ ok, used[attribute] = finalizer(attribute,stack) ---~ done = done or ok ---~ end ---~ else ---~ texio.write_nl(string.format("undefined attribute %s",name)) ---~ end ---~ end ---~ if done then ---~ stack = do_collapse_page(stack) ---~ for name, plugin in pairs(shipouts.plugins) do ---~ local attribute = attributes.numbers[name] ---~ if used[attribute] then ---~ local flusher = plugin.flusher ---~ if flusher then ---~ flusher(attribute,stack,used[attribute]) ---~ end ---~ end ---~ end ---~ else ---~ stack = true ---~ end ---~ input.stop_timing(nodes) ---~ end ---~ return stack ---~ end ---~ ---~ function states.finalize(what,attribute,stack) ---~ if what.enabled then ---~ if current > 0 then ---~ local list = stack ---~ if #stack == 1 then ---~ list = stack[#stack][8] ---~ end ---~ list[#list+1], current, done, used[0] = what.none, 0, true, true ---~ end ---~ end ---~ return done, used ---~ end ---~ ---~ function states.process(what,attribute,stack,i,node,kind) ---~ if what.enabled then ---~ local a = node[3] ---~ if a then ---~ local c = a[attribute] ---~ if c then ---~ if current ~= c and (kind == 'glyph' or kind == 'rule') then ---~ stack[i], current, done, used[c] = nodes.inline(what.data[c], node), c, true, true ---~ end ---~ elseif current > 0 then ---~ stack[i], current, done, used[0] = nodes.inline(what.none, node), 0, true, true ---~ end ---~ end ---~ end ---~ end diff --git a/tex/context/base/attr-ini.tex b/tex/context/base/attr-ini.tex index 60746d560..d579429dd 100644 --- a/tex/context/base/attr-ini.tex +++ b/tex/context/base/attr-ini.tex @@ -51,10 +51,15 @@ \defineattribute[mark] \defineattribute[status] +\defineattribute[trigger] % feature inheritance % \defineattribute[language] \defineattribute[skip] \defineattribute[penalty] +\startruntimectxluacode + nodes.trigger = \dogetattributeid{trigger} +\stopruntimectxluacode + % \dosetattribute{status}{1} % temp here / will be indirect ! just for testing @@ -67,8 +72,10 @@ % 1=off 2=gray 3=spot 4=rgb 5=cmyk 6=cmy % only 1/2/4/5 are supported % -% we could combine this in one attribute but this is not faster and also -% less flexible because sometimes we want to freeze the attribute bit +% We could combine this in one attribute but this is not faster and also +% less flexible because sometimes we want to freeze the attribute bit. +% +% Watch out: real color support will be implemented later. \newcount\currentcolormodel @@ -76,51 +83,11 @@ {\currentcolormodel\ctxlua{tex.print(colors.setmodel('colormodel','#1'))}% \dosetattribute{colormodel}{\the\currentcolormodel}} -\setcolormodel{all} % when no color, reset ! ! - -\def\registerrgbcolor#1#2#3#4% r g b -- print or sprint - {\scratchcounter\ctxlua{tex.print(colors.register('color','#1','rgb',#2,#3,#4))}% - \setevalue{(ca:#1)}{\number\scratchcounter}% - \setevalue{(cv:#1)}{\ctxlua{tex.print(colors.filter(\number\scratchcounter))}}% - \setevalue{(cs:#1)}{\dosetattribute{color}{\the\scratchcounter}}} - -\def\registercmykcolor#1#2#3#4#5% c m y k - {\scratchcounter\ctxlua{tex.print(colors.register('color','#1','cmyk',#2,#3,#4,#5))}% - \setevalue{(ca:#1)}{\number\scratchcounter}% - \setevalue{(cv:#1)}{\ctxlua{tex.print(colors.filter(\number\scratchcounter))}}% - \setevalue{(cs:#1)}{\dosetattribute{color}{\the\scratchcounter}}} - -\def\registergraycolor#1#2% s - {\scratchcounter\ctxlua{tex.print(colors.register('color','#1','gray',#2))}% - \setevalue{(ca:#1)}{\number\scratchcounter}% - \setevalue{(cv:#1)}{\ctxlua{tex.print(colors.filter(\number\scratchcounter))}}% - \setevalue{(cs:#1)}{\dosetattribute{color}{\the\scratchcounter}}} - -\def\registerspotcolor#1#2#3% p name - {\scratchcounter\ctxlua{tex.print(colors.register('color','#1','spot',#2,#3))}% - \setevalue{(ca:#1)}{\number\scratchcounter}% - \setevalue{(cv:#1)}{\ctxlua{tex.print(colors.filter(\number\scratchcounter))}}% - \setevalue{(cs:#1)}{\dosetattribute{color}{\the\scratchcounter}}} - -\def\somecolorvalue #1{\csname(cv:#1)\endcsname} -\def\somecolorswitch #1{\csname(cs:#1)\endcsname} -\def\somecolorattribute#1{\csname(ca:#1)\endcsname} - -\def\getMPcolorspec#1% - {\expandafter\expandafter\expandafter\dogetMPcolorspec\csname (cv:#1)\endcsname\relax} - -\def\dogetMPcolorspec#1:#2:#3:#4:#5:#6:#7:#8:#9\relax % some day we will just pass a attribute number in pre/post - {\ifcase\currentcolormodel\or - \ifcase#1\or#2\or(#3,#4,#5)\or(#6,#7,#8,#9)\fi\or#2\or(#3,#4,#5)\or(#6,#7,#8,#9)% - \fi} - -% \registerrgbcolor {red} {1}{0}{0} -% \registerrgbcolor {green} {0}{1}{0} -% \registerrgbcolor {blue} {0}{0}{1} -% \registercmykcolor {cyan} {1}{0}{0}{0} -% \registercmykcolor {magenta} {0}{1}{0}{0} -% \registercmykcolor {yellow} {0}{0}{1}{0} -% \registergraycolor {black} {0} +\setcolormodel{all} + +\def\registerrgbcolor #1#2#3#4{\ctxlua{colors.register('color','#1','rgb' ,#2,#3,#4)}} +\def\registercmykcolor#1#2#3#4#5{\ctxlua{colors.register('color','#1','cmyk',#2,#3,#4,#5)}} +\def\registergraycolor #1#2{\ctxlua{colors.register('color','#1','gray',#2)}} % transparency @@ -139,9 +106,12 @@ \defineattribute[overprint] \def\registeroverprint#1#2% - {\initializePDFoverprint % temp here + {\initializePDFoverprint % temp here, to be tested in la code (states.collect) \setvalue{(os:#1)}{\dosetattribute{overprint}{\ctxlua{tex.print(overprints.register('#2'))}}}} +\def\dotriggeroverprint#1% + {\csname(os:#1)\endcsname} + % \registeroverprint{knockout} {knockout} % \registeroverprint{overprint}{overprint} @@ -150,9 +120,12 @@ \defineattribute[negative] \def\registernegative#1#2% - {\initializePDFnegative % temp here + {\initializePDFnegative % temp here, to be tested in la code (states.collect) \setvalue{(ns:#1)}{\dosetattribute{negative}{\ctxlua{tex.print(negatives.register('#2'))}}}} +\def\dotriggernegative#1% + {\csname(ns:#1)\endcsname} + % \registernegative{positive}{positive} % \registernegative{negative}{negative} @@ -160,8 +133,13 @@ \defineattribute[effect] -\def\registereffect#1% - {\setevalue{(es:#1)}{\dosetattribute{effect}{\ctxlua{tex.print(effects.register('#1'))}}}} +\def\registereffect#1#2#3% #2=stretch #3=rulethickness + {\setxvalue{(es:#1:#2:\number\dimexpr#3\relax)}% + {\dosetattribute{effect}{\ctxlua{tex.print(effects.register('#1',#2,\number\dimexpr#3\relax))}}}} + +\def\dotriggereffect#1#2#3% + {\ifcsname(es:#1:#2:\number\dimexpr#3\relax)\endcsname\else\registereffect{#1}{#2}{#3}\fi + \csname(es:#1:#2:\number\dimexpr#3\relax)\endcsname} % \registereffect{normal} % \registereffect{inner} @@ -186,14 +164,48 @@ % {\ctxlua{nodes.process_page(tex.box[\number\nextbox])}% % \primitive\shipout\box\nextbox}} -\def\processshipoutbox#1% % hack till we have access to pdf backend - {\setbox\nextbox\hbox{#1}% - \ctxlua{nodes.process_page(tex.box[\number\nextbox])}% - \hbox{\ctxlua{states.flush()}\box\nextbox}} +\newbox\finalizedshipoutbox + +\def\finalizeshipoutbox#1% % hack till we have access to pdf backend + {\global\setbox\finalizedshipoutbox\hbox{#1}% + \ctxlua{nodes.process_page(tex.box[\number\finalizedshipoutbox])}% + \hbox{\ctxlua{states.flush()}\box\finalizedshipoutbox}} % \def\shipout % {\dowithnextbox{\ctxlua{tex.primitive('shipout', nodes.process_page(tex.nextbox)}}} \let\normalshipout\shipout +% Objects are processed indepently \unknown\ actually we may need a proper callback. + +\def\finalizeobjectbox#1% + {\ctxlua{nodes.process_page(tex.box[\number#1])}} + +% tricky stuff: + +\newcount\attributeboxcount + +\edef\startinheritattributes{\dosetattribute {trigger}{1}} +\edef\stopinheritattributes {\doresetattribute{trigger}} + +\def\doattributedcopy {\afterassignment\dodoattributedcopy\attributeboxcount} +\def\doattributedbox {\afterassignment\dodoattributedbox \attributeboxcount} + +\def\dodoattributedcopy{\startinheritattributes\ifvbox\attributeboxcount\vbox\else\hbox\fi{\unhcopy\attributeboxcount}\stopinheritattributes} +\def\dodoattributedbox {\startinheritattributes\ifvbox\attributeboxcount\vbox\else\hbox\fi{\unhbox \attributeboxcount}\stopinheritattributes} + +\def\enableattributeinheritance + {\ctxlua{nodes.triggering=true}% + \let\attributedcopy\doattributedcopy + \let\attributedbox \doattributedbox} + +\def\disableattributeinheritance + {\ctxlua{nodes.triggering=false}% + \let\attributedcopy\copy + \let\attributedbox \box} + +\disableattributeinheritance + +% \enableattributeinheritance % will become default + \protect \endinput diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua index 0daa91c0d..d7a2044a2 100644 --- a/tex/context/base/char-ini.lua +++ b/tex/context/base/char-ini.lua @@ -23,10 +23,15 @@ characters = characters or { } characters.data = characters.data or { } characters.context = characters.context or { } -_empty_table_ = { } -_empty_table_.__index = function(t,k) return "" end +do + local _empty_table_ = { __index = function(t,k) return "" end } -setmetatable(characters.data,_empty_table_) + function table.set_empty_metatable(t) + setmetatable(t,_empty_table_) + end +end + +table.set_empty_metatable(characters.data) --[[ldx--

At this point we assume that the big data table is loaded. From this diff --git a/tex/context/base/char-utf.lua b/tex/context/base/char-utf.lua index 79f5718fd..2d11a1794 100644 --- a/tex/context/base/char-utf.lua +++ b/tex/context/base/char-utf.lua @@ -62,7 +62,9 @@ end function characters.filters.utf.collapse(str) if characters.filters.utf.collapsing and str and #str > 1 then - characters.filters.utf.initialize() + if not characters.filters.utf.initialized then -- saves a call + characters.filters.utf.initialize() + end local tokens, first, done = { }, false, false local cg = characters.graphemes for second in string.utfcharacters(str) do @@ -152,7 +154,9 @@ do function characters.filters.utf.collapse(str) if characters.filters.utf.collapsing and str then if #str > 1 then - characters.filters.utf.initialize() + if not characters.filters.utf.initialized then -- saves a call + characters.filters.utf.initialize() + end local tokens, first, done = { }, false, false for second in string.utfcharacters(str) do if cr[second] then @@ -257,7 +261,7 @@ end function characters.filters.process(str) if characters.filters.activated then - for _,v in pairs(characters.filters.sequences) do + for _,v in ipairs(characters.filters.sequences) do str = v(str) end return str diff --git a/tex/context/base/colo-hex.tex b/tex/context/base/colo-hex.tex index b493b8c6b..e60f2a0ae 100644 --- a/tex/context/base/colo-hex.tex +++ b/tex/context/base/colo-hex.tex @@ -11,6 +11,10 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +\beginLUATEX + \endinput +\endLUATEX + \ifx\dodododefinecolor\undefined \beginTEX \endinput \endTEX \else diff --git a/tex/context/base/colo-ini.tex b/tex/context/base/colo-ini.tex index 687d41da3..4e747707f 100644 --- a/tex/context/base/colo-ini.tex +++ b/tex/context/base/colo-ini.tex @@ -13,9 +13,6 @@ \writestatus{loading}{Context Color Macros / initialization} -%D To do: stroke versus fill color -%D 1000 100 10 -> constants - %D Possible optimization: store level in mark instead of name \unprotect @@ -367,7 +364,6 @@ \fi} \def\paletcolorspec#1% -% {\executeifdefined{\??cr\currentpalet#1}{\executeifdefined{\??cr#1}\empty}} {\csname\??cr\currentpalet#1\endcsname} %D Hex color support is not enabled by default. You need to say \type @@ -661,6 +657,12 @@ \newif\ifpermitcolormode \permitcolormodetrue +\def\startregistercolor[#1]% + {\permitcolormodefalse\startcolor[#1]\permitcolormodetrue} + +\def\stopregistercolor + {\permitcolormodefalse\stopcolor\permitcolormodetrue} + \def\dowithcolor#1#2% #1=\action #2=color {\ifincolor\ifpermitcolormode \ifcsname\??cr\currentpalet#2\endcsname @@ -1572,7 +1574,7 @@ g=>\chardef\currentcolorchannel6,% b=>\chardef\currentcolorchannel7,% s=>\chardef\currentcolorchannel8,% - \v!no=>,% \currentcolorchannel0,% all colors + \v!no=>,% \currentcolorchannel0,% all colors \s!default=>,% \currentcolorchannel0,% all colors \s!unknown=>\filterspotcolortrue \edef\currentspotcolor{\commalistelement}]% @@ -1660,6 +1662,13 @@ \expandafter\secondoftwoarguments \fi} +\def\doifcolor#1% + {\ifcsname\??cr\ifcsname\??cr\currentpalet#1\endcsname\currentpalet\fi#1\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + %D \macros %D {localstartcolor,localstopcolor} %D @@ -2191,17 +2200,45 @@ %D don't cross page boundaries in the way color does. Therefore %D we don't need stacks and marks. Just to be compatible with %D color support we offer both 'global' and 'local' commands. +%D +%D \starttyping +%D \def\localstartraster[#1]% +%D {\doifelsenothing{#1} +%D {\dostartgraymode\@@rsscreen} +%D {\dostartgraymode{#1}}} +%D +%D \def\localstopraster +%D {\dostopgraymode} +%D +%D \let\startraster\localstartraster +%D \let\stopraster \localstopraster +%D \stoptyping +%D +%D The next alternative is slower, since it works on top of the +%D color (stack) mechanism, but it does provide nesting. + +\def\dosetrastercolor#1% + {\edef\@@cl@@s{#1}% + \ifx\@@cl@@s\empty + \let\@@cl@@s\@@rsscreen + \fi + \let\@@cl@@t\@@cl@@z % else we get rogue + \let\@@cl@@a\@@cl@@z % transpancies + \setevalue{\??cr\??rs}{\colorSpattern}} + +% beware, don't add extra grouping, else color in tables +% fails \def\localstartraster[#1]% - {\doifelsenothing{#1} - {\dostartgraymode\@@rsscreen} - {\dostartgraymode{#1}}} + {\ifincolor\dosetrastercolor{#1}\localstartcolor[\??rs]\fi} + +\def\startraster[#1]% + {\ifincolor\dosetrastercolor{#1}\startcolor[\??rs]\fi} -\def\localstopraster - {\dostopgraymode} +\def\localstopraster{\ifincolor\localstopcolor\fi} +\def\stopraster {\ifincolor\stopcolor\fi} -\let\startraster\localstartraster -\let\stopraster \localstopraster +\def\raster[#1]{\groupedcommand{\startraster[#1]}{\stopraster}} %D In this documentation we will not go into too much details %D on palets. Curious users can find more information on this @@ -2280,22 +2317,23 @@ {\doifvaluesomething{\??pa#1} {\setevalue{\??pa#1}{\csname\??pa#1\endcsname,}}% \setevalue{\??pa#1}{\csname\??pa#1\endcsname##1}% - \doifassignmentelse{##2} - {% == \definepalet[test][xx={y=.4}] - \definecolor[\??pa#1:##1][##2]% - \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi - {\??cr#1:##1}{\csname\??cr\??pa#1:##1\endcsname}} - {% == \definepalet[test][xx=green] - \doifdefinedelse{\??cr##2} - {\iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi - {\??cr#1:##1}{\csname\??cr##2\endcsname}} - {\letvalue{\??cr#1:##1}\colorXpattern}}}% + \dodefinepaletcolor{#1}{##1}{##2}}% \def\dododefinepalet##1% {\dodododefinepalet[##1]}% \processcommalist[#2]\dododefinepalet} {\doifdefined{\??pa#2} {\expanded{\dodefinepalet[#1][\csname\??pa\??pa#2\endcsname]}}}} +\def\dodefinepaletcolor#1#2#3% + {\doifassignmentelse{#3} + {% == \definepalet[test][xx={y=.4}] + \definecolor[\??pa#1:#2][#3]% + \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{\??cr#1:#2}{\csname\??cr\??pa#1:#2\endcsname}} + {% == \definepalet[test][xx=green] + \doifdefinedelse{\??cr#3} + {\iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{\??cr#1:#2}{\csname\??cr#3\endcsname}} + {\letvalue{\??cr#1:#2}\colorXpattern}}} + \let\paletsize\!!zerocount \def\getpaletsize[#1]% @@ -2386,28 +2424,51 @@ \def\definecolorgroup {\dotripleempty\dodefinecolorgroup} -\def\dodefinecolorgroup[#1][#2][#3]% +% \def\dodefinecolorgroup[#1][#2][#3]% +% {\ifthirdargument +% \processaction +% [#2] +% [ \v!cmyk=>\edef\currentcolorspace{C}, +% \v!rgb=>\edef\currentcolorspace{R}, +% \v!gray=>\edef\currentcolorspace{S}, +% \v!spot=>\edef\currentcolorspace{P}, +% \v!s=>\edef\currentcolorspace{S}, +% \s!unknown=>\edef\currentcolorspace{R}]% +% \colorcount\zerocount +% \def\dododefinecolorgroup##1% +% {\advance\colorcount \plusone +% \setevalue{\??cr#1:\the\colorcount}{\currentcolorspace:##1:0:0}}% +% \processcommalist[#3]\dododefinecolorgroup +% \else +% \doifinstringelse{:}{#2} +% {\definecolorgroup[#1][\v!rgb][#2]} +% {\doloop +% {\doifdefinedelse{\??cr#2:\recurselevel} +% {\setevalue{\??cr#1:\recurselevel}% +% {\csname\??cr#2:\recurselevel\endcsname}} +% {\exitloop}}}% +% \fi} + +\def\dododefinecolorgroupgray [#1][#2:#3]{\definecolor [#1:\the\colorcount][s=#2]} +\def\dododefinecolorgrouprgb [#1][#2:#3:#4:#5]{\definecolor [#1:\the\colorcount][r=#2,g=#3,b=#4]} +\def\dododefinecolorgroupcmyk[#1][#2:#3:#4:#5:#6]{\definecolor [#1:\the\colorcount][c=#2,m=#3=,y=#4,k=#5]} +\def\dododefinecolorgroupspot [#1][#2:#3:#4]{\definespotolor[#1:\the\colorcount][#2][p=#3]} + +\def\dododefinecolorgroup#1#2% + {\advance\colorcount\plusone + \getvalue{dododefinecolorgroup\currentcolorspace}[#1][#2:0:0:0:0]} + +\def\dodefinecolorgroup[#1][#2][#3]% obsolete, just use palets {\ifthirdargument - \processaction - [#2] - [ \v!cmyk=>\edef\currentcolorspace{C}, - \v!rgb=>\edef\currentcolorspace{R}, - \v!gray=>\edef\currentcolorspace{S}, - \v!spot=>\edef\currentcolorspace{P}, - \v!s=>\edef\currentcolorspace{S}, - \s!unknown=>\edef\currentcolorspace{R}]% + \doifelsenothing{#2}{\let\currentcolorspace\v!rgb}{\def\currentcolorspace{#2}}% \colorcount\zerocount - \def\dododefinecolorgroup##1% - {\advance\colorcount \plusone - \setevalue{\??cr#1:\the\colorcount}{\currentcolorspace:##1:0:0}}% - \processcommalist[#3]\dododefinecolorgroup + \processcommalist[#3]{\dododefinecolorgroup{#1}}% \else \doifinstringelse{:}{#2} {\definecolorgroup[#1][\v!rgb][#2]} {\doloop {\doifdefinedelse{\??cr#2:\recurselevel} - {\setevalue{\??cr#1:\recurselevel}% - {\csname\??cr#2:\recurselevel\endcsname}} + {\setevalue{\??cr#1:\recurselevel}{\csname\??cr#2:\recurselevel\endcsname}} {\exitloop}}}% \fi} @@ -2443,11 +2504,11 @@ %D \hbox to \hsize %D {\hss %D \showcolorgroup [red] [vertical,name,number]\hss -%D \showcolorgroup [green] [vertical,name]\hss +%D \showcolorgroup [green] [vertical,name]\hss %D \showcolorgroup [blue] [vertical,name]\hss %D \showcolorgroup [cyan] [vertical,name]\hss -%D \showcolorgroup [magenta] [vertical,name]\hss -%D \showcolorgroup [yellow] [vertical,name]\hss} +%D \showcolorgroup [magenta][vertical,name]\hss +%D \showcolorgroup [yellow] [vertical,name]\hss} %D \stoplinecorrection %D %D These groups are used to define palets {\em alfa} upto {\em @@ -2584,9 +2645,6 @@ \def\doMPcolor#1:% #1 can be \relax ! ! ! i.e. an empty color {\csname MPc\@EA\ifx\csname MPc\string#1\endcsname\relax B\else#1\fi\endcsname} -% \def\doMPcolor#1:% #1 can be \relax ! ! ! i.e. an empty color -% {\csname MPc\ifcsname MPc#1\endcsname#1\else B\fi\endcsname} - \def\MPcR{\doMPrgb} \def\MPcC{\ifMPcmykcolors\@EA\doMPcmykY\else\@EA\doMPcmykN\fi} \def\MPcS{\doMPgray} @@ -2600,8 +2658,6 @@ \def\grayMP {scaledgray} \def\spotMP {spotcolor} -\let\processMP\spotMP % for some time, will become obsolete - \def\doMPtransparent#1#2:#3:#4\end {\ifcase#2\space(#1)\else\transparentMP(#2,#3,(#1))\fi} @@ -2617,12 +2673,6 @@ \def\doMPcmykN#1:#2:#3:#4:#5\end#6\end {\doMPtransparent{\cmykASrgbMP(#1,#2,#3,#4,#6)}#5\end} -% \def\doMPspotY#1:#2:#3\end#4\end -% {\doMPtransparent{\spotMP("#1",#2)}#3\end} -% -% \def\doMPspotN#1:#2:#3\end#4\end -% {\scaledMPcolor{#2}{#1}} - \def\doMPspotY#1:#2:#3:#4:#5\end#6\end % best make #3 same as #1 when empty {\doMPtransparent{multitonecolor("#1",#2,"#3","#4")}#5\end} @@ -2635,6 +2685,8 @@ \def\unknownMPcolor {(0,0,0)} +\let\processMP\spotMP % for some time, will become obsolete, brrr + %D \macros %D {PDFcolor,FDFcolor} %D @@ -2644,30 +2696,6 @@ \def\PDFcolorvalue#1{\handlecolorwith\doPDFcolorvalue\csname\??cr#1\endcsname:::::::\end} \def\FDFcolor #1{\handlecolorwith\doFDFcolor \csname\??cr#1\endcsname:::::::\end} -% \def\doPDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end -% {\if #1R#2 #3 #4 rg% -% \else\if#1C#2 #3 #4 #5 k% -% \else\if#1S#2 g% -% \else\if#1P#3 g% todo -% \else 0 g% -% \fi\fi\fi\fi} -% -% \def\doPDFcolorvalue#1:#2:#3:#4:#5:#6:#7:#8\end -% {\if #1R#2 #3 #4% -% \else\if#1C#2 #3 #4 #5% -% \else\if#1S#2% -% \else\if#1P#3% -% \else 0% -% \fi\fi\fi\fi} -% -% \def\doFDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end -% {[\if #1R#2 #3 #4% -% \else\if#1C#2 #3 #4 #5% -% \else\if#1S#2% -% \else\if#1P#3% todo -% \else 0% -% \fi\fi\fi\fi]} - \def\doPDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end {\if #1R#2 #3 #4 rg% \else\if#1C#2 #3 #4 #5 k% @@ -2795,8 +2823,6 @@ \let\negatedcolorcomponent\firstofoneargument -\beginETEX - \def\negatedcolorcomponent#1% {\ifdim\dimexpr\onepoint-#1\onepoint\relax<\zeropoint \!!zerocount @@ -2807,6 +2833,4 @@ \def\negatecolorcomponent#1% #1 = \macro {\edef#1{\negatedcolorcomponent{#1}}} -\endETEX - \protect \endinput diff --git a/tex/context/base/colo-run.tex b/tex/context/base/colo-run.tex index 0b44f2ee5..9cb797c4d 100644 --- a/tex/context/base/colo-run.tex +++ b/tex/context/base/colo-run.tex @@ -98,7 +98,7 @@ {\dodoubleargument\doshowcolorgroup} \gdef\doshowcolorgroup[#1][#2]% - {\doifdefined{\??cr#1:1} + {\doifcolor{#1:1} {\doifinsetelse\v!vertical{#2} {\showverticalcolorgroup[#1][#2]} {\showhorizontalcolorgroup[#1][#2]}}} @@ -119,8 +119,8 @@ \graycolor[#1:##1]{\vrule\!!width4em\!!height\zeropoint\!!depth\strutdp}\cr \doifinset\v!value{#2}{\colorvalue{#1:##1}\strut}\crcr}} \def\doshowgroup##1% - {\doifdefined{\??cr#1:##1} - {\vbox{\dodoshowgroup{##1}}}} + {\doifcolor{#1:##1} + {\vbox{\dodoshowgroup{##1}}}}% \hbox {\doifinset\v!name{#2} {\strut @@ -137,12 +137,12 @@ \setuppalet \tabskip\zeropoint \def\rule - {\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp} + {\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}% \def\doshowgroup##1% - {\doifdefined{\??cr#1:##1} + {\doifcolor{#1:##1} {\doifinset\v!number{#2}{##1\hskip.5em}& \color[#1:##1]{\rule}\graycolor[#1:##1]{\rule}& - \doifinset\v!value{#2}{\hskip.5em\colorvalue{#1:##1}}\crcr}} + \doifinset\v!value{#2}{\hskip.5em\colorvalue{#1:##1}}\crcr}}% \halign {\hss##&\hss##\hss&##\hss\cr &\doifinset\v!name{#2}{\strut#1}&\crcr @@ -210,7 +210,7 @@ {\dosingleargument\docomparecolorgroup} \gdef\docomparecolorgroup[#1]% - {\doifdefined{\??cr#1:1} + {\doifcolor{#1:1} {\hbox {\dodocomparecolorgroup\color[#1]% \quad @@ -220,7 +220,7 @@ {\localvbox {\!!counta\zerocount \dorecurse{15} - {\doifdefined{\??cr#2:\recurselevel}{\advance\!!counta\plusone}} + {\doifcolor{#2:\recurselevel}{\advance\!!counta\plusone}} \!!widtha2em\relax \hsize\!!counta\!!widtha \def\rule @@ -236,36 +236,37 @@ \endgraf} \dorecurse\!!counta{\dododocomparecolorgroup\recurselevel}}} -% \def\execcolorRCSP#1:{\csname execcolor#1\endcsname} -> \execcolorR - \gdef\dogetcolorcomponents#1% {\doifelsenothing{#1} - {\global\globalscratchtoks{\TB}} - {\startnointerference - \localcolortrue - \def\doexeccolorR ##1:##2:##3:##4:##5\od{\global\globalscratchtoks{\NC\Od#1 \NC\Nm #1 \NC a=\Do##4 \enspace t=\Do##5 \NC r=\Do##1 \enspace g=\Do##2 \enspace b=\Do##3 \NC\NR}}% - \def\doexeccolorC##1:##2:##3:##4:##5:##6\od{\global\globalscratchtoks{\NC\Od#1 \NC\Nm #1 \NC a=\Do##5 \enspace t=\Do##6 \NC c=\Do##1 \enspace m=\Do##2 \enspace y=\Do##3 \enspace k=\Do##4 \NC\NR}}% - \def\doexeccolorS ##1:##2:##3\od{\global\globalscratchtoks{\NC\Od#1 \NC\Nm #1 \NC a=\Do##2 \enspace t=\Do##3 \NC s=\Do##1 \NC\NR}}% - %\def\doexeccolorP##1:##2:##3:##4:##5:##6\od{\global\globalscratchtoks{\NC\Od#1 \NC\Nm #1 \NC a=\Do##5 \enspace t=\Do##6 \NC p=\Do##4 \enspace f=\Do##2 \enspace d=\Do##3 \enspace n=##1 \NC\NR}}% - \def\doexeccolorP##1:##2:##3:##4:##5:##6\od{\global\globalscratchtoks{\NC\Od#1 \NC\Nm #1 \NC a=\Do##5 \enspace t=\Do##6 \NC p=\Do##4 \enspace n=##1 \NC\NR}}% - \let\doexeccolorPindex\doexeccolorP - \backgroundline[#1]{}% - \stopnointerference}% - \appendetoks\the\globalscratchtoks\to\scratchtoks} + {\appendtoks + \TB + \to \scratchtoks} + {\appendtoks + \NC\showcolorbar[#1]\NC#1\NC\transparencycomponents{#1}\NC\colorcomponents{#1}\NC \NR + \to \scratchtoks}} + +% \gdef\showcolorcomponents[#1]% +% {\bgroup +% \def\bars##1{\backgroundline[##1]{\strut\enspace\color[white]{white}\enspace\color[black]{black}\enspace}}% +% \scratchtoks\emptytoks +% \appendtoks\starttabulate[|l|l|l|l|]\to\scratchtoks +% \appendtoks\NC color \NC name \NC transparency \NC specification \NC\NR\TB\to\scratchtoks +% \processcommacommand[#1]\dogetcolorcomponents +% \appendtoks\stoptabulate\to\scratchtoks +% \tt\the\scratchtoks +% \egroup} -\newdimen\colorcomponentwidth % for my eyes only +\gdef\showcolorbar[#1]% + {\backgroundline[#1]{\strut\enspace\color[white]{white}\enspace\color[black]{black}\enspace}} \gdef\showcolorcomponents[#1]% - {\bgroup - \def\Od##1 {\backgroundline[##1]{\strut\enspace\color[white]{white}\enspace\color[black]{black}\enspace}}% - \def\Do##1 {\twodigitrounding{##1}}% - \def\Nm##1 {\ifdim\colorcomponentwidth>\zeropoint\hbox to \colorcomponentwidth\fi{##1}}% - \scratchtoks\emptytoks - \appendtoks\starttabulate[|l|l|l|p|]\to\scratchtoks - \appendtoks\NC color \NC name \NC transparency \NC specification \NC\NR\TB\to\scratchtoks + {\begingroup + \scratchtoks{\TB}% \processcommacommand[#1]\dogetcolorcomponents - \appendtoks\stoptabulate\to\scratchtoks - \tt\the\scratchtoks - \egroup} + \starttabulate[|lT|lT|lT|lT|] + \NC color \NC name \NC transparency \NC specification \NC\NR + \the\scratchtoks + \stoptabulate + \endgroup} \protect \endinput diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv index 0a4803c4a..a3296003a 100644 --- a/tex/context/base/cont-new.mkiv +++ b/tex/context/base/cont-new.mkiv @@ -15,7 +15,7 @@ \writestatus\m!lua{tfm over afm, wide fonts not yet supported} \to \everystoptext -\ctxlua { fonts.define.method = 2 } % normally 3 +% \ctxlua { fonts.define.method = 2 } % normally 3 \unprotect @@ -26,21 +26,30 @@ % texmf.instance will become just texmf \appendtoks - \writestatus\m!lua{input load time - \ctxlua{input.loadtime(texmf.instance)} seconds}% - \writestatus\m!lua{fonts load time - \ctxlua{input.loadtime(fonts)} seconds}% - \writestatus\m!lua{mps conversion time - \ctxlua{input.loadtime(mptopdf)} seconds}% - \writestatus\m!lua{node processing time - \ctxlua{input.loadtime(nodes)} second}% - \writestatus\m!lua{used config path - \ctxlua{tex.print(cache.configpath(texmf.instance))}}% - \writestatus\m!lua{used cache path - \ctxlua{tex.print(cache.path)}}% - \writestatus\m!lua{modules/dumps/instances - \ctxlua{tex.print((status.luabytecodes-500).."/"..input.storage.done.."/"..status.luastates)}}% - \writestatus\m!lua{current memory usage - \ctxlua{tex.print(status.luastate_bytes)} bytes}% - \writestatus\m!lua{loaded fonts - \ctxlua{tex.print(fonts.logger.report())}}% + \writestatus\m!lua{input load time - \ctxlua{input.loadtime(texmf.instance)} seconds}% + \writestatus\m!lua{fonts load time - \ctxlua{input.loadtime(fonts)} seconds}% + \writestatus\m!lua{mps conversion time - \ctxlua{input.loadtime(mptopdf)} seconds}% + \writestatus\m!lua{node processing time - \ctxlua{input.loadtime(nodes)} seconds}% + \writestatus\m!lua{attribute processing time - \ctxlua{input.loadtime(attributes)} seconds}% + \writestatus\m!lua{used config path - \ctxlua{tex.print(caches.configpath(texmf.instance))}}% + \writestatus\m!lua{used cache path - \ctxlua{tex.print(caches.path)}}% + \writestatus\m!lua{modules/dumps/instances - \ctxlua{tex.print((status.luabytecodes-500).."/"..input.storage.done.."/"..status.luastates)}}% + \writestatus\m!lua{current memory usage - \ctxlua{tex.print(status.luastate_bytes)} bytes}% + \writestatus\m!lua{loaded fonts - \ctxlua{tex.print(fonts.logger.report())}}% \to \everystoptext \def\resettimer {\ctxlua{environment.starttime = os.clock()}} \def\elapsedtime {\ctxlua{tex.sprint(os.clock()-environment.starttime)}} \let\elapsedseconds \elapsedtime +%D For me. + +\def\traceluausage + {\ctxlua{debugger.enable()}% + \appendtoks + \ctxlua{debugger.disable() debugger.showstats(texio.write,5000)}% + \to \everybye} + %D Fonts (experimental AFM loading} % \ctxlua { @@ -56,10 +65,7 @@ \appendtoksonce \loadallXfontmapfiles \to \everystarttext \appendtoksonce \loadallXfontmapfiles \to \everybeforepagebody -\def\loadallXfontmapfiles{\ctxlua { - local s = fonts.map.flushlines("pdftex","") - tex.sprint(tex.ctxcatcodes,s) -}} +\def\loadallXfontmapfiles{\ctxlua{fonts.map.flush("pdftex")}} % \ctxlua{ % do @@ -95,3 +101,6 @@ % } \protect \endinput + +% \expanded{\defineactivecharacter \number"2000E} {\textdir TRT\relax} +% \expanded{\defineactivecharacter \number"2000F} {\textdir TLT\relax} diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex index 0ee61b10a..906eabec9 100644 --- a/tex/context/base/cont-new.tex +++ b/tex/context/base/cont-new.tex @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2007.08.09 13:04} +\newcontextversion{2007.08.20 10:21} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new @@ -31,6 +31,31 @@ \let\then\relax % \ifnum1>2\then -) +% \setupcaption [figure] [align=flushleft] +% \setupcaption [figure-1] [align=flushleft,leftmargin=10mm] +% \setupcaption [figure-2] [align=flushleft,leftmargin=10mm,rightmargin=-10mm,width=\textwidth] +% +% \startsetups somefigure +% \ifdim\floatsetupwidth>\textwidth +% \placesetupfloat[figure-2] +% \else +% \placesetupfloat[figure-1] +% \fi +% \stopsetups +% +% \placefloatwithsetups[somefigure]{}{\externalfigure[dummy][width=5cm,height=2cm]} + +\def\placefloatwithsetups + {\dotripleempty\doplacefloatwithsetups} + +\def\doplacefloatwithsetups[#1][#2][#3]#4% + {\def\floatsetupcaption {#4}% + \def\floatsetupcontent {\copy\nextbox}% + \def\floatsetupwidth {\wd\nextbox}% + \def\floatsetupheight {\ht\nextbox}% + \def\placesetupfloat[##1]{\placefloat[##1][#2][#3]{\floatsetupcaption}{\floatsetupcontent}}% + \dowithnextbox{\setups[#1]}\vbox} + \chardef\baselinegridmode=0 % option in layout / 1=permit_half_lines \def\dodosetupwhitespace @@ -1763,32 +1788,6 @@ \setinnerparpositions % see "techniek" for application \to \everytabulate -%D This alternative is slower, since it works on top of the -%D color (stack) mechanism, but it does provide nesting. - -\def\dosetrastercolor#1% - {\edef\@@cl@@s{#1}% - \ifx\@@cl@@s\empty - \let\@@cl@@s\@@rsscreen - \fi - \let\@@cl@@t\@@cl@@z % else we get rogue - \let\@@cl@@a\@@cl@@z % transpancies - \setevalue{\??cr\??rs}{\colorSpattern}} - -% beware, don't add extra grouping, else color in tables -% fails - -\def\localstartraster[#1]% - {\ifincolor\dosetrastercolor{#1}\localstartcolor[\??rs]\fi} - -\def\startraster[#1]% - {\ifincolor\dosetrastercolor{#1}\startcolor[\??rs]\fi} - -\def\localstopraster{\ifincolor\localstopcolor\fi} -\def\stopraster {\ifincolor\stopcolor\fi} - -\def\raster[#1]{\groupedcommand{\startraster[#1]}{\stopraster}} - \def\fontclassname#1#2% {\ifcsname\??ff#1#2\endcsname \fontclassname{#1}{\csname\??ff#1#2\endcsname}% diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex index 541ae1ead..024af80f5 100644 --- a/tex/context/base/context.tex +++ b/tex/context/base/context.tex @@ -42,7 +42,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2007.08.09 13:04} +\edef\contextversion{2007.08.20 10:21} %D For those who want to use this: @@ -208,7 +208,6 @@ \loadmkivfile{attr-ini.tex} \loadmkivfile{node-ini.tex} - %D We also use some third party macros. These are loaded by %D saying: @@ -300,7 +299,7 @@ \loadcorefile{spec-def.tex} \loadcorefile{spec-var.tex} -\loadcorefile{colo-ini.tex} +\doiffileelse{colo-new.tex}{\loadcorefile{colo-new.tex}}{\loadcorefile{colo-ini.tex}} \loadcorefile{colo-ext.tex} %D For the moment we load a lot of languages. In the future @@ -481,6 +480,8 @@ %D These macros are loaded last since they overload and|/|or %D extend previously defined ones. +\loadmkivfile{lxml-ini.tex} + \loadcorefile{xtag-ini.tex} \loadcorefile{xtag-ext.tex} \loadcorefile{xtag-prs.tex} @@ -625,8 +626,8 @@ \unprotect \beginLUATEX \appendtoks - \writestatus\m!lua{used config path - \ctxlua{tex.print(cache.configpath(texmf.instance))}}% - \writestatus\m!lua{used cache path - \ctxlua{tex.print(cache.path)}}% + \writestatus\m!lua{used config path - \ctxlua{tex.print(caches.configpath(texmf.instance))}}% + \writestatus\m!lua{used cache path - \ctxlua{tex.print(caches.path)}}% \to \everydump \endLUATEX \protect diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua index 349d33688..b6af6be9a 100644 --- a/tex/context/base/core-con.lua +++ b/tex/context/base/core-con.lua @@ -14,10 +14,10 @@ slower but look nicer this way.

Some code may move to a module in the language namespace.

--ldx]]-- -convert = convert or { } -language = language or { } +converters = converters or { } +languages = languages or { } -language.counters = { +languages.counters = { ['**'] = { 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, @@ -70,95 +70,99 @@ language.counters = { } } -function convert.chr(n, m) +function converters.chr(n, m) if n > 0 and n < 27 then tex.sprint(string.char(n+m)) end end -function convert.maxchrs(n,m,cmd) +function converters.maxchrs(n,m,cmd) if n <= m then tex.sprint(tex.texcatcodes, cmd .. "{" .. n .. "}") else - convert.maxchrs(math.floor((n-1)/m),m,cmd) + converters.maxchrs(math.floor((n-1)/m),m,cmd) tex.sprint(tex.texcatcodes, cmd .. "{" .. ((n-1)%m + 1) .. "}") end end -function convert.chrs(n,m) +function converters.chrs(n,m) if n <= 26 then tex.sprint(string.char(n+m)) else - convert.chrs(math.floor((n-1)/26),m) + converters.chrs(math.floor((n-1)/26),m) tex.sprint(string.char(((n-1)%26 + 1)+m)) end end -function convert.alphabetic(n,code) - local code = language.counters[code] or language.counters['**'] - convert.do_alphabetic(n,#code,function(n) return code[n] end) -end +do -function convert.Alphabetic(n,code) - local code = language.counters[code] or language.counters['**'] - convert.do_alphabetic(n,#code,function(n) return characters.uccode(code[n]) end) -end + local function do_alphabetic(n,max,chr) + if n <= max then + characters.flush(chr(n)) + else + do_alphabetic(math.floor((n-1)/max),max,chr) + characters.flush(chr((n-1)%max+1)) + end + end -function convert.do_alphabetic(n,max,chr) - if n <= max then - characters.flush(chr(n)) - else - convert.do_alphabetic(math.floor((n-1)/max),max,chr) - characters.flush(chr((n-1)%max+1)) + function converters.alphabetic(n,code) + local code = languages.counters[code] or languages.counters['**'] + do_alphabetic(n,#code,function(n) return code[n] end) end + + function converters.Alphabetic(n,code) + local code = languages.counters[code] or languages.counters['**'] + do_alphabetic(n,#code,function(n) return characters.uccode(code[n]) end) + end + end -function convert.character(n) convert.chr (n,96) end -function convert.Character(n) convert.chr (n,64) end -function convert.characters(n) convert.chrs(n,96) end -function convert.Characters(n) convert.chrs(n,64) end +function converters.character(n) converters.chr (n,96) end +function converters.Character(n) converters.chr (n,64) end +function converters.characters(n) converters.chrs(n,96) end +function converters.Characters(n) converters.chrs(n,64) end -function convert.weekday(year,month,day) +function converters.weekday(year,month,day) tex.sprint(os.date("%w",os.time{year=year,month=month,day=day})+1) end -function convert.lpy(year) +function converters.lpy(year) return (year % 400 == 0) or ((year % 100 ~= 0) and (year % 4 == 0)) end -function convert.leapyear(year) - if convert.lpy(year) then tex.sprint(1) else tex.sprint(0) end +function converters.leapyear(year) + if converters.lpy(year) then tex.sprint(1) else tex.sprint(0) end end -convert.mth = { +converters.mth = { [false] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, [true] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } } -function convert.nofdays(year,month) - tex.sprint(convert.mth[convert.lpy(year)][month]) +function converters.nofdays(year,month) + tex.sprint(converters.mth[converters.lpy(year)][month]) end -function convert.year () tex.sprint(os.date("%Y")) end -function convert.month () tex.sprint(os.date("%m")) end -function convert.hour () tex.sprint(os.date("%H")) end -function convert.minute () tex.sprint(os.date("%M")) end -function convert.second () tex.sprint(os.date("%S")) end -function convert.textime() tex.sprint(tonumber(os.date("%H"))*60+tonumber(os.date("%M"))) end +function converters.year () tex.sprint(os.date("%Y")) end +function converters.month () tex.sprint(os.date("%m")) end +function converters.hour () tex.sprint(os.date("%H")) end +function converters.minute () tex.sprint(os.date("%M")) end +function converters.second () tex.sprint(os.date("%S")) end +function converters.textime() tex.sprint(tonumber(os.date("%H"))*60+tonumber(os.date("%M"))) end -convert.rom = { +converters.rom = { { [0] = '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' }, { [0] = '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC' }, { [0] = '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM' }, } -function convert.toroman(n) +function converters.toroman(n) if n >= 4000 then - return convert.toroman(math.floor(n/1000)) .. " " .. convert.toroman(n%1000) + return converters.toroman(math.floor(n/1000)) .. " " .. converters.toroman(n%1000) else - return string.rep("M",math.floor(n/1000)) .. convert.rom[3][math.floor((n%1000)/100)] .. - convert.rom[2][math.floor((n%100)/10)] .. convert.rom[1][math.floor((n% 10)/1)] + return string.rep("M",math.floor(n/1000)) .. converters.rom[3][math.floor((n%1000)/100)] .. + converters.rom[2][math.floor((n%100)/10)] .. converters.rom[1][math.floor((n% 10)/1)] end end -function convert.romannumerals(n) return tex.sprint(string.tolower(convert.toroman(n))) end -function convert.Romannumerals(n) return tex.sprint( convert.toroman(n) ) end +function converters.romannumerals(n) return tex.sprint(string.lower(converters.toroman(n))) end +function converters.Romannumerals(n) return tex.sprint( converters.toroman(n) ) end diff --git a/tex/context/base/core-con.mkiv b/tex/context/base/core-con.mkiv index afed14f1d..390f9c595 100644 --- a/tex/context/base/core-con.mkiv +++ b/tex/context/base/core-con.mkiv @@ -15,47 +15,47 @@ \registerctxluafile{core-con}{1.001} -\def\romannumerals#1{\ctxlua{convert.romannumerals(\number#1)}} -\def\Romannumerals#1{\ctxlua{convert.Romannumerals(\number#1)}} +\def\romannumerals#1{\ctxlua{converters.romannumerals(\number#1)}} +\def\Romannumerals#1{\ctxlua{converters.Romannumerals(\number#1)}} -\def\greeknumerals#1{\ctxlua{convert.alphabetic(\number#1,"gr")}} -\def\Greeknumerals#1{\ctxlua{convert.Alphabetic(\number#1,"gr")}} +\def\greeknumerals#1{\ctxlua{converters.alphabetic(\number#1,"gr")}} +\def\Greeknumerals#1{\ctxlua{converters.Alphabetic(\number#1,"gr")}} -\def\character #1{\ctxlua{convert.character (\number#1)}} -\def\Character #1{\ctxlua{convert.Character (\number#1)}} -\def\characters#1{\ctxlua{convert.characters(\number#1)}} -\def\Characters#1{\ctxlua{convert.Characters(\number#1)}} +\def\character #1{\ctxlua{converters.character (\number#1)}} +\def\Character #1{\ctxlua{converters.Character (\number#1)}} +\def\characters#1{\ctxlua{converters.characters(\number#1)}} +\def\Characters#1{\ctxlua{converters.Characters(\number#1)}} -\def\languagecharacters#1{\ctxlua{convert.alphabetic(\number#1,"\currentlanguage")}} % new -\def\languageCharacters#1{\ctxlua{convert.Alphabetic(\number#1,"\currentlanguage")}} % new +\def\languagecharacters#1{\ctxlua{converters.alphabetic(\number#1,"\currentlanguage")}} % new +\def\languageCharacters#1{\ctxlua{converters.Alphabetic(\number#1,"\currentlanguage")}} % new -\def\getdayoftheweek#1#2#3{\normalweekday\ctxlua{convert.weekday(\number#1,\number#2,\number#3)}} -\def\dayoftheweek #1#2#3{\doconvertday{\ctxlua{convert.weekday(\number#1,\number#2,\number#3)}}} +\def\getdayoftheweek#1#2#3{\normalweekday\ctxlua{converters.weekday(\number#1,\number#2,\number#3)}} +\def\dayoftheweek #1#2#3{\doconvertday{\ctxlua{converters.weekday(\number#1,\number#2,\number#3)}}} \def\doifleapyearelse#1% - {\ifcase\ctxlua{convert.leapyear(\number#1)} + {\ifcase\ctxlua{converters.leapyear(\number#1)} \@EA\secondoftwoarguments \else \@EA\firstoftwoarguments \fi} \def\getdayspermonth#1#2% - {\edef\numberofdays{\ctxlua{convert.nofdays(\number#1,\number#2)}}} + {\edef\numberofdays{\ctxlua{converters.nofdays(\number#1,\number#2)}}} \def\dayspermonth#1#2% - {\ctxlua{convert.nofdays(\number#1,\number#2)}} + {\ctxlua{converters.nofdays(\number#1,\number#2)}} \def\calculatecurrenttime - {\edef\currenthour {\ctxlua{convert.hour ()}}% - \edef\currentminute{\ctxlua{convert.minute()}}% - \edef\currentsecond{\ctxlua{convert.second()}}} + {\edef\currenthour {\ctxlua{converters.hour ()}}% + \edef\currentminute{\ctxlua{converters.minute()}}% + \edef\currentsecond{\ctxlua{converters.second()}}} % problem is that we calculate with those numbers % -% \def\time {\numexpr\ctxlua{convert.textime()}\relax} -% \def\year {\numexpr\ctxlua{convert.year ()}\relax} -% \def\month{\numexpr\ctxlua{convert.month ()}\relax} -% \def\day {\numexpr\ctxlua{convert.day ()}\relax} +% \def\time {\numexpr\ctxlua{converters.textime()}\relax} +% \def\year {\numexpr\ctxlua{converters.year ()}\relax} +% \def\month{\numexpr\ctxlua{converters.month ()}\relax} +% \def\day {\numexpr\ctxlua{converters.day ()}\relax} % \dayoftheweek{2006}{9}{15} % \doifleapyearelse{2000}{OK}{NOT OK} @@ -67,17 +67,17 @@ % we could use an auxiliary macro to save some bytes in the format % -% \def\dolanguagecharacters#1#2{\ctxlua{convert.alphabetic(\number#2,"#1")}} +% \def\dolanguagecharacters#1#2{\ctxlua{converters.alphabetic(\number#2,"#1")}} % this does not belong here, but in a lang-module -\def\arabicnumerals #1{\ctxlua{convert.alphabetic(\number#1,"arabic")}} -\def\persiannumerals #1{\ctxlua{convert.alphabetic(\number#1,"persian")}} -\def\thainumerals #1{\ctxlua{convert.alphabetic(\number#1,"thai")}} -\def\devanagarinumerals#1{\ctxlua{convert.alphabetic(\number#1,"devanagari")}} -\def\gurmurkhinumerals #1{\ctxlua{convert.alphabetic(\number#1,"gurmurkhi")}} -\def\gujaratinumerals #1{\ctxlua{convert.alphabetic(\number#1,"gujarati")}} -\def\tibetannumerals #1{\ctxlua{convert.alphabetic(\number#1,"tibetan")}} +\def\arabicnumerals #1{\ctxlua{converters.alphabetic(\number#1,"arabic")}} +\def\persiannumerals #1{\ctxlua{converters.alphabetic(\number#1,"persian")}} +\def\thainumerals #1{\ctxlua{converters.alphabetic(\number#1,"thai")}} +\def\devanagarinumerals#1{\ctxlua{converters.alphabetic(\number#1,"devanagari")}} +\def\gurmurkhinumerals #1{\ctxlua{converters.alphabetic(\number#1,"gurmurkhi")}} +\def\gujaratinumerals #1{\ctxlua{converters.alphabetic(\number#1,"gujarati")}} +\def\tibetannumerals #1{\ctxlua{converters.alphabetic(\number#1,"tibetan")}} \defineconversion[arabicnumerals] [\arabicnumerals] \defineconversion[persiannumerals] [\persiannumerals] diff --git a/tex/context/base/core-mat.tex b/tex/context/base/core-mat.tex index c73ee1cca..b994580f9 100644 --- a/tex/context/base/core-mat.tex +++ b/tex/context/base/core-mat.tex @@ -2308,7 +2308,7 @@ \tabskip\zeropoint \eqaligncolumn\zerocount % could be \scratchcounter \processcommacommand[\mathmatrixparameter\c!align]{\advance\eqaligncolumn\plusone\dosetmatrixcolumn}% - \scratchcounter=\ifnum\eqaligncolumn>\scratchcounter \eqaligncolumn \else \plusone \fi + \scratchcounter=\ifnum\eqaligncolumn>\zerocount \eqaligncolumn \else \plusone \fi \global\eqaligncolumn\plusone \preparemathmatrix } % uses scratchcounter diff --git a/tex/context/base/core-obj.tex b/tex/context/base/core-obj.tex index d8de15133..a1b0796d1 100644 --- a/tex/context/base/core-obj.tex +++ b/tex/context/base/core-obj.tex @@ -118,6 +118,16 @@ {\checkobjectreferences \letbeundefined{\r!object#1::#2}} +%D \macros +%D {finalizeobjectbox} +%D +%D This one provides a hook for last minute object box processing +%D we need this in \MKIV. + +\ifx\finalizeobjectbox\undefined + \let\finalizeobjectbox\gobbleoneargument +\fi + %D Somehow there is a rounding error problem in either \PDFTEX\ %D or in viewers, or maybe it is conforming the specs. The next %D variable compensate for it by removing the rather tight diff --git a/tex/context/base/core-rul.tex b/tex/context/base/core-rul.tex index 696f3f01c..ea6ff441c 100644 --- a/tex/context/base/core-rul.tex +++ b/tex/context/base/core-rul.tex @@ -482,7 +482,34 @@ %D by \TEX\ itself, the latter one depends on the driver. This %D macro also support a negative offset. -\def\dooutlinebox +% \def\dooutlinebox +% {\setbox\framebox\vbox % rules on top of box +% {\scratchdimen \framedparameter\c!frameoffset\relax +% \frameddimenwd\dimexpr\wd\framebox+2\scratchdimen\relax +% \frameddimenht\dimexpr\ht\framebox+ \scratchdimen\relax +% \frameddimendp\dimexpr\dp\framebox+ \scratchdimen+\framedparameter\c!framedepth\relax +% \ifdim\frameddimendp<\zeropoint +% \advance\frameddimenht \frameddimendp +% \scratchdimen-\frameddimendp +% \frameddimendp\zeropoint +% \else +% \scratchdimen\zeropoint +% \fi +% \setbox\extraframebox\hbox +% {\dostrokedbox}% +% \setbox\extraframebox\hbox +% {\raise\scratchdimen\vbox +% {\moveleft\framedparameter\c!frameoffset\box\extraframebox}}% +% \wd\extraframebox\wd\framebox +% \ht\extraframebox\ht\framebox +% \dp\extraframebox\dp\framebox +% \hbox +% {\box\framebox\hskip-\wd\extraframebox +% \doifsomething{\framedparameter\c!framecolor}% no else needed, +% {\color[\framedparameter\c!framecolor]}% % +% {\box\extraframebox}}}} % but {} here + +\def\dooutlinebox % we needed to move the color command in order to apply attributes properly {\setbox\framebox\vbox % rules on top of box {\scratchdimen \framedparameter\c!frameoffset\relax \frameddimenwd\dimexpr\wd\framebox+2\scratchdimen\relax @@ -496,18 +523,15 @@ \scratchdimen\zeropoint \fi \setbox\extraframebox\hbox - {\dostrokedbox}% + {\doifsomething{\framedparameter\c!framecolor}{\color[\framedparameter\c!framecolor]}{\dostrokedbox}}% \setbox\extraframebox\hbox {\raise\scratchdimen\vbox - {\moveleft\framedparameter\c!frameoffset\box\extraframebox}}% + {\moveleft\framedparameter\c!frameoffset + \box\extraframebox}}% \wd\extraframebox\wd\framebox \ht\extraframebox\ht\framebox \dp\extraframebox\dp\framebox - \hbox - {\box\framebox\hskip-\wd\extraframebox - \doifsomething{\framedparameter\c!framecolor}% no else needed, - {\color[\framedparameter\c!framecolor]}% % - {\box\extraframebox}}}} % but {} here + \hbox{\box\framebox\hskip-\wd\extraframebox\box\extraframebox}}} \def\dostrokedbox {\doifelse{\framedparameter\c!framecorner}\v!rectangular @@ -779,8 +803,6 @@ \fi % new, experimental dirty hook \framedparameter\c!extras - % we need to register the (outer) color - \startregistercolor[\framedparameter\c!foregroundcolor]% % to get the right spacing \doifvaluesomething{\@@framed\c!foregroundstyle} {\@EA\doconvertfont\csname\@@framed\c!foregroundstyle\endcsname\empty}% @@ -912,9 +934,9 @@ \else\ifx\localstrut\v!local \setfontstrut \else + \setstrut \fi\fi\fi \ifboxhasstrut - \setstrut \let\localbegstrut\begstrut \let\localendstrut\endstrut \let\localstrut \strut @@ -977,6 +999,8 @@ {\ifdim\!!framedwidth >\zeropoint\the\!!framedwidth \else\zeropoint\fi}% \edef\framedheight% a new feature, visible for user {\ifdim\!!framedheight>\zeropoint\the\!!framedheight\else\zeropoint\fi}% + % we need to register the (outer) color + \startregistercolor[\framedparameter\c!foregroundcolor]% % first alternative %\def\dowithframedbox% % {\let\postprocessframebox\relax %new @@ -989,7 +1013,6 @@ % \let\postprocessframebox\relax %new % \stoplocalframed} % \next} - % third alternative \@@startframedorientation \afterassignment\dodowithframebox \setbox\framebox\next} @@ -1039,6 +1062,7 @@ \def\stoplocalframed {\dontshowcomposition \@@stopframedorientation % hm, wrong place ! should rotatethe result (after reshape) + \stopregistercolor \handleframedlocator\c!before\@@locallocation \ifboxhasformat \ifx\@@localautowidth\v!force @@ -1071,7 +1095,6 @@ \ht\scratchbox\ht\framebox \dp\scratchbox\dp\framebox \setbox\framebox\box\scratchbox}% - \stopregistercolor \docolorframebox \ifboxhasoffset \dooffsetframebox diff --git a/tex/context/base/core-sec.tex b/tex/context/base/core-sec.tex index b92fbb21c..79ee538d7 100644 --- a/tex/context/base/core-sec.tex +++ b/tex/context/base/core-sec.tex @@ -1196,22 +1196,32 @@ \dosomebreak{\penalty\!!counta}% \egroup} +\newconditional\ignorehandlepagebreak + \def\handlepagebreak#1% - {\dohandlepagebreakAA{#1}% - \ifnum\countervalue{\??se\previoussection\@@sectie}>\zerocount\relax - \ifnum\countervalue{\??se\@@sectie}>\zerocount - \dohandlepagebreakB{#1}% + {\ifconditional\ignorehandlepagebreak + \setfalse\ignorehandlepagebreak + \else + \dohandlepagebreakAA{#1}% + \ifnum\countervalue{\??se\previoussection\@@sectie}>\zerocount\relax + \ifnum\countervalue{\??se\@@sectie}>\zerocount + \dohandlepagebreakB{#1}% + \else + \doifnotvalue{\??ko#1\c!continue}\v!yes{\dohandlepagebreakB{#1}}% + \fi \else - \doifnotvalue{\??ko#1\c!continue}\v!yes{\dohandlepagebreakB{#1}}% + \dohandlepagebreakB{#1}% \fi - \else - \dohandlepagebreakB{#1}% - \fi - \dohandlepagebreakAB{#1}} + \dohandlepagebreakAB{#1}% + \fi} -\def\handlepagebreakC#1% - {\xdef\@@kolevel{\getvalue{\??se\@@sectie\c!level}}% - \nobreak} +\def\handlenopagebreak#1% + {\ifconditional\ignorehandlepagebreak + \setfalse\ignorehandlepagebreak + \else + \xdef\@@kolevel{\getvalue{\??se\@@sectie\c!level}}% + \nobreak + \fi} \def\localheadheight {\strutht} \def\localheaddepth {\strutdp} @@ -1419,6 +1429,8 @@ % todo: write to list etc in both args or in enclosing h/vbox else it gets % lost when no #1 or #2 is typeset +% we will use variables here + \def\dodododoconstructhead#1[#2]#3#4% [ref] {number} {title} {\def\currenthead{#1}% dus #1 overal vervangen \let\finalsectionnumber\dofinalsectionnumber % overloaded ungrouped -) @@ -1641,6 +1653,7 @@ \fi \flushingcolumnfloatstrue \someheadconversionfalse + \setfalse\ignorehandlepagebreak \let\fullsectionnumber\limitedfullsectionnumber % ignorespaces prevents spaces creeping in when after=\dontleavehmode \ifdisplaysectionhead\ignorespaces\else\expandafter\GotoPar\fi} @@ -2052,7 +2065,7 @@ {\ifhmode \scratchcounter=\lastpenalty\unpenalty % no beauty in this \ifdim\lastskip=\headsignal - \handlepagebreakC{#1}% + \handlenopagebreak{#1}% \global\settrue\continuoussectionhead \else \penalty\scratchcounter diff --git a/tex/context/base/core-spa.lua b/tex/context/base/core-spa.lua index c6090ab13..586a90d3d 100644 --- a/tex/context/base/core-spa.lua +++ b/tex/context/base/core-spa.lua @@ -238,8 +238,10 @@ do end end - function collapser(head,where) - if head then + -- local free = node.free + + local function collapser(head,where) + if head and head.next then local trace = nodes.trace_collapse local current, tail = head, nil local glue_order, glue_data = 0, nil @@ -364,21 +366,21 @@ do local head, tail = nil, nil function nodes.flush_vertical_spacing() - input.start_timing(nodes) if head then - t = collapser(head) + input.start_timing(nodes) + local t = collapser(head) head = nil -- tail = nil + input.stop_timing(nodes) + return t else - t = nil + return nil end - input.stop_timing(nodes) - return t end function nodes.handle_page_spacing(t, where) -- we need to add the latest t too, else we miss skips and such - if t then + if t and t.next then local tt = node.slide(t) local id = tt.id if id == glue then -- or id == penalty then -- or maybe: if not hlist or vlist @@ -409,8 +411,12 @@ do end function nodes.handle_vbox_spacing(t) - local tail = node.slide(t) - return collapser(t,'whole') + if t and t.next then + local tail = node.slide(t) + return collapser(t,'whole') + else + return t + end end end diff --git a/tex/context/base/core-spa.tex b/tex/context/base/core-spa.tex index 159624c0d..aef7ac698 100644 --- a/tex/context/base/core-spa.tex +++ b/tex/context/base/core-spa.tex @@ -2387,8 +2387,7 @@ \!!height\strutheight \!!depth \strutdepth \hss}}% - \struttotal\strutht - \advance\struttotal\strutdp} + \struttotal\dimexpr\strutht+\strutdp\relax} %D The dimen \type {\struttotal} holds the exact size of the %D strut; occasionally a one scaled point difference can show @@ -3225,52 +3224,31 @@ \beginETEX -% \unexpanded\def\dostartattributes#1#2#3% -% {\begingroup % geen \bgroup, anders in mathmode lege \hbox -% \ifcsname#1#3\endcsname -% \let\dostopattributes\@@dostopattributes -% \startcolor[\csname#1#3\endcsname]% -% \else -% \let\dostopattributes\@@nostopattributes -% \fi -% \ifcsname#1#2\endcsname -% \@EAEAEA\doconvertfont\@EA\@EA\csname#1#2\endcsname -% \fi} -% -% \unexpanded\def\@@dostopattributes% -% {\stopcolor -% \finishparbasedattributes -% \endgroup} -% -% \unexpanded\def\@@nostopattributes% -% {\finishparbasedattributes -% \endgroup} - -\unexpanded\def\dostartattributes#1#2#3% - {\begingroup % geen \bgroup, anders in mathmode lege \hbox - \ifincolor - \ifcsname#1#3\endcsname - \let\dostopattributes\@@dostopattributes - \doglobalstartcolor[\csname#1#3\endcsname]% - \else - \let\dostopattributes\@@nostopattributes - \fi - \else - \let\dostopattributes\@@nostopattributes - \fi - \ifcsname#1#2\endcsname - % \@EAEAEA\doconvertfont\@EA\@EA\csname#1#2\endcsname - \@EA\doconvertfont\csname#1#2\@EA\endcsname - \fi} + \unexpanded\def\dostartattributes#1#2#3% + {\begingroup % geen \bgroup, anders in mathmode lege \hbox + \ifincolor + \ifcsname#1#3\endcsname + \let\dostopattributes\@@dostopattributes + \faststartcolor[\csname#1#3\endcsname]% + \else + \let\dostopattributes\@@nostopattributes + \fi + \else + \let\dostopattributes\@@nostopattributes + \fi + \ifcsname#1#2\endcsname + % \@EAEAEA\doconvertfont\@EA\@EA\csname#1#2\endcsname + \@EA\doconvertfont\csname#1#2\@EA\endcsname + \fi} -\unexpanded\def\@@dostopattributes - {\doglobalstopcolor - \finishparbasedattributes - \endgroup} + \unexpanded\def\@@dostopattributes + {\faststopcolor + \finishparbasedattributes + \endgroup} -\unexpanded\def\@@nostopattributes - {\finishparbasedattributes - \endgroup} + \unexpanded\def\@@nostopattributes + {\finishparbasedattributes + \endgroup} \endETEX @@ -3278,20 +3256,19 @@ \beginTEX -\unexpanded\def\dosetfontattribute#1#2% - {\@EA\ifx\csname#1#2\endcsname\relax\else - \@EAEAEA\doconvertfont\@EA\@EA\csname#1#2\endcsname - \fi\empty} + \unexpanded\def\dosetfontattribute#1#2% + {\@EA\ifx\csname#1#2\endcsname\relax\else + \@EA\doconvertfont\csname#1#2\@EA\endcsname + \fi\empty} \endTEX \beginETEX \ifcsname -\unexpanded\def\dosetfontattribute#1#2% - {\ifcsname#1#2\endcsname - % \@EAEAEA\doconvertfont\@EA\@EA\csname#1#2\endcsname - \@EA\doconvertfont\csname#1#2\@EA\endcsname - \fi\empty} + \unexpanded\def\dosetfontattribute#1#2% + {\ifcsname#1#2\endcsname + \@EA\doconvertfont\csname#1#2\@EA\endcsname + \fi\empty} \endETEX @@ -3300,24 +3277,24 @@ \beginETEX \ifcsname -\unexpanded\def\doattributes#1#2#3#4% - {\begingroup % geen \bgroup, anders in mathmode lege \hbox - \ifincolor - \ifcsname#1#3\endcsname - \let\dostopattributes\@@dostopattributes - \doglobalstartcolor[\csname#1#3\endcsname]% - \else - \let\dostopattributes\endgroup - \fi - \else - \let\dostopattributes\endgroup - \fi - \ifcsname#1#2\endcsname - % \@EAEAEA\doconvertfont\@EA\@EA\csname#1#2\endcsname - \@EA\doconvertfont\csname#1#2\@EA\endcsname - \fi - {#4}% - \dostopattributes} + \unexpanded\def\doattributes#1#2#3#4% + {\begingroup % geen \bgroup, anders in mathmode lege \hbox + \ifincolor + \ifcsname#1#3\endcsname + \let\dostopattributes\@@dostopattributes + \faststartcolor[\csname#1#3\endcsname]% + \else + \let\dostopattributes\endgroup + \fi + \else + \let\dostopattributes\endgroup + \fi + \ifcsname#1#2\endcsname + % \@EAEAEA\doconvertfont\@EA\@EA\csname#1#2\endcsname + \@EA\doconvertfont\csname#1#2\@EA\endcsname + \fi + {#4}% + \dostopattributes} \endETEX @@ -3963,6 +3940,13 @@ \newtoks \everyleftofalignedline \newtoks \everyrightofalignedline +\def\shiftalignedline#1#2#3#4% left, right, inner, outer + {\rightorleftpageaction + {\everyleftofalignedline {\hskip\dimexpr#1+#3\relax}% + \everyrightofalignedline{\hskip\dimexpr#2+#4\relax}} + {\everyleftofalignedline {\hskip\dimexpr#1+#4\relax}% + \everyrightofalignedline{\hskip\dimexpr#2+#3\relax}}} + % \def\doalignline#1#2% \\ == newline % {\begingroup % \setlocalhsize % new diff --git a/tex/context/base/core-tab.tex b/tex/context/base/core-tab.tex index 5828e85f7..edfa4b27b 100644 --- a/tex/context/base/core-tab.tex +++ b/tex/context/base/core-tab.tex @@ -366,13 +366,21 @@ \catcode`\|=\@@active \catcode`\"=\@@active +% \gdef\pushouterbarandquote +% {\ifForgetTableBarAndQuote +% \let|\letterbar +% \let"\letterdoublequote +% \ifnum\catcode`\|=\@@active \let\outertablebar |\else\let\outertablebar \relax\fi +% \ifnum\catcode`\"=\@@active \let\outertablequote"\else\let\outertablequote\relax\fi +% \fi} + \gdef\pushouterbarandquote - {\ifForgetTableBarAndQuote - \let|\letterbar - \let"\letterdoublequote - \ifnum\catcode`\|=\@@active \let\outertablebar |\else\let\outertablebar \relax\fi - \ifnum\catcode`\"=\@@active \let\outertablequote"\else\let\outertablequote\relax\fi - \fi} + {\ifForgetTableBarAndQuote + \ifnum\catcode`\|=\@@active \let\outertablebar |\else\let\outertablebar \relax\fi + \ifnum\catcode`\"=\@@active \let\outertablequote"\else\let\outertablequote\relax\fi + \let|\letterbar + \let"\letterdoublequote + \fi} \gdef\popouterbarandquote {\ifForgetTableBarAndQuote @@ -1197,13 +1205,22 @@ \global\TABLEinbreakfalse \firststagestartTABLE} +% \def\stoptables +% {\ifconditional\tablerepeattail\else\insertTABLEtail\fi +% \finishTABLE +% \egroup +% \dosplittablebox\tablecontentbox +% \flushnotes +% \egroup} + \def\stoptables - {\ifconditional\tablerepeattail\else\insertTABLEtail\fi - \finishTABLE - \egroup - \dosplittablebox\tablecontentbox - \flushnotes - \egroup} + {\chuckTABLEautorow % AM: before the tail, else noalign problem + \ifconditional\tablerepeattail\else\insertTABLEtail\fi + \finishTABLE + \egroup + \dosplittablebox\tablecontentbox + \flushnotes + \egroup} \newdimen\TABLEcaptionheight % obsolete diff --git a/tex/context/base/core-uti.mkiv b/tex/context/base/core-uti.mkiv index 6883f2227..a9f7982f8 100644 --- a/tex/context/base/core-uti.mkiv +++ b/tex/context/base/core-uti.mkiv @@ -55,6 +55,8 @@ \immediatewriteutilitytua{-- escape\space: \!!bs\space...\space\!!es}% \immediatewriteutilitytua{-- version: \utilityversion}% \immediatewriteutilitytua{}% + \immediatewriteutilitytua{-- begin of utility file}% + \immediatewriteutilitytua{}% \immediatewriteutilitytua{do}% \immediatewriteutilitytua{if job and job.version and not job.version == "\utilityversion" then return end}% \immediatewriteutilitytua{if not job then job = { } end}% @@ -63,6 +65,8 @@ \appendtoks \immediatewriteutilitytua{end}% + \immediatewriteutilitytua{}% + \immediatewriteutilitytua{-- end of utility file}% %immediate\closeout\utility@tua \to \everycloseutilities @@ -72,8 +76,12 @@ \ctxlua { do if not job then job = { } end job.version = "\utilityversion" - local settings = loadfile("\jobname.tuc") - if settings then settings() end + % local settings = loadfile("\jobname.tuc") + local settings = io.loaddata("\jobname.tuc") + if settings:find("\letterpercent -\letterpercent -\letterpercent s*end of utility file \letterpercent s$") then + settings = loadstring(data) + if settings then settings() end + end end}% \to \everyjob diff --git a/tex/context/base/core-var.tex b/tex/context/base/core-var.tex index 0fba2b3b3..0b0c7e2ca 100644 --- a/tex/context/base/core-var.tex +++ b/tex/context/base/core-var.tex @@ -279,6 +279,9 @@ \newevery \everyfontswitch \EveryFontSwitch \newevery \everydefinedfont \relax +\newevery \everybeforeoutput \relax +\newevery \everyafteroutput \relax + \newevery \everybeforedisplayformula \relax \def\cleanupfeatures{\the\everycleanupfeatures} diff --git a/tex/context/base/font-afm.lua b/tex/context/base/font-afm.lua index 8afeb84e0..c4e326d0a 100644 --- a/tex/context/base/font-afm.lua +++ b/tex/context/base/font-afm.lua @@ -19,7 +19,7 @@ away.

fonts = fonts or { } fonts.afm = fonts.afm or { } -fonts.afm.version = 1.10 -- incrementing this number one up will force a re-cache +fonts.afm.version = 1.13 -- incrementing this number one up will force a re-cache fonts.afm.syncspace = true -- when true, nicer stretch values fonts.afm.enhance_data = true -- best leave this set to true fonts.afm.trace_features = false @@ -54,7 +54,7 @@ do if designsize then data.designsize = tonumber(designsize) end end - local function get_charmetrics(characters,charmetrics) + local function get_charmetrics(data,charmetrics,vector) local characters = data.characters local chr, str, ind = { }, "", 0 for k,v in charmetrics:gmatch("([%a]+) +(.-) *;") do @@ -82,10 +82,12 @@ do chr.ligatures[plus] = becomes end end - if str ~= "" then characters[str] = chr end + if str ~= "" then + characters[str] = chr + end end - local function get_kernpairs(characters,kernpairs) + local function get_kernpairs(data,kernpairs) local characters = data.characters for one, two, value in kernpairs:gmatch("KPX +(.-) +(.-) +(.-)\n") do local chr = characters[one] @@ -102,17 +104,41 @@ do end end + local function get_indexes(data,filename) + local pfbname = input.find_file(texmf.instance,file.removesuffix(file.basename(filename))..".pfb","pfb") or "" + if pfbname ~= "" then + data.luatex = data.luatex or { } + data.luatex.filename = pfbname + local pfbblob = fontforge.open(pfbname) + if pfbblob then + local characters = data.characters + local pfbdata = fontforge.to_table(pfbblob) + if pfbdata and pfbdata.glyphs then + for index, glyph in pairs(pfbdata.glyphs) do + local name = glyph.name + if name then + local char = characters[name] + if char then + char.index = index + end + end + end + end + end + end + end + function fonts.afm.read_afm(filename) local ok, afmblob, size = input.loadbinfile(texmf.instance,filename) -- has logging -- local ok, afmblob = true, file.readdata(filename) if ok and afmblob then - data = { + local data = { version = version or '0', characters = { }, filename = file.removesuffix(file.basename(filename)) } afmblob = afmblob:gsub("StartCharMetrics(.-)EndCharMetrics", function(charmetrics) - get_charmetrics(data,charmetrics) + get_charmetrics(data,charmetrics,vector) return "" end) afmblob = afmblob:gsub("StartKernPairs(.-)EndKernPairs", function(kernpairs) @@ -124,6 +150,7 @@ do get_variables(data,fontmetrics) return "" end) + get_indexes(data,filename) return data else return nil @@ -268,11 +295,12 @@ function fonts.afm.copy_to_tfm(data) tfm.characters[t.unicode] = t end end - tfm.encodingbytes = 2 - tfm.units = 1000 - tfm.name = data.filename - tfm.type = "real" + tfm.encodingbytes = data.encodingbytes or 2 tfm.fullname = data.fullname + tfm.filename = data.filename + tfm.name = data.name + tfm.type = "real" + tfm.units = 1000 tfm.stretch = stretch tfm.slant = slant tfm.direction = 0 @@ -341,10 +369,6 @@ function fonts.afm.copy_to_tfm(data) end end - ---~ function set_x(w,h) return h*slant+w*stretch end ---~ function set_y(h) return h end - --[[ldx--

Originally we had features kind of hard coded for files but since I expect to support more font formats, I decided @@ -367,7 +391,7 @@ function fonts.afm.set_features(tfmdata) local mode = tfmdata.mode or fonts.mode local fi = fonts.initializers[mode] if fi and fi.afm then - function initialize(list) -- using tex lig and kerning + local function initialize(list) -- using tex lig and kerning if list then for _, f in ipairs(list) do local value = features[f] @@ -387,7 +411,7 @@ function fonts.afm.set_features(tfmdata) end local fm = fonts.methods[mode] if fm and fm.afm then - function register(list) -- node manipulations + local function register(list) -- node manipulations if list then for _, f in ipairs(list) do if features[f] and fm.afm[f] then -- brr @@ -406,25 +430,46 @@ function fonts.afm.set_features(tfmdata) end function fonts.afm.afm_to_tfm(specification) - local afmfile = specification.filename or specification.name - local features = specification.features.normal - local cache_id = specification.hash - local tfmdata = containers.read(fonts.tfm.cache, cache_id) -- cache with features applied - if not tfmdata then - local afmdata = fonts.afm.load(afmfile) - if not table.is_empty(afmdata) then - tfmdata = fonts.afm.copy_to_tfm(afmdata) - if not table.is_empty(tfmdata) then - tfmdata.shared = tfmdata.shared or { } - tfmdata.unique = tfmdata.unique or { } - tfmdata.shared.afmdata = afmdata - tfmdata.shared.features = features - fonts.afm.set_features(tfmdata) + local afmname = specification.filename or specification.name + local encoding, filename = afmname:match("^(.-)%-(.*)$") -- context: encoding-name.* + if encoding and filename and fonts.enc.known[encoding] then +-- only when no bla-name is found + fonts.tfm.set_normal_feature(specification,'encoding',encoding) -- will go away + if fonts.trace then + logs.report("define font", string.format("stripping encoding prefix from filename %s",afmname)) + end + afmname = filename + else + local tfmname = input.findbinfile(texmf.instance,afmname,"ofm") or "" + if tfmname ~= "" then + if fonts.trace then + logs.report("define font", string.format("fallback from afm to tfm for %s",afmname)) + end + afmname = "" + end + end + if afmname == "" then + return nil + else + local features = specification.features.normal + local cache_id = specification.hash + local tfmdata = containers.read(fonts.tfm.cache, cache_id) -- cache with features applied + if not tfmdata then + local afmdata = fonts.afm.load(afmname) + if not table.is_empty(afmdata) then + tfmdata = fonts.afm.copy_to_tfm(afmdata) + if not table.is_empty(tfmdata) then + tfmdata.shared = tfmdata.shared or { } + tfmdata.unique = tfmdata.unique or { } + tfmdata.shared.afmdata = afmdata + tfmdata.shared.features = features + fonts.afm.set_features(tfmdata) + end end + tfmdata = containers.write(fonts.tfm.cache,cache_id,tfmdata) end - tfmdata = containers.write(fonts.tfm.cache,cache_id,tfmdata) + return tfmdata end - return tfmdata end --[[ldx-- @@ -446,39 +491,36 @@ function fonts.tfm.set_normal_feature(specification,name,value) end function fonts.tfm.read_from_afm(specification) - local name, size, tfmtable = specification.name, specification.size, nil - local encoding, filename = name:match("^(.-)%-(.*)$") -- context: encoding-name.* - if filename and encoding and fonts.enc.known[encoding] then - fonts.tfm.set_normal_feature(specification,'encoding',encoding) - else - encoding = nil -- fonts.tfm.default_encoding - filename = name - end - if filename ~= "" then - tfmtable = fonts.afm.afm_to_tfm(specification) - if tfmtable then - tfmtable.name = name - tfmtable = fonts.tfm.scale(tfmtable, size) - filename = input.findbinfile(texmf.instance,filename,"pfb") - if filename then - tfmtable.format, tfmtable.filename = 'type1', filename - else - tfmtable.format, tfmtable.filename = 'pk', nil - end - if fonts.dontembed[filename] then - tfmtable.file = nil - end - -- begin of map hack + local tfmtable = fonts.afm.afm_to_tfm(specification) + if tfmtable then + tfmtable.name = specification.name + tfmtable = fonts.tfm.scale(tfmtable, specification.size) + local afmdata = tfmtable.shared.afmdata + local filename = afmdata and afmdata.luatex and afmdata.luatex.filename + if not filename then + -- try to locate anyway and set afmdata.luatex.filename + end + if filename then + tfmtable.encodingbytes = 2 + tfmtable.filename = input.findbinfile(texmf.instance,filename,"") or filename + tfmtable.fullname = afmdata.fullname or afmdata.fontname + tfmtable.format = 'type1' + tfmtable.name = afmdata.luatex.filename or tfmtable.name + end + if fonts.dontembed[filename] then + tfmtable.file = nil + end + if false then -- no afm with pk local mapentry = { name = tfmtable.name, fullname = tfmtable.fullname, stretch = tfmtable.stretch, slant = tfmtable.slant, - file = tfmtable.filename, + fontfile = tfmtable.filename, } - -- end of map hack - fonts.map.data[name] = mapentry + fonts.map.data[specification.name] = mapentry end + fonts.logger.save(tfmtable,'afm',specification) end return tfmtable end diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index 581005c8a..16b3e90b7 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -20,7 +20,7 @@ fonts.vf = fonts.vf or { } fonts.used = fonts.used or { } fonts.tfm.version = 1.01 -fonts.tfm.cache = containers.define("fonts", "tfm", fonts.tfm.version, false) +fonts.tfm.cache = containers.define("fonts", "tfm", fonts.tfm.version, false) -- better in font-tfm --[[ldx--

Choosing a font by name and specififying its size is only part of the @@ -73,8 +73,9 @@ and prepares a table that will move along as we proceed.

--ldx]]-- function fonts.define.analyze(name, size, id) - local specification = name or 'unknown' - local lookup, rest = name:match("^(.-):(.+)$") + name = name or 'unknown' + local specification = name + local lookup, rest = specification:match("^(.-):(.+)$") local sub = "" if lookup == 'file' or lookup == 'name' then name = rest @@ -235,15 +236,19 @@ function fonts.tfm.read_and_define(name,size) -- no id local id = fonts.tfm.internalized[hash] if not id then local fontdata = fonts.tfm.read(specification) - if not fonts.tfm.internalized[hash] then - id = font.define(fontdata) - fonts.tfm.id[id] = fontdata - fonts.tfm.internalized[hash] = id - if fonts.trace then - logs.report("define font", string.format("at 1 id %s, hash: %s",id,hash)) + if fontdata then + if not fonts.tfm.internalized[hash] then + id = font.define(fontdata) + fonts.tfm.id[id] = fontdata + fonts.tfm.internalized[hash] = id + if fonts.trace then + logs.report("define font", string.format("at 1 id %s, hash: %s",id,hash)) + end + else + id = fonts.tfm.internalized[hash] end else - id = fonts.tfm.internalized[hash] + id = 0 -- signal end end return fonts.tfm.id[id], id @@ -272,7 +277,6 @@ function fonts.tfm.readers.opentype(specification,suffix,what) if fullname and fullname ~= "" then specification.filename, specification.format = fullname, what -- hm, so we do set the filename, then tfmtable = fonts.tfm.read_from_open_type(specification) -- we need to do it for all matches / todo - fonts.logger.save(tfmtable,suffix,specification) end return tfmtable else @@ -288,23 +292,19 @@ function fonts.tfm.readers.afm(specification,method) local fullname, tfmtable = nil, nil method = method or fonts.define.method if method == 2 then - fullname = input.findbinfile(texmf.instance,specification.name,"ofm") -- ? - if not fullname or fullname == "" then + fullname = input.findbinfile(texmf.instance,specification.name,"ofm") or "" + if fullname == "" then tfmtable = fonts.tfm.read_from_afm(specification) - fonts.logger.save(tfmtable,'afm',specification) else -- redundant specification.filename = fullname tfmtable = fonts.tfm.read_from_tfm(specification) - fonts.logger.save(tfmdata,'tfm',specification) end elseif method == 3 then -- maybe also findbinfile here if fonts.define.auto_afm then tfmtable = fonts.tfm.read_from_afm(specification) - fonts.logger.save(tfmtable,'afm',specification) end elseif method == 4 then -- maybe also findbinfile here tfmtable = fonts.tfm.read_from_afm(specification) - fonts.logger.save(tfmtable,'afm',specification) end return tfmtable end @@ -312,7 +312,6 @@ end function fonts.tfm.readers.tfm(specification) local fullname, tfmtable = nil, nil tfmtable = fonts.tfm.read_from_tfm(specification) - fonts.logger.save(tfmtable,'tfm',specification) return tfmtable end @@ -394,6 +393,10 @@ function fonts.define.specify.preset_context(name,features) fonts.define.specify.context_setups[name] = t end +function fonts.define.specify.context_tostring(name,kind,separator,yes,no,strict) + return aux.hash_to_string(table.merged(fonts[kind].features.default or {},fonts.define.specify.context_setups[name] or {}),separator,yes,no,strict) +end + function fonts.define.specify.split_context(features) if fonts.define.specify.context_setups[features] then return fonts.define.specify.context_setups[features] @@ -472,9 +475,19 @@ function fonts.define.read(name,size,id) else fontdata = fonts.tfm.internalized[hash] end + end if not fontdata then - logs.error("defining font", string.format("name: %s, loading aborted",specification.name)) + logs.error("define font", string.format("name: %s, loading aborted",specification.name)) + elseif fonts.trace and type(fontdata) == "table" then + logs.report("use font",string.format("%s font n:%s s:%s b:%s e:%s p:%s f:%s", + fontdata.type or "unknown", + fontdata.name or "?", + fontdata.size or "default", + fontdata.encodingbytes or "?", + fontdata.encodingname or "unicode", + fontdata.fullname or "?", + file.basename(fontdata.filename or "?"))) end return fontdata end @@ -490,11 +503,25 @@ end --~ end function fonts.vf.find(name) - local format = fonts.logger.format(name) - if format == 'tfm' or format == 'ofm' then - return input.findbinfile(texmf.instance,name,"ovf") + name = file.removesuffix(file.basename(name)) + if fonts.tfm.resolve_vf then + local format = fonts.logger.format(name) + if format == 'tfm' or format == 'ofm' then + if fonts.trace then + logs.report("define font",string.format("locating vf for %s",name)) + end + return input.findbinfile(texmf.instance,name,"ovf") + else + if fonts.trace then + logs.report("define font",string.format("vf for %s is already taken care of",name)) + end + return nil -- "" + end else - return nil -- "" + if fonts.trace then + logs.report("define font",string.format("locating vf for %s",name)) + end + return input.findbinfile(texmf.instance,name,"ovf") end end @@ -503,4 +530,4 @@ end --ldx]]-- callback.register('define_font' , fonts.define.read) -callback.register('find_vf_file', fonts.vf.find ) +callback.register('find_vf_file', fonts.vf.find ) -- not that relevant any more diff --git a/tex/context/base/font-enc.lua b/tex/context/base/font-enc.lua index a29ed83d3..3cc6433b2 100644 --- a/tex/context/base/font-enc.lua +++ b/tex/context/base/font-enc.lua @@ -12,8 +12,8 @@ them in tables. But we may do so some day, for consistency.

--ldx]]-- fonts.enc = fonts.enc or { } -fonts.enc.version = 1.01 -fonts.enc.cache = containers.define("fonts", "enc", fonts.enc.version, false) +fonts.enc.version = 1.03 +fonts.enc.cache = containers.define("fonts", "enc", fonts.enc.version, true) fonts.enc.known = { texnansi = true, @@ -52,12 +52,13 @@ will be used.

function fonts.enc.load(filename) local name = file.removesuffix(filename) local data = containers.read(fonts.enc.cache,name) - if data then - local vector, tag, hash = { }, "", { } + if not data then + local vector, tag, hash, unicodes = { }, "", { }, { } local foundname = input.find_file(texmf.instance,filename,'enc') if foundname and foundname ~= "" then local ok, encoding, size = input.loadbinfile(texmf.instance,foundname) if ok and encoding then + local enccodes = characters.context.enccodes encoding = encoding:gsub("%%(.-)\n","") local tag, vec = encoding:match("/(%w+)%s*%[(.*)%]%s*def") local i = 0 @@ -69,12 +70,22 @@ function fonts.enc.load(filename) else -- duplicate, play safe for tex ligs and take first end + if enccodes[ch] then + unicodes[enccodes[ch]] = i + end end i = i + 1 end end end - data = containers.write(fonts.enc.cache, name, { name=name, tag=tag, vector=vector, hash=hash }) + local data = { + name=name, + tag=tag, + vector=vector, + hash=hash, + unicodes=unicodes + } + data = containers.write(fonts.enc.cache, name, data) end return data end diff --git a/tex/context/base/font-ini.lua b/tex/context/base/font-ini.lua index 16fcf7271..d4adf360b 100644 --- a/tex/context/base/font-ini.lua +++ b/tex/context/base/font-ini.lua @@ -49,7 +49,8 @@ do local unset_attribute = node.unset_attribute function fonts.color.set(n,c) - set_attribute(n,attribute,mapping[c] or -1) + -- local mc = mapping[c] if mc then unset_attribute((n,attribute) else set_attribute(n,attribute,mc) end + set_attribute(n,attribute,mapping[c] or -1) -- also handles -1 now end function fonts.color.reset(n) unset_attribute(n,attribute) diff --git a/tex/context/base/font-ini.mkiv b/tex/context/base/font-ini.mkiv index dd597d41f..45ff3480e 100644 --- a/tex/context/base/font-ini.mkiv +++ b/tex/context/base/font-ini.mkiv @@ -31,12 +31,14 @@ \def\otfchar#1{\ctxlua{fonts.otf.char("#1")}} -\registerrgbcolor {font:init} {1}{0}{0}% -\registerrgbcolor {font:medi} {0}{1}{0}% -\registerrgbcolor {font:fina} {0}{0}{1}% -\registerrgbcolor {font:isol} {0}{1}{1}% -\registerrgbcolor {font:mark} {1}{0}{1}% -\registerrgbcolor {font:rest} {1}{1}{0}% +%D: We cannot yet inherit because no colors are predefined. + +\definecolor[font:init][r=.75] +\definecolor[font:medi][g=.75] +\definecolor[font:fina][b=.75] +\definecolor[font:isol][y=.75] +\definecolor[font:mark][m=.75] +\definecolor[font:rest][c=.75] %D goodies: %D @@ -69,4 +71,12 @@ \def\doinstallfontfeature[#1][#2]% {\ctxlua{fonts.install_feature("#1","#2")}} +%D Not yet in \MKII. + +\def\fontfeatureslist + {\dodoubleargument\dofontfeatureslist} + +\def\dofontfeatureslist[#1][#2]% todo: arg voor type + {\ctxlua{tex.sprint(tex.ctxcatcodes,fonts.define.specify.context_tostring("#1","otf","\luaescapestring{#2}","yes","no",true))}} + \protect \endinput diff --git a/tex/context/base/font-map.lua b/tex/context/base/font-map.lua index 4aecde445..64ff268fb 100644 --- a/tex/context/base/font-map.lua +++ b/tex/context/base/font-map.lua @@ -11,38 +11,39 @@ if not modules then modules = { } end modules ['font-map'] = { of obsolete. Some code may move to runtime or auxiliary modules.

--ldx]]-- -fonts = fonts or { } -fonts.map = fonts.map or { } -fonts.map.data = fonts.map.data or { } -fonts.map.done = fonts.map.done or { } -fonts.map.line = fonts.map.line or { } -fonts.map.loaded = fonts.map.loaded or { } -fonts.map.direct = fonts.map.direct or { } +fonts = fonts or { } +fonts.map = fonts.map or { } +fonts.map.data = fonts.map.data or { } +fonts.map.encodings = fonts.map.encodings or { } +fonts.map.done = fonts.map.done or { } +fonts.map.loaded = fonts.map.loaded or { } +fonts.map.direct = fonts.map.direct or { } +fonts.map.line = fonts.map.line or { } function fonts.map.line.pdfmapline(tag,str) return "\\loadmapline[" .. tag .. "][" .. str .. "]" end function fonts.map.line.pdftex(e) -- so far no combination of slant and stretch - if e.name and e.file then + if e.name and e.fontfile then local fullname = e.fullname or "" - if e.slant and tonumber(e.slant) ~= 0 then + if e.slant and e.slant ~= 0 then if e.encoding then - return fonts.map.line.pdfmapline("=",string.format('%s %s "%g SlantFont" <%s <%s',e.name,fullname,e.slant,e.encoding,e.file)) + return fonts.map.line.pdfmapline("=",string.format('%s %s "%g SlantFont" <%s <%s',e.name,fullname,e.slant,e.encoding,e.fontfile)) else - return fonts.map.line.pdfmapline("=",string.format('%s %s "%g SlantFont" <%s',e.name,fullname,e.slant,e.file)) + return fonts.map.line.pdfmapline("=",string.format('%s %s "%g SlantFont" <%s',e.name,fullname,e.slant,e.fontfile)) end - elseif e.stretch and tonumber(e.stretch) ~= 1 and tonumber(e.stretch) ~= 0 then + elseif e.stretch and e.stretch ~= 1 and e.stretch ~= 0 then if e.encoding then - return fonts.map.line.pdfmapline("=",string.format('%s %s "%g ExtendFont" <%s <%s',e.name,fullname,e.stretch,e.encoding,e.file)) + return fonts.map.line.pdfmapline("=",string.format('%s %s "%g ExtendFont" <%s <%s',e.name,fullname,e.stretch,e.encoding,e.fontfile)) else - return fonts.map.line.pdfmapline("=",string.format('%s %s "%g ExtendFont" <%s',e.name,fullname,e.stretch,e.file)) + return fonts.map.line.pdfmapline("=",string.format('%s %s "%g ExtendFont" <%s',e.name,fullname,e.stretch,e.fontfile)) end else if e.encoding then - return fonts.map.line.pdfmapline("=",string.format('%s %s <%s <%s',e.name,fullname,e.encoding,e.file)) + return fonts.map.line.pdfmapline("=",string.format('%s %s <%s <%s',e.name,fullname,e.encoding,e.fontfile)) else - return fonts.map.line.pdfmapline("=",string.format('%s %s <%s',e.name,fullname,e.file)) + return fonts.map.line.pdfmapline("=",string.format('%s %s <%s',e.name,fullname,e.fontfile)) end end else @@ -50,123 +51,71 @@ function fonts.map.line.pdftex(e) -- so far no combination of slant and stretch end end -function fonts.map.flushlines(backend,separator) - local t = { } - for k,v in pairs(fonts.map.data) do - if not fonts.map.done[k] then - local str = fonts.map.line[backend](v) - if str then - t[#t+1] = str - end - fonts.map.done[k] = true - end +function fonts.map.flush(backend) -- will also erase the accumulated data + local flushline = fonts.map.line[backend or "pdftex"] or fonts.map.line.pdftex + for _, e in pairs(fonts.map.data) do + tex.sprint(tex.ctxcatcodes,flushline(e)) end - return table.join(t,separator or "") + fonts.map.data = { } end -fonts.map.line.dvips = fonts.map.line.pdftex -fonts.map.line.dvipdfmx = function() end - -function fonts.map.process_entries(filename, backend, handle) - local root = xml.load(filename,true) - if root then - if not handle then handle = texio.write_nl end - xml.process_attributes(root, "/fontlist/font", function(e,k) - local str = fonts.map.line[backend](e) - if str then - handle(str) - end - end) - end -end +fonts.map.line.dvips = fonts.map.line.pdftex +fonts.map.line.dvipdfmx = function() end function fonts.map.convert_entries(filename) if not fonts.map.loaded[filename] then - local root = xml.load(filename,true) -- todo: stop garbage collector - if root then - garbagecollector.push() - xml.process_attributes(root, "/fontlist/font", function(e,k) - if e.name and e.file then - fonts.map.data[e.name] = e - -- fonts.map.data[e.name].name = nil -- beware, deletes xml entry as well - end - end) - garbagecollector.pop() - end + fonts.map.data, fonts.map.encodings = fonts.map.load_file(filename,fonts.map.data, fonts.map.encodings) fonts.map.loaded[filename] = true end end -function fonts.map.direct.pdftex(filename) - fonts.map.process_entries(filename,'pdftex',function(str) - tex.sprint(tex.ctxcatcodes,str) - end) -end - --- the next one will go to a runtime module, no need to put this in the format - -function fonts.map.convert_file(filename, handle) -- when handle is string, then assume file - local f, g = io.open(filename), nil +function fonts.map.load_file(filename, entries, encodings) + entries = entries or { } + encodings = encodings or { } + local f = io.open(filename) if f then - if not handle then - handle = print - elseif type(handle) == "string" then - g = io.open(handle,"w") - function handle(str) - g:write(str .. "\n") - end - end - handle("\n") - handle(string.format("\n", "generated by context")) - handle(string.format("\n", filename)) - for line in f:lines() do - local comment = line:match("^[%#%%]%s*(.*)%s*$") - if comment then -- todo: optional - handle(string.format(" ", comment)) - elseif line:find("^\s*$") then - handle("") - else - name, fullname, spec, encoding, file = line:match("^(%S+)%s+(%S-)%s*\"([^\"]-)\"%s*<%s*(%S-)%s*<%s*(%S-)%s*$") - if not name then - name, fullname, spec, file = line:match("^(%S+)%s+(%S-)%s*\"([^\"]-)\"%s*<%s*(%S-)%s*$") - end - if not name then - name, fullname, encoding, file = line:match("^(%S+)%s+(%S-)%s*<%s*(%S-)%s*<%s*(%S-)%s*$") - end - if not name then - name, fullname, file = line:match("^(%S+)%s+(%S-)%s*<%s*(%S-)%s*$") - end - if name and name ~= "" and file and file ~= "" then - t = { } - if name then t[#t+1] = string.format("name='%s'" , name) end - if fullname and fullname ~= "" then t[#t+1] = string.format("fullname='%s'", fullname) end - if encoding and encoding ~= "" then t[#t+1] = string.format("encoding='%s'", encoding) end - if file then t[#t+1] = string.format("file='%s'" , file) end - if spec then - local a, b = spec:match("^([%d%.])%s+(%a+)$") - if a and b and b == "ExtendFont" then t[#t+1] = string.format("slant='%s'" , a) end - if a and b and b == "SlantFont" then t[#t+1] = string.format("stretch='%s'", a) end + local data = f:read("*a") + if data then + for line in data:gmatch("(.-)[\n\t]") do + if line:find("^[%#%%%s]") then + -- print(line) + else + local stretch, slant, name, fullname, fontfile, encoding + line = line:gsub('"(.+)"', function(s) + stretch = s:find('"([^"]+) ExtendFont"') + slant = s:find('"([^"]+) SlantFont"') + return "" + end) + if not name then + -- name fullname encoding fontfile + name, fullname, encoding, fontfile = line:match("^(%S+)%s+(%S*)[%s<]+(%S*)[%s<]+(%S*)%s*$") + end + if not name then + -- name fullname (flag) fontfile encoding + name, fullname, fontfile, encoding = line:match("^(%S+)%s+(%S*)[%d%s<]+(%S*)[%s<]+(%S*)%s*$") + end + if not name then + -- name fontfile + name, fontfile = line:match("^(%S+)%s+[%d%s<]+(%S*)%s*$") + end + if name then + if encoding == "" then encoding = nil end + entries[name] = { + name = name, -- handy + fullname = fullname, + encoding = encoding, + fontfile = fontfile, + slant = tonumber(slant), + stretch = tonumber(stretch) + } + encodings[name] = encoding + elseif line ~= "" then + -- print(line) end - handle(string.format(" ",table.concat(t," "))) end end end - handle("\n") f:close() - if g then g:close() end end + return entries, encodings end - ---~ fonts.map.convert_file("c:/data/develop/tex/texmf/fonts/map/dvips/lm/lm-ec.map") ---~ fonts.map.convert_file("maptest.map") ---~ fonts.map.convert_file("maptest.map", "maptest-1.xml") ---~ fonts.map.convert_file("c:/data/develop/tex/texmf/fonts/map/pdftex/updmap/pdftex.map") ---~ fonts.map.convert_file("c:/data/develop/tex/texmf/fonts/map/pdftex/updmap/pdftex.map", "maptest-2.xml") - ---~ fonts.map.convert_entries('maptest-2.xml') ---~ fonts.map.process_entries('maptest.xml','pdftex') - ---~ print(table.serialize(fonts.map.data)) - ---~ tex.sprint(fonts.map.flushlines("pdftex","\n")) ---~ str = fonts.map.flushlines("pdftex") diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua index 8dec45481..8331a5177 100644 --- a/tex/context/base/font-otf.lua +++ b/tex/context/base/font-otf.lua @@ -33,7 +33,7 @@ in the table.

fonts = fonts or { } fonts.otf = fonts.otf or { } -fonts.otf.version = 1.56 -- incrementing this number one up will force a re-cache +fonts.otf.version = 1.60 -- incrementing this number one up will force a re-cache fonts.otf.tables = fonts.otf.tables or { } fonts.otf.meanings = fonts.otf.meanings or { } fonts.otf.enhance_data = false @@ -727,7 +727,9 @@ function fonts.otf.load(filename,format,sub,featurefile) fonts.otf.enhance.analyze(data,filename) logs.report("load otf","enhance: after") fonts.otf.enhance.after(data,filename) - logs.report("load otf","save in cache") + logs.report("load otf","enhance: patch") + fonts.otf.enhance.patch(data,filename) + logs.report("load otf","saving: in cache") data = containers.write(fonts.otf.cache, name, data) else logs.error("load otf","loading failed") @@ -750,6 +752,8 @@ function fonts.otf.load(filename,format,sub,featurefile) return data end +-- todo: normalize, design_size => designsize + function fonts.otf.enhance.analyze(data,filename) local t = { filename = file.basename(filename), @@ -764,27 +768,150 @@ function fonts.otf.enhance.analyze(data,filename) data.luatex = t end +function fonts.otf.load_cidmap(filename) + local data = io.loaddata(filename) + if data then + local unicodes, names = { }, {} + data = data:gsub("^(%d+)%s+(%d+)\n","") + for a,b in data:gmatch("(%d+)%s+([%d%a]+)\n") do + unicodes[tonumber(a)] = tonumber(b,16) + end + for a,b,c in data:gmatch("(%d+)%.%.(%d+)%s+([%d%a]+)%s*\n") do + c = tonumber(c,16) + for i=tonumber(a),tonumber(b) do + unicodes[i] = c + c = c + 1 + end + end + for a,b in data:gmatch("(%d+)%s+\/(%S+)%s*\n") do + names[tonumber(a)] = b + end + local supplement, registry, ordering = filename:match("^(.-)%-(.-)%-()%.(.-)$") + return { + supplement = supplement, + registry = registry, + ordering = ordering, + filename = filename, + unicodes = unicodes, + names = names + } + else + return nil + end +end + +fonts.otf.cidmaps = { } + +function fonts.otf.cidmap(registry,ordering,supplement) + local template = "%s-%s-%s.cidmap" + local filename = string.format(template,registry,ordering,supplement) + local supplement = tonumber(supplement) + if not fonts.otf.cidmaps[filename] then + for i=supplement,0,-1 do + logs.report("load otf",string.format("checking cidmap, registry: %s, ordering: %s, supplement: %s",registry,ordering,i)) + filename = string.format(template,registry,ordering,i) + local fullname = input.find_file(texmf.instance,filename,'cid') or "" + if fullname ~= "" then + local cidmap = fonts.otf.load_cidmap(fullname) + if cidmap then + logs.report("load otf",string.format("using cidmap file %s",filename)) + fonts.otf.cidmaps[filename] = cidmap + if i < supplement then + for j=i+1,supplement do + filename = string.format(template,registry,ordering,j) + fonts.otf.cidmaps[filename] = cidmap -- copy of ref + end + end + return cidmap + end + end + end + end + return nil +end + +--~ ["cidinfo"]={ +--~ ["ordering"]="Japan1", +--~ ["registry"]="Adobe", +--~ ["supplement"]=6, +--~ ["version"]=6, +--~ }, + function fonts.otf.enhance.before(data,filename) local private = 0xE000 - local uni_to_int = data.map.map - local int_to_uni = data.map.backmap - for index, glyph in pairs(data.glyphs) do - if index > 0 and glyph.unicodeenc == -1 then - while uni_to_int[private] do - private = private + 1 + if data.subfonts and table.is_empty(data.glyphs) then + local cidinfo = data.cidinfo + if cidinfo.registry then + local cidmap = fonts.otf.cidmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement) + if cidmap then + local glyphs, uni_to_int, int_to_uni, nofnames, nofunicodes, zerobox = { }, { }, { }, 0, 0, { 0, 0, 0, 0 } + local unicodes, names = cidmap.unicodes, cidmap.names + for n, subfont in pairs(data.subfonts) do + for index, g in pairs(subfont.glyphs) do + if not next(g) then + -- dummy entry + else + local unicode, name = unicodes[index], names[index] + g.cidindex = n + g.boundingbox = g.boundingbox or zerobox + g.name = g.name or name or "unknown" + if unicode then + g.unicodeenc = unicode + uni_to_int[unicode] = index + int_to_uni[index] = unicode + nofunicodes = nofunicodes + 1 + elseif name then + g.unicodeenc = -1 + nofnames = nofnames + 1 + end + glyphs[index] = g + end + end + subfont.glyphs = nil + end + logs.report("load otf",string.format("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)) + data.glyphs = glyphs + data.map = data.map or { } + data.map.map = uni_to_int + data.map.backmap = int_to_uni + else + logs.report("load otf",string.format("unable to remap cid font, missing cid file for %s",filename)) end - uni_to_int[private] = index - int_to_uni[index] = private - glyph.unicodeenc = private - logs.report("load otf",string.format("enhance: glyph %s at index %s is moved to private unicode slot %s",glyph.name,index,private)) + else + logs.report("load otf",string.format("font %s has no glyphs",filename)) end end + if data.map then + local uni_to_int = data.map.map + local int_to_uni = data.map.backmap + for index, glyph in pairs(data.glyphs) do + if index > 0 and glyph.unicodeenc == -1 then + while uni_to_int[private] do + private = private + 1 + end + uni_to_int[private] = index + int_to_uni[index] = private + glyph.unicodeenc = private + if fonts.trace then + logs.report("load otf",string.format("enhance: glyph %s at index %s is moved to private unicode slot %s",glyph.name,index,private)) + end + end + end + else + data.map = { map = {}, backmap = {} } + end if data.ttf_tables then for _, v in ipairs(data.ttf_tables) do if v.data then v.data = "deleted" end --~ if v.data then v.data = v.data:gsub("\026","\\026") end -- does not work out well end end + table.compact(data.glyphs) + if data.subfonts then + for _, subfont in pairs(data.subfonts) do + table.compact(subfont.glyphs) + end + end end function fonts.otf.enhance.after(data,filename) @@ -792,13 +919,21 @@ function fonts.otf.enhance.after(data,filename) for index, glyph in pairs(data.glyphs) do if glyph.kerns then local mykerns = { } - for k,v in ipairs(glyph.kerns) do - local mkl = mykerns[v.lookup] - if not mkl then - mkl = { [unicodes[v.char]] = v.off } - mykerns[v.lookup] = mkl - else - mkl[unicodes[v.char]] = v.off + for k,v in pairs(glyph.kerns) do + local vc, vo, vl = v.char, v.off, v.lookup + if vc and vo and vl then -- brrr, wrong! we miss the non unicode ones + local uvc = unicodes[vc] + if uvc then + local mkl = mykerns[vl] + if not mkl then + mkl = { [unicodes[vc]] = vo } + mykerns[v.lookup] = mkl + else + mkl[unicodes[vc]] = vo + end + else + logs.report("load otf", string.format("problems with unicode %s of kern %s at glyph %s",vc,k,index)) + end end end glyph.mykerns = mykerns @@ -806,6 +941,35 @@ function fonts.otf.enhance.after(data,filename) end end +fonts.otf.enhance.patches = { } + +function fonts.otf.enhance.patch(data,filename) + local basename = file.basename(filename) + for pattern, action in pairs(fonts.otf.enhance.patches) do + if basename:find(pattern) then + action(data,filename) + end + end +end + +do -- will move to a typescript + + local function patch(data,filename) + if data.design_size == 0 then + local ds = (file.basename(filename)):match("(%d+)") + if ds then + logs.report("load otf",string.format("patching design size (%s)",ds)) + data.design_size = tonumber(ds) * 10 + end + end + end + + fonts.otf.enhance.patches["^lmroman"] = patch + fonts.otf.enhance.patches["^lmsans"] = patch + fonts.otf.enhance.patches["^lmmono"] = patch + +end + function fonts.otf.analyze_class(data,class) local classes = { } for index, glyph in pairs(data.glyphs) do @@ -941,7 +1105,7 @@ function fonts.otf.set_features(tfmdata) local mode = tfmdata.mode or fonts.mode local fi = fonts.initializers[mode] if fi and fi.otf then - function initialize(list) -- using tex lig and kerning + local function initialize(list) -- using tex lig and kerning if list then for _, f in ipairs(list) do local value = features[f] @@ -962,7 +1126,7 @@ function fonts.otf.set_features(tfmdata) end local fm = fonts.methods[mode] if fm and fm.otf then - function register(list) -- node manipulations + local function register(list) -- node manipulations if list then for _, f in ipairs(list) do if features[f] and fm.otf[f] then -- brr @@ -1042,39 +1206,42 @@ function fonts.otf.copy_to_tfm(data) for k,v in pairs(data.map.map) do -- k = unicode, v = slot local d = data.glyphs[v] - -- if d then if d and (force or d.name) then - local t = { } - t.index = v - t.unicode = k - t.name = d.name or ".notdef" - t.boundingbox = d.boundingbox or nil - t.width = d.width or 0 - t.height = d.boundingbox[4] or 0 - t.depth = - d.boundingbox[2] or 0 - t.class = d.class + local t = { + index = v, + unicode = k, + name = d.name or ".notdef", + boundingbox = d.boundingbox or nil, + width = d.width or 0, + height = d.boundingbox[4] or 0, + depth = - d.boundingbox[2] or 0, + class = d.class, + } if d.class == "mark" then - t.width = -t.width + t.width = - t.width end characters[k] = t end end + local designsize = data.designsize or data.design_size or 100 + if designsize == 0 then + designsize = 100 + end + local spaceunits = 500 tfm.units = data.units_per_em or 1000 - -- we need a runtime lookup because of running from cdrom or zip + -- we need a runtime lookup because of running from cdrom or zip, brrr tfm.filename = input.findbinfile(texmf.instance,data.luatex.filename,"") or data.luatex.filename tfm.fullname = data.fullname or data.fontname + tfm.encodingbytes = 2 tfm.cidinfo = data.cidinfo - -- if not tfm.cidinfo.registry then tfm.cidinfo.registry = "" end tfm.cidinfo.registry = tfm.cidinfo.registry or "" - tfm.name = file.removesuffix(file.basename(tfm.filename)) tfm.type = "real" tfm.stretch = 0 -- stretch tfm.slant = 0 -- slant tfm.direction = 0 tfm.boundarychar_label = 0 tfm.boundarychar = 65536 - tfm.designsize = ((data.designsize or 100)/10)*65536 - local spaceunits = 500 + tfm.designsize = (designsize/10)*65536 tfm.spacer = "500 units" data.isfixedpitch = data.pfminfo and data.pfminfo.panose and data.pfminfo.panose["proportion"] == "Monospaced" data.charwidth = nil @@ -1084,19 +1251,25 @@ function fonts.otf.copy_to_tfm(data) if data.isfixedpitch then if data.glyphs[unicodes['space']] then spaceunits, tfm.spacer = data.glyphs[unicodes['space']].width, "space" - elseif data.glyphs[unicodes['emdash']] then + end + if not spaceunits and data.glyphs[unicodes['emdash']] then spaceunits, tfm.spacer = data.glyphs[unicodes['emdash']].width, "emdash" - elseif data.charwidth then + end + if not spaceunits and data.charwidth then + spaceunits, tfm.spacer = data.charwidth, "charwidth" + end + else + if data.glyphs[unicodes['space']] then + spaceunits, tfm.spacer = data.glyphs[unicodes['space']].width, "space" + end + if not spaceunits and data.glyphs[unicodes['emdash']] then + spaceunits, tfm.spacer = data.glyphs[unicodes['emdash']].width/2, "emdash/2" + end + if not spaceunits and data.charwidth then spaceunits, tfm.spacer = data.charwidth, "charwidth" end - elseif data.glyphs[unicodes['space']] then - spaceunits, tfm.spacer = data.glyphs[unicodes['space']].width, "space" - elseif data.glyphs[unicodes['emdash']] then - spaceunits, tfm.spacer = data.glyphs[unicodes['emdash']].width/2, "emdash/2" - elseif data.charwidth then - spaceunits, tfm.spacer = data.charwidth, "charwidth" end - spaceunits = tonumber(spaceunits) + spaceunits = tonumber(spaceunits) or 500 -- brrr tfm.parameters[1] = 0 -- slant tfm.parameters[2] = spaceunits -- space tfm.parameters[3] = 500 -- space_stretch @@ -1122,9 +1295,13 @@ function fonts.otf.copy_to_tfm(data) end if data.pfminfo and data.pfminfo.os2_xheight and data.pfminfo.os2_xheight > 0 then tfm.parameters[5] = data.pfminfo.os2_xheight - elseif data.glyphs[unicodes['x']] and data.glyphs[unicodes['x']].height then - tfm.parameters[5] = data.glyphs[unicodes['x']].height + else + local x = characters[unicodes['x']] + if x then + tfm.parameters[5] = x.height + end end + -- [6] return tfm else return nil @@ -1137,8 +1314,19 @@ function fonts.tfm.read_from_open_type(specification) tfmtable.name = specification.name tfmtable.sub = specification.sub tfmtable = fonts.tfm.scale(tfmtable, specification.size) - tfmtable.file = file.basename(specification.filename) - tfmtable.format = specification.format + -- here we resolve the name; file can be relocated, so this info is not in the cache + local otfdata = tfmtable.shared.otfdata + local filename = otfdata and otfdata.luatex and otfdata.luatex.filename + if not filename then + -- try to locate anyway and set otfdata.luatex.filename + end + if filename then + tfmtable.encodingbytes = 2 + tfmtable.filename = input.findbinfile(texmf.instance,filename,"") or filename + tfmtable.fullname = otfdata.fullname or otfdata.fontname + tfmtable.format = specification.format + end + fonts.logger.save(tfmtable,file.extname(specification.filename),specification) end return tfmtable end @@ -1148,27 +1336,52 @@ end fonts.otf.default_language = 'latn' fonts.otf.default_script = 'dflt' -function fonts.otf.valid_feature(otfdata,language,script) -- return hash is faster +--~ function fonts.otf.valid_feature(otfdata,language,script) -- return hash is faster +--~ local language = language or fonts.otf.default_language +--~ local script = script or fonts.otf.default_script +--~ if not (script and language) then +--~ return boolean.alwaystrue +--~ else +--~ language = string.padd(language:lower(),4) +--~ script = string.padd(script:lower (),4) +--~ local t = { } +--~ for k,v in pairs(otfdata.luatex.subtables) do +--~ local vv = v[script] +--~ if vv and vv[language] then +--~ t[k] = vv[language].valid +--~ end +--~ end +--~ local always = otfdata.luatex.always_valid -- for the moment not per feature +--~ --~ return function(kind,tag) -- is the kind test needed +--~ --~ return always[tag] or (kind and t[kind] and t[kind][tag]) +--~ --~ end +--~ return function(kind,tag) -- better inline +--~ return always[tag] or (t[kind] and t[kind][tag]) +--~ end +--~ end +--~ end + +function fonts.otf.valid_feature(otfdata,language,script,feature) -- return hash is faster local language = language or fonts.otf.default_language local script = script or fonts.otf.default_script if not (script and language) then - return boolean.alwaystrue + return true else language = string.padd(language:lower(),4) script = string.padd(script:lower (),4) - local t = { } - for k,v in pairs(otfdata.luatex.subtables) do - local vv = v[script] - if vv and vv[language] then - t[k] = vv[language].valid - end - end - local always = otfdata.luatex.always_valid -- for the moment not per feature - return function(kind,tag) -- is the kind test needed - return always[tag] or kind and t[kind] and t[kind][tag] - end +--~ local t = { } +--~ for k,v in pairs(otfdata.luatex.subtables) do +--~ local vv = v[script] +--~ if vv and vv[language] then +--~ t[k] = vv[language].valid +--~ end +--~ end + local ft = otfdata.luatex.subtables[feature] + local st = ft[script] + return false, otfdata.luatex.always_valid, st and st[language] and st[language].valid end end + function fonts.otf.some_valid_feature(otfdata,language,script,kind) local language = language or fonts.otf.default_language local script = script or fonts.otf.default_script @@ -1464,13 +1677,21 @@ do end end else -- check if this valid is still ok - local valid = fonts.otf.valid_feature(otfdata,tfmdata.language,tfmdata.script) +--~ local valid = fonts.otf.valid_feature(otfdata,tfmdata.language,tfmdata.script) + local forced, always, okay = fonts.otf.valid_feature(otfdata,tfmdata.language,tfmdata.script,kind) for _,o in pairs(otfdata.glyphs) do if o.lookups then - for lookup, ps in pairs(o.lookups) do - if valid(kind,lookup) then - collect(lookup,o,ps) - end +--~ for lookup, ps in pairs(o.lookups) do +--~ if valid(kind,lookup) then +--~ collect(lookup,o,ps) +--~ end +--~ end + if forced then + for lookup, ps in pairs(o.lookups) do collect(lookup,o,ps) end + elseif okay then + for lookup, ps in pairs(o.lookups) do if always[lookup] or okay[lookup] then collect(lookup,o,ps) end end + else + for lookup, ps in pairs(o.lookups) do if always[lookup] then collect(lookup,o,ps) end end end end end @@ -1818,7 +2039,7 @@ end do - prepare = fonts.otf.features.prepare.feature + local prepare = fonts.otf.features.prepare.feature function fonts.initializers.node.otf.afrc(tfm,value) return prepare(tfm,'afrc',value) end function fonts.initializers.node.otf.akhn(tfm,value) return prepare(tfm,'akhn',value) end @@ -1984,7 +2205,7 @@ do -- todo: components / else subtype 0 / maybe we should be able to force this - function toligature(start,stop,char,markflag) + local function toligature(start,stop,char,markflag) if start ~= stop then local deletemarks = markflag ~= "mark" start.subtype = 1 @@ -2356,7 +2577,7 @@ do return start, done end - chainprocs = { } -- we can probably optimize this because they're all internal lookups + local chainprocs = { } -- we can probably optimize this because they're all internal lookups -- For the moment we save each looked up glyph in the sequence, which is ok because -- each lookup in the chain has its own sequence. This saves memory. Only ligatures @@ -3191,6 +3412,9 @@ end do local glyph = node.id('glyph') + local glue = node.id('glue') + local penalty = node.id('penalty') + local fontdata = fonts.tfm.id local set_attribute = node.set_attribute local has_attribute = node.has_attribute @@ -3236,6 +3460,8 @@ do -- arab / todo: 0640 tadwil + -- this info eventually will go into char-def + local isol = { [0x0621] = true, } @@ -3377,6 +3603,122 @@ do return head, done end + -- han (chinese) (unfinished) + + -- this info eventually will go into char-def + + local no_init = table.tohash { + 0x3001, 0x3002, 0x2014, 0xFF5E, 0x2019, 0x201D, 0x3015, 0x3009, + 0x300B, 0x300D, 0x300F, 0x3017, 0x3011, 0x2237, 0x00B0, 0x2032, + 0x2033, 0xFF01, 0xFF02, 0xFF07, 0xFF09, 0xFF0C, 0xFF0E, 0xFF1A, + 0xFF1B, 0xFF1F, 0xFF3D, 0xFF5D, + } + + local no_fina = table.tohash { + 0x2018, 0x201C, 0x3014, 0x3008, 0x300A, 0x300C, 0x300E, 0x3016, + 0x3010, 0xFF08, 0xFF3B, 0xFF40, 0xFF5B, + } + + local no_xxxx = table.tohash { + 0x00B7, 0x00A8, 0x2026, 0xFF1E, + } + + local allowbreak = node.new("penalty") + local nobreak = node.new("penalty") +--~ local zeroskip = node.new("glue") + + allowbreak.penalty = -100 + nobreak.penalty = 10000 +--~ zeroskip.subtype = 0 +--~ zeroskip.spec = node.new('glue_spec') +--~ zeroskip.spec.width = 0 +--~ zeroskip.spec.stretch = 0 +--~ zeroskip.spec.shrink = 0 + + -- an alternative is to deal with it in the line breaker + + local function is_han_character(char) + return + (char>=0x04E00 and char<=0x09FFF) or + (char>=0x03400 and char<=0x04DFF) or + (char>=0x20000 and char<=0x2A6DF) or + (char>=0x0F900 and char<=0x0FAFF) or + (char>=0x2F800 and char<=0x2FA1F) + end + + function fonts.analyzers.methods.hang(head,font) -- maybe make a special version with no trace + local characters = fontdata[font].characters + local current, done = head, false + local trace = fonts.color.trace + local prevchinese = false + local function unskip() + if prevchinese then + local temp = current.prev + while temp and temp.id == glue do + head, temp = nodes.delete(head,temp) + if temp then temp = temp.prev end + end + end + end + while current do + if current.id == glyph then + if current.font == font then + local char = current.char + if no_init[char] then + done = true + set_attribute(current,state,1) -- before + if trace then fcs(current,"font:init") end -- we need nice names + if current.prev then + unskip() + head, current = node.insert_before(head,current,node.copy(nobreak)) + current = current.next + end + prevchinese = true + elseif no_fina[char] then + done = true + set_attribute(current,state,2) -- after + if trace then fcs(current,"font:fina") end -- we need nice names + if current.prev then + unskip() + head, current = node.insert_before(head,current,node.copy(allowbreak)) + current = current.next + end + if current and current.next then + head, current = node.insert_after(head,current,node.copy(nobreak)) + current = current.next + end + prevchinese = true + elseif no_xxxx[char] then + done = true + set_attribute(current,state,3) -- xxxx + if trace then fcs(current,"font:medi") end -- we need nice names + if current.prev then -- todo + unskip() + head, current = node.insert_before(head,current,node.copy(allowbreak)) + current = current.next + end + prevchinese = true + elseif is_han_character(char) then + if current.prev and current.prev.id ~= penalty then + unskip() + head, current = node.insert_before(head,current,node.copy(allowbreak)) + current = current.next + end + prevchinese = true + else + prevchinese = false + end + else + prevchinese = false + end + end + if current then + current = current.next + end + end + return head, done + end + end -- experimental and will probably change diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua index 77898a4a2..fdd99e6f2 100644 --- a/tex/context/base/font-syn.lua +++ b/tex/context/base/font-syn.lua @@ -54,6 +54,10 @@ function fonts.names.filters.afm(name) end end +function fonts.names.filters.pfb(name) + return fontforge.info(name) +end + --[[ldx--

The scanner loops over the filters using the information stored in the file databases. Watch how we check not only for the names, but also @@ -61,7 +65,7 @@ for combination with the weight of a font.

--ldx]]-- fonts.names.filters.list = { - "otf", "ttf", "ttc", "afm" + "otf", "ttf", "ttc", "afm" -- pfb is quite messy, too many messages, maybe broken } fonts.names.filters.fixes = { diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua index 21a02a67b..103f71c12 100644 --- a/tex/context/base/font-tfm.lua +++ b/tex/context/base/font-tfm.lua @@ -23,6 +23,35 @@ fonts.triggers = fonts.triggers or { } -- brrr supplied by .

--ldx]]-- +fonts.tfm.resolve_vf = true -- false + +function fonts.tfm.enhance(tfmdata,specification) + local name, size = specification.name, specification.size + local encoding, filename = name:match("^(.-)%-(.*)$") -- context: encoding-name.* + if filename and encoding and fonts.enc.known[encoding] then + local data = fonts.enc.load(encoding) + if data then + local characters = tfmdata.characters + tfmdata.encoding = encoding + local vector = data.vector + for k, v in pairs(characters) do + v.name = vector[k] + v.index = k + end + for k,v in pairs(data.unicodes) do + if k ~= v then + -- if not characters[k] then + if fonts.trace then + logs.report("define font",string.format("mapping %s onto %s",k,v)) + end + characters[k] = characters[v] + -- end + end + end + end + end +end + function fonts.tfm.read_from_tfm(specification) local fname, tfmdata = specification.filename, nil if fname then @@ -41,32 +70,24 @@ function fonts.tfm.read_from_tfm(specification) if fonts.trace then logs.report("define font",string.format("loading tfm file %s at size %s",fname,specification.size)) end - tfmdata = font.read_tfm(fname,specification.size) + tfmdata = font.read_tfm(fname,specification.size) -- not cached, fast enough if tfmdata then ---~ fonts.logger.save(tfmdata,'tfm',specification) ---~ if false then - fname = input.findbinfile(texmf.instance, specification.name, 'ovf') - if fname and fname ~= "" then -callback.register('find_vf_file', nil) - local vfdata = font.read_vf(fname,specification.size) - if vfdata then - local chars = tfmdata.characters - for k,v in ipairs(vfdata.characters) do - chars[k].commands = v.commands - end ---~ tfmdata.type = 'virtual' - local fnts = vfdata.fonts - for k,v in ipairs(fnts) do - local dummy, id = fonts.tfm.read_and_define(v.name,v.size) - fnts[k].id = id - if fonts.trace then - logs.report("define font",string.format("vf file %s needs tfm file %s (id %s)", fname, v.name, id)) + if fonts.tfm.resolve_vf then + fonts.logger.save(tfmdata,file.extname(fname),specification) -- strange, why here + fname = input.findbinfile(texmf.instance, specification.name, 'ovf') + if fname and fname ~= "" then + local vfdata = font.read_vf(fname,specification.size) -- not cached, fast enough + if vfdata then + local chars = tfmdata.characters + for k,v in pairs(vfdata.characters) do -- no ipairs, can have holes + chars[k].commands = v.commands end + tfmdata.type = 'virtual' + tfmdata.fonts = vfdata.fonts end - tfmdata.fonts = fnts end end ---~ end + fonts.tfm.enhance(tfmdata,specification) end else if fonts.trace then @@ -123,13 +144,13 @@ function fonts.tfm.scale(tfmtable, scaledpoints) local tc = t.characters for k,v in pairs(tfmtable.characters) do local chr = { - unicode = v.unicode, - name = v.name, - index = v.index or k, - width = scale(v.width , delta), - height = scale(v.height, delta), - depth = scale(v.depth , delta), - class = v.class + unicode = v.unicode, + name = v.name, + index = v.index or k, + width = scale(v.width , delta), + height = scale(v.height, delta), + depth = scale(v.depth , delta), + class = v.class } local b = v.boundingbox -- maybe faster to have llx etc not in table if b then @@ -158,13 +179,15 @@ function fonts.tfm.scale(tfmtable, scaledpoints) tp[k] = scale(v,delta) end end ---~ t.encodingbytes = tfmtable.encodingbytes or 2 +--~ t.encodingbytes = tfmtable.encodingbytes or 1 +--~ t.filename = t.filename or tfmtable.filename or tfmtable.file or nil +--~ t.fullname = t.fullname or tfmtable.fullname or tfmtable.full or nil +--~ t.name = t.name or tfmtable.name or nil t.size = scaledpoints t.italicangle = tfmtable.italicangle t.ascender = scale(tfmtable.ascender or 0,delta) t.descender = scale(tfmtable.descender or 0,delta) - -- new / some data will move here - t.shared = tfmtable.shared or { } + t.shared = tfmtable.shared or { } if t.unique then t.unique = table.fastcopy(tfmtable.unique) else @@ -180,8 +203,11 @@ we now have several readers it may be handy to know what reader is used for which font.

--ldx]]-- -function fonts.logger.save(tfmtable,source,specification) +function fonts.logger.save(tfmtable,source,specification) -- save file name in spec here ! ! ! ! ! ! if tfmtable and specification and specification.specification then + if fonts.trace then + logs.report("define font",string.format("registering %s as %s",specification.name,source)) + end specification.source = source fonts.loaded[specification.specification] = specification fonts.used[specification.name] = source diff --git a/tex/context/base/l-aux.lua b/tex/context/base/l-aux.lua index 59ff42539..f5aa7e67e 100644 --- a/tex/context/base/l-aux.lua +++ b/tex/context/base/l-aux.lua @@ -10,7 +10,7 @@ do hash = { } - function set(key,value) + local function set(key,value) hash[key] = value end @@ -34,6 +34,50 @@ do return hash end + local pattern = lpeg.Ct((space * value * comma)^1) + + function aux.settings_to_array(str) + return lpeg.match(pattern,str) + end + +end + +--~ do +--~ str = "a=1, b=2, c=3, d={abc}" + +--~ for k,v in pairs(aux.settings_to_hash (str)) do print(k,v) end +--~ for k,v in pairs(aux.settings_to_array(str)) do print(k,v) end +--~ end + +function aux.hash_to_string(h,separator,yes,no,strict) + if h then + local t = { } + for _,k in ipairs(table.sortedkeys(h)) do + local v = h[k] + if type(v) == "boolean" then + if yes and no then + if v then + t[#t+1] = k .. '=' .. yes + elseif not strict then + t[#t+1] = k .. '=' .. no + end + elseif v or not strict then + t[#t+1] = k .. '=' .. tostring(v) + end + else + t[#t+1] = k .. '=' .. v + end + end + return table.concat(t,separator or ",") + else + return "" + end end ---~ print(table.serialize(aux.settings_to_hash("aaa=bbb, ccc={d,d,d}"))) +function aux.array_to_string(a,separator) + if a then + return table.concat(a,separator or ",") + else + return "" + end +end diff --git a/tex/context/base/l-boolean.lua b/tex/context/base/l-boolean.lua index 128e1d069..e1efa4ad4 100644 --- a/tex/context/base/l-boolean.lua +++ b/tex/context/base/l-boolean.lua @@ -16,6 +16,8 @@ function toboolean(str) return str == "true" or str == "yes" or str == "on" or str == "1" elseif type(str) == "number" then return tonumber(str) ~= 0 + elseif type(str) == "nil" then + return false else return str end diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua index 67bf44b5a..496346b33 100644 --- a/tex/context/base/l-file.lua +++ b/tex/context/base/l-file.lua @@ -101,7 +101,7 @@ end --~ print("a/a" .. " == " .. file.collapse_path("a/b/c/../../a")) function file.collapse_path(str) - local ok = false + local ok, n = false, 0 while not ok do ok = true str, n = str:gsub("[^%./]+/%.%./", function(s) diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua index 9b594ff8a..9940de9b2 100644 --- a/tex/context/base/l-string.lua +++ b/tex/context/base/l-string.lua @@ -305,3 +305,15 @@ end --~ print(is_number("+0.1")) --~ print(is_number("-.1")) --~ print(is_number("+.1")) + +function string:split_settings() -- no {} handling, see l-aux for lpeg variant + if self:find("=") then + local t = { } + for k,v in self:gmatch("(%a+)=([^%,]*)") do + t[k] = v + end + return t + else + return nil + end +end diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua index 79d87139b..f68e29d23 100644 --- a/tex/context/base/l-table.lua +++ b/tex/context/base/l-table.lua @@ -65,6 +65,24 @@ function table.prepend(t, list) end end +function table.merge(t, ...) + for _, list in ipairs({...}) do + for k,v in pairs(list) do + t[k] = v + end + end +end + +function table.merged(...) + local tmp = { } + for _, list in ipairs({...}) do + for k,v in pairs(list) do + tmp[k] = v + end + end + return tmp +end + if not table.fastcopy then function table.fastcopy(old) -- fast one @@ -486,6 +504,24 @@ function table.are_equal(a,b,n,m) end end +function table.compact(t) + if t then + for k,v in pairs(t) do + if not next(v) then + t[k] = nil + end + end + end +end + +function table.tohash(t) + local h = { } + for _, v in pairs(t) do -- no ipairs here + h[v] = true + end + return h +end + --~ function table.are_equal(a,b) --~ return table.serialize(a) == table.serialize(b) --~ end diff --git a/tex/context/base/l-tex.lua b/tex/context/base/l-tex.lua index 3d87fe6e3..89925f602 100644 --- a/tex/context/base/l-tex.lua +++ b/tex/context/base/l-tex.lua @@ -89,7 +89,7 @@ end if lua then do - delayed = { } -- could also be done with closures + local delayed = { } -- could also be done with closures function lua.delay(f) delayed[#delayed+1] = f diff --git a/tex/context/base/l-utils.lua b/tex/context/base/l-utils.lua index 02efebe08..c4676a83d 100644 --- a/tex/context/base/l-utils.lua +++ b/tex/context/base/l-utils.lua @@ -113,10 +113,15 @@ function utils.merger.selfclean(name) ) end +utils.lua.compile_strip = true + function utils.lua.compile(luafile, lucfile) -- utils.report("compiling",luafile,"into",lucfile) os.remove(lucfile) - local command = "-s -o " .. string.quote(lucfile) .. " " .. string.quote(luafile) + local command = "-o " .. string.quote(lucfile) .. " " .. string.quote(luafile) + if utils.lua.compile_strip then + command = "-s " .. command + end if os.execute("texluac " .. command) == 0 then return true elseif os.execute("luac " .. command) == 0 then diff --git a/tex/context/base/l-xml.lua b/tex/context/base/l-xml.lua new file mode 100644 index 000000000..b60f521d2 --- /dev/null +++ b/tex/context/base/l-xml.lua @@ -0,0 +1,887 @@ +if not modules then modules = { } end modules ['l-xml'] = { + version = 1.001, + comment = "this module is the basis for the lxml-* ones", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +--[[ldx-- +

Tthe parser used here is inspired by the variant discussed in the lua book, but +handles comment and processing instructions, has a different structure, provides +parent access; a first version used different tricky but was less optimized to we +went this route.

+ +

Expecially the lpath code is experimental, we will support some of xpath, but +only things that make sense for us; as compensation it is possible to hook in your +own functions. Apart from preprocessing content for we also need +this module for process management, like handling and +files.

+ + +a/b/c /*/c (todo: a/b/(pattern)/d) +a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n) +a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n) + + +

Beware, the interface may change. For instance at, ns, tg, dt may get more +verbose names. Once the code is stable we will also removee some tracing and +optimize the code.

+--ldx]]-- + +xml = xml or { } +tex = tex or { } + +do + + -- The dreadful doctype comes in many disguises: + -- + -- + -- + -- + -- + -- + -- + + local doctype_patterns = { + "", + "", + "", + "", + "", + "" + } + + -- We assume no "<" which is the lunatic part of the xml spec + -- especially since ">" is permitted; otherwise we need a char + -- by char parser ... more something for later ... normally + -- entities will be used anyway. + + local function prepare(data) -- todo: option to delete doctype stuff, comment, etc + -- pack (for backward compatibility) + if type(data) == "table" then + data = table.concat(data,"") + end + -- CDATA + data = data:gsub("<%!%[CDATA%[(.-)%]%]>", function(txt) + return string.format("<@cd@>%s",txt:to_hex()) + end) + -- DOCTYPE + data = data:gsub("^(.-)(<[^%!%?])", function(a,b) + if a:find("%s",d:to_hex()) end) + end + end + return a .. b + end,1) + -- comment / does not catch doctype + data = data:gsub("<%!%-%-(.-)%-%->", function(txt) + return string.format("<@cm@>%s",txt:to_hex()) + end) + -- processing instructions + data = data:gsub("<%?(.-)%?>", function(txt) + return string.format("<@pi@>%s",txt:to_hex()) + end) + return data + end + + local function split(s) + local t = {} + for namespace, tag, _,val in s:gmatch("(%w-):?(%w+)=([\"\'])(.-)%3") do + if namespace == "" then + t[tag] = val + else + t[tag] = val + end + end + return t + end + + function xml.convert(data,no_root,collapse) + local data = prepare(data) + local stack, top = {}, {} + local i, j, errorstr = 1, 1, nil + stack[#stack+1] = top + top.dt = { } + local dt = top.dt + while true do + local ni, first, attributes, last, fulltag + ni, j, first, fulltag, attributes, last = data:find("<(/-)([^%s%>/]+)%s*([^>]-)%s*(/-)>", j) + if not ni then break end + local namespace, tag = fulltag:match("^(.-):(.+)$") + if not tag then + namespace, tag = "", fulltag + end + local text = data:sub(i, ni-1) + if (text == "") or (collapse and text:find("^%s*$")) then + -- no need for empty text nodes, beware, also packs x y z + -- so is not that useful unless used with empty elements + else + dt[#dt+1] = text + end + if first == "/" then + -- end tag + local toclose = table.remove(stack) -- remove top + top = stack[#stack] + if #stack < 1 then + errorstr = "nothing to close with " .. tag + break + end + if toclose.tg ~= tag then + errorstr = "unable to close " .. toclose.tg .. " with " .. tag + break + end + dt= top.dt + dt[#dt+1] = toclose + elseif last == "/" then + -- empty element tag + if attributes == "" then + dt[#dt+1] = { ns=namespace, tg=tag } + else + dt[#dt+1] = { ns=namespace, tg=tag, at=split(attributes) } + end + setmetatable(top, { __tostring = xml.text } ) + dt[#dt].__p__ = top + else + -- begin tag + if attributes == "" then + top = { ns=namespace, tg=tag, dt = { } } + else + top = { ns=namespace, tg=tag, at=split(attributes), dt = { } } + end + top.__p__ = stack[#stack] + setmetatable(top, { __tostring = xml.text } ) + dt = top.dt + stack[#stack+1] = top + end + i = j + 1 + end + if not errorstr then + local text = data:sub(i) + if dt and not text:find("^%s*$") then + dt[#dt+1] = text + end + if #stack > 1 then + errorstr = "unclosed " .. stack[#stack].tg + end + end + if errorstr then + -- stack = { [1] = { tg = "error", dt = { [1] = errorstr } } } + stack = { { tg = "error", dt = { errorstr } } } + setmetatable(stack, { __tostring = xml.text } ) + end + if no_root then + return stack[1] + else + local t = { tg = '@rt@', dt = stack[1].dt } + setmetatable(t, { __tostring = xml.text } ) + return t + end + end + +end + +function xml.load(filename,collapse) + if type(filename) == "string" then + local root, f = { }, io.open(filename,'r') -- no longer 'rb' + if f then + root = xml.convert(f:read("*all"),false,collapse) + f:close() + end + return root + else + return xml.convert(filename:read("*all"),false,collapse) + end +end + +function xml.toxml(data,collapse) + local t = { xml.convert(data,true,collapse) } + if #t > 1 then + return t + else + return t[1] + end +end + +function xml.serialize(e, handle, textconverter, attributeconverter) -- check if string:format is faster + local format = string.format + handle = handle or (tex and tex.sprint) or io.write + local function flush(before,e,after) + handle(before) + for _,ee in ipairs(e.dt) do -- i added, todo iloop + xml.serialize(ee,handle,string.from_hex) + end + handle(after) + end + if e then + if e.tg then + if e.tg == "@pi@" then + flush("") + elseif e.tg == "@cm@" then + flush("") + elseif e.tg == "@cd@" then + flush("") + elseif e.tg == "@dd@" then + flush("") + elseif e.tg == "@rt@" then + xml.serialize(e.dt,handle,textconverter,attributeconverter) + else + if e.ns ~= "" then + handle(format("<%s:%s",e.ns,e.tg)) + else + handle(format("<%s",e.tg)) + end + if e.at then + if attributeconverter then + for k,v in pairs(e.at) do + handle(format(' %s=%q',k,attributeconverter(v))) + end + else + for k,v in pairs(e.at) do + handle(format(' %s=%q',k,v)) + end + end + end + if e.dt then + handle(">") + for k,ee in ipairs(e.dt) do -- i added, for i=1,n is faster + xml.serialize(ee,handle,textconverter,attributeconverter) + end + handle(format("",e.tg)) + else + handle("/>") + end + end + elseif type(e) == "string" then + if textconverter then + handle(textconverter(e)) + else + handle(e) + end + else + for _,ee in ipairs(e) do -- i added + xml.serialize(ee,handle,textconverter,attributeconverter) + end + end + end +end + +function xml.string(e,handle) + if e.tg then + if e.dt then + for _,ee in ipairs(e.dt) do -- i added + xml.string(ee,handle) + end + end + else + handle(e) + end +end + +function xml.save(root,name) + local f = io.open(name,"w") + if f then + xml.serialize(root,function(s) f:write(s) end) + f:close() + end +end + +function xml.stringify(root) + local result = { } + xml.serialize(root,function(s) result[#result+1] = s end) + return table.concat(result,"") +end + +xml.tostring = xml.stringify + +function xml.stringify_text(root) -- no root element + if root and root.dt then + return xml.stringify(root) + else + return "" + end +end + +function xml.text(dt) -- no root element + if dt then + return xml.stringify(dt) + else + return "" + end +end + +function xml.body(t) -- removes initial pi + if t and t.dt and t.tg == "@rt@" then + for k,v in ipairs(t.dt) do + if type(v) == "table" and v.tg ~= "@pi@" then + return v + end + end + end + return t +end + +-- call: e[k] = xml.empty() or xml.empty(e,k) + +function xml.empty(e,k) -- erases an element but keeps the table intact + if e and k then + e[k] = "" + return e[k] + else + return "" + end +end + +-- call: e[k] = xml.assign(t) or xml.assign(e,k,t) + +function xml.assign(e,k,t) -- assigns xml tree / more testing will be done + if e and k then + if type(t) == "table" then + e[k] = xml.body(t) + else + e[k] = t -- no parsing + end + return e[k] + else + return xml.body(t) + end +end + +-- 0=nomatch 1=match 2=wildcard 3=ancestor + +-- "tag" +-- "tag1/tag2/tag3" +-- "*/tag1/tag2/tag3" +-- "/tag1/tag2/tag3" +-- "/tag1/tag2|tag3" +-- "tag[@att='value'] +-- "tag1|tag2[@att='value'] + +xml.trace_lpath = false + +function xml.tag(e) + return e.tg or "" +end + +function xml.att(e,a) + return (e.at and e.at[a]) or "" +end + +xml.attribute = xml.att + +do + + local cache = { } + + local function fault ( ) return 0 end + local function wildcard( ) return 2 end + local function result (b) if b then return 1 else return 0 end end + + -- we can avoid functions: m[i] = number|function + + function xml.lpath(str) --maybe @rt@ special + str = str or "*" + local m = cache[str] + if not m then + -- todo: text() + if not str then + if xml.trace_lpath then print("lpath", "no string", "wildcard") end + m = { + function(e) + if xml.trace_lpath then print(2, 1, "wildcard", e.tg) end + return 2 + end + } + elseif type(str) == "table" then + if xml.trace_lpath then print("lpath", "table" , "inherit") end + m = str + else + if str == "" or str == "*" then + if xml.trace_lpath then print("lpath", "empty or *", "wildcard") end + m = { + function(e) + if xml.trace_lpath then print(2, 2, "wildcard", e.tg) end + return 2 + end + } + else + m = { } + if str:find("^/") then + -- done in split + else + if xml.trace_lpath then print("lpath", "/", "wildcard") end + m[#m+1] = function(e,i) + if xml.trace_lpath then print(2, 3, "wildcard", e.tg) end + return 2 + end + end + for v in str:gmatch("([^/]+)") do + if v == "" or v == "*" then + if #m > 0 then -- when not, then we get problems with root being second (after (we could start at dt[2]) + if xml.trace_lpath then print("lpath", "empty or *", "wildcard") end + m[#m+1] = function(e,i) + if xml.trace_lpath then print(2, 4, "wildcard", e.ns, e.tg) end + return 2 + end + end + elseif v == ".." then + if xml.trace_lpath then print("lpath", "..", "ancestor") end + m[#m+1] = function(e,i) + if xml.trace_lpath then print(3, 5, "ancestor", e.__p__.tg) end + return 3 + end + else + local n, a, t = v:match("^(.-)%[@(.-)=(.-)%]$") + if n and a and t then + local s = "" + local ns, tg = n:match("^(.-):(.+)$") + if tg then + s, n = ns, tg + end + -- t = t:gsub("^([\'\"])([^%1]*)%1$", "%2") -- todo + t = t:gsub("^\'(.*)\'$", "%1") -- todo + t = t:gsub("^\"(.*)\"$", "%1") -- todo + if v:find("|") then + -- todo: ns ! ! ! ! ! ! ! ! ! + local tt = n:split("|") + if xml.trace_lpath then print("lpath", "match", t, n) end + m[#m+1] = function(e,i) + for _,v in ipairs(tt) do -- i added, todo: iloop + if e.at and e.tg == v and e.at[a] == t then + if xml.trace_lpath then print(1, 6, "element ", v, "attribute", t) end + return 1 + end + end + if xml.trace_lpath then print(1, 6, "no match") end + return 0 + end + else + if xml.trace_lpath then print("lpath", "match", t, n) end + m[#m+1] = function(e,i) + if e.at and e.ns == s and e.tg == n and e.at[a] == t then + if xml.trace_lpath then print(1, 7, "element ", n, "attribute", t) end + return 1 + else + if xml.trace_lpath then print(1, 7, "no match") end + return 0 + end + end + end + elseif v:find("|") then + local tt = v:split("|") + for k,v in ipairs(tt) do -- i added, iloop is faster + if xml.trace_lpath then print("lpath", "or match", v) end + local ns, tg = v:match("^(.-):(.+)$") + if not tg then + ns, tg = "", v + end + tt[k] = function(e,i) + if ns == e.ns and tg == e.tg then + if xml.trace_lpath then print(1, 8, "element ", ns, tg) end + return 1 + else + if xml.trace_lpath then print(1, 8, "no match", ns, tg) end + return 0 + end + end + end + m[#m+1] = function(e,i) + for _,v in ipairs(tt) do -- i added, iloop is faster + if v(e,i) then + return 1 + end + end + return 0 + end + else + if xml.trace_lpath then print("lpath", "match", v) end + local ns, tg = v:match("^(.-):(.+)$") + if not tg then + ns, tg = "", v + end + m[#m+1] = function(e,i) + if ns == e.ns and tg == e.tg then + if xml.trace_lpath then print(1, 9, "element ", ns, tg) end + return 1 + else + if xml.trace_lpath then print(1, 9, "no match", ns, tg) end + return 0 + end + end + end + end + end + end + if xml.trace_lpath then print("lpath", "result", str, "size", #m) end + end + cache[str] = m + end + return m + end + + function xml.traverse_tree(root,pattern,handle,reverse,index,wildcard) + if root and root.dt then + index = index or 1 + local match = pattern[index] or wildcard +--~ local prev = pattern[index-1] or fault -- better use the wildcard + local traverse = xml.traverse_tree + local rootdt = root.dt + local start, stop, step = 1, #rootdt, 1 + if reverse and index == #pattern then + start, stop, step = stop, start, -1 + end + for k=start,stop,step do + local e = rootdt[k] + if e.tg then + local m = (type(match) == "function" and match(e,index)) or match + if m == 1 then -- match + if index < #pattern then + if not traverse(e,pattern,handle,reverse,index+1) then return false end + elseif handle(rootdt,k) then + return false + end + elseif m == 2 then -- wildcard (not ok, now same as 3) + if index < #pattern then + if not traverse(e,pattern,handle,reverse,index+1,true) then return false end + elseif handle(rootdt,k) then + return false + end + elseif m == 3 then -- ancestor + local ep = e.__p__ + if index < #pattern then + if not traverse(ep,pattern,handle,reverse,index+1) then return false end + elseif handle(rootdt,k) then + return false + end +--~ elseif prev(e,index) == 2 then -- wildcard +--~ if not traverse(e,pattern,handle,reverse,index) then return false end + elseif wildcard then -- maybe two kind of wildcards: * ** // + if not traverse(e,pattern,handle,reverse,index,wildcard) then return false end + end + else + local edt = e.dt + if edt then + -- todo ancester + for kk=1,#edt do + local ee = edt[kk] + if match(ee,index) > 0 then + if index < #pattern then + if not traverse(ee,pattern,handle,reverse,index+1) then return false end + elseif handle(rootdt,k) then +--~ elseif handle(edt,kk) then + return false + end + elseif prev(ee) == 2 then + if not traverse(ee,pattern,handle,reverse,index) then return false end + end + end + end + end + end + end + return true + end + + local traverse, lpath, convert = xml.traverse_tree, xml.lpath, xml.convert + + xml.filters = { } + + function xml.filters.default(root,pattern) + local ee, kk + traverse(root, lpath(pattern), function(e,k) ee,kk = e,k return true end) + return ee and ee[kk], ee, kk + end + function xml.filters.reverse(root,pattern) + local ee, kk + traverse(root, lpath(pattern), function(e,k) ee,kk = e,k return true end,'reverse') + return ee and ee[kk], ee, kk + end + function xml.filters.count(root, pattern) + local n = 0 + traverse(root, lpath(pattern), function(e,k) n = n + 1 end) + return n + end + function xml.filters.first(root,pattern) + local ee, kk + traverse(root, lpath(pattern), function(e,k) ee,kk = e,k return true end) + return ee and ee[kk], ee, kk + end + function xml.filters.last(root,pattern) + local ee, kk + traverse(root, lpath(pattern), function(e,k) ee,kk = e,k return true end, 'reverse') + return ee and ee[kk], ee, kk + end + function xml.filters.index(root,pattern,arguments) + local ee, kk, reverse, i = nil, ni, false, tonumber(arguments or '1') or 1 + if i and i ~= 0 then + if i < 0 then + reverse, i = true, -i + end + traverse(root, lpath(pattern), function(e,k) ee, kk, i = e, k , i-1 return i == 0 end, reverse) + if i > 0 then + return nil, nil, nil + else + return ee and ee[kk], ee, kk + end + else + return nil, nil, nil + end + end + function xml.filters.attributes(root,pattern,arguments) + local ee, kk + traverse(root, lpath(pattern), function(e,k) ee,kk = e,k return true end) + local ekat = ee and ee[kk] and ee[kk].at + if ekat then + if arguments then + return ekat[arguments] or "", ee, kk + else + return ekat, ee, kk + end + else + return {}, ee, kk + end + end + function xml.filters.text(root,pattern,arguments) + local ek, ee, kk = xml.filters.index(root,pattern,arguments) + return (ek and ek.dt and ek.dt[1]) or "" + end + + function xml.filter(root,pattern) + local pat, fun, arg = pattern:match("^(.+)/(.-)%((.*)%)$") + if fun then + return (xml.filters[fun] or xml.filters.default)(root,pat,arg) + else + pat, arg = pattern:match("^(.+)/@(.-)$") + if arg then + return xml.filters.attributes(root,pat,arg) + else + return xml.filters.default(root,pattern) + end + end + end + + xml.filters.position = xml.filters.index + + -- these may go away + + xml.index_element = xml.filters.index + xml.count_elements = xml.filters.count + xml.first_element = xml.filters.first + xml.last_element = xml.filters.last + xml.index_text = xml.filters.text + xml.first_text = function (root,pattern) return xml.filters.text(root,pattern, 1) end + xml.last_text = function (root,pattern) return xml.filters.text(root,pattern,-1) end + + -- so far + + function xml.get_text(root,pattern,reverse) + local ek + traverse(root, lpath(pattern), function(e,k) ek = e and e[k] end, reverse) + return (ek and ek.dt and ek.dt[1]) or "" + end + + function xml.each_element(root, pattern, handle, reverse) + local ok + traverse(root, lpath(pattern), function(e,k) ok = true handle(e[k],e,k) end, reverse) + return ok + end + + function xml.get_element(root,pattern,reverse) + local ee, kk + traverse(root, lpath(pattern), function(e,k) ee,kk = e,k end, reverse) + return ee and ee[kk], ee, kk + end + + function xml.all_elements(root, pattern, handle, reverse) + local t = { } + traverse(root, lpath(pattern), function(e,k) t[#t+1] = e[k] end) + return t + end + + function xml.all_texts(root, pattern, handle, reverse) + local t = { } + traverse(root, lpath(pattern), function(e,k) + local ek = e[k] + t[#t+1] = (ek and ek.dt and ek.dt[1]) or "" + end) + return t + end + + -- array for each + + function xml.insert_element(root, pattern, element, before) -- todo: element als functie + if root and element then + local matches, collect = { }, nil + if type(element) == "string" then + element = convert(element,true) + end + if element and element.td == "@rt@" then + element = element.dt + end + if element then + if before then + collect = function(e,k) matches[#matches+1] = { e, element, k } end + else + collect = function(e,k) matches[#matches+1] = { e, element, k + 1 } end + end + traverse(root, lpath(pattern), collect) + for i=#matches,1,-1 do + local m = matches[i] + local t, element, at = m[1],m[2],m[3] + -- when string, then element is { dt = { ... }, { ... } } + if element.tg then + table.insert(t,at,element) -- untested + elseif element.dt then + for _,v in ipairs(element.dt) do -- i added + table.insert(t,at,v) + at = at + 1 + end + end + end + end + end + end + + -- first, last, each + + xml.insert_element_after = xml.insert_element + xml.insert_element_before = function(r,p,e) xml.insert_element(r,p,e,true) end + + function xml.delete_element(root, pattern) + local matches, deleted = { }, { } + local collect = function(e,k) matches[#matches+1] = { e, k } end + traverse(root, lpath(pattern), collect) + for i=#matches,1,-1 do + local m = matches[i] + deleted[#deleted+1] = table.remove(m[1],m[2]) + end + return deleted + end + + function xml.replace_element(root, pattern, element) + if type(element) == "string" then + element = convert(element,true) + end + if element and element.td == "@rt@" then + element = element.dt + end + if element then + local collect = function(e,k) + e[k] = element.dt -- maybe not clever enough + end + traverse(root, lpath(pattern), collect) + end + end + + function xml.process(root, pattern, handle) + traverse(root, lpath(pattern), function(e,k) + if e[k].dt then + for k,v in ipairs(e[k].dt) do if v.tg then handle(v) end end -- i added + end + end) + end + + -- function xml.process_attributes(root, pattern, handle) + -- traverse(root, lpath(pattern), function(e,k) handle(e[k].at) end) + -- end + + function xml.process_attributes(root, pattern, handle) + traverse(root, lpath(pattern), function(e,k) + local ek = e[k] + local a = ek.at or { } + handle(a) + if next(a) then + ek.at = a + else + ek.at = nil + end + end) + end + + function xml.package(tag,attributes,data) + local n, t = tag:match("^(.-):(.+)$") + if attributes then + return { ns = n or "", tg = t or tag, dt = data or "", at = attributes } + else + return { ns = n or "", tg = t or tag, dt = data or "" } + end + end + + -- some special functions, handy for the manual: + + function xml.gsub(t,old,new) + if t.dt then + for k,v in ipairs(t.dt) do + if type(v) == "string" then + t.dt[k] = v:gsub(old,new) + else + xml.gsub(v,old,new) + end + end + end + end + + function xml.strip_leading_spaces(ek, e, k) -- cosmetic, for manual + if e and k and e[k-1] and type(e[k-1]) == "string" then + local s = e[k-1]:match("\n(%s+)") + xml.gsub(ek,"\n"..string.rep(" ",#s),"\n") + end + end + + function xml.serialize_path(root,lpath,handle) + local ek, e, k = xml.first_element(root,lpath) + ek = table.copy(ek) + xml.strip_leading_spaces(ek,e,k) + xml.serialize(ek,handle) + end + +end + +xml.count = xml.filters.count +xml.index = xml.filters.index +xml.first = xml.filters.first +xml.last = xml.filters.last + +xml.each = xml.each_element +xml.all = xml.all_elements + +xml.insert = xml.insert_element_after +xml.after = xml.insert_element_after +xml.before = xml.insert_element_before +xml.delete = xml.delete_element +xml.replace = xml.replace_element + +-- a few helpers, the may move to lxml modules + +function xml.include(xmldata,element,attribute,pathlist,collapse) + element = element or 'ctx:include' + attribute = attribute or 'name' + pathlist = pathlist or { '.' } + local function include(ek,e,k) + local name = (ek.at and ek.at[attribute]) or "" + if name ~= "" then + -- maybe file lookup in tree + local fullname + for _, path in ipairs(pathlist) do + if path == '.' then + fullname = name + else + fullname = file.join(path,name) + end + local f = io.open(fullname) + if f then + xml.assign(e,k,xml.load(f,collapse)) + f:close() + break + else + xml.empty(e,k) + end + end + else + xml.empty(e,k) + end + end + while xml.each(xmldata, element, include) do end +end + diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua index 5259a085e..aa00a8fd1 100644 --- a/tex/context/base/lang-ini.lua +++ b/tex/context/base/lang-ini.lua @@ -108,7 +108,7 @@ do local bynode = node.traverse local bychar = string.utfcharacters - function reconstruct(prev,str,fnt) + local function reconstruct(prev,str,fnt) local done = false if #str < 4 then -- too short diff --git a/tex/context/base/lang-sla.mkiv b/tex/context/base/lang-sla.mkiv index dfa56bab5..479012615 100644 --- a/tex/context/base/lang-sla.mkiv +++ b/tex/context/base/lang-sla.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\def\sloveniancharacters#1{\ctxlua{convert.alphabetic(\number#1,"sl")}} -\def\slovenianCharacters#1{\ctxlua{convert.Alphabetic(\number#1,"sl")}} +\def\sloveniancharacters#1{\ctxlua{converters.alphabetic(\number#1,"sl")}} +\def\slovenianCharacters#1{\ctxlua{converters.Alphabetic(\number#1,"sl")}} \endinput diff --git a/tex/context/base/luat-cbk.lua b/tex/context/base/luat-cbk.lua index a6145ec3b..efb534d7d 100644 --- a/tex/context/base/luat-cbk.lua +++ b/tex/context/base/luat-cbk.lua @@ -104,7 +104,7 @@ do garbagecollector.trace = false garbagecollector.tune = false -- for the moment - function report(format) + local function report(format) if garbagecollector.trace then -- texio.write_nl(string.format(format,level,status.luastate_bytes)) texio.write_nl(string.format(format,level,collectgarbage("count"))) diff --git a/tex/context/base/luat-crl.lua b/tex/context/base/luat-crl.lua index 9d15b4896..129832765 100644 --- a/tex/context/base/luat-crl.lua +++ b/tex/context/base/luat-crl.lua @@ -4,10 +4,10 @@ -- copyright: PRAGMA ADE / ConTeXt Development Team -- license : see context related readme files -if not versions then versions = { } end versions['luat-crl'] = 1.001 -if not curl then curl = { } end +if not versions then versions = { } end versions['luat-crl'] = 1.001 +if not curl then curl = { } end -curl.cachepath = cache.setpath(texmf.instance,"curl") +curl.cachepath = caches.setpath(texmf.instance,"curl") curl.cached = { } diff --git a/tex/context/base/luat-ini.lua b/tex/context/base/luat-ini.lua index 022055e7f..e7757d51b 100644 --- a/tex/context/base/luat-ini.lua +++ b/tex/context/base/luat-ini.lua @@ -7,5 +7,20 @@ if not modules then modules = { } end modules ['luat-ini'] = { } --[[ldx-- -

We cannot load anything yet.

+

We cannot load anything yet. However what we will do us reserve a fewtables. +These can be used for runtime user data or third party modules and will not be +cluttered by macro package code.

+--ldx]]-- + +userdata = userdata or { } +thirddata = thirddata or { } +document = document or { } + +--[[ldx-- +

Please create a namespace within these tables before using them!

+ + +userdata ['my.name'] = { } +thirddata['tricks' ] = { } + --ldx]]-- diff --git a/tex/context/base/luat-ini.tex b/tex/context/base/luat-ini.tex index 800950baf..3b0a61e62 100644 --- a/tex/context/base/luat-ini.tex +++ b/tex/context/base/luat-ini.tex @@ -41,27 +41,25 @@ %D A few more goodies: -\def\dostartlua#1% +\long\def\dostartlua#1% {\begingroup \obeylualines - \directlua#1\iftrue{\else}\fi} + \dodostartlua{#1}} -\def\dostoplua - {\iffalse{\else}\fi - \endgroup} +\long\def\dodostartlua#1#2\stoplua + {\expanded{\endgroup\noexpand\directlua#1{#2}}} -\def\dostartluacode#1% +\long\def\dostartluacode#1% {\begingroup \obeylualines \obeyluatokens - \directlua#1\iftrue{\else}\fi} + \dodostartluacode{#1}} -\def\dostopluacode % no unexpanded, else no } seen - {\iffalse{\else}\fi - \endgroup} +\long\def\dodostartluacode#1#2\stopluacode + {\expanded{\endgroup\noexpand\directlua#1{#2}}} -\def\startlua {\dostartlua \zerocount} \def\stoplua {\dostoplua} -\def\startluacode{\dostartluacode\zerocount} \def\stopluacode {\dostopluacode} +\def\startlua {\dostartlua \zerocount} +\def\startluacode{\dostartluacode\zerocount} %D Some delayed definitions: diff --git a/tex/context/base/luat-inp.lua b/tex/context/base/luat-inp.lua index 6551d1011..541bde5c3 100644 --- a/tex/context/base/luat-inp.lua +++ b/tex/context/base/luat-inp.lua @@ -72,6 +72,7 @@ input.formats['pfb'] = 'T1FONTS' input.suffixes['pfb'] = { 'pfb', 'pfa' } input.formats['vf'] = 'VFFONTS' input.suffixes['vf'] = { 'vf' } input.formats['fea'] = 'FONTFEATURES' input.suffixes['fea'] = { 'fea' } +input.formats['cid'] = 'FONTCIDMAPS' input.suffixes['cid'] = { 'cid', 'cidmap' } input.formats ['texmfscripts'] = 'TEXMFSCRIPTS' -- new input.suffixes['texmfscripts'] = { 'rb', 'pl', 'py' } -- 'lua' @@ -79,10 +80,10 @@ input.suffixes['texmfscripts'] = { 'rb', 'pl', 'py' } -- 'lua' input.formats ['lua'] = 'LUAINPUTS' -- new input.suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } --- here we catch a few new thingies +-- here we catch a few new thingies (todo: add these paths to context.tmf) function input.checkconfigdata(instance) - function fix(varname,default) + local function fix(varname,default) local proname = varname .. "." .. instance.progname or "crap" if not instance.environment[proname] and not instance.variables[proname] == "" and not instance.environment[varname] and not instance.variables[varname] == "" then instance.variables[varname] = default @@ -90,6 +91,7 @@ function input.checkconfigdata(instance) end fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") fix("FONTFEATURES", ".;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTCIDMAPS" , ".;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") end -- backward compatible ones @@ -98,6 +100,8 @@ input.alternatives = { } input.alternatives['map files'] = 'map' input.alternatives['enc files'] = 'enc' +input.alternatives['cid files'] = 'cid' +input.alternatives['fea files'] = 'fea' input.alternatives['opentype fonts'] = 'otf' input.alternatives['truetype fonts'] = 'ttf' input.alternatives['truetype collections'] = 'ttc' @@ -609,8 +613,11 @@ function input.generators.tex(instance,specification) full = spec end for name in directory(full) do - if name == '.' or name == ".." then - -- skip + if name:find("^%.") then + -- skip + elseif name:find("[%~%`%!%#%$%%%^%&%*%(%)%=%{%}%[%]%:%;\"\'%|%|%<%>%,%?\n\r\t]") then + -- texio.write_nl("skipping " .. name) + -- skip else mode = attributes(full..name,'mode') if mode == "directory" then @@ -1407,7 +1414,7 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec pathname = pathname:gsub("([%-%.])","%%%1") -- this also influences pathname = pathname:gsub("/+$", '/.*') -- later usage of pathname pathname = pathname:gsub("//", '/.-/') - expr = "^" .. pathname + local expr = "^" .. pathname -- input.debug('?',expr) for _, f in pairs(filelist) do if f:find(expr) then @@ -1529,7 +1536,8 @@ end function input.find_given_files(instance,filename) local bname, result = file.basename(filename), { } for k, hash in ipairs(instance.hashes) do - local blist = instance.files[hash.tag][bname] + local files = instance.files[hash.tag] + local blist = files[bname] if not blist then local rname = "remap:"..bname blist = files[rname] @@ -1596,9 +1604,11 @@ function input.find_wildcard_files(instance,filename) -- todo: remap: if name:find("%*") then for k, hash in ipairs(instance.hashes) do for kk, hh in pairs(files[hash.tag]) do - if (kk:lower()):find(name) then - if doit(hh,kk,hash,allresults) then done = true end - if done and not allresults then break end + if not kk:find("^remap:") then + if (kk:lower()):find(name) then + if doit(hh,kk,hash,allresults) then done = true end + if done and not allresults then break end + end end end end @@ -1812,7 +1822,7 @@ function input.validators.visibility.context(path, name) path = path[1] or path -- some day a loop return not ( path:find("latex") or - path:find("doc") or +-- path:find("doc") or path:find("tex4ht") or path:find("source") or -- path:find("config") or @@ -1869,17 +1879,49 @@ function input.with_files(instance,pattern,handle) end end -function input.update_script(oldname,newname) -- oldname -> own.name, not per se a suffix +--~ function input.update_script(oldname,newname) -- oldname -> own.name, not per se a suffix +--~ newname = file.addsuffix(newname,"lua") +--~ local newscript = input.clean_path(input.find_file(instance, newname)) +--~ local oldscript = input.clean_path(oldname) +--~ input.report("old script", oldscript) +--~ input.report("new script", newscript) +--~ if oldscript ~= newscript and (oldscript:find(file.removesuffix(newname).."$") or oldscript:find(newname.."$")) then +--~ local newdata = io.loaddata(newscript) +--~ if newdata then +--~ input.report("old script content replaced by new content") +--~ io.savedata(oldscript,newdata) +--~ end +--~ end +--~ end + +function input.update_script(instance,oldname,newname) -- oldname -> own.name, not per se a suffix + local scriptpath = "scripts/context/lua" newname = file.addsuffix(newname,"lua") - newscript = input.clean_path(input.find_file(instance, newname)) - oldscript = input.clean_path(oldname) - input.report("old script", oldscript) - input.report("new script", newscript) - if oldscript ~= newscript and (oldscript:find(file.removesuffix(newname).."$") or oldscript:find(newname.."$")) then - newdata = io.loaddata(newscript) - if newdata then - input.report("old script content replaced by new content") - io.savedata(oldscript,newdata) + local oldscript = input.clean_path(oldname) + input.report("to be replaced old script", oldscript) + local newscripts = input.find_files(instance, newname) or { } + if #newscripts == 0 then + input.report("unable to locate new script") + else + for _, newscript in ipairs(newscripts) do + newscript = input.clean_path(newscript) + input.report("checking new script", newscript) + if oldscript == newscript then + input.report("old and new script are the same") + elseif not newscript:find(scriptpath) then + input.report("new script should come from",scriptpath) + elseif not (oldscript:find(file.removesuffix(newname).."$") or oldscript:find(newname.."$")) then + input.report("invalid new script name") + else + local newdata = io.loaddata(newscript) + if newdata then + input.report("old script content replaced by new content") + io.savedata(oldscript,newdata) + break + else + input.report("unable to load new script") + end + end end end end diff --git a/tex/context/base/luat-lib.tex b/tex/context/base/luat-lib.tex index 6c5c63227..84b5bcfff 100644 --- a/tex/context/base/luat-lib.tex +++ b/tex/context/base/luat-lib.tex @@ -49,7 +49,7 @@ \registerctxluafile{l-utils} {1.001} \registerctxluafile{l-tex} {1.001} \registerctxluafile{l-xml} {1.001} -\registerctxluafile{l-xmlctx} {1.001} +%registerctxluafile{l-xmlctx} {1.001} \registerctxluafile{luat-cbk} {1.001} \registerctxluafile{luat-lib} {1.001} diff --git a/tex/context/base/luat-tex.lua b/tex/context/base/luat-tex.lua index 8e770f9de..1b2412594 100644 --- a/tex/context/base/luat-tex.lua +++ b/tex/context/base/luat-tex.lua @@ -60,7 +60,7 @@ if texconfig and not texlua then t = { utftype = u, -- may go away lines = l, - current = 0, + current = 0, -- line number, not really needed handle = nil, noflines = #l, close = function() @@ -68,15 +68,23 @@ if texconfig and not texlua then input.show_close(filename) end, reader = function(self) - if not self then self = t end - if self.current >= #self.lines then + self = self or t + local current, lines = self.current, self.lines + if current >= #lines then return nil else - self.current = self.current + 1 - if input.filters.utf_translator then - return input.filters.utf_translator(self.lines[t.current]) + self.current = current + 1 + local line = lines[self.current] + if line == "" then + return "" else - return self.lines[self.current] + local translator = input.filters.utf_translator + -- return (translator and translator(line)) or line + if translator then + return translator(line) + else + return line + end end end end @@ -86,13 +94,15 @@ if texconfig and not texlua then -- todo: file;name -> freeze / eerste regel scannen -> freeze t = { reader = function(self) - if not self then self = t end -- not used - if input.filters.dynamic_translator then - return input.filters.dynamic_translator(file_handle:read()) + local line = file_handle:read() + if line == "" then + return "" elseif input.filters.utf_translator then - return input.filters.utf_translator(file_handle:read()) + return input.filters.utf_translator(line) + elseif input.filters.dynamic_translator then + return input.filters.dynamic_translator(line) else - return file_handle:read() + return line end end, close = function() diff --git a/tex/context/base/luat-tmp.lua b/tex/context/base/luat-tmp.lua index 84966bd2c..58a195986 100644 --- a/tex/context/base/luat-tmp.lua +++ b/tex/context/base/luat-tmp.lua @@ -22,30 +22,30 @@ being written at the same time is small. We also need to extend luatools with a recache feature.

--ldx]]-- -cache = cache or { } -dir = dir or { } -texmf = texmf or { } - -cache.path = cache.path or nil -cache.base = cache.base or "luatex-cache" -cache.more = cache.more or "context" -cache.direct = false -- true is faster but may need huge amounts of memory -cache.trace = false -cache.tree = false -cache.temp = cache.temp or os.getenv("TEXMFCACHE") or os.getenv("HOME") or os.getenv("HOMEPATH") or os.getenv("VARTEXMF") or os.getenv("TEXMFVAR") or os.getenv("TMP") or os.getenv("TEMP") or os.getenv("TMPDIR") or nil -cache.paths = cache.paths or { cache.temp } - -if not cache.temp or cache.temp == "" then +caches = caches or { } +dir = dir or { } +texmf = texmf or { } + +caches.path = caches.path or nil +caches.base = caches.base or "luatex-cache" +caches.more = caches.more or "context" +caches.direct = false -- true is faster but may need huge amounts of memory +caches.trace = false +caches.tree = false +caches.temp = caches.temp or os.getenv("TEXMFCACHE") or os.getenv("HOME") or os.getenv("HOMEPATH") or os.getenv("VARTEXMF") or os.getenv("TEXMFVAR") or os.getenv("TMP") or os.getenv("TEMP") or os.getenv("TMPDIR") or nil +caches.paths = caches.paths or { caches.temp } + +if not caches.temp or caches.temp == "" then print("\nFATAL ERROR: NO VALID TEMPORARY PATH\n") os.exit() end -function cache.configpath(instance) +function caches.configpath(instance) return input.expand_var(instance,"TEXMFCNF") end -function cache.treehash(instance) - local tree = cache.configpath(instance) +function caches.treehash(instance) + local tree = caches.configpath(instance) if not tree or tree == "" then return false else @@ -53,49 +53,49 @@ function cache.treehash(instance) end end -function cache.setpath(instance,...) - if not cache.path then +function caches.setpath(instance,...) + if not caches.path then if lfs and instance then - for _,v in pairs(cache.paths) do + for _,v in pairs(caches.paths) do for _,vv in pairs(input.expanded_path_list(instance,v)) do if lfs.isdir(vv) then - cache.path = vv + caches.path = vv break end end - if cache.path then break end + if caches.path then break end end end - if not cache.path then - cache.path = cache.temp + if not caches.path then + caches.path = caches.temp end - cache.path = input.clean_path(cache.path) -- to be sure + caches.path = input.clean_path(caches.path) -- to be sure if lfs then - cache.tree = cache.tree or cache.treehash(instance) - if cache.tree then - cache.path = dir.mkdirs(cache.path,cache.base,cache.more,cache.tree) + caches.tree = caches.tree or caches.treehash(instance) + if caches.tree then + caches.path = dir.mkdirs(caches.path,caches.base,caches.more,caches.tree) else - cache.path = dir.mkdirs(cache.path,cache.base,cache.more) + caches.path = dir.mkdirs(caches.path,caches.base,caches.more) end end end - if not cache.path then - cache.path = '.' + if not caches.path then + caches.path = '.' end - cache.path = input.clean_path(cache.path) + caches.path = input.clean_path(caches.path) if lfs and not table.is_empty({...}) then - local pth = dir.mkdirs(cache.path,...) + local pth = dir.mkdirs(caches.path,...) return pth end - return cache.path + return caches.path end -function cache.setluanames(path,name) +function caches.setluanames(path,name) return path .. "/" .. name .. ".tma", path .. "/" .. name .. ".tmc" end -function cache.loaddata(path,name) - local tmaname, tmcname = cache.setluanames(path,name) +function caches.loaddata(path,name) + local tmaname, tmcname = caches.setluanames(path,name) local loader = loadfile(tmcname) or loadfile(tmaname) if loader then return loader() @@ -104,18 +104,18 @@ function cache.loaddata(path,name) end end -function cache.is_writable(filepath,filename) - local tmaname, tmcname = cache.setluanames(filepath,filename) +function caches.is_writable(filepath,filename) + local tmaname, tmcname = caches.setluanames(filepath,filename) return file.is_writable(tmaname) end -function cache.savedata(filepath,filename,data,raw) -- raw needed for file cache - local tmaname, tmcname = cache.setluanames(filepath,filename) +function caches.savedata(filepath,filename,data,raw) -- raw needed for file cache + local tmaname, tmcname = caches.setluanames(filepath,filename) local reduce, simplify = true, true if raw then reduce, simplify = false, false end - if cache.direct then + if caches.direct then file.savedata(tmaname, table.serialize(data,'return',true,true)) else table.tofile (tmaname, data,'return',true,true) -- maybe not the last true @@ -127,7 +127,7 @@ end if tex and texconfig and texconfig.formatname and texconfig.formatname == "" then if not texconfig.luaname then texconfig.luaname = "cont-en.lua" end - texconfig.formatname = cache.setpath(instance,"format") .. "/" .. texconfig.luaname:gsub("%.lu.$",".fmt") + texconfig.formatname = caches.setpath(instance,"format") .. "/" .. texconfig.luaname:gsub("%.lu.$",".fmt") end --[[ldx-- @@ -149,7 +149,7 @@ containers.trace = false do -- local report local function report(container,tag,name) - if cache.trace or containers.trace or container.trace then + if caches.trace or containers.trace or container.trace then logs.report(string.format("%s cache",container.subcategory),string.format("%s: %s",tag,name or 'invalid')) end end @@ -163,7 +163,7 @@ do -- local report enabled = enabled, version = version or 1.000, trace = false, - path = cache.setpath(texmf.instance,category,subcategory), + path = caches.setpath(texmf.instance,category,subcategory), } else return nil @@ -171,13 +171,13 @@ do -- local report end function containers.is_usable(container, name) - return container.enabled and cache.is_writable(container.path, name) + return container.enabled and caches.is_writable(container.path, name) end function containers.is_valid(container, name) if name and name ~= "" then - local cs = container.storage[name] - return cs and not table.is_empty(cs) and cs.cache_version == container.version + local storage = container.storage[name] + return storage and not table.is_empty(storage) and storage.cache_version == container.version else return false end @@ -185,7 +185,7 @@ do -- local report function containers.read(container,name) if container.enabled and not container.storage[name] then - container.storage[name] = cache.loaddata(container.path,name) + container.storage[name] = caches.loaddata(container.path,name) if containers.is_valid(container,name) then report(container,"loaded",name) else @@ -204,7 +204,7 @@ do -- local report if container.enabled then local unique, shared = data.unique, data.shared data.unique, data.shared = nil, nil - cache.savedata(container.path, name, data) + caches.savedata(container.path, name, data) report(container,"saved",name) data.unique, data.shared = unique, shared end @@ -229,7 +229,7 @@ function input.aux.save_data(instance, dataname, check) for cachename, files in pairs(instance[dataname]) do local name if input.usecache then - name = file.join(cache.setpath(instance,"trees"),md5.hex(cachename)) + name = file.join(caches.setpath(instance,"trees"),md5.hex(cachename)) else name = file.join(cachename,dataname) end @@ -321,7 +321,7 @@ end function input.aux.load_data(instance,pathname,dataname,filename) local luaname, lucname, pname, fname if input.usecache then - pname, fname = cache.setpath(instance,"trees"), md5.hex(pathname) + pname, fname = caches.setpath(instance,"trees"), md5.hex(pathname) filename = file.join(pname,fname) else if not filename or (filename == "") then @@ -357,7 +357,7 @@ input.automounted = input.automounted or { } function input.automount(instance,usecache) local mountpaths = input.simplified_list(input.expansion(instance,'TEXMFMOUNT')) if table.is_empty(mountpaths) and usecache then - mountpaths = { cache.setpath(instance,"mount") } + mountpaths = { caches.setpath(instance,"mount") } end if not table.is_empty(mountpaths) then input.starttiming(instance) diff --git a/tex/context/base/luat-tra.lua b/tex/context/base/luat-tra.lua index 90756d359..f5c077f41 100644 --- a/tex/context/base/luat-tra.lua +++ b/tex/context/base/luat-tra.lua @@ -8,61 +8,79 @@ if not versions then versions = { } end versions['luat-tra'] = 1.001 debugger = { } -debugger.counters = { } -debugger.names = { } - -function debugger.hook() - local f = debug.getinfo(2,"f").func - if debugger.counters[f] == nil then - debugger.counters[f] = 1 - debugger.names[f] = debug.getinfo(2,"Sn") - else - debugger.counters[f] = debugger.counters[f] + 1 +do + + local counters = { } + local names = { } + local getinfo = debug.getinfo + + local function hook() + local f = getinfo(2,"f").func + if f then + if counters[f] == nil then + counters[f] = 1 +--~ names[f] = debug.getinfo(2,"Sn") +--~ names[f] = debug.getinfo(2,"n") + names[f] = debug.getinfo(f) + else + counters[f] = counters[f] + 1 + end + end end -end -function debugger.getname(func) - local n = debugger.names[func] - if n.what == "C" then - return n.name + local function getname(func) + local n = names[func] + if n then + if n.what == "C" then + return n.name or '' + else + -- source short_src linedefined what name namewhat nups func + local name = n.name or n.namewhat or n.what + if not name or name == "" then name = "?" end + return string.format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name) + end + else + return "unknown" + end end - local lc = string.format("[%s]:%s", n.short_src, n.linedefined) - if n.namewhat ~= "" then - return string.format("%s (%s)", lc, n.name) - else - return lc + + function debugger.showstats(printer,threshold) + printer = printer or texio.write or print + threshold = threshold or 0 + local total, grandtotal, functions = 0, 0, 0 + printer("\n") -- ugly but ok + for func, count in pairs(counters) do + if count > threshold then + printer(string.format("%8i %s\n", count, getname(func))) + total = total + count + end + grandtotal = grandtotal + count + functions = functions + 1 + end + printer(string.format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold)) end -end -function debugger.showstats(printer,threshold) - if not printer then printer = print end - if not threshold then threshold = 0 end - for func, count in pairs(debugger.counters) do - if count > threshold then - printer(string.format("%8i %s\n", count, debugger.getname(func))) + function debugger.savestats(filename,threshold) + local f = io.open(filename,'w') + if f then + debugger.showstats(function(str) f:write(str) end,threshold) + f:close() end end -end -function debugger.savestats(filename,threshold) - local f = io.open(filename,'w') - if f then - debugger.showstats(function(str) f:write(str) end,threshold) - f:close() + function debugger.enable() + debug.sethook(hook,"c") end -end -function debugger.enable() - debug.sethook(debugger.hook,"c") -end + function debugger.disable() + debug.sethook() + --~ counters[debug.getinfo(2,"f").func] = nil + end -function debugger.disable() - debug.sethook() ---~ debugger.counters[debug.getinfo(2,"f").func] = nil -end + function debugger.tracing() + return tonumber((os.env['MTX.TRACE.CALLS'] or os.env['MTX_TRACE_CALLS'] or 0)) > 0 + end -function debugger.tracing() - return tonumber((os.env['MTX.TRACE.CALLS'] or os.env['MTX_TRACE_CALLS'] or 0)) > 0 end --~ debugger.enable() diff --git a/tex/context/base/lxml-ini.lua b/tex/context/base/lxml-ini.lua new file mode 100644 index 000000000..f2a42eeea --- /dev/null +++ b/tex/context/base/lxml-ini.lua @@ -0,0 +1,33 @@ +if not modules then modules = { } end modules ['lxml-ini'] = { + version = 1.001, + comment = "companion to lxml-ini.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +document = document or { } +document.xml = document.xml or { } + +lxml = { } +lxml.loaded = { } + +function lxml.root(id) + return lxml.loaded[id] +end + +function lxml.load(id,filename) + lxml.loaded[id] = xml.load(filename) +end + +function lxml.first(id,pattern) + tex.sprint(xml.tostring(xml.first_text(lxml.loaded[id],pattern))) +end + +function lxml.last(id,pattern) + tex.sprint(xml.tostring(xml.last_text (lxml.loaded[id],pattern))) +end + +function lxml.index(id,pattern,i) + tex.sprint(xml.tostring(xml.index_text(lxml.loaded[id],pattern,i))) +end diff --git a/tex/context/base/lxml-ini.tex b/tex/context/base/lxml-ini.tex new file mode 100644 index 000000000..3f21bf0fa --- /dev/null +++ b/tex/context/base/lxml-ini.tex @@ -0,0 +1,23 @@ +%D \module +%D [ file=lxml-ini, +%D version=2007.08.17, +%D title=\CONTEXT\ \LUA\ based \XML\ Support, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{Context L-XML Macros (initialization)} + +\registerctxluafile{lxml-ini}{1.001} + +\def\xmlload #1#2{\ctxlua{lxml.load ("#1","#2")}} +\def\xmlfirst #1#2{\ctxlua{lxml.first("#1","#2")}} +\def\xmllast #1#2{\ctxlua{lxml.last ("#1","#2")}} +\def\xmlindex#1#2#3{\ctxlua{lxml.index("#1","#2",#3)}} + +\endinput diff --git a/tex/context/base/meta-mis.tex b/tex/context/base/meta-mis.tex index 6b39fa0dd..29ab43007 100644 --- a/tex/context/base/meta-mis.tex +++ b/tex/context/base/meta-mis.tex @@ -27,7 +27,7 @@ currentpicture := currentpicture shifted (-4cm,0) ; fill fullcircle scaled 3cm withcolor cmyk(0,0,1,0) ; fill fullcircle scaled 2cm withcolor cmyk(0,1,0,0) ; - fill fullcircle scaled 1cm withcolor cmyk(0,0,1,0) ; + fill fullcircle scaled 1cm withcolor cmyk(1,0,0,0) ; currentpicture := currentpicture shifted (-4cm,0) ; draw fullcircle scaled 3cm dashed evenly ; draw fullcircle scaled 2cm dashed withdots ; diff --git a/tex/context/base/meta-pdf.lua b/tex/context/base/meta-pdf.lua index 56e09bb1f..3a745da17 100644 --- a/tex/context/base/meta-pdf.lua +++ b/tex/context/base/meta-pdf.lua @@ -105,7 +105,7 @@ end function mptopdf.steps.convert() mptopdf.data = mptopdf.data:gsub("%c%((.-)%) (.-) (.-) fshow", function(str,font,scale) - table.insert(mptopdf.texts,{mptopdf.steps.descape(str), font, scale}) + mptopdf.texts[mptopdf.texts+1] = {mptopdf.steps.descape(str), font, scale} return "\n" .. #mptopdf.texts .. " textext" end) mptopdf.data = mptopdf.data:gsub("%[%s*(.-)%s*%]", function(str) @@ -165,17 +165,17 @@ function mptopdf.flushpath(cmd) local function concat(px, py) return (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d end - for _,v in pairs(mptopdf.stack.path) do + for _,v in ipairs(mptopdf.stack.path) do v[1],v[2] = concat(v[1],v[2]) if #v == 7 then v[3],v[4] = concat(v[3],v[4]) v[5],v[6] = concat(v[5],v[6]) end - table.insert(path, table.concat(v," ")) + path[#path+1] = table.concat(v," ") end else - for _,v in pairs(mptopdf.stack.path) do - table.insert(path, table.concat(v," ")) + for _,v in ipairs(mptopdf.stack.path) do + path[#path+1] = table.concat(v," ") end end mptopdf.flushconcat() @@ -363,23 +363,52 @@ end --~ end --~ end -function mp.setrgbcolor(r,g,b) -- extra check - r, g = tonumber(r), tonumber(g) -- needed when we use lpeg - if r == 0.0123 and g < 0.01 then - mptopdf.texcode("\\MPSspecial{" .. g*10000 .. "}{" .. b*10000 .. "}") - elseif r == 0.123 and r < 0.1 then - mptopdf.texcode("\\MPSspecial{" .. g* 1000 .. "}{" .. b* 1000 .. "}") - else - mptopdf.texcode("\\MPSrgb{" .. r .. "}{" .. g .. "}{" .. b .. "}") +if ctx and ctx.aux and ctx.aux.definecolor then + + logs.report("mptopdf", "using attribute based mps colors") + + -- todo: convert pdf specials to lua code + + function mp.setrgbcolor(r,g,b) -- extra check + r, g, b = tonumber(r), tonumber(g), tonumber(b) -- needed when we use lpeg + if r == 0.0123 and g < 0.01 then + mptopdf.texcode("\\doresetattribute{transparency}\\MPSspecial{" .. g*10000 .. "}{" .. b*10000 .. "}") + elseif r == 0.123 and r < 0.1 then + mptopdf.texcode("\\doresetattribute{transparency}\\MPSspecial{" .. g* 1000 .. "}{" .. b* 1000 .. "}") + else + mptopdf.texcode("\\doresetattribute{transparency}\\dosetattribute{color}{" .. colors.register('color',nil,'rgb',r,g,b) .. "}") + end end -end -function mp.setcmykcolor(c,m,y,k) - mptopdf.texcode("\\MPScmyk{" .. c .. "}{" .. m .. "}{" .. y .. "}{" .. k .. "}") -end + function mp.setcmykcolor(c,m,y,k) + mptopdf.texcode("\\doresetattribute{transparency}\\dosetattribute{color}{" .. colors.register('color',nil,'cmyk',tonumber(c),tonumber(m),tonumber(y),tonumber(k)) .. "}") + end + + function mp.setgray(s) + mptopdf.texcode("\\doresetattribute{transparency}\\dosetattribute{color}{" .. colors.register('color',nil,'gray',tonumber(s)) .. "}") + end + +else + + function mp.setrgbcolor(r,g,b) -- extra check + r, g = tonumber(r), tonumber(g) -- needed when we use lpeg + if r == 0.0123 and g < 0.01 then + mptopdf.texcode("\\MPSspecial{" .. g*10000 .. "}{" .. b*10000 .. "}") + elseif r == 0.123 and r < 0.1 then + mptopdf.texcode("\\MPSspecial{" .. g* 1000 .. "}{" .. b* 1000 .. "}") + else + mptopdf.texcode("\\MPSrgb{" .. r .. "}{" .. g .. "}{" .. b .. "}") + end + end + + function mp.setcmykcolor(c,m,y,k) + mptopdf.texcode("\\MPScmyk{" .. c .. "}{" .. m .. "}{" .. y .. "}{" .. k .. "}") + end + + function mp.setgray(s) + mptopdf.texcode("\\MPSgray{" .. s .. "}") + end -function mp.setgray(s) - mptopdf.texcode("\\MPSgray{" .. s .. "}") end function mp.specials(version,signal,factor) -- 2.0 123 1000 diff --git a/tex/context/base/meta-pdf.mkiv b/tex/context/base/meta-pdf.mkiv index dadf760a6..d10734547 100644 --- a/tex/context/base/meta-pdf.mkiv +++ b/tex/context/base/meta-pdf.mkiv @@ -24,8 +24,6 @@ % 7.4 : mkiv, simulated clean direct lua from mp % 0.3 : time taken by tex to handle converted code -% Maybe delayed load, only at first call of the converter. - \registerctxluafile{meta-pdf}{1.003} %D Plugin. diff --git a/tex/context/base/meta-pdf.tex b/tex/context/base/meta-pdf.tex index ad4a57fd9..8ac736818 100644 --- a/tex/context/base/meta-pdf.tex +++ b/tex/context/base/meta-pdf.tex @@ -811,7 +811,7 @@ {\global\let\MPresolvedspace\MPcmykspace \xdef\MPresolvedcolor{##1 ##2 ##3 ##4}}% \def\dostartspotcolormode##1##2% - {\global\let\MPspotspace\empty + {\global\let\MPspotspace\empty % left over ? \xdef\MPresolvedspace{##1}% \xdef\MPresolvedcolor{##2}% \global\let\MPspotspace\MPresolvedspace}% signal @@ -961,4 +961,51 @@ % filldraw boundingbox currentpicture enlarged -3cm withpen pencircle scaled 1pt withcolor .5white ; % \stopMPcode +% This code will move to meta-pdf.mkiv and the call to lua will move to the +% converter code (saves a lua call). We will do this when we made the final +% move to attribute bases color . + +\ifx\colorversion\undefined \else \ifnum\colorversion>\plusone + + \def\dohandleMPgraycolor #1{\dosetattribute{color}{\ctxlua{tex.sprint(colors.register('color',nil,'gray',#1))}}} + \def\dohandleMPrgbcolor #1#2#3{\dosetattribute{color}{\ctxlua{tex.sprint(colors.register('color',nil,'rgb' ,#1,#2,#3))}}} + \def\dohandleMPcmykcolor#1#2#3#4{\dosetattribute{color}{\ctxlua{tex.sprint(colors.register('color',nil,'cmyk',#1,#2,#3,#4))}}} + \def\dohandleMPspotcolor#1#2#3#4{\dosetattribute{color}{\ctxlua{tex.sprint(colors.register('color',nil,'spot',"#1",#2,"#3","#4"))}}} + + \def\dohandleMPgraytransparency #1#2#3{\dosetattribute{color}{\ctxlua{tex.sprint(colors.register('color',nil,'gray',#1))}}% + \dosetattribute{transparency}{\ctxlua{tex.sprint(transparencies.register(nil,#2,#3))}}} + \def\dohandleMPrgbtransparency #1#2#3#4#5{\dosetattribute{color}{\ctxlua{tex.sprint(colors.register('color',nil,'rgb' ,#1,#2,#3))}}% + \dosetattribute{transparency}{\ctxlua{tex.sprint(transparencies.register(nil,#4,#5))}}} + \def\dohandleMPcmyktransparency#1#2#3#4#5#6{\dosetattribute{color}{\ctxlua{tex.sprint(colors.register('color',nil,'cmyk',#1,#2,#3,#4))}}% + \dosetattribute{transparency}{\ctxlua{tex.sprint(transparencies.register(nil,#5,#6))}}} + \def\dohandleMPspottransparency#1#2#3#4#5#6{\dosetattribute{color}{\ctxlua{tex.sprint(colors.register('color',nil,'spot',"#1",#2,"#3","#4"))}}% + \dosetattribute{transparency}{\ctxlua{tex.sprint(transparencies.register(nil,#5,#6))}}} + + % \dostartgraycolormode\!!zerocount} % kind of hackery initialization + + \def\resolveMPgraycolor#1\to#2% + {\global\let\MPresolvedspace\MPgrayspace + \edef#2{\ctxlua{tex.sprint(ctx.pdfcolorvalue(\number\currentcolormodel,colors.register('color',nil,'gray',#1)))}}} + + \def\resolveMPrgbcolor#1#2#3\to#4% + {\global\let\MPresolvedspace\MPrgbspace + \edef#4{\ctxlua{tex.sprint(ctx.pdfcolorvalue(\number\currentcolormodel,colors.register('color',nil,'rgb' ,#1,#2,#3)))}}} + + \def\resolveMPcmykcolor#1#2#3#4\to#5% + {\global\let\MPresolvedspace\MPcmykspace + \edef#5{\ctxlua{tex.sprint(ctx.pdfcolorvalue(\number\currentcolormodel,colors.register('color',nil,'cmyk',#1,#2,#3,#4)))}}} + + \def\resolveMPspotcolor#1#2#3#4\to#5% + {\xdef\MPresolvedspace{#1}% + \xdef\MPresolvedcolor{#4}% + \global\let\MPspotspace\MPresolvedspace + \edef#5{\ctxlua{tex.sprint(ctx.pdfcolorvalue(\number\currentcolormodel,colors.register('color',nil,'spot',"#1",#2,"#3","#4")))}}} + + \let\MPSgray\dohandleMPgraycolor + \let\MPSrgb \dohandleMPrgbcolor + \let\MPScmyk\dohandleMPcmykcolor + \let\MPspot \dohandleMPspotcolor + +\fi \fi + \protect \endinput diff --git a/tex/context/base/mult-con.tex b/tex/context/base/mult-con.tex index 043d5fb6e..22103e615 100644 --- a/tex/context/base/mult-con.tex +++ b/tex/context/base/mult-con.tex @@ -736,6 +736,10 @@ subsubsubsubsubsubject: subsubsubsubsubonderwerp subsubsubsubsub ausgleichen rovnovaha bilanciamento balanta equilibre + bookmark: bookmark bookmark + bookmark zalozka + segnalibro semncarte + marquepage wfactor: bfactor wfactor bfaktor sfaktor wfactor factorw @@ -1160,6 +1164,14 @@ subsubsubsubsubsubject: subsubsubsubsubonderwerp subsubsubsubsub linkerrand levyokraj marginesinistro marginestanga margegauche + innermargin: binnenmarge innermargin + innermargin innermargin + margineinterno innermargin + margeinterieure + outermargin: buitenmarge outermargin + outermargin outermargin + margineesterno outermargin + margeexterieure leftmargindistance: linkermargeafstand leftmargindistance linkerrandabstand vzdalenostlevehookraje distanzamarginesinistro distantamarginestanga diff --git a/tex/context/base/mult-sys.tex b/tex/context/base/mult-sys.tex index f10e91cfe..74538a2aa 100644 --- a/tex/context/base/mult-sys.tex +++ b/tex/context/base/mult-sys.tex @@ -177,6 +177,8 @@ \definesystemconstant {layer} \definesystemconstant {effect} \definesystemconstant {negative} +\definesystemconstant {color} +\definesystemconstant {transparency} \definesystemconstant {black} \definesystemconstant {white} diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua index 77835e04b..4ef9e05eb 100644 --- a/tex/context/base/node-ini.lua +++ b/tex/context/base/node-ini.lua @@ -11,8 +11,8 @@ if not modules then modules = { } end modules ['node-ini'] = { implement a few helper functions.

--ldx]]-- -nodes = nodes or { } -nodes.trace = false +nodes = nodes or { } +nodes.trace = false -- handy helpers @@ -59,7 +59,7 @@ nodes.processors.char = { } nodes.processors.char.proc = { } function nodes.report(t,done) - if nodes.trace then + if nodes.trace then -- best also test this before calling if done then if status.output_active then texio.write(string.format("<++ %s>",nodes.count(t))) @@ -296,6 +296,309 @@ if not fonts then fonts = { } end if not fonts.tfm then fonts.tfm = { } end if not fonts.tfm.id then fonts.tfm.id = { } end +do + + local glyph, hlist, vlist = node.id('glyph'), node.id('hlist'), node.id('vlist') + local pushmarks = false + + function nodes.process_glyphs(head) + if status.output_active then -- not ok, we need a generic blocker, pagebody ! / attr tex.attibutes + -- 25% calls + return true + elseif not head then + -- 25% calls + return true + elseif not head.next and (head.id == hlist or head.id == vlist) then + return head + else + -- either next or not, but definitely no already processed list + input.start_timing(nodes) + local usedfonts, found, fontdata, done = { }, false, fonts.tfm.id, false + for n in node.traverse_id(glyph,head) do + local font = n.font + if not usedfonts[font] then + local shared = fontdata[font].shared + if shared and shared.processors then + usedfonts[font], found = shared.processors, true + end + end + end + if found then + local tail = head + if head.next then + tail = node.slide(head) + else + head.prev = nil + end + for font, processors in pairs(usedfonts) do + if pushmarks then + local h, d = fonts.pushmarks(head,font) + head, done = head or h, done or d + end + for _, processor in ipairs(processors) do + local h, d = processor(head,font) + head, done = head or h, done or d + end + if pushmarks then + local h, d = fonts.popmarks(head,font) + head, done = head or h, done or d + end + end + end + input.stop_timing(nodes) + if nodes.trace then + nodes.report(head,done) + end + if done then + return head -- something changed + elseif head then + return true -- nothing changed + else + return false -- delete list + end + end + end + +end + +-- vbox: grouptype: vbox vtop output split_off split_keep | box_type: exactly|aditional +-- hbox: grouptype: hbox adjusted_hbox(=hbox_in_vmode) | box_type: exactly|aditional + +do + + local contains, set, attribute = node.has_attribute, node.set_attribute, tex.attribute + + function nodes.inherit_attributes(n) + if n then + local i = 1 + while true do + local a = attribute[i] + if a < 0 then + break + else + local ai = contains(n,i) + if not ai then + set(n,i,a) + end + i = i + 1 + end + end + end + end + +end + +callback.register('pre_linebreak_filter', nodes.process_glyphs) +callback.register('hpack_filter', nodes.process_glyphs) + +--~ callback.register('pre_linebreak_filter', function(t,...) +--~ print("pre_linebreak_filter",...) +--~ return nodes.process_glyphs(t) +--~ end ) +--~ callback.register('hpack_filter', function(t,...) +--~ print("hpack_filter",...) +--~ return nodes.process_glyphs(t) +--~ end ) + +function nodes.length(head) + if head then + local m = 0 + for n in node.traverse(head) do + m = m + 1 + end + return m + else + return 0 + end +end + +do + +--~ function nodes.totable(n) +--~ local function totable(n) +--~ local f, tt = node.fields(n.id,n.subtype), { } +--~ for _,v in ipairs(f) do +--~ local nv = n[v] +--~ if nv then +--~ local tnv = type(nv) +--~ if tnv == "string" or tnv == "number" then +--~ tt[v] = nv +--~ else -- userdata +--~ tt[v] = nodes.totable(nv) +--~ end +--~ end +--~ end +--~ return tt +--~ end +--~ local t = { } +--~ while n do +--~ t[#t+1] = totable(n) +--~ n = n.next +--~ end +--~ return t +--~ end + + local expand = { + list = true, + pre = true, + post = true, + spec = true, + attr = true, + components = true, + } + + -- flat: don't use next, but indexes + -- verbose: also add type + + function nodes.totable(n,flat,verbose) + local function totable(n,verbose) + local f = node.fields(n.id,n.subtype) + local tt = { } + for _,v in ipairs(f) do + if n[v] then + if v == "ref_count" then + -- skip + elseif expand[v] then -- or: type(n[v]) ~= "string" or type(n[v]) ~= "number" + tt[v] = nodes.totable(n[v],flat,verbose) + else + tt[v] = n[v] + end + end + end + if verbose then + tt.type = node.type(tt.id) + end + return tt + end + if n then + if flat then + local t = { } + while n do + t[#t+1] = totable(n,verbose) + n = n.next + end + return t + else + local t = totable(n,verbose) + if n.next then + t.next = nodes.totable(n.next,flat,verbose) + end + return t + end + else + return { } + end + end + + local function key(k) + if type(k) == "number" then + return "["..k.."]" + else + return k + end + end + + local function serialize(root,name,handle,depth,m) + handle = handle or print + if depth then + depth = depth .. " " + handle(("%s%s={"):format(depth,key(name))) + else + depth = "" + if type(name) == "string" then + if name == "return" then + handle("return {") + else + handle(name .. "={") + end + elseif type(name) == "number" then + handle("[" .. name .. "]={") + else + handle("t={") + end + end + if root then + local fld + if root.id then + fld = node.fields(root.id,root.subtype) + else + fld = table.sortedkeys(root) + end + if type(root) == 'table' and root['type'] then -- userdata or table + handle(("%s %s=%q,"):format(depth,'type',root['type'])) + end + for _,k in ipairs(fld) do + if k then + local v = root[k] + local t = type(v) + if t == "number" then + handle(("%s %s=%s,"):format(depth,key(k),v)) + elseif t == "string" then + handle(("%s %s=%q,"):format(depth,key(k),v)) + elseif v then -- userdata or table + serialize(v,k,handle,depth,m+1) + end + end + end + if root['next'] then -- userdata or table + serialize(root['next'],'next',handle,depth,m+1) + end + end + if m and m > 0 then + handle(("%s},"):format(depth)) + else + handle(("%s}"):format(depth)) + end + end + + function nodes.serialize(root,name) + local t = { } + local function flush(s) + t[#t+1] = s + end + serialize(root, name, flush, nil, 0) + return table.concat(t,"\n") + end + + function nodes.serializebox(n,flat,verbose) + return nodes.serialize(nodes.totable(tex.box[n],flat,verbose)) + -- return nodes.serialize(tex.box[n]) + end + + function nodes.visualizebox(...) + -- tex.sprint(tex.ctxcatcodes,"\\starttyping\n" .. nodes.serializebox(...) .. "\n\\stoptyping\n") + tex.print(tex.ctxcatcodes,"\\starttyping") + tex.print(nodes.serializebox(...)) + tex.print("\\stoptyping") + end + +end + +if not node.list_has_attribute then + + function node.list_has_attribute(list,attribute) + if list and attribute then + for n in node.traverse(list) do + local a = has_attribute(n,attribute) + if a then return a end + end + end + return false + end + +end + +function nodes.pack_list(head) + local t = { } + for n in node.traverse(head) do + t[#t+1] = tostring(n) + end + return t +end + +-- old code + + --~ function nodes.do_process_glyphs(stack) --~ if not stack or #stack == 0 then --~ return false @@ -634,272 +937,3 @@ if not fonts.tfm.id then fonts.tfm.id = { } end --~ end --~ end - -do - - local glyph = node.id('glyph') - local pushmarks = false - - function do_process_glyphs(head) -- beware, we need to handle shifted heads -- todo - if not head then - return head - end - local usedfonts, found, fontdata = { }, false, fonts.tfm.id - for n in node.traverse_id(glyph,head) do - local font = n.font - if not usedfonts[font] then - local shared = fontdata[font].shared - if shared and shared.processors then - usedfonts[font], found = shared.processors, true - end - end - end - if not found then - return head, false - else - local tail, done = node.slide(head), false - for font, processors in pairs(usedfonts) do - if pushmarks then - local h, d = fonts.pushmarks(head,font) - head, done = head or h, done or d - end - for _, processor in ipairs(processors) do - local h, d = processor(head,font) - head, done = head or h, done or d - end - if pushmarks then - local h, d = fonts.popmarks(head,font) - head, done = head or h, done or d - end - end - return head, done - end - end - - function nodes.process_glyphs(head) - if status.output_active then -- not ok, we need a generic blocker, pagebody ! / attr tex.attibutes - return true - else - input.start_timing(nodes) - local head, done = do_process_glyphs(head) - input.stop_timing(nodes) - nodes.report(head,done) - if done then - return head -- something changed - elseif head then - return true -- nothing changed - else - return false -- delete list - end - end - end - -end - --- vbox: grouptype: vbox vtop output split_off split_keep | box_type: exactly|aditional --- hbox: grouptype: hbox adjusted_hbox(=hbox_in_vmode) | box_type: exactly|aditional - -callback.register('pre_linebreak_filter', nodes.process_glyphs) -callback.register('hpack_filter', nodes.process_glyphs) - ---~ callback.register('pre_linebreak_filter', function(t,...) ---~ print("pre_linebreak_filter",...) ---~ return nodes.process_glyphs(t) ---~ end ) ---~ callback.register('hpack_filter', function(t,...) ---~ print("hpack_filter",...) ---~ return nodes.process_glyphs(t) ---~ end ) - -function nodes.length(head) - if head then - local m = 0 - for n in node.traverse(head) do - m = m + 1 - end - return m - else - return 0 - end -end - -do - ---~ function nodes.totable(n) ---~ function totable(n) ---~ local f, tt = node.fields(n.id,n.subtype), { } ---~ for _,v in ipairs(f) do ---~ local nv = n[v] ---~ if nv then ---~ local tnv = type(nv) ---~ if tnv == "string" or tnv == "number" then ---~ tt[v] = nv ---~ else -- userdata ---~ tt[v] = nodes.totable(nv) ---~ end ---~ end ---~ end ---~ return tt ---~ end ---~ local t = { } ---~ while n do ---~ t[#t+1] = totable(n) ---~ n = n.next ---~ end ---~ return t ---~ end - - local expand = { - list = true, - pre = true, - post = true, - spec = true, - attr = true, - components = true, - } - - -- flat: don't use next, but indexes - -- verbose: also add type - - function nodes.totable(n,flat,verbose) - function totable(n,verbose) - local f = node.fields(n.id,n.subtype) - local tt = { } - for _,v in ipairs(f) do - if n[v] then - if v == "ref_count" then - -- skip - elseif expand[v] then -- or: type(n[v]) ~= "string" or type(n[v]) ~= "number" - tt[v] = nodes.totable(n[v],flat,verbose) - else - tt[v] = n[v] - end - end - end - if verbose then - tt.type = node.type(tt.id) - end - return tt - end - if flat then - local t = { } - while n do - t[#t+1] = totable(n,verbose) - n = n.next - end - return t - else - local t = totable(n,verbose) - if n.next then - t.next = nodes.totable(n.next,flat,verbose) - end - return t - end - end - - local function key(k) - if type(k) == "number" then - return "["..k.."]" - else - return k - end - end - - local function serialize(root,name,handle,depth,m) - handle = handle or print - if depth then - depth = depth .. " " - handle(("%s%s={"):format(depth,key(name))) - else - depth = "" - if type(name) == "string" then - if name == "return" then - handle("return {") - else - handle(name .. "={") - end - elseif type(name) == "number" then - handle("[" .. name .. "]={") - else - handle("t={") - end - end - if root then - local fld - if root.id then - fld = node.fields(root.id,root.subtype) - else - fld = table.sortedkeys(root) - end - if type(root) == 'table' and root['type'] then -- userdata or table - handle(("%s %s=%q,"):format(depth,'type',root['type'])) - end - for _,k in ipairs(fld) do - if k then - local v = root[k] - local t = type(v) - if t == "number" then - handle(("%s %s=%s,"):format(depth,key(k),v)) - elseif t == "string" then - handle(("%s %s=%q,"):format(depth,key(k),v)) - elseif v then -- userdata or table - serialize(v,k,handle,depth,n+1) - end - end - end - if root['next'] then -- userdata or table - serialize(root['next'],'next',handle,depth,n+1) - end - end - if m and m > 0 then - handle(("%s},"):format(depth)) - else - handle(("%s}"):format(depth)) - end - end - - function nodes.serialize(root,name) - local t = { } - local function flush(s) - t[#t+1] = s - end - serialize(root, name, flush, nil, nil) - return table.concat(t,"\n") - end - - function nodes.serializebox(n,flat,verbose) - return nodes.serialize(nodes.totable(tex.box[n],flat,verbose)) - -- return nodes.serialize(tex.box[n]) - end - - function nodes.visualizebox(...) - -- tex.sprint(tex.ctxcatcodes,"\\starttyping\n" .. nodes.serializebox(...) .. "\n\\stoptyping\n") - tex.print(tex.ctxcatcodes,"\\starttyping") - tex.print(nodes.serializebox(...)) - tex.print("\\stoptyping") - end - -end - -if not node.list_has_attribute then - - function node.list_has_attribute(list,attribute) - if list and attribute then - for n in node.traverse(list) do - local a = has_attribute(n,attribute) - if a then return a end - end - end - return false - end - -end - -function nodes.pack_list(head) - local t = { } - for n in node.traverse(head) do - t[#t+1] = tostring(n) - end - return t -end - diff --git a/tex/context/base/page-flt.tex b/tex/context/base/page-flt.tex index 6ebade65d..157864d44 100644 --- a/tex/context/base/page-flt.tex +++ b/tex/context/base/page-flt.tex @@ -186,6 +186,9 @@ \def\floatparameter #1{\csname\??fl\currentfloat#1\endcsname} \def\floatcaptionparameter#1{\csname\??kj\currentfloat#1\endcsname} +% \def\floatparameter #1{\csname \ifcsname\??fl\currentfloat#1\endcsname\??fl\currentfloat\else\??bk\fi#1\endcsname} +% \def\floatcaptionparameter#1{\csname\??kj\ifcsname\??kj\currentfloat#1\endcsname \currentfloat \fi#1\endcsname} + % for the moment we need to define the parameters anyway, first we need to implement a % proper parent chain (also for framed); no problem now that machines are fast (tests % show that this may save 20 k or more in the format) @@ -194,7 +197,7 @@ % \def\floatcaptionparameter#1{\executeifdefined{\??kj\currentfloat#1}{\csname\??bk#1\endcsname}} \def\setupfloats - {\dodoubleargument\getparameters[\??bk]} + {\dodoubleargument\getparameters[\??bk]} % funny, why not \??fl, must be a reason \def\setupcaptions {\dodoubleargument\getparameters[\??kj]} @@ -233,7 +236,7 @@ {\edef\currentfloat{#1}% \doifelsenothing\currentfloat {\let\currentfloat\v!figure} - {\doifundefined{\??fl#1\c!default}{\let\currentfloat\v!figure}}% + {}% {\doifundefined{\??fl#1\c!default}{\let\currentfloat\v!figure}}% \doifelsenothing{#2} {\edef\floatlocation{\floatparameter\c!default}} {\edef\floatlocation{#2}}% @@ -320,7 +323,7 @@ \global\chardef\textfloatmethod\floatparameter\c!textmethod \global\chardef\sidefloatalign\zerocount \globallet\floatrotation\!!zerocount - \calculatefloatskips{#1}% + \calculatefloatskips \ifparfloat \processaction [\floatparameter\c!sidealign] @@ -510,41 +513,41 @@ % pas op, maxbreedte niet instellen als plaats=links/rechts -\def\setlocalfloatdimensions#1#2#3#4% experimental / #3 box number #4 prefix +\def\setlocalfloatdimensions#1#2#3% experimental / #3 box number #4 prefix {\global\sidefloatshift \zeropoint % duplicate \global\sidefloatmaximum\zeropoint\relax % duplicate \ifextrafloatactions \ifdim\sidefloatdownshift=\zeropoint\else - #4\setbox#3\vbox + #3\setbox#2\vbox {\vskip\sidefloatdownshift\nointerlineskip\box#3}% \fi \doifsomething{\floatparameter\c!minwidth} {\scratchdimen\floatparameter\c!minwidth\relax - \ifdim\wd#3<\scratchdimen - #4\setbox#3\hbox to \scratchdimen + \ifdim\wd#2<\scratchdimen + #3\setbox#2\hbox to \scratchdimen {\doifnot{\floatparameter\c!location}\v!left \hss - \box#3% + \box#2% \doifnot{\floatparameter\c!location}\v!right\hss}% \fi}% % todo: rand / rug - \doifinset\v!hanging{#2} - {\doifcommonelse{\v!inleft,\v!leftmargin}{#2} + \doifinset\v!hanging{#1} + {\doifcommonelse{\v!inleft,\v!leftmargin}{#1} {\letvalue{\??fl\currentfloat\c!maxwidth}\leftmarginwidth}% - {\doifcommon{\v!inright,\v!rightmargin}{#2} + {\doifcommon{\v!inright,\v!rightmargin}{#1} {\letvalue{\??fl\currentfloat\c!maxwidth}\rightmarginwidth}}}% \doifsomething{\floatparameter\c!maxwidth} {\scratchdimen\floatparameter\c!maxwidth\relax - \ifdim\wd#3>\scratchdimen + \ifdim\wd#2>\scratchdimen \doifcommonelse{\v!inright,\v!rightmargin,\v!rightedge - \v!inleft,\v!leftmargin,\v!leftedge}{#2} + \v!inleft,\v!leftmargin,\v!leftedge}{#1} {\global\sidefloatmaximum\scratchdimen} - {#4\setbox#3\hbox to \scratchdimen - {\doifcommonelse{\v!right,\v!left}{#2} - {\doifnotinset\v!right{#2}\hss - \box#3% - \doifnotinset\v!left{#2}\hss}% + {#3\setbox#2\hbox to \scratchdimen + {\doifcommonelse{\v!right,\v!left}{#1} + {\doifnotinset\v!right{#1}\hss + \box#2% + \doifnotinset\v!left{#1}\hss}% {\doifnot{\floatparameter\c!location}\v!left\hss - \box#3% + \box#2% \doifnot{\floatparameter\c!location}\v!right\hss}}}% \fi}% \fi} @@ -582,18 +585,22 @@ [#1] [%\c!width=8\lineheight, % 15\bodyfontsize, %\c!height=6\lineheight, % 10\bodyfontsize, -\c!offset=\v!overlay, -\c!width=\v!fit, -\c!height=\v!fit, + \c!offset=\v!overlay, + \c!width=\v!fit, + \c!height=\v!fit, \c!minwidth=, \c!maxwidth=, \c!maxheight=, \c!criterium=, -% inherited + % inherited \c!sidespacebefore=\@@bksidespacebefore, \c!sidespaceafter=\@@bksidespaceafter, \c!sidealign=\@@bksidealign, % \v!line \c!margin=\@@bkmargin, + \c!leftmargin=\@@bkleftmargin, + \c!rightmargin=\@@bkrightmargin, + \c!innermargin=\@@bkinnermargin, + \c!outermargin=\@@bkoutermargin, \c!leftmargindistance=\@@bkleftmargindistance, \c!rightmargindistance=\@@bkrightmargindistance, \c!frame=\@@bkframe, @@ -612,6 +619,7 @@ %\c!local=\@@bklocal, \c!textmethod=\@@bktextmethod, \c!sidemethod=\@@bksidemethod, + \c!method=\@@bkmethod, \c!pageboundaries=, \c!default=]% \setupcaption @@ -627,9 +635,9 @@ %\c!before=\@@kjbefore, \c!inbetween=\@@kjinbetween, %\c!after=\@@kjafter, -\c!spacebefore=\@@kjspacebefore, -\c!spaceinbetween=\@@kjspaceinbetween, -\c!spaceafter=\@@kjspaceafter, + \c!spacebefore=\@@kjspacebefore, + \c!spaceinbetween=\@@kjspaceinbetween, + \c!spaceafter=\@@kjspaceafter, \c!width=\@@kjwidth, \c!minwidth=\@@kjminwidth, \c!align=\@@kjalign, @@ -642,16 +650,17 @@ \c!stopper=\@@kjstopper, \c!suffix=\@@kjsuffix, % hook \c!command=\@@kjcommand, - \c!conversion=\@@kjconversion + \c!conversion=\@@kjconversion, + \c!leftmargin=\@@kjleftmargin, + \c!rightmargin=\@@kjrightmargin, + \c!outermargin=\@@kjoutermargin, + \c!innermargin=\@@kjinnermargin, + \c!setups=\@@kjsetups, ]% \definenumber % \definelabel [#1] [\c!text=#1, \c!location=\v!intext, -% \c!way=\getvalue{\??kj#1\c!way}, -% \c!blockway=\getvalue{\??kj#1\c!blockway}, -% \c!sectionnumber=\getvalue{\??kj#1\c!sectionnumber}, -% \c!conversion=\getvalue{\??kj#1\c!conversion}]% \c!way=\floatcaptionparameter\c!way, \c!blockway=\floatcaptionparameter\c!blockway, \c!sectionnumber=\floatcaptionparameter\c!sectionnumber, @@ -684,17 +693,19 @@ \c!maxwidth,\c!maxheight,\c!minwidth, \c!margin,\c!sidespacebefore,\c!sidespaceafter,\c!sidealign, \c!leftmargindistance,\c!rightmargindistance,\c!criterium, + \c!leftmargin,\c!rightmargin,\c!innermargin,\c!outermargin, \c!frame,\c!radius,\c!corner,\c!location,\c!background,\c!framecolor, \c!backgroundscreen,\c!backgroundcolor,\c!backgroundoffset, \c!topframe,\c!bottomframe,\c!leftframe,\c!rightframe, \c!frameoffset,\c!pageboundaries,\c!default, - \c!textmethod,\c!sidemethod]% + \c!textmethod,\c!sidemethod,\c!method]% \copyparameters[\??kj#1][\??kj#3] [\c!location,\c!before,\c!inbetween,\c!after, \c!spacebefore,\c!spaceinbetween,\c!spaceafter, \c!width,\c!headstyle,\c!headcolor,\c!style,\c!color, \c!textstyle,\c!textcolor,\c!minwidth, - \c!align,\c!number,\c!way,\c!blockway, + \c!align,\c!number,\c!way,\c!blockway,\c!setups, + \c!leftmargin,\c!rightmargin,\c!innermargin,\c!outermargin, \c!sectionnumber,\c!separator,\c!stopper,\c!suffix,\c!distance,\c!conversion]% \definenumber[#1][#3]% \presetlabeltext[#1=\labeltext{#3}]% @@ -710,6 +721,7 @@ \c!maxwidth,\c!maxheight,\c!minwidth, \c!margin,\c!sidespacebefore,\c!sidespaceafter,\c!sidealign, \c!leftmargindistance,\c!rightmargindistance,\c!criterium, + \c!leftmargin,\c!rightmargin,\c!innermargin,\c!outermargin, \c!frame,\c!radius,\c!corner,\c!location,\c!background,\c!framecolor, \c!backgroundscreen,\c!backgroundcolor,\c!backgroundoffset, \c!topframe,\c!bottomframe,\c!leftframe,\c!rightframe, @@ -720,7 +732,8 @@ \c!spacebefore,\c!spaceinbetween,\c!spaceafter, \c!width,\c!headstyle,\c!headcolor,\c!style,\c!color, \c!textstyle,\c!textcolor,\c!minwidth, - \c!align,\c!number,\c!way,\c!blockway, + \c!leftmargin,\c!rightmargin,\c!innermargin,\c!outermargin, + \c!align,\c!number,\c!way,\c!blockway,\c!setups, \c!sectionnumber,\c!separator,\c!stopper,\c!suffix,\c!distance,\c!conversion]% \definenumber[#1][#3]% \presetlabeltext[#1=\labeltext{#3}]% @@ -867,35 +880,6 @@ \def\doinsertfloatinfo {\dofloatinfomessage<4{\the\totalnoffloats}} -% \def\dogetfloat -% {\ifsomefloatwaiting -% \global\setbox\floatlist\vbox -% {\unvbox\floatlist -% \global\setbox\globalscratchbox\lastbox}% -% \ifcenterfloatbox -% \ifdim\wd\globalscratchbox<\hsize -% \setbox\floatbox\hbox to \hsize{\hss\box\globalscratchbox\hss}% -% \else -% \setbox\floatbox\box\globalscratchbox % local ! -% % retain special alignments -% \ifinsidecolumns -% \ifdim\wd\floatbox>\makeupwidth -% \wd\floatbox\makeupwidth -% \fi -% \fi -% \fi -% \else -% \setbox\floatbox\box\globalscratchbox % local ! -% \fi -% \global\advance\savednoffloats \minusone -% \ifcase\savednoffloats -% \global\somefloatwaitingfalse -% \fi -% \else -% \global\savednoffloats\zerocount -% \global\setbox\floatbox\box\voidb@x -% \fi} - \def\dogetfloat {\ifsomefloatwaiting \global\setbox\floatlist\vbox @@ -1233,7 +1217,7 @@ % voor het plaatsen van tabellen en figuren (klopt niet % meer). % -% \dofloat {plaats} {label1} {label2} {kader} +% \dofloat {plaats} {label1} {label2} % % \docompletefloat {nummer} {referentie} {lijst} % {plaats} {label1} {label2} {inhoud} @@ -1270,17 +1254,17 @@ {\setbox0\vbox{\whitespace\expanded{\blank[#2]}}% \global#1\ht0}}} -\def\calculatefloatskips#1% todo floatparam - {{\docalculatefloatskip\floattopskip \@@bkspacebefore - \docalculatefloatskip\floatbottomskip \@@bkspaceafter - \docalculatefloatskip\sidefloattopskip {\getvalue{\??fl#1\c!sidespacebefore}}% \@@bksidespacebefore - \docalculatefloatskip\sidefloatbottomskip{\getvalue{\??fl#1\c!sidespaceafter}}% \@@bksidespaceafter - \gdef\sidefloattopoffset{\openstrutdepth}% was \def - \global\floatsideskip \getvalue{\??fl#1\c!margin}% - \global\sidefloatleftshift \getvalue{\??fl#1\c!leftmargindistance}% - \global\sidefloatrightshift\getvalue{\??fl#1\c!rightmargindistance}% - \global\noftopfloats\@@bkntop \relax - \global\nofbotfloats\@@bknbottom\relax}} +\def\calculatefloatskips + {{\docalculatefloatskip\floattopskip \@@bkspacebefore + \docalculatefloatskip\floatbottomskip \@@bkspaceafter + \docalculatefloatskip\sidefloattopskip {\floatparameter\c!sidespacebefore}% + \docalculatefloatskip\sidefloatbottomskip{\floatparameter\c!sidespaceafter }% + \gdef \sidefloattopoffset{\openstrutdepth}% was \def + \global\floatsideskip \floatparameter\c!margin + \global\sidefloatleftshift \floatparameter\c!leftmargindistance + \global\sidefloatrightshift\floatparameter\c!rightmargindistance + \global\noftopfloats \@@bkntop \relax + \global\nofbotfloats \@@bknbottom\relax}} \let\floatcaptionsuffix\empty % an optional suffix \let\floatcaptionnumber\empty % a logical counter @@ -1338,20 +1322,20 @@ \let\placefloatlabeltext \placefloatcaptiontext \let\placefloatlabelreference \placefloatcaptionreference -\def\borderedfloatbox#1% - {\localframed[\??fl#1][\c!location=\v!normal]{\box\floatbox}} +\def\borderedfloatbox + {\localframed[\??fl\currentfloat][\c!location=\v!normal]{\box\floatbox}} \newbox\captionbox -\def\putcompletecaption#1#2#3% +\def\putcompletecaption#1#2% {\doifsomething{\floatcaptionparameter\c!spacebefore}{\blank[\floatcaptionparameter\c!spacebefore]}% % \floatcaptionparameter\c!before % test for side effects first \noindent - \xdef\lastcaptiontag{\strut#2}% - \dostartattributes{\??kj#1}\c!style\c!color\empty + \xdef\lastcaptiontag{\strut#1}% + \dostartattributes{\??kj\currentfloat}\c!style\c!color\empty \ifnofloatnumber \else - \hbox{\doattributes{\??kj#1}\c!headstyle\c!headcolor{\strut#2}}% + \hbox{\doattributes{\??kj\currentfloat}\c!headstyle\c!headcolor{\strut#1}}% \ifnofloatcaption \else \ifemptyfloatcaption \else \doifelsenothing{\floatcaptionparameter\c!spaceinbetween} {\scratchskip\floatcaptionparameter\c!distance\relax @@ -1363,10 +1347,10 @@ \globallet\lastcaptionht\!!zeropoint \globallet\lastcaptiondp\!!zeropoint \else - \doattributes{\??kj#1}\c!textstyle\c!textcolor + \doattributes{\??kj\currentfloat}\c!textstyle\c!textcolor {\xdef\lastcaptionht{\strutheight}% \xdef\lastcaptiondp{\strutdepth}% - \begstrut#3\endstrut\endgraf}% + \begstrut#2\endstrut\endgraf}% \fi \dostopattributes % \floatcaptionparameter\c!after % test for side effects first @@ -1389,10 +1373,42 @@ %\stelblokkopjesin[\c!align=\v!left] %\stelblokkopjesin[\c!align=\v!right] -\def\docheckcaptioncontent#1#2#3#4% + +% \definefloat [figure-1] [figure] +% \definefloat [figure-2] [figure] +% \setupfloat [figure-1] [location=left,leftmargin=10mm] +% \setupfloat [figure-2] [location=left,leftmargin=-5mm] +% \setupcaption [figure-1] [align=flushleft] +% \setupcaption [figure-2] [align=flushleft,leftmargin=15mm] +% +% \startsetups somefigure +% \ifdim\wd\nextbox>\textwidth +% \placefloat[figure-2][][]{}{\box\nextbox} +% \else +% \placefloat[figure-1][][]{}{\box\nextbox} +% \fi +% \stopsetups +% +% \def\setupswithbox[#1]{\dowithnextbox{\setups[#1]}\vbox} +% +% test \setupswithbox[somefigure]{\framed[width=3cm] {}} test +% test \setupswithbox[somefigure]{\framed[width=\dimexpr\textwidth+3cm\relax]{}} test + +\def\dosetcaptionthings + {\setups[\floatcaptionparameter\c!setups]% expanded ? +% \advance\leftskip \floatcaptionparameter\c!leftmargin +% \advance\rightskip\floatcaptionparameter\c!rightmargin + \relax} + +\def\dofakecaptionthings + {\hbox{\dosetcaptionthings\hskip\leftskip\hskip\rightskip}} + +\def\docheckcaptioncontent#1#2% {\ifnofloatcaption \else \setbox\tempcaptionbox\hbox - {\trialtypesettingtrue\notesenabledfalse\putcompletecaption{#4}{#2}{#3}}% + {\trialtypesettingtrue + \notesenabledfalse + \putcompletecaption{#1}{#2}}% % new, \placefigure{\XMLflush{somecaption}}{} passes earlier empty check % so here we misuse the scratch box; actually this means that the previous % test can go away (some day, when i redo this module) @@ -1401,6 +1417,8 @@ \ifnofloatnumber \global\nofloatcaptiontrue \fi + \else + \setbox\tempcaptionbox\hbox{\dosetcaptionthings\hskip\leftskip\box\tempcaptionbox}% yet incomplete \fi \fi} @@ -1408,56 +1426,21 @@ \ifx\moveboxontogrid\undefined \let\movecaptionontogrid\gobblethreearguments \fi -% \def\dosetpagfloat#1#2#3#4% \copy wegwerken -% {\bgroup -% \setlocalfloathsize -% \ifnum\floatrotation>0 -% \swapdimens\hsize\vsize -% \fi -% \forgetall -% \postponenotes -% \dontcomplain -% \setbox\tempfloatbox\vbox{\borderedfloatbox{#4}}% -% \def\locatefloat -% {\chardef\alignstrutmode\zerocount -% \alignedline{\floatparameter\c!location}\v!middle}% -% \docheckcaptioncontent{#1}{#2}{#3}{#4}% -% \ifnofloatcaption -% \dopreparenocaption{#1}{#2}{#3}{#4}% -% \edef\width{\the\wd\floatbox}% -% \doglobal\addlocalbackgroundtobox\floatbox -% \else -% % todo: installable maken, variant/method=auto vs macro -% \doifinsetelse{\floatcaptionparameter\c!location}{\v!high,\v!middle,\v!low} -% {\dopreparesidecaption{#1}{#2}{#3}{#4}} -% {\doifelse{\floatcaptionparameter\c!minwidth}\v!fit -% {\doifelse{\floatcaptionparameter\c!width}\v!max -% {\dopreparestackcaptionmax{#1}{#2}{#3}{#4}} -% {\ifdim\wd\tempcaptionbox>\wd\tempfloatbox % wider caption -% \doifelse{\floatcaptionparameter\c!width}\v!fit -% {\dopreparestackcaptionaut{#1}{#2}{#3}{#4}} -% {\dopreparestackcaptionwid{#1}{#2}{#3}{#4}}% -% \else -% \dopreparestackcaptionmin{#1}{#2}{#3}{#4}% -% \fi}} -% {\dopreparestackcaptionfix{#1}{#2}{#3}{#4}}}% new, special effects (see icare) -% \edef\width{\the\wd\tempfloatbox}% -% \addlocalbackgroundtobox\tempfloatbox -% \setbox\tempcaptionbox\hbox{\floatcaptionparameter\c!command{\box\tempcaptionbox}}% -% \moveboxontogrid\tempcaptionbox{\floatcaptionparameter\c!grid}\lastcaptionht -% \addlocalbackgroundtobox\tempcaptionbox -% \buildfloatbox -% \fi -% \ifnum\floatrotation>0 -% \global\setbox\floatbox\vbox -% {\rotate[\c!rotation=\floatrotation]{\box\floatbox}}% -% \edef\width{\the\wd\tempfloatbox}% -% \else -% \postcenterfloatbox\width -% \fi -% \egroup} - -\def\dosetpagfloat#1#2#3#4% \copy wegwerken +\def\locatefloatbox + {\chardef\alignstrutmode\zerocount + \shiftalignedline + {\floatparameter\c!leftmargin }{\floatparameter\c!rightmargin}% + {\floatparameter\c!innermargin}{\floatparameter\c!outermargin}% + \alignedline{\floatparameter\c!location}\v!middle} + +\def\locatecaptionbox + {\chardef\alignstrutmode\zerocount + \shiftalignedline + {\floatcaptionparameter\c!leftmargin }{\floatcaptionparameter\c!rightmargin}% + {\floatcaptionparameter\c!innermargin}{\floatcaptionparameter\c!outermargin}% + \alignedline{\floatparameter\c!location}\v!middle} + +\def\dosetpagfloat#1#2#3% \copy wegwerken {\bgroup \setlocalfloathsize \ifnum\floatrotation>0 @@ -1466,25 +1449,31 @@ \forgetall \postponenotes \dontcomplain - \setbox\tempfloatbox\vbox{\borderedfloatbox{#4}}% - \def\locatefloat - {\chardef\alignstrutmode\zerocount - \alignedline{\floatparameter\c!location}\v!middle}% - \docheckcaptioncontent{#1}{#2}{#3}{#4}% - \ifnofloatcaption - \dopreparenocaption{#1}{#2}{#3}{#4}% - \edef\width{\the\wd\floatbox}% - \doglobal\addlocalbackgroundtobox\floatbox - \else - % todo: installable maken, variant/method=auto vs macro - \dopreparedocaption{#1}{#2}{#3}{#4}% - \settracedcaptionbox - \edef\width{\the\wd\tempfloatbox}% - \addlocalbackgroundtobox\tempfloatbox - \setbox\tempcaptionbox\hbox{\floatcaptionparameter\c!command{\box\tempcaptionbox}}% - \moveboxontogrid\tempcaptionbox{\floatcaptionparameter\c!grid}\lastcaptionht - \addlocalbackgroundtobox\tempcaptionbox - \buildfloatbox + \setbox\tempfloatbox\vbox{\borderedfloatbox}% + \let\locatefloat \locatefloatbox + \let\locatecaption\locatecaptionbox + \docheckcaptioncontent{#2}{#3}% + \ifcase\floatparameter\c!method + \or % automatic + \ifnofloatcaption + \dopreparenocaption{#1}{#2}{#3}% + \edef\width{\the\wd\floatbox}% + \doglobal\addlocalbackgroundtobox\floatbox + \else + % todo: installable maken, variant/method=auto vs macro + \dopreparedocaption{#1}{#2}{#3}% + \settracedcaptionbox + \edef\width{\the\wd\tempfloatbox}% + \addlocalbackgroundtobox\tempfloatbox + \setbox\tempcaptionbox\hbox + {\dosetcaptionthings + \floatcaptionparameter\c!command{\box\tempcaptionbox}}% + \moveboxontogrid\tempcaptionbox{\floatcaptionparameter\c!grid}\lastcaptionht + \addlocalbackgroundtobox\tempcaptionbox + \buildfloatbox + \fi + \or % semi automatic + \or % manual \fi \ifnum\floatrotation>0 \global\setbox\floatbox\vbox @@ -1498,31 +1487,31 @@ \def\captionminwidth {15\bodyfontsize} \def\captionovershoot {2em} -\def\dopreparenocaption#1#2#3#4% +\def\dopreparenocaption#1#2#3% {\global\setbox\floatbox\vbox % pas op als wd groter dan hsize {\ifinsidecolumns\ifdim\wd\tempfloatbox>\hsize \let\locatefloat\relax \fi\fi \locatefloat{\copy\tempfloatbox}}} -\def\dopreparedocaption#1#2#3#4% +\def\dopreparedocaption#1#2#3% {\doifinsetelse{\floatcaptionparameter\c!location}{\v!top,\v!bottom} {\doifinsetelse{\floatcaptionparameter\c!width}{\v!fit,\v!max} {\doifelse{\floatcaptionparameter\c!minwidth}\v!fit {\doifelse{\floatcaptionparameter\c!width}\v!max - {\dopreparestackcaptionmax{#1}{#2}{#3}{#4}} + {\dopreparestackcaptionmax{#1}{#2}{#3}} {\ifdim\wd\tempcaptionbox>\wd\tempfloatbox % wider caption \doifelse{\floatcaptionparameter\c!width}\v!fit - {\dopreparestackcaptionaut{#1}{#2}{#3}{#4}} - {\dopreparestackcaptionwid{#1}{#2}{#3}{#4}}% + {\dopreparestackcaptionaut{#1}{#2}{#3}} + {\dopreparestackcaptionwid{#1}{#2}{#3}}% \else - \dopreparestackcaptionmin{#1}{#2}{#3}{#4}% + \dopreparestackcaptionmin{#1}{#2}{#3}% \fi}} - {\dopreparestackcaptionfix{#1}{#2}{#3}{#4}}}% - {\dopreparesidewidthcaption{#1}{#2}{#3}{#4}}}% new, special effects (see icare) + {\dopreparestackcaptionfix{#1}{#2}{#3}}}% + {\dopreparesidewidthcaption{#1}{#2}{#3}}}% new, special effects (see icare) {\doifinsetelse{\floatcaptionparameter\c!width}{\v!fit,\v!max} - {\dopreparesideautocaption{#1}{#2}{#3}{#4}} - {\dopreparesidewidthcaption{#1}{#2}{#3}{#4}}}} + {\dopreparesideautocaption{#1}{#2}{#3}} + {\dopreparesidewidthcaption{#1}{#2}{#3}}}} % \def\dosettempcaptionbox % {\dosetraggedvbox{\floatcaptionparameter\c!align}% @@ -1530,11 +1519,12 @@ \def\dosettempcaptionbox {\setbox\tempcaptionbox\vbox\bgroup - %expanded{\setupalign[\v!new,\v!reset,\floatcaptionparameter\c!align,\v!old]}% wrong! see icare - \expanded{\setupalign[\v!reset,\floatcaptionparameter\c!align]}% i need to check what reset does - \let\next} + %expanded{\setupalign[\v!new,\v!reset,\floatcaptionparameter\c!align,\v!old]}% wrong! see icare + \expanded{\setupalign[\v!reset,\floatcaptionparameter\c!align]}% i need to check what reset does + \dosetcaptionthings + \let\next} -\def\dopreparesideautocaption#1#2#3#4% +\def\dopreparesideautocaption#1#2#3% {\scratchdimen\dimexpr\hsize-\wd\tempfloatbox-\@@bkmargin\relax % was \tfskipsize\relax \ifdim\wd\tempcaptionbox>\scratchdimen \ifdim\wd\tempcaptionbox<1.3\scratchdimen @@ -1543,35 +1533,35 @@ \fi \dosettempcaptionbox {\hsize\scratchdimen - \putcompletecaption{#4}{#2}{#3}}} + \putcompletecaption{#2}{#3}}} -\def\dopreparesidewidthcaption#1#2#3#4% +\def\dopreparesidewidthcaption#1#2#3% {\dosettempcaptionbox {\hsize\floatcaptionparameter\c!width - \putcompletecaption{#4}{#2}{#3}}} + \putcompletecaption{#2}{#3}}} -\def\dopreparestackcaptionfix#1#2#3#4% +\def\dopreparestackcaptionfix#1#2#3% {\dosettempcaptionbox {\hsize\floatcaptionparameter\c!minwidth % special effects - \putcompletecaption{#4}{#2}{#3}}} + \putcompletecaption{#2}{#3}}} -\def\dopreparestackcaptionmax#1#2#3#4% +\def\dopreparestackcaptionmax#1#2#3% {\dosettempcaptionbox {\hsize\wd\tempfloatbox - \putcompletecaption{#4}{#2}{#3}}} + \putcompletecaption{#2}{#3}}} -\def\dopreparestackcaptionwid#1#2#3#4% +\def\dopreparestackcaptionwid#1#2#3% {\dosettempcaptionbox {\hsize\floatcaptionparameter\c!width - \putcompletecaption{#4}{#2}{#3}}} + \putcompletecaption{#2}{#3}}} -\def\dopreparestackcaptionmin#1#2#3#4% +\def\dopreparestackcaptionmin#1#2#3% {\dosettempcaptionbox {\hsize\wd\tempfloatbox \doifnothing{\floatcaptionparameter\c!align}\raggedcenter % on purpose overloads align ! - \putcompletecaption{#4}{#2}{#3}}} + \putcompletecaption{#2}{#3}}} -\def\dopreparestackcaptionaut#1#2#3#4% +\def\dopreparestackcaptionaut#1#2#3% {\doifsomething{\floatcaptionparameter\c!align} {\doifnotinset{\v!middle}{\floatcaptionparameter\c!align}% {\let\captionovershoot\!!zeropoint}}% @@ -1582,7 +1572,7 @@ {\trialtypesettingtrue \hsize\captionhsize \notesenabledfalse - \putcompletecaption{#4}{#2}{#3}}% + \putcompletecaption{#2}{#3}}% \ifdim\ht\scratchbox>\lineheight % more lines \dosettempcaptionbox {\hsize\captionhsize @@ -1590,11 +1580,11 @@ \ifdim\hsize<\captionminwidth\relax \hsize\captionhsize \fi - \putcompletecaption{#4}{#2}{#3}}% + \putcompletecaption{#2}{#3}}% \else \dosettempcaptionbox {\hsize\captionhsize - \putcompletecaption{#4}{#2}{#3}}% + \putcompletecaption{#2}{#3}}% \fi \else % float is smaller of equal to \hsize @@ -1609,30 +1599,30 @@ \advance\scratchdimen 3em % an average word length \ifdim\scratchdimen<\hsize \hsize\scratchdimen \fi \notesenabledfalse - \putcompletecaption{#4}{#2}{#3}}% + \putcompletecaption{#2}{#3}}% \ifdim\ht\scratchbox>\lineheight % at least an average word longer than a line \dosettempcaptionbox {\scratchdimen\captionhsize \advance\scratchdimen \captionovershoot \ifdim\scratchdimen<\hsize \hsize\scratchdimen \fi - \putcompletecaption{#4}{#2}{#3}}% + \putcompletecaption{#2}{#3}}% \else % just over a line, don't use an overshoot % % % todo: outer/inner and such \doifcommonelse{\floatcaptionparameter\c!align}{\v!left,\v!right,\v!flushleft,\v!flushright} {\dosettempcaptionbox {\hsize\captionhsize % strange : \raggedcenter - \putcompletecaption{#4}{#2}{#3}}} + \putcompletecaption{#2}{#3}}} {% nicer \dosettempcaptionbox {\hsize\captionhsize \doifnothing{\floatcaptionparameter\c!align}\raggedcenter% overloads - \putcompletecaption{#4}{#2}{#3}}}% + \putcompletecaption{#2}{#3}}}% \fi \fi} -\def\dopreparesidecaption#1#2#3#4% +\def\dopreparesidecaption#1#2#3% {\scratchdimen\dimexpr\hsize-\wd\tempfloatbox-\@@bkmargin\relax % was \tfskipsize\relax \ifdim\wd\tempcaptionbox>\scratchdimen \ifdim\wd\tempcaptionbox<1.3\scratchdimen @@ -1642,7 +1632,7 @@ \dosettempcaptionbox % \setbox\tempcaptionbox\vbox {\hsize\scratchdimen \doifnothing{\floatcaptionparameter\c!align}\raggedright % on purpose overloads align ! - \putcompletecaption{#4}{#2}{#3}}} + \putcompletecaption{#2}{#3}}} \newdimen\tempfloatheight \newdimen\tempfloatwidth @@ -1781,62 +1771,6 @@ \def\dofloatboxmiddlebuilder {\dofloatboxnextbuilder{\vfill\box\tempcaptionbox\vfill}} -% \def\dofloatboxnormalstackbuilder#1#2#3#4% hbox needed -% {\tempfloatwidth\wd\tempfloatbox -% \ifparfloat -% \hbox{#3}\dofloatboxbetweenstack\hbox{#4}% -% \else -% \hbox{#1}\dofloatboxbetweenstack\hbox{#2}% -% \fi} - -% \def\dofloatboxgridstackbuilder#1#2#3#4% -% {\dp\tempcaptionbox\strutdepth -% \setbox\scratchbox\vbox -% {\tempfloatwidth\wd\tempfloatbox -% \ifparfloat -% #3\vss\dofloatboxbetweenstack#4% -% \else -% #1\vss\dofloatboxbetweenstack#2% -% \fi}% -% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy -% \vbox to \noflines\lineheight{\unvbox\scratchbox}} - -% \def\dofloatboxstretchstackbuilder#1#2#3#4% -% {\dp\tempcaptionbox\strutdepth -% \setbox\scratchbox\vbox -% {\locatefloat{\copy#1}% -% \locatefloat{\copy#2}}% -% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy -% \vbox to \noflines\lineheight -% {\tempfloatwidth\wd\tempfloatbox -% \ifparfloat -% #3\vss\dofloatboxbetweenstack\vss#4% -% \else -% #1\vss\dofloatboxbetweenstack\vss#2% -% \fi}} - -% \def\dofloatboxtopbuilder -% {\let\next\dofloatboxnormalstackbuilder -% \expanded{\processallactionsinset[\floatcaptionparameter\c!location]} -% [ \v!grid=>\let\next\dofloatboxgridstackbuilder, -% \v!stretch=>\let\next\dofloatboxstretchstackbuilder]% -% \next -% {\locatetextfloat{\box\tempcaptionbox}} -% {\locatefloat {\box\tempfloatbox }} -% {\locatesidefloat{\box\tempcaptionbox}} -% {\hbox {\box\tempfloatbox }}} - -% \def\dofloatboxbottombuilder -% {\let\next\dofloatboxnormalstackbuilder -% \expanded{\processallactionsinset[\floatcaptionparameter\c!location]} -% [ \v!grid=>\let\next\dofloatboxgridstackbuilder, -% \v!stretch=>\let\next\dofloatboxstretchstackbuilder]% -% \next -% {\locatefloat {\box\tempfloatbox }} -% {\locatetextfloat{\box\tempcaptionbox}} -% {\hbox {\box\tempfloatbox }} -% {\locatesidefloat{\box\tempcaptionbox}}} - % \definefloat % [lefty][lefties][figure] % \setupfloat @@ -1917,8 +1851,8 @@ \def\dofloatboxstretchtopstackbuilder {\dp\tempcaptionbox\strutdepth \setbox\scratchbox\vbox - {\locatefloat{\copy\tempcaptionbox}% - \locatefloat{\copy\tempfloatbox }}% + {\locatecaption{\copy\tempcaptionbox}% + \locatefloat {\copy\tempfloatbox }}% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy \vbox to \noflines\lineheight {\tempfloatwidth\wd\tempfloatbox @@ -1935,8 +1869,8 @@ \def\dofloatboxstretchbotstackbuilder {\dp\tempcaptionbox\strutdepth \setbox\scratchbox\vbox - {\locatefloat{\copy\tempfloatbox }% - \locatefloat{\copy\tempcaptionbox}}% + {\locatefloat {\copy\tempfloatbox }% + \locatecaption{\copy\tempcaptionbox}}% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy \vbox to \noflines\lineheight {\tempfloatwidth\wd\tempfloatbox @@ -1964,8 +1898,8 @@ \v!stretch=>\let\next\dofloatboxstretchstackbuilder]% \next} -\def\relocatecaptionright#1{\locatefloat{\hbox to \tempfloatwidth{\hss#1}}} -\def\relocatecaptionleft #1{\locatefloat{\hbox to \tempfloatwidth{#1\hss}}} +\def\relocatecaptionright#1{\locatecaption{\hbox to \tempfloatwidth{\hss#1}}} +\def\relocatecaptionleft #1{\locatecaption{\hbox to \tempfloatwidth{#1\hss}}} \long\def\installfloatboxbuilder#1#2{\setvalue{\??kj:#1}{#2}} @@ -1980,7 +1914,7 @@ \executeifdefined{\??kj:\floatcaptionarrangement}{\getvalue{\??kj:\s!default}}}} \def\locatetextfloat - {\let\next\locatefloat + {\let\next\locatecaption \expanded{\processallactionsinset[\floatcaptionparameter\c!location]} [ \v!left=>\let\next\relocatecaptionleft, \v!right=>\let\next\relocatecaptionright, @@ -2041,19 +1975,19 @@ \box\floatbox \ifdone\hskip\effectiverightskip\fi\hss}} -\def\dosetparfloat#1#2#3#4% +\def\dosetparfloat#1#2#3% {\bgroup \forgetall \postponenotes \dontcomplain %\showcomposition - \setbox\tempfloatbox\vbox{\borderedfloatbox{#4}}% + \setbox\tempfloatbox\vbox{\borderedfloatbox}% \addlocalbackgroundtobox\tempfloatbox % no \doglobal - \docheckcaptioncontent{#1}{#2}{#3}{#4}% + \docheckcaptioncontent{#2}{#3}% \ifnofloatcaption \global\setbox\floatbox\vbox{\box\tempfloatbox}% \else - \dopreparedosidecaption{#1}{#2}{#3}{#4}% + \dopreparedosidecaption{#1}{#2}{#3}% \settracedcaptionbox \setbox\tempcaptionbox\hbox{\floatcaptionparameter\c!command{\box\tempcaptionbox}}% \moveboxontogrid\tempcaptionbox{\floatcaptionparameter\c!grid}\lastcaptionht @@ -2062,24 +1996,29 @@ \fi \egroup} -\def\dopreparedosidecaption#1#2#3#4% will be enhanced +\def\dopreparedosidecaption#1#2#3% will be enhanced {\doifelse{\floatcaptionparameter\c!width}\v!max {\dosettempcaptionbox - {\hsize\wd\tempfloatbox\putcompletecaption{#4}{#2}{#3}}}% + {\hsize\wd\tempfloatbox + \putcompletecaption{#2}{#3}}}% {\doifelse{\floatcaptionparameter\c!width}\v!fit {\ifdim\wd\tempcaptionbox>\wd\tempfloatbox\relax \setbox\tempcaptionbox\vbox - {\forgetall\hsize\wd\tempfloatbox\putcompletecaption{#4}{#2}{#3}}% + {\forgetall % needed? + \hsize\wd\tempfloatbox + \dosetcaptionthings + \putcompletecaption{#2}{#3}}% \else \setbox\tempcaptionbox\hbox to \wd\tempfloatbox {\hss\box\tempcaptionbox\hss}% \fi} {\dosettempcaptionbox {\hsize\floatcaptionparameter\c!width % \wd\tempfloatbox - \putcompletecaption{#4}{#2}{#3}}}}} + \putcompletecaption{#2}{#3}}}}} \def\buildsidefloatbox - {\let\locatefloat\relax + {\let\locatefloat \relax + \let\locatecaption\relax \def\locatesidefloat##1% {\begingroup \chardef\alignstrutmode\zerocount @@ -2090,16 +2029,12 @@ \newif\ifparfloat -\long\def\dosetfloatbox#1#2#3#4% todo : \global\setbox +\long\def\dosetfloatbox#1#2#3% todo : \global\setbox {\ifvisible \par \edef\floatcaptiondirectives{\floatparameter\c!location,\floatcaptionparameter\c!location}% - \ifparfloat - \@EA\dosetparfloat % {#1}{#2}{#3}{#4}% - \else - \@EA\dosetpagfloat % {#1}{#2}{#3}{#4}% - \fi{#1}{#2}{#3}{#4}% - \setlocalfloatdimensions{#4}{#1}\floatbox\global % tzt arg 3/4 weg + \ifparfloat\@EA\dosetparfloat\else\@EA\dosetpagfloat\fi{#1}{#2}{#3}% + \setlocalfloatdimensions{#1}\floatbox\global % tzt arg 3/4 weg \setbox\floatbox\hbox {\dosavefloatdata\restoretextcolor{\box\floatbox}}% \global\floatheight\ht\floatbox @@ -2126,8 +2061,8 @@ \newcounter\noxfloatlocations -\long\def\dofloat#1#2#3#4% - {\dosetfloatbox{#1}{#2}{#3}{#4}% +\long\def\dofloat#1#2#3% + {\dosetfloatbox{#1}{#2}{#3}% \dogetfloatbox{#1}\empty} \let\naturalfloatheight\!!zeropoint @@ -2159,7 +2094,7 @@ \vss % gets rid of the depth (unless tabulate) \rawpagereference\s!flt{#2}}% \egroup - \dofloat{#4}{}{#6}{#1}% + \dofloat{#4}{}{#6}% \else \doglobal\convertargument#6\to\asciititle % \asciititle is global \ifnofloatnumber @@ -2167,7 +2102,7 @@ {\unvbox\floatbox % no \vss, keep the depth \rawreference\s!flt{#2}{{}{\asciititle}}}% \egroup - \dofloat{#4}{}{#6}{#1}% + \dofloat{#4}{}{#6}% \else \preparefloatnumber{#1}% \global\setbox\floatbox\vbox @@ -2177,7 +2112,7 @@ \dowritetolist{#3}{\composedsectionnumber}{#6}{#3}}% \egroup \preparefullnumber{\??kj#1}\composedsectionnumber\preparednumber - \dofloat{#4}{\labeltexts{#5}{\preparednumber}}{#6}{#1}% + \dofloat{#4}{\labeltexts{#5}{\preparednumber}}{#6}% \fi \fi \global\insidefloatfalse} @@ -2454,13 +2389,18 @@ \c!before=, % not used (yet) \c!inbetween={\blank[\v!medium]}, \c!after=, % not used (yet) -\c!spacebefore=, -\c!spaceinbetween=, % replaces fuzzy inbetween dual usage -\c!spaceafter=, + \c!spacebefore=, + \c!spaceinbetween=, % replaces fuzzy inbetween dual usage + \c!spaceafter=, \c!width=\v!fit, \c!minwidth=\v!fit, % id est: the width of the floatbox in some cases \c!headstyle=\v!bold, \c!headcolor=, + \c!leftmargin=\zeropoint, + \c!rightmargin=\zeropoint, + \c!outermargin=\zeropoint, + \c!innermargin=\zeropoint, + \c!setups=, \c!style=\v!normal, \c!color=, \c!textstyle=, @@ -2505,6 +2445,11 @@ \c!sidemethod=\ifgridsnapping2\else1\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt) \c!indentnext=\v!no, \c!margin=1em, + \c!method=1, + \c!leftmargin=\zeropoint, % displacement in 'normal floats' + \c!rightmargin=\zeropoint, % idem + \c!innermargin=\zeropoint, % idem + \c!outermargin=\zeropoint, % idem \c!leftmargindistance=\zeropoint, \c!rightmargindistance=\@@bkleftmargindistance, \c!ntop=2, diff --git a/tex/context/base/page-imp.tex b/tex/context/base/page-imp.tex index 3acf201bc..039f36f4c 100644 --- a/tex/context/base/page-imp.tex +++ b/tex/context/base/page-imp.tex @@ -144,7 +144,7 @@ \let\pagestoshipout\empty % {1,3,6} \chardef\whichpagetoshipout=0 % 0=all 1=odd 2=even -\ifx\processshipoutbox\undefined \let\processshipoutbox\firstofoneargument \fi +\ifx\finalizeshipoutbox\undefined \let\finalizeshipoutbox\firstofoneargument \fi \def\actualshipout#1% {\global\advance\shippedoutpages\plusone @@ -172,7 +172,7 @@ \vskip\scratchdimen \hskip\scratchdimen \hbox % \setbox0=\box.. is nicer - {\setbox0\hbox{\processshipoutbox{#1}}% just in case there are objects there, hook for testing + {\setbox0\hbox{\finalizeshipoutbox{#1}}% just in case there are objects there, hook for testing \setbox\scratchbox\hbox {% before the main one ! \ifcase\realfolio \or diff --git a/tex/context/base/page-ini.tex b/tex/context/base/page-ini.tex index a51395730..2582f2dc0 100644 --- a/tex/context/base/page-ini.tex +++ b/tex/context/base/page-ini.tex @@ -780,9 +780,6 @@ %D Some hooks: -\newtoks \everybeforeoutput -\newtoks \everyafteroutput - \output{\inotrtrue\the\everybeforeoutput\the\mainoutput\the\everyafteroutput} \installoutput\synchronizeoutput % maybe add pagediscards diff --git a/tex/context/base/prop-ini.tex b/tex/context/base/prop-ini.tex index db6a45c8d..b7aef6e18 100644 --- a/tex/context/base/prop-ini.tex +++ b/tex/context/base/prop-ini.tex @@ -39,14 +39,6 @@ {\csname\s!check\currentpropertytype property\endcsname \global\expandafter\let\csname\??py\s!check\currentproperty\endcsname\empty} -% \def\checkproperty[#1]% -% {\bgroup -% \def\currentproperty{#1}% -% \docheckproperty -% \egroup} -% -% oeps, was wrong, no reset - \def\checkproperty[#1]% {\bgroup \def\currentproperty{#1}% @@ -122,14 +114,14 @@ \doifelsevalue{\??py#1\c!method}\v!command {\doifelsevalue{\??py#1\c!global}\v!yes {\setgvalue{\e!start#1}{\dostartproperty{#1}}% - \letgvalue{\e!stop#1}\dostopproperty}% + \letgvalue{\e!stop #1}\dostopproperty}% {\setgvalue{\e!start#1}{\dostartgproperty{#1}}% - \letgvalue{\e!stop#1}\dostopgproperty}}% + \letgvalue{\e!stop #1}\dostopgproperty}}% {\doifelsevalue{\??py#1\c!global}\v!yes {\setgvalue{\e!start#2}[##1]{\dostartproperty{##1}}% - \letgvalue{\e!stop#2}\dostopproperty}% + \letgvalue{\e!stop #2}\dostopproperty}% {\setgvalue{\e!start#2}[##1]{\dostartgproperty{##1}}% - \letgvalue{\e!stop#2}\dostopgproperty}}} + \letgvalue{\e!stop #2}\dostopgproperty}}} \def\nododefineproperty[#1][#2][#3]% {} @@ -146,17 +138,6 @@ \getparameters[\??py][#1]% \fi} -% \def\propertyparameter#1% expands to #1 when not defined (see \define...) -% {\csname\??py -% \ifcsname\??py\currentproperty#1\endcsname -% \currentproperty#1% -% \else\ifcsname\??py\currentpropertytype#1\endcsname -% \currentpropertytype#1% -% \else -% :n:\currentproperty -% \fi\fi -% \endcsname} - \letvalue{\??py\s!empty}\empty % beware, normally \*parameter concerns the current one diff --git a/tex/context/base/prop-lay.tex b/tex/context/base/prop-lay.tex index 0e5038d19..f29298976 100644 --- a/tex/context/base/prop-lay.tex +++ b/tex/context/base/prop-lay.tex @@ -17,14 +17,6 @@ \unprotect -% \def\checklayerproperty -% {\dodefineviewerlayer -% \currentproperty % tag -% {\checkedpropertyparameter\c!title\currentproperty}% -% {\checkedpropertyparameter\c!state\v!start}% visible or hidden -% {0}% type (1=frozen) -% {0}}% printable - \def\checklayerproperty {\doifelse{\checkedpropertyparameter\v!printable\currentproperty}\v!no {\def\printviewerlayer{0}} diff --git a/tex/context/base/prop-mis.mkii b/tex/context/base/prop-mis.mkii new file mode 100644 index 000000000..3b372546d --- /dev/null +++ b/tex/context/base/prop-mis.mkii @@ -0,0 +1,155 @@ +%D \module +%D [ file=prop-mis, +%D version=2004.05.29, % some code moved from private modules +%D title=\CONTEXT\ Property Macros, +%D subtitle=Miscelaneous, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\unprotect + +%D Overprint cum suis. + +\definepropertyhandler \v!overprint {\dostartoverprint} +\definepropertyhandler \v!knockout {\dostopoverprint } + +\def\startoverprintproperty + {\ifincolor + \propertyhandler\currentproperty + \dooverprintmark\currentproperty + \fi} + +\def\stopoverprintproperty + {\ifincolor + \ifcase\currentpropertylevel\or + \dostopoverprint + \dooverprintmark\empty + \else + \propertyhandler\previousproperty + \dooverprintmark\previousproperty + \fi + \fi} + +\rawnewmark\overprintmark + +\def\dooverprintmark#1% + {\ifinpagebody \else \ifinframed \else + \expanded{\rawsetmark\noexpand\overprintmark{#1}}% + \fi \fi} + +\def\pushoverprintproperty + {\doifsomething{\rawgetbotmark\overprintmark}\dostopoverprint} + +\def\popoverprintproperty + {\doifsomething{\rawgetbotmark\overprintmark}% + {\propertyhandler{\rawgetbotmark\overprintmark}}} + +\def\popsplitoverprintproperty + {\getsplitmarks\overprintmark % hier wel + \doifsomething{\rawgetsplitbotmark\overprintmark}% + {\propertyhandler{\rawgetsplitbotmark\overprintmark}}} + +\appendtoks \pushoverprintproperty \to \everypushproperties +\appendtoks \popoverprintproperty \to \everypopproperties +\appendtoks \popsplitoverprintproperty \to \everypopsplitproperties + +%D Negative cum suis. + +\definepropertyhandler \v!negative {\dostartnegative} +\definepropertyhandler \v!positive {\dostopnegative } + +\def\startnegativeproperty + {\ifincolor + \propertyhandler\currentproperty + \donegativemark\currentproperty + \fi} + +\def\stopnegativeproperty + {\ifincolor + \ifcase\currentpropertylevel\or + \dostopnegative + \donegativemark\empty + \else + \propertyhandler\previousproperty + \donegativemark\previousproperty + \fi + \fi} + +\rawnewmark\negativemark + +\def\donegativemark#1% + {\ifinpagebody \else \ifinframed \else + \expanded{\rawsetmark\noexpand\negativemark{#1}}% + \fi \fi} + +\def\pushnegativeproperty + {\doifsomething{\rawgetbotmark\negativemark}\dostopnegative} + +\def\popnegativeproperty + {\doifsomething{\rawgetbotmark\overprintmark}% + {\propertyhandler{\rawgetbotmark\negativemark}}} + +\def\popsplitnegativeproperty + {\getsplitmarks\negativemark % hier wel + \doifsomething{\rawgetsplitbotmark\negativemark}% + {\propertyhandler{\rawgetsplitbotmark\negativemark}}} + +\appendtoks \pushnegativeproperty \to \everypushproperties +\appendtoks \popnegativeproperty \to \everypopproperties +\appendtoks \popsplitnegativeproperty \to \everypopsplitproperties + +%D Effects. + +\definepropertyhandler \v!normal {0} +\definepropertyhandler \v!inner {0} +\definepropertyhandler \v!outer {1} +\definepropertyhandler \v!both {2} +\definepropertyhandler \v!hidden {3} + +\def\effectpropertydata#1% + {{\propertyhandler{#1}}% + {\propertyparameter{#1}\c!rulethickness}% + {\propertyparameter{#1}\c!stretch}} + +\def\starteffectproperty + {\expanded{\dostartfonteffect\effectpropertydata\currentproperty}% + \doeffectmark{\effectpropertydata\currentproperty}} + +\def\stopeffectproperty + {\dostopfonteffect + \ifcase\currentpropertylevel\or + \doeffectmark\empty + \else + \expanded{\dostartfonteffect\effectpropertydata\previousproperty}% + \doeffectmark{\effectpropertydata\previousproperty}% + \fi} + +\rawnewmark\effectmark + +\def\doeffectmark#1% + {\ifinpagebody \else \ifinframed \else + \expanded{\rawsetmark\noexpand\effectmark{#1}}% could be number + \fi \fi} + +\def\pusheffectproperty + {\doifsomething{\rawgetbotmark\effectmark}\dostopfonteffect} + +\def\popeffectproperty + {\doifsomething{\rawgetbotmark\effectmark}% + {\expanded{\dostartfonteffect\rawgetbotmark\effectmark}}} + +\def\popspliteffectproperty + {\getsplitmarks\effectmark + \doifsomething{\rawgetsplitbotmark\effectmark}% + {\expanded{\dostartfonteffect\rawgetsplitbotmark\effectmark}}} + +\appendtoks \pusheffectproperty \to \everypushproperties +\appendtoks \popeffectproperty \to \everypopproperties +\appendtoks \popspliteffectproperty \to \everypopsplitproperties + +\protect \endinput diff --git a/tex/context/base/prop-mis.mkiv b/tex/context/base/prop-mis.mkiv new file mode 100644 index 000000000..ee292155e --- /dev/null +++ b/tex/context/base/prop-mis.mkiv @@ -0,0 +1,46 @@ +%D \module +%D [ file=prop-mis, +%D version=2004.05.29, % some code moved from private modules +%D title=\CONTEXT\ Property Macros, +%D subtitle=Miscelaneous, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\unprotect + +%D Overprint cum suis. + +\definepropertyhandler \v!overprint {\dotriggeroverprint\v!overprint} +\definepropertyhandler \v!knockout {\dotriggeroverprint\v!knockout } + +\def\startoverprintproperty{\dotriggeroverprint\v!overprint} +\def\stopoverprintproperty {\dotriggeroverprint\v!knockout } + +%D Negative cum suis.\def\dotriggeroverprint#1{\csname(os:#1)\endcsname} + +\definepropertyhandler \v!negative {\dotriggernegative\v!negative} +\definepropertyhandler \v!positive {\dotriggernegative\v!positive} + +\def\startnegativeproperty{\dotriggernegative\v!negative} +\def\stopnegativeproperty {\dotriggernegative\v!positive} + +%D Effects. + +\def\mktriggereffect#1% + {\dotriggereffect{#1}{\propertyparameter{#1}\c!stretch}{\propertyparameter{#1}\c!rulethickness}} + +\definepropertyhandler \v!normal {\mktriggereffect\v!normal} +\definepropertyhandler \v!inner {\mktriggereffect\v!inner } +\definepropertyhandler \v!outer {\mktriggereffect\v!outer } +\definepropertyhandler \v!both {\mktriggereffect\v!both } +\definepropertyhandler \v!hidden {\mktriggereffect\v!hidden} + +\def\starteffectproperty{\mktriggereffect\currentproperty} +\def\stopeffectproperty {\mktriggereffect\v!normal } + +\protect \endinput diff --git a/tex/context/base/prop-mis.tex b/tex/context/base/prop-mis.tex index 769fc33f4..ed287d044 100644 --- a/tex/context/base/prop-mis.tex +++ b/tex/context/base/prop-mis.tex @@ -26,97 +26,11 @@ \defineproperty[\v!overprint][\s!overprint] [\c!method=\v!command] \defineproperty[\v!knockout] [\s!overprint] [\c!method=\v!command] -\definepropertyhandler \v!overprint {\dostartoverprint} -\definepropertyhandler \v!knockout {\dostopoverprint } - -\def\startoverprintproperty - {\ifincolor - \propertyhandler\currentproperty - \dooverprintmark\currentproperty - \fi} - -\def\stopoverprintproperty - {\ifincolor - \ifcase\currentpropertylevel\or - \dostopoverprint - \dooverprintmark\empty - \else - \propertyhandler\previousproperty - \dooverprintmark\previousproperty - \fi - \fi} - -\rawnewmark\overprintmark - -\def\dooverprintmark#1% - {\ifinpagebody \else \ifinframed \else - \expanded{\rawsetmark\noexpand\overprintmark{#1}}% - \fi \fi} - -\def\pushoverprintproperty - {\doifsomething{\rawgetbotmark\overprintmark}\dostopoverprint} - -\def\popoverprintproperty - {\doifsomething{\rawgetbotmark\overprintmark}% - {\propertyhandler{\rawgetbotmark\overprintmark}}} - -\def\popsplitoverprintproperty - {\getsplitmarks\overprintmark % hier wel - \doifsomething{\rawgetsplitbotmark\overprintmark}% - {\propertyhandler{\rawgetsplitbotmark\overprintmark}}} - -\appendtoks \pushoverprintproperty \to \everypushproperties -\appendtoks \popoverprintproperty \to \everypopproperties -\appendtoks \popsplitoverprintproperty \to \everypopsplitproperties - %D Negation. \defineproperty [\v!negative] [\s!negative] [\c!method=\v!command] \defineproperty [\v!positive] [\s!negative] [\c!method=\v!command] -\definepropertyhandler \v!negative {\dostartnegative} -\definepropertyhandler \v!positive {\dostopnegative } - -\def\startnegativeproperty - {\ifincolor - \propertyhandler\currentproperty - \donegativemark\currentproperty - \fi} - -\def\stopnegativeproperty - {\ifincolor - \ifcase\currentpropertylevel\or - \dostopnegative - \donegativemark\empty - \else - \propertyhandler\previousproperty - \donegativemark\previousproperty - \fi - \fi} - -\rawnewmark\negativemark - -\def\donegativemark#1% - {\ifinpagebody \else \ifinframed \else - \expanded{\rawsetmark\noexpand\negativemark{#1}}% - \fi \fi} - -\def\pushnegativeproperty - {\doifsomething{\rawgetbotmark\negativemark}\dostopnegative} - -\def\popnegativeproperty - {\doifsomething{\rawgetbotmark\overprintmark}% - {\propertyhandler{\rawgetbotmark\negativemark}}} - -\def\popsplitnegativeproperty - {\getsplitmarks\negativemark % hier wel - \doifsomething{\rawgetsplitbotmark\negativemark}% - {\propertyhandler{\rawgetsplitbotmark\negativemark}}} - -\appendtoks \pushnegativeproperty \to \everypushproperties -\appendtoks \popnegativeproperty \to \everypopproperties -\appendtoks \popsplitnegativeproperty \to \everypopsplitproperties - %D Special font effects. \setupproperty @@ -130,95 +44,8 @@ \defineproperty [\v!normal] [\s!effect] \defineproperty [\v!hidden] [\s!effect] -\definepropertyhandler \v!normal {0} -\definepropertyhandler \v!inner {0} -\definepropertyhandler \v!outer {1} -\definepropertyhandler \v!both {2} -\definepropertyhandler \v!hidden {3} - -% \def\handleeffectproperty#1% -% {\expanded{\dostartfonteffect -% {\propertyhandler{#1}}% -% {\propertyparameter{#1}\c!lijndikte}% -% {\propertyparameter{#1}\c!rek}}} - -% \def\starteffectproperty -% {\handleeffectproperty\currentproperty -% \doeffectmark\currentproperty} - -% \def\stopeffectproperty -% {\dostopfonteffect -% \ifcase\currentpropertylevel\or -% \doeffectmark\empty -% \else -% \handleeffectproperty\previousproperty -% \doeffectmark\previousproperty -% \fi} - -% \rawnewmark\effectmark - -% \def\doeffectmark#1% -% {\ifinpagebody \else \ifinframed \else -% \expanded{\rawsetmark\noexpand\effectmark{#1}}% could be number -% \fi \fi} - -% \def\pusheffectproperty -% {\doifsomething{\rawgetbotmark\effectmark}\dostopfonteffect} - -% \def\popeffectproperty -% {\doifsomething{\rawgetbotmark\effectmark}% -% {\handleeffectproperty{\rawgetbotmark\effectmark}}} - -% \def\popspliteffectproperty -% {\getsplitmarks\effectmark -% \doifsomething{\rawgetsplitbotmark\effectmark}% -% {\handleeffectproperty{\rawgetsplitbotmark\effectmark}}} - -% \appendtoks \pusheffectproperty \to \everypushproperties -% \appendtoks \popeffectproperty \to \everypopproperties -% \appendtoks \popspliteffectproperty \to \everypopsplitproperties - -% % - -\def\effectpropertydata#1% - {{\propertyhandler{#1}}% - {\propertyparameter{#1}\c!rulethickness}% - {\propertyparameter{#1}\c!stretch}} - -\def\starteffectproperty - {\expanded{\dostartfonteffect\effectpropertydata\currentproperty}% - \doeffectmark{\effectpropertydata\currentproperty}} - -\def\stopeffectproperty - {\dostopfonteffect - \ifcase\currentpropertylevel\or - \doeffectmark\empty - \else - \expanded{\dostartfonteffect\effectpropertydata\previousproperty}% - \doeffectmark{\effectpropertydata\previousproperty}% - \fi} - -\rawnewmark\effectmark - -\def\doeffectmark#1% - {\ifinpagebody \else \ifinframed \else - \expanded{\rawsetmark\noexpand\effectmark{#1}}% could be number - \fi \fi} - -\def\pusheffectproperty - {\doifsomething{\rawgetbotmark\effectmark}\dostopfonteffect} - -\def\popeffectproperty - {\doifsomething{\rawgetbotmark\effectmark}% - {\expanded{\dostartfonteffect\rawgetbotmark\effectmark}}} - -\def\popspliteffectproperty - {\getsplitmarks\effectmark - \doifsomething{\rawgetsplitbotmark\effectmark}% - {\expanded{\dostartfonteffect\rawgetsplitbotmark\effectmark}}} +%D Plugin: -\appendtoks \pusheffectproperty \to \everypushproperties -\appendtoks \popeffectproperty \to \everypopproperties -\appendtoks \popspliteffectproperty \to \everypopsplitproperties +\loadmarkfile{prop-mis} \protect \endinput diff --git a/tex/context/base/s-abr-01.tex b/tex/context/base/s-abr-01.tex index 98e36e2f1..3933b0a63 100644 --- a/tex/context/base/s-abr-01.tex +++ b/tex/context/base/s-abr-01.tex @@ -46,6 +46,7 @@ \logo [CD] {cd} \logo [CDROM] {cdrom} \logo [CID] {cid} +\logo [CJK] {cjk} \logo [CMR] {cmr} \logo [CMYK] {cmyk} \logo [CODHOST] {CodHost} diff --git a/tex/context/base/spec-dpx.tex b/tex/context/base/spec-dpx.tex index 44bbe10b6..d8ec1e518 100644 --- a/tex/context/base/spec-dpx.tex +++ b/tex/context/base/spec-dpx.tex @@ -393,6 +393,7 @@ \global\let\currentPDFresources\empty \fi \special{pdf:exobj}}% + \finalizeobjectbox\nextbox \smashbox\nextbox \flushatshipout{\box\nextbox}% \egroup}% @@ -749,6 +750,7 @@ {\scratchdimen\wd#2\scratchdimen.5\scratchdimen\hskip-\the\scratchdimen \special{pdf:uxobj @MPPDF::\MPPDFobjectcounter}}}}% \expanded{\doDVIPDFMXstartobject\zerocount{MPPDF}\MPPDFobjectcounter{\the\wd#2}{\the\ht#2}{\the\dp#2}}% + \finalizeobjectbox#2% \box#2% \doDVIPDFMXstopobject} diff --git a/tex/context/base/spec-fdf.tex b/tex/context/base/spec-fdf.tex index 7b99dfcc9..3531ca0d9 100644 --- a/tex/context/base/spec-fdf.tex +++ b/tex/context/base/spec-fdf.tex @@ -329,12 +329,9 @@ \def\doPDFsetupwhateverbox#1#2#3#4#5#6% watch the extra arguments {\bgroup - \!!widtha#5% - \advance\!!widtha#3% - \!!heighta-#6% - \!!heightb#2% extra argument - \advance\!!heightb -#4% - \advance\!!heighta \!!heightb + \!!widtha \dimexpr#5+#3\relax + \!!heightb\dimexpr#2-#4\relax + \!!heighta\dimexpr\!!heightb-#6\relax % sometimes whole values give better results % \PointsToWholeBigPoints{#3}\left % \PointsToWholeBigPoints\!!heighta\bottom @@ -2972,12 +2969,6 @@ {\doPDFregistersomeindexcolor{#1}{#2}{#3}{#4}{Gray}{0.0 1.0}% {pop}} -% \def\doPDFregisterfigurecolor#1% -% {\dogetobjectreference -% {PDF\ifcase\internalspotcolorsize{#1} CS\or CS\else IX\fi} -% {\internalspotcolorname{#1}} -% \PDFimagecolorreference} - \let\checkpredefinedcolor\predefineindexcolor % we need an index in order to negate bitmaps \def\doPDFregisterfigurecolor#1% always an index color diff --git a/tex/context/base/spec-tpd.tex b/tex/context/base/spec-tpd.tex index 428eb2750..37926efb5 100644 --- a/tex/context/base/spec-tpd.tex +++ b/tex/context/base/spec-tpd.tex @@ -906,6 +906,7 @@ % won't work in xforms; some day I will optimize % this. \the\everyPDFxform + \finalizeobjectbox\nextbox \immediate\pdfxform resources {\currentPDFresources\the\pdfpageresources}% \nextbox @@ -1360,6 +1361,7 @@ \def\setMPPDFobject#1#2% resources boxnumber {\the\everyPDFxform + \finalizeobjectbox{#2}% \immediate\pdfxform resources{#1}#2% \edef\getMPPDFobject{\noexpand\pdfrefxform\the\pdflastxform}} diff --git a/tex/context/base/syst-con.lua b/tex/context/base/syst-con.lua index 273bc5b5c..9f35d68b6 100644 --- a/tex/context/base/syst-con.lua +++ b/tex/context/base/syst-con.lua @@ -1,30 +1,28 @@ --- filename : syst-con.lua --- comment : companion to syst-con.tex (in ConTeXt) --- author : Hans Hagen, PRAGMA-ADE, Hasselt NL --- copyright: PRAGMA ADE / ConTeXt Development Team --- license : see context related readme files +if not modules then modules = { } end modules ['syst-con'] = { + version = 1.001, + comment = "companion to syst-con.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} --- remark : compact version +converters = converters or { } -if not versions then versions = { } end versions['syst-con'] = 1.001 -if not convert then convert = { } end - --- For raw 8 bit characters, the offset is 0x110000 (bottom of plane 18) --- at the top of luatex's char range but outside the unicode range. - -function convert.lchexnumber (n) tex.sprint(string.format("%x" ,n)) end -function convert.uchexnumber (n) tex.sprint(string.format("%X" ,n)) end -function convert.lchexnumbers (n) tex.sprint(string.format("%02x",n)) end -function convert.uchexnumbers (n) tex.sprint(string.format("%02X",n)) end -function convert.octnumber (n) tex.sprint(string.format("%03o",n)) end -function convert.hexstringtonumber(n) tex.sprint(tonumber(n,16)) end -function convert.octstringtonumber(n) tex.sprint(tonumber(n, 8)) end -function convert.rawcharacter (n) tex.sprint(unicode.utf8.char(0x110000+n)) end +--[[ldx-- +

For raw 8 bit characters, the offset is 0x110000 (bottom of plane 18) at +the top of 's char range but outside the unicode range.

+--ldx]]-- do - local char = unicode.utf8.char - local flush = tex.sprint + local char, flush, format = unicode.utf8.char, tex.sprint, string.format - function convert.rawcharacter(n) flush(char(0x110000+n)) end + function converters.lchexnumber (n) flush(format("%x" ,n)) end + function converters.uchexnumber (n) flush(format("%X" ,n)) end + function converters.lchexnumbers (n) flush(format("%02x",n)) end + function converters.uchexnumbers (n) flush(format("%02X",n)) end + function converters.octnumber (n) flush(format("%03o",n)) end + function converters.hexstringtonumber(n) flush(tonumber(n,16)) end + function converters.octstringtonumber(n) flush(tonumber(n, 8)) end + function converters.rawcharacter (n) flush(char(0x110000+n)) end end diff --git a/tex/context/base/syst-con.mkiv b/tex/context/base/syst-con.mkiv index ddc9fe564..2f84395f0 100644 --- a/tex/context/base/syst-con.mkiv +++ b/tex/context/base/syst-con.mkiv @@ -15,13 +15,13 @@ \unprotect -\def\lchexnumber #1{\ctxlua{convert.lchexnumber(\number#1)}} -\def\uchexnumber #1{\ctxlua{convert.uchexnumber(\number#1)}} -\def\lchexnumbers #1{\ctxlua{convert.lchexnumbers(\number#1)}} -\def\uchexnumbers #1{\ctxlua{convert.uchexnumbers(\number#1)}} -\def\octnumber #1{\ctxlua{convert.octnumber(\number#1)}} -\def\hexstringtonumber#1{\ctxlua{convert.hexstringtonumber("#1")}} -\def\octstringtonumber#1{\ctxlua{convert.octstringtonumber("#1")}} -\def\rawcharacter #1{\ctxlua{convert.rawcharacter(\number#1)}} +\def\lchexnumber #1{\ctxlua{converters.lchexnumber(\number#1)}} +\def\uchexnumber #1{\ctxlua{converters.uchexnumber(\number#1)}} +\def\lchexnumbers #1{\ctxlua{converters.lchexnumbers(\number#1)}} +\def\uchexnumbers #1{\ctxlua{converters.uchexnumbers(\number#1)}} +\def\octnumber #1{\ctxlua{converters.octnumber(\number#1)}} +\def\hexstringtonumber#1{\ctxlua{converters.hexstringtonumber("#1")}} +\def\octstringtonumber#1{\ctxlua{converters.octstringtonumber("#1")}} +\def\rawcharacter #1{\ctxlua{converters.rawcharacter(\number#1)}} \protect \endinput diff --git a/tex/context/base/toks-ini.lua b/tex/context/base/toks-ini.lua index ad046be50..cf313ceb3 100644 --- a/tex/context/base/toks-ini.lua +++ b/tex/context/base/toks-ini.lua @@ -48,8 +48,8 @@ tokens.letters = function(str) return t end -collector = collector or { } -collector.data = collector.data or { } +collectors = collectors or { } +collectors.data = collectors.data or { } function tex.printlist(data) callbacks.push('token_filter', function () @@ -58,27 +58,27 @@ function tex.printlist(data) end) end -function collector.flush(tag) - tex.printlist(collector.data[tag]) +function collectors.flush(tag) + tex.printlist(collectors.data[tag]) end -function collector.test(tag) - tex.printlist(collector.data[tag]) +function collectors.test(tag) + tex.printlist(collectors.data[tag]) end -collector.registered = { } +collectors.registered = { } -function collector.register(name) - collector.registered[token.csname_id(name)] = name +function collectors.register(name) + collectors.registered[token.csname_id(name)] = name end -function collector.install(tag,end_cs) - collector.data[tag] = { } - local data = collector.data[tag] +function collectors.install(tag,end_cs) + collectors.data[tag] = { } + local data = collectors.data[tag] local call = token.command_id("call") local relax = token.command_id("relax") local endcs = token.csname_id(end_cs) - local expand = collector.registered + local expand = collectors.registered local get = token.get_next -- so no callback! while true do local t = get() @@ -93,13 +93,13 @@ function collector.install(tag,end_cs) end end -collector.show_methods = { } +collectors.show_methods = { } -function collector.show(tag, method) +function collectors.show(tag, method) if type(tag) == "table" then - collector.show_methods[method or 'a'](tag) + collectors.show_methods[method or 'a'](tag) else - collector.show_methods[method or 'a'](collector.data[tag]) + collectors.show_methods[method or 'a'](collectors.data[tag]) end end @@ -108,7 +108,7 @@ commands = commands or { } commands.letter = token.command_id("letter") commands.other = token.command_id("other_char") -function collector.default_words(t,str) +function collectors.default_words(t,str) t[#t+1] = tokens.bgroup t[#t+1] = token.create("red") for k,v in ipairs(str) do @@ -117,10 +117,10 @@ function collector.default_words(t,str) t[#t+1] = tokens.egroup end -function collector.with_words(tag,handle) +function collectors.with_words(tag,handle) local t, w = { }, { } - handle = handle or collector.default_words - for _,v in ipairs(collector.data[tag]) do + handle = handle or collectors.default_words + for _,v in ipairs(collectors.data[tag]) do if v[1] == commands.letter then w[#w+1] = v[2] else @@ -134,10 +134,10 @@ function collector.with_words(tag,handle) if #w > 0 then handle(t,w) end - collector.data[tag] = t + collectors.data[tag] = t end -function collector.show_token(t) +function collectors.show_token(t) if t then local cmd, chr, id, cs, name = t[1], t[2], t[3], nil, token.command_name(t) or "" if cmd == commands.letter or cmd == commands.other then @@ -159,13 +159,13 @@ function collector.show_token(t) end end -function collector.trace() +function collectors.trace() local t = token.get_next() - texio.write_nl(collector.show_token(t)) + texio.write_nl(collectors.show_token(t)) return t end -collector.show_methods.a = function(data) -- no need to store the table, just pass directly +collectors.show_methods.a = function(data) -- no need to store the table, just pass directly local flush, ct = tex.sprint, tex.ctxcatcodes local template = "\\NC %s\\NC %s\\NC %s\\NC %s\\NC %s\\NC\\NR " flush(ct, "\\starttabulate[|T|Tr|cT|Tr|T|]") @@ -192,7 +192,7 @@ collector.show_methods.a = function(data) -- no need to store the table, just pa flush(ct, "\\stoptabulate") end -collector.show_methods.b_c = function(data,swap) -- no need to store the table, just pass directly +collectors.show_methods.b_c = function(data,swap) -- no need to store the table, just pass directly local flush, ct = tex.sprint, tex.ctxcatcodes local template = "\\NC %s\\NC %s\\NC %s\\NC\\NR" if swap then @@ -228,5 +228,5 @@ collector.show_methods.b_c = function(data,swap) -- no need to store the table, flush(ct, "\\stoptabulate") end -collector.show_methods.b = function(tag) collector.show_methods.b_c(tag,false) end -collector.show_methods.c = function(tag) collector.show_methods.b_c(tag,true ) end +collectors.show_methods.b = function(tag) collectors.show_methods.b_c(tag,false) end +collectors.show_methods.c = function(tag) collectors.show_methods.b_c(tag,true ) end diff --git a/tex/context/base/toks-ini.tex b/tex/context/base/toks-ini.tex index 873cfa4d5..d3aa9cb5d 100644 --- a/tex/context/base/toks-ini.tex +++ b/tex/context/base/toks-ini.tex @@ -15,11 +15,11 @@ \registerctxluafile{toks-ini}{1.001} -\def\starttokens [#1]{\ctxlua{collector.install("#1", "stoptokens")}} +\def\starttokens [#1]{\ctxlua{collectors.install("#1", "stoptokens")}} \let\stoptokens \relax -\def\flushtokens [#1]{\ctxlua{collector.flush("#1")}} -\def\showtokens [#1]{\ctxlua{collector.show("#1")}} -\def\testtokens [#1]{\ctxlua{collector.with_words("#1")}} -\def\registertoken #1{\ctxlua{collector.register("#1")}} +\def\flushtokens [#1]{\ctxlua{collectors.flush("#1")}} +\def\showtokens [#1]{\ctxlua{collectors.show("#1")}} +\def\testtokens [#1]{\ctxlua{collectors.with_words("#1")}} +\def\registertoken #1{\ctxlua{collectors.register("#1")}} \endinput diff --git a/tex/context/interface/keys-cz.xml b/tex/context/interface/keys-cz.xml index 05766e2c8..8a5946ba9 100644 --- a/tex/context/interface/keys-cz.xml +++ b/tex/context/interface/keys-cz.xml @@ -1,6 +1,6 @@ - + @@ -182,6 +182,7 @@ + @@ -287,6 +288,8 @@ + + diff --git a/tex/context/interface/keys-de.xml b/tex/context/interface/keys-de.xml index 3461fc0fa..7fd1c0971 100644 --- a/tex/context/interface/keys-de.xml +++ b/tex/context/interface/keys-de.xml @@ -1,6 +1,6 @@ - + @@ -182,6 +182,7 @@ + @@ -287,6 +288,8 @@ + + diff --git a/tex/context/interface/keys-en.xml b/tex/context/interface/keys-en.xml index 3867cf38f..530e61e66 100644 --- a/tex/context/interface/keys-en.xml +++ b/tex/context/interface/keys-en.xml @@ -1,6 +1,6 @@ - + @@ -182,6 +182,7 @@ + @@ -287,6 +288,8 @@ + + diff --git a/tex/context/interface/keys-fr.xml b/tex/context/interface/keys-fr.xml index 5680b44a7..2ba33594d 100644 --- a/tex/context/interface/keys-fr.xml +++ b/tex/context/interface/keys-fr.xml @@ -1,6 +1,6 @@ - + @@ -182,6 +182,7 @@ + @@ -287,6 +288,8 @@ + + diff --git a/tex/context/interface/keys-it.xml b/tex/context/interface/keys-it.xml index c9de9c5e9..088c25d10 100644 --- a/tex/context/interface/keys-it.xml +++ b/tex/context/interface/keys-it.xml @@ -1,6 +1,6 @@ - + @@ -182,6 +182,7 @@ + @@ -287,6 +288,8 @@ + + diff --git a/tex/context/interface/keys-nl.xml b/tex/context/interface/keys-nl.xml index 08c82396f..63fff53f1 100644 --- a/tex/context/interface/keys-nl.xml +++ b/tex/context/interface/keys-nl.xml @@ -1,6 +1,6 @@ - + @@ -182,6 +182,7 @@ + @@ -287,6 +288,8 @@ + + diff --git a/tex/context/interface/keys-ro.xml b/tex/context/interface/keys-ro.xml index 9a0c50c08..7d3b33673 100644 --- a/tex/context/interface/keys-ro.xml +++ b/tex/context/interface/keys-ro.xml @@ -1,6 +1,6 @@ - + @@ -182,6 +182,7 @@ + @@ -287,6 +288,8 @@ + + -- cgit v1.2.3