From e4c575ea1e6cb242b3b8441eb4febc0e469412f2 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 10 Mar 2008 23:20:00 +0100 Subject: stable 2008.03.10 23:20 --- metapost/context/base/mp-tool.mp | 5 +- scripts/context/lua/luatools.lua | 876 ++++++++++---------- scripts/context/lua/mtx-check.lua | 138 ++++ scripts/context/lua/mtx-context.lua | 20 +- scripts/context/lua/mtx-update.lua | 392 +++++---- scripts/context/lua/mtx-watch.lua | 194 ++--- scripts/context/lua/mtxrun.lua | 665 ++++++++++----- scripts/context/ruby/ctxtools.rb | 50 +- tex/context/base/attr-ini.lua | 127 ++- tex/context/base/attr-ini.tex | 4 - tex/context/base/char-cmp.lua | 9 +- tex/context/base/char-def.lua | 594 +++++++------- tex/context/base/char-ini.lua | 76 +- tex/context/base/cont-new.mkiv | 6 + tex/context/base/cont-sys.ori | 1 + tex/context/base/context-characters.lmx | 104 +++ tex/context/base/context-debug.lmx | 28 +- tex/context/base/context-error.lmx | 4 +- tex/context/base/context.tex | 3 +- tex/context/base/core-buf.lua | 4 + tex/context/base/core-fig.tex | 1348 +------------------------------ tex/context/base/core-inc.lua | 819 +++++++++++++++++++ tex/context/base/core-inc.mkii | 1326 ++++++++++++++++++++++++++++++ tex/context/base/core-inc.mkiv | 399 +++++++++ tex/context/base/core-inc.tex | 18 + tex/context/base/core-job.lua | 137 +++- tex/context/base/core-job.mkiv | 6 + tex/context/base/core-mat.tex | 9 +- tex/context/base/core-ntb.tex | 29 +- tex/context/base/core-reg.mkii | 4 +- tex/context/base/core-reg.mkiv | 6 +- tex/context/base/core-reg.tex | 55 +- tex/context/base/core-rul.tex | 10 +- tex/context/base/core-spa.lua | 25 +- tex/context/base/core-spa.tex | 4 +- tex/context/base/core-tsp.tex | 17 +- tex/context/base/core-two.mkii | 24 +- tex/context/base/core-two.mkiv | 13 +- tex/context/base/core-two.tex | 1 + tex/context/base/core-uti.tex | 1 + tex/context/base/enco-utf.tex | 8 +- tex/context/base/font-afm.lua | 47 +- tex/context/base/font-def.lua | 13 +- tex/context/base/font-enc.lua | 70 +- tex/context/base/font-ext.lua | 225 ++++++ tex/context/base/font-fbk.lua | 173 +--- tex/context/base/font-ini.mkiv | 10 +- tex/context/base/font-otf.lua | 994 ++++++++++++++--------- tex/context/base/font-run.tex | 7 +- tex/context/base/font-syn.lua | 4 +- tex/context/base/font-tfm.lua | 115 +-- tex/context/base/hand-ini.mkii | 698 ++++++++++++++++ tex/context/base/hand-ini.mkiv | 50 ++ tex/context/base/hand-ini.tex | 688 +--------------- tex/context/base/l-aux.lua | 15 + tex/context/base/l-file.lua | 42 +- tex/context/base/l-io.lua | 28 - tex/context/base/l-lpeg.lua | 1 - tex/context/base/l-os.lua | 27 +- tex/context/base/l-string.lua | 25 + tex/context/base/l-table.lua | 27 +- tex/context/base/l-url.lua | 36 +- tex/context/base/l-xml.lua | 79 +- tex/context/base/luat-crl.lua | 7 +- tex/context/base/luat-deb.lua | 74 +- tex/context/base/luat-deb.tex | 4 +- tex/context/base/luat-env.lua | 187 +++-- tex/context/base/luat-env.tex | 46 +- tex/context/base/luat-ini.lua | 2 +- tex/context/base/luat-inp.lua | 196 ++--- tex/context/base/luat-lib.lua | 12 +- tex/context/base/luat-lmx.lua | 6 +- tex/context/base/luat-sta.lua | 183 +++++ tex/context/base/luat-tex.lua | 119 +-- tex/context/base/luat-tmp.lua | 2 +- tex/context/base/luat-tre.lua | 45 ++ tex/context/base/luat-zip.lua | 259 +++--- tex/context/base/lxml-ini.lua | 63 +- tex/context/base/lxml-ini.tex | 15 +- tex/context/base/math-ini.lua | 25 +- tex/context/base/meta-pdf.lua | 248 +++--- tex/context/base/mult-con.tex | 224 ++--- tex/context/base/mult-ini.lua | 56 ++ tex/context/base/mult-ini.mkii | 131 +++ tex/context/base/mult-ini.mkiv | 41 + tex/context/base/mult-ini.tex | 307 +++---- tex/context/base/mult-sys.tex | 5 +- tex/context/base/node-ini.lua | 193 ++++- tex/context/base/node-ini.tex | 10 + tex/context/base/page-flt.tex | 33 +- tex/context/base/page-ini.tex | 2 +- tex/context/base/page-num.tex | 2 +- tex/context/base/page-one.tex | 3 + tex/context/base/prop-ini.tex | 14 - tex/context/base/prop-mis.tex | 18 +- tex/context/base/s-abr-01.tex | 1 + tex/context/base/s-pre-64.tex | 4 +- tex/context/base/spec-fdf.tex | 4 +- tex/context/base/syst-ext.tex | 50 +- tex/context/base/syst-new.tex | 4 +- tex/context/base/syst-xtx.tex | 4 + tex/context/base/toks-ini.tex | 12 +- tex/context/base/type-gyr.tex | 25 +- tex/context/base/type-ini.tex | 12 +- tex/context/base/type-one.tex | 1 - tex/context/base/type-otf.tex | 2 +- tex/context/base/x-cals.mkiv | 8 +- tex/context/base/x-fig-00.tex | 144 ++-- tex/context/base/x-mmp.mkiv | 4 +- tex/context/base/x-res-04.tex | 96 +-- tex/context/base/x-set-11.tex | 4 +- tex/context/interface/keys-cz.xml | 3 +- tex/context/interface/keys-de.xml | 3 +- tex/context/interface/keys-en.xml | 3 +- tex/context/interface/keys-fr.xml | 3 +- tex/context/interface/keys-it.xml | 3 +- tex/context/interface/keys-nl.xml | 3 +- tex/context/interface/keys-ro.xml | 3 +- tex/context/patterns/lang-agr.pat | 986 ++++++++++++++++++++-- tex/context/sample/montgomery.tex | 13 + tex/context/sample/sample.tex | 7 +- tex/context/test/x-cals-test.xml | 124 +++ tex/context/user/cont-sys.rme | 1 + 123 files changed, 9519 insertions(+), 5473 deletions(-) create mode 100644 scripts/context/lua/mtx-check.lua create mode 100644 tex/context/base/context-characters.lmx create mode 100644 tex/context/base/core-inc.lua create mode 100644 tex/context/base/core-inc.mkii create mode 100644 tex/context/base/core-inc.mkiv create mode 100644 tex/context/base/core-inc.tex create mode 100644 tex/context/base/font-ext.lua create mode 100644 tex/context/base/hand-ini.mkii create mode 100644 tex/context/base/hand-ini.mkiv create mode 100644 tex/context/base/luat-sta.lua create mode 100644 tex/context/base/luat-tre.lua create mode 100644 tex/context/base/mult-ini.lua create mode 100644 tex/context/base/mult-ini.mkii create mode 100644 tex/context/base/mult-ini.mkiv create mode 100644 tex/context/sample/montgomery.tex diff --git a/metapost/context/base/mp-tool.mp b/metapost/context/base/mp-tool.mp index a98f73922..567ff16fd 100644 --- a/metapost/context/base/mp-tool.mp +++ b/metapost/context/base/mp-tool.mp @@ -2220,9 +2220,10 @@ enddef ; % handy for myself def addbackground text t = - begingroup ; save p ; picture p ; + begingroup ; save p, b ; picture p ; path b ; + b := boundingbox currentpicture ; p := currentpicture ; currentpicture := nullpicture ; - fill boundingbox p t ; addto currentpicture also p ; + fill b t ; setbounds currentpicture to b ; addto currentpicture also p ; endgroup ; enddef ; diff --git a/scripts/context/lua/luatools.lua b/scripts/context/lua/luatools.lua index b6a158f6e..24e3bda9d 100644 --- a/scripts/context/lua/luatools.lua +++ b/scripts/context/lua/luatools.lua @@ -363,6 +363,31 @@ function string:split_settings() -- no {} handling, see l-aux for lpeg variant end end +local patterns_escapes = { + ["-"] = "%-", + ["."] = "%.", + ["+"] = "%+", + ["*"] = "%*", + ["%"] = "%%", + ["("] = "%)", + [")"] = "%)", + ["["] = "%[", + ["]"] = "%]", +} + + +function string:pattesc() + return (self:gsub(".",patterns_escapes)) +end + +function string:tohash() + local t = { } + for s in self:gmatch("([^, ]+)") do -- lpeg + t[s] = true + end + return t +end + -- filename : l-lpeg.lua -- author : Hans Hagen, PRAGMA-ADE, Hasselt NL @@ -406,7 +431,6 @@ end - -- filename : l-table.lua -- comment : split off from luat-lib -- author : Hans Hagen, PRAGMA-ADE, Hasselt NL @@ -488,7 +512,8 @@ end --~ return t --~ end -function table.merge(t, ...) +function table.merge(t, ...) -- first one is target + t = t or {} local lst = {...} for i=1,#lst do for k, v in pairs(lst[i]) do @@ -1017,6 +1042,14 @@ function table.tohash(t) return h end +function table.fromhash(t) + local h = { } + for k, v in pairs(t) do -- no ipairs here + if v then h[#h+1] = k end + end + return h +end + function table.contains(t, v) if t then for i=1, #t do @@ -1048,6 +1081,22 @@ end --~ return table.serialize(a) == table.serialize(b) --~ end +function table.clone(t,p) -- t is optional or nil or table + if not p then + t, p = { }, t or { } + elseif not t then + t = { } + end + setmetatable(t, { __index = function(_,key) return p[key] end }) + return t +end + + +function table.hexed(t,seperator) + local tt = { } + for i=1,#t do tt[i] = string.format("0x%04X",t[i]) end + return table.concat(tt,seperator or " ") +end -- filename : l-io.lua @@ -1119,38 +1168,10 @@ function io.noflines(f) return n end ---~ t, f, n = os.clock(), io.open("testbed/sample-utf16-bigendian-big.txt",'rb'), 0 ---~ for a in io.characters(f) do n = n + 1 end ---~ print(string.format("characters: %s, time: %s", n, os.clock()-t)) - do local sb = string.byte ---~ local nextchar = { ---~ [ 4] = function(f) ---~ return f:read(1), f:read(1), f:read(1), f:read(1) ---~ end, ---~ [ 2] = function(f) ---~ return f:read(1), f:read(1) ---~ end, ---~ [ 1] = function(f) ---~ return f:read(1) ---~ end, ---~ [-2] = function(f) ---~ local a = f:read(1) ---~ local b = f:read(1) ---~ return b, a ---~ end, ---~ [-4] = function(f) ---~ local a = f:read(1) ---~ local b = f:read(1) ---~ local c = f:read(1) ---~ local d = f:read(1) ---~ return d, c, b, a ---~ end ---~ } - local nextchar = { [ 4] = function(f) return f:read(1,1,1,1) @@ -1457,6 +1478,19 @@ end if not os.exec then os.exec = os.execute end if not os.spawn then os.spawn = os.execute end +--~ os.type : windows | unix (new, we already guessed os.platform) +--~ os.name : windows | msdos | linux | macosx | solaris | .. | generic (new) + +if not io.fileseparator then + if string.find(os.getenv("PATH"),";") then + io.fileseparator, io.pathseparator, os.platform = "\\", ";", os.type or "windows" + else + io.fileseparator, io.pathseparator, os.platform = "/" , ":", os.type or "unix" + end +end + +os.platform = os.platform or os.type or (io.pathseparator == ";" and "windows") or "unix" + function os.launch(str) if os.platform == "windows" then os.execute("start " .. str) -- os.spawn ? @@ -1476,19 +1510,15 @@ if not os.times then -- cstime = children system time function os.times() return { - utime = os.clock(), -- user - stime = 0, -- system - cutime = 0, -- children user - cstime = 0, -- children system + utime = os.gettimeofday(), -- user + stime = 0, -- system + cutime = 0, -- children user + cstime = 0, -- children system } end end -if os.gettimeofday then - os.clock = os.gettimeofday -else - os.gettimeofday = os.clock -end +os.gettimeofday = os.gettimeofday or os.clock do local startuptime = os.gettimeofday() @@ -1535,11 +1565,11 @@ if not versions then versions = { } end versions['l-file'] = 1.001 if not file then file = { } end function file.removesuffix(filename) - return filename:gsub("%.%a+$", "") + return filename:gsub("%.[%a%d]+$", "") end function file.addsuffix(filename, suffix) - if not filename:find("%.%a-$") then + if not filename:find("%.[%a%d]+$") then return filename .. "." .. suffix else return filename @@ -1547,7 +1577,11 @@ function file.addsuffix(filename, suffix) end function file.replacesuffix(filename, suffix) - return (filename:gsub("%.%a+$", "." .. suffix)) + if not filename:find("%.[%a%d]+$") then + return filename .. "." .. suffix + else + return (filename:gsub("%.[%a%d]+$","."..suffix)) + end end function file.dirname(name) @@ -1566,12 +1600,36 @@ function file.extname(name) return name:match("^.+%.([^/\\]-)$") or "" end +function file.stripsuffix(name) + return (name:gsub("%.[%a%d]+$","")) +end + +--~ function file.join(...) +--~ local t = { ... } +--~ for i=1,#t do +--~ t[i] = (t[i]:gsub("\\","/")):gsub("/+$","") +--~ end +--~ return table.concat(t,"/") +--~ end + +--~ print(file.join("x/","/y")) +--~ print(file.join("http://","/y")) +--~ print(file.join("http://a","/y")) +--~ print(file.join("http:///a","/y")) +--~ print(file.join("//nas-1","/y")) + function file.join(...) - local t = { ... } - for i=1,#t do - t[i] = (t[i]:gsub("\\","/")):gsub("/+$","") + local pth = table.concat({...},"/") + pth = pth:gsub("\\","/") + local a, b = pth:match("^(.*://)(.*)$") + if a and b then + return a .. b:gsub("//+","/") + end + a, b = pth:match("^(//)(.*)$") + if a and b then + return a .. b:gsub("//+","/") end - return table.concat(t,"/") + return (pth:gsub("//+","/")) end function file.is_writable(name) @@ -1650,6 +1708,111 @@ file.readdata = io.loaddata file.savedata = io.savedata +-- filename : l-url.lua +-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL +-- copyright: PRAGMA ADE / ConTeXt Development Team +-- license : see context related readme files + +if not versions then versions = { } end versions['l-url'] = 1.001 +if not url then url = { } end + +-- from the spec (on the web): +-- +-- foo://example.com:8042/over/there?name=ferret#nose +-- \_/ \______________/\_________/ \_________/ \__/ +-- | | | | | +-- scheme authority path query fragment +-- | _____________________|__ +-- / \ / \ +-- urn:example:animal:ferret:nose + +do + + local function tochar(s) + return string.char(tonumber(s,16)) + end + + local colon, qmark, hash, slash, percent, endofstring = lpeg.P(":"), lpeg.P("?"), lpeg.P("#"), lpeg.P("/"), lpeg.P("%"), lpeg.P(-1) + + local hexdigit = lpeg.R("09","AF","af") + local escaped = percent * lpeg.C(hexdigit * hexdigit) / tochar + + local scheme = lpeg.Cs((escaped+(1-colon-slash-qmark-hash))^0) * colon + lpeg.Cc("") + local authority = slash * slash * lpeg.Cs((escaped+(1- slash-qmark-hash))^0) + lpeg.Cc("") + local path = slash * lpeg.Cs((escaped+(1- qmark-hash))^0) + lpeg.Cc("") + local query = qmark * lpeg.Cs((escaped+(1- hash))^0) + lpeg.Cc("") + local fragment = hash * lpeg.Cs((escaped+(1- endofstring))^0) + lpeg.Cc("") + + local parser = lpeg.Ct(scheme * authority * path * query * fragment) + + function url.split(str) + return (type(str) == "string" and parser:match(str)) or str + end + +end + +function url.hashed(str) + local s = url.split(str) + return { + scheme = (s[1] ~= "" and s[1]) or "file", + authority = s[2], + path = s[3], + query = s[4], + fragment = s[5], + original=str + } +end + +function url.filename(filename) + local t = url.hashed(filename) + return (t.scheme == "file" and t.path:gsub("^/([a-zA-Z])([:|])/)","%1:")) or filename +end + +function url.query(str) + if type(str) == "string" then + local t = { } + for k, v in str:gmatch("([^&=]*)=([^&=]*)") do + t[k] = v + end + return t + else + return str + end +end + +--~ print(url.filename("file:///c:/oeps.txt")) +--~ print(url.filename("c:/oeps.txt")) +--~ print(url.filename("file:///oeps.txt")) +--~ print(url.filename("file:///etc/test.txt")) +--~ print(url.filename("/oeps.txt")) + +-- from the spec on the web (sort of): +--~ +--~ function test(str) +--~ print(table.serialize(url.hashed(str))) +--~ end +---~ +--~ test("%56pass%20words") +--~ test("file:///c:/oeps.txt") +--~ test("file:///c|/oeps.txt") +--~ test("file:///etc/oeps.txt") +--~ test("file://./etc/oeps.txt") +--~ test("file:////etc/oeps.txt") +--~ test("ftp://ftp.is.co.za/rfc/rfc1808.txt") +--~ test("http://www.ietf.org/rfc/rfc2396.txt") +--~ test("ldap://[2001:db8::7]/c=GB?objectClass?one#what") +--~ test("mailto:John.Doe@example.com") +--~ test("news:comp.infosystems.www.servers.unix") +--~ test("tel:+1-816-555-1212") +--~ test("telnet://192.0.2.16:80/") +--~ test("urn:oasis:names:specification:docbook:dtd:xml:4.1.2") +--~ test("/etc/passwords") +--~ test("http://www.pragma-ade.com/spaced%20name") + +--~ test("zip:///oeps/oeps.zip#bla/bla.tex") +--~ test("zip:///oeps/oeps.zip?bla/bla.tex") + + -- filename : l-dir.lua -- comment : split off from luat-lib -- author : Hans Hagen, PRAGMA-ADE, Hasselt NL @@ -2112,6 +2275,8 @@ function utils.lua.compile(luafile, lucfile) end end + + -- filename : luat-lib.lua -- comment : companion to luat-lib.tex -- author : Hans Hagen, PRAGMA-ADE, Hasselt NL @@ -2135,19 +2300,13 @@ os.setlocale(nil,nil) -- useless feature and even dangerous in luatex if not io.fileseparator then if string.find(os.getenv("PATH"),";") then - io.fileseparator, io.pathseparator, os.platform = "\\", ";", "windows" + io.fileseparator, io.pathseparator, os.platform = "\\", ";", os.type or "windows" else - io.fileseparator, io.pathseparator, os.platform = "/" , ":", "unix" + io.fileseparator, io.pathseparator, os.platform = "/" , ":", os.type or "unix" end end -if not os.platform then - if io.pathseparator == ";" then - os.platform = "windows" - else - os.platform = "unix" - end -end +os.platform = os.platform or os.type or (io.pathseparator == ";" and "windows") or "unix" -- arg normalization -- @@ -2346,17 +2505,22 @@ input.formats ['lua'] = 'LUAINPUTS' -- new input.suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } -- here we catch a few new thingies (todo: add these paths to context.tmf) +-- +-- FONTFEATURES = .;$TEXMF/fonts/fea// +-- FONTCIDMAPS = .;$TEXMF/fonts/cid// -function input.checkconfigdata(instance) +function input.checkconfigdata(instance) -- not yet ok, no time for debugging now 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 + local p = instance.environment[proname] + local v = instance.environment[varname] + if not ((p and p ~= "") or (v and v ~= "")) then + instance.variables[varname] = default -- or environment? end end fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") - fix("FONTFEATURES", ".;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") - fix("FONTCIDMAPS" , ".;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") end -- backward compatible ones @@ -2457,6 +2621,11 @@ function input.reset() end +function input.reset_hashes(instance) + instance.lists = { } + instance.found = { } +end + function input.bare_variable(str) -- return string.gsub(string.gsub(string.gsub(str,"%s+$",""),'^"(.+)"$',"%1"),"^'(.+)'$","%1") return (str:gsub("\s*([\"\']?)(.+)%1\s*", "%2")) @@ -2522,7 +2691,7 @@ input.settrace(tonumber(os.getenv("MTX.INPUT.TRACE") or os.getenv("MTX_INPUT_TRA -- loading the database files. do - local clock = os.clock + local clock = os.gettimeofday or os.clock function input.starttiming(instance) if instance then @@ -2796,6 +2965,7 @@ function input.aux.extend_texmf_var(instance,specification) -- crap instance.variables['TEXMF'] = "{" .. instance.variables['TEXMF'] .. "}" end input.expand_variables(instance) + input.reset_hashes(instance) end -- locators @@ -2811,28 +2981,6 @@ function input.locatedatabase(instance,specification) return input.methodhandler('locators', instance, specification) end ---~ poor mans solution, from before we had lfs.isdir ---~ ---~ function input.locators.tex(instance,specification) ---~ if specification and specification ~= '' then ---~ local files = { ---~ file.join(specification,'files'..input.lucsuffix), ---~ file.join(specification,'files'..input.luasuffix), ---~ file.join(specification,input.lsrname) ---~ } ---~ for _, filename in pairs(files) do ---~ local f = io.open(filename) ---~ if f then ---~ input.logger('! tex locator', specification..' found') ---~ input.aux.append_hash(instance,'file',specification,filename) ---~ f:close() ---~ return ---~ end ---~ end ---~ input.logger('? tex locator', specification..' not found') ---~ end ---~ end - function input.locators.tex(instance,specification) if specification and specification ~= '' and lfs.isdir(specification) then input.logger('! tex locator', specification..' found') @@ -3191,8 +3339,6 @@ function input.expand_variables(instance) for k,v in pairs(instance.expansions) do instance.expansions[k] = v:gsub("\\", '/') end - -- ########## - --~ input.splitexpansions(instance) -- better not, fuzzy end function input.aux.expand_vars(instance,lst) -- simple vars @@ -3350,15 +3496,12 @@ do end function input.register_extra_path(instance,paths,subpaths) + local ep = instance.extra_paths or { } + local n = #ep if paths and paths ~= "" then - local ep = instance.extra_paths - if not ep then - ep = { } - instance.extra_paths = ep - end - local n = #ep - if subpath and subpaths ~= "" then + if subpaths and subpaths ~= "" then for p in paths:gmatch("[^,]+") do + -- we gmatch each step again, not that fast, but used seldom for s in subpaths:gmatch("[^,]+") do local ps = p .. "/" .. s if not done[ps] then @@ -3375,10 +3518,24 @@ do end end end - if n < #ep then - instance.lists = { } + elseif subpaths and subpaths ~= "" then + for i=1,n do + -- we gmatch each step again, not that fast, but used seldom + for s in subpaths:gmatch("[^,]+") do + local ps = ep[i] .. "/" .. s + if not done[ps] then + ep[#ep+1] = input.clean_path(ps) + done[ps] = true + end + end end end + if #ep > 0 then + instance.extra_paths = ep -- register paths + end + if #ep > n then + instance.lists = { } -- erase the cache + end end end @@ -3633,7 +3790,7 @@ input.is_readable.tex = input.is_readable.file -- name/name function input.aux.collect_files(instance,names) - local filelist = nil + local filelist = { } for _, fname in pairs(names) do if fname then if input.trace > 2 then @@ -3665,15 +3822,20 @@ function input.aux.collect_files(instance,names) if blobfile then if type(blobfile) == 'string' then if not dname or blobfile:find(dname) then - if not filelist then filelist = { } end - -- input.logger('= collected', blobpath.." | "..blobfile.." | "..bname) - filelist[#filelist+1] = file.join(blobpath,blobfile,bname) + filelist[#filelist+1] = { + hash.type, + file.join(blobpath,blobfile,bname), -- search + input.concatinators[hash.type](blobpath,blobfile,bname) -- result + } end else for _, vv in pairs(blobfile) do if not dname or vv:find(dname) then - if not filelist then filelist = { } end - filelist[#filelist+1] = file.join(blobpath,vv,bname) + filelist[#filelist+1] = { + hash.type, + file.join(blobpath,vv,bname), -- search + input.concatinators[hash.type](blobpath,vv,bname) -- result + } end end end @@ -3684,7 +3846,11 @@ function input.aux.collect_files(instance,names) end end end - return filelist + if #filelist > 0 then + return filelist + else + return nil + end end function input.suffix_of_format(str) @@ -3703,54 +3869,30 @@ function input.suffixes_of_format(str) end end ---~ function input.aux.qualified_path(filename) -- make platform dependent / not good yet ---~ return ---~ filename:find("^%.+/") or ---~ filename:find("^/") or ---~ filename:find("^%a+%:") or ---~ filename:find("^%a+##") ---~ end - ---~ function input.normalize_name(original) ---~ -- internally we use type##spec##subspec ; this hackery slightly slows down searching ---~ local str = original or "" ---~ str = str:gsub("::", "##") -- :: -> ## ---~ str = str:gsub("^(%a+)://" ,"%1##") -- zip:// -> zip## ---~ str = str:gsub("(.+)##(.+)##/(.+)","%1##%2##%3") -- ##/spec -> ##spec ---~ if (input.trace>1) and (original ~= str) then ---~ input.logger('= normalizer',original.." -> "..str) ---~ end ---~ return str ---~ end +do -do -- called about 700 times for an empty doc (font initializations etc) + -- called about 700 times for an empty doc (font initializations etc) -- i need to weed the font files for redundant calls local letter = lpeg.R("az","AZ") - local separator = lpeg.P("##") + local separator = lpeg.P("://") - local qualified = lpeg.P(".")^0 * lpeg.P("/") + letter*lpeg.P(":") + letter^1*separator - local normalized = lpeg.Cs( - (letter^1*(lpeg.P("://")/"##") * (1-lpeg.P(false))^1) + - (lpeg.P("::")/"##" + (1-separator)^1*separator*(1-separator)^1*separator*(lpeg.P("/")/"") + 1)^0 - ) + local qualified = lpeg.P(".")^0 * lpeg.P("/") + letter*lpeg.P(":") + letter^1*separator + local rootbased = lpeg.P("/") + letter*lpeg.P(":") - -- ./name ../name /name c: zip## (todo: use url internally and get rid of ##) + -- ./name ../name /name c: :// function input.aux.qualified_path(filename) return qualified:match(filename) end + function input.aux.rootbased_path(filename) + return rootbased:match(filename) + end - -- zip:// -> zip## ; :: -> ## ; aa##bb##/cc -> aa##bb##cc function input.normalize_name(original) - local str = normalized:match(original or "") - if input.trace > 1 and original ~= str then - input.logger('= normalizer',original.." -> "..str) - end - return str + return original end -end --- split the next one up, better for jit +end function input.aux.register_in_trees(instance,name) if not name:find("^%.") then @@ -3758,11 +3900,13 @@ function input.aux.register_in_trees(instance,name) end end +-- split the next one up, better for jit + function input.aux.find_file(instance,filename) -- todo : plugin (scanners, checkers etc) local result = { } local stamp = nil - filename = input.normalize_name(filename) - filename = file.collapse_path(filename:gsub("\\","/")) + filename = input.normalize_name(filename) -- elsewhere + filename = file.collapse_path(filename:gsub("\\","/")) -- elsewhere -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -3834,7 +3978,7 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec local typespec = input.variable_of_format(filetype) local pathlist = input.expanded_path_list(instance,typespec) if not pathlist or #pathlist == 0 then - -- no pathlist, access check only + -- no pathlist, access check only / todo == wildcard if input.trace > 2 then input.logger('? filename',filename) input.logger('? filetype',filetype or '?') @@ -3849,8 +3993,9 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec end -- this is actually 'other text files' or 'any' or 'whatever' local filelist = input.aux.collect_files(instance,wantedfiles) - filename = filelist and filelist[1] - if filename then + local lf = filelist and filelist[1] + if fl then + filename = fl[3] result[#result+1] = filename done = true end @@ -3860,8 +4005,8 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec local doscan, recurse if input.trace > 2 then input.logger('? filename',filename) - if pathlist then input.logger('? path list',table.concat(pathlist," | ")) end - if filelist then input.logger('? file list',table.concat(filelist," | ")) end + -- if pathlist then input.logger('? path list',table.concat(pathlist," | ")) end + -- if filelist then input.logger('? file list',table.concat(filelist," | ")) end end -- a bit messy ... esp the doscan setting here for _, path in pairs(pathlist) do @@ -3874,16 +4019,18 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec -- compare list entries with permitted pattern pathname = pathname:gsub("([%-%.])","%%%1") -- this also influences pathname = pathname:gsub("/+$", '/.*') -- later usage of pathname - pathname = pathname:gsub("//", '/.-/') + pathname = pathname:gsub("//", '/.-/') -- not ok for /// but harmless local expr = "^" .. pathname -- input.debug('?',expr) - for _, f in pairs(filelist) do + for _, fl in ipairs(filelist) do + local f = fl[2] if f:find(expr) then -- input.debug('T',' '..f) if input.trace > 2 then input.logger('= found in hash',f) end - result[#result+1] = f + --- todo, test for readable + result[#result+1] = fl[3] input.aux.register_in_trees(instance,f) -- for tracing used files done = true if not instance.allresults then break end @@ -3893,7 +4040,7 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec end end if not done and doscan then - -- check if on disk / unchecked / does not work at all + -- check if on disk / unchecked / does not work at all / also zips if input.method_is_file(pathname) then -- ? local pname = pathname:gsub("%.%*$",'') if not pname:find("%*") then @@ -3970,10 +4117,7 @@ end if not input.concatinators then input.concatinators = { } end -function input.concatinators.tex(tag,path,name) - return tag .. '/' .. path .. '/' .. name -end - +input.concatinators.tex = file.join input.concatinators.file = input.concatinators.tex function input.find_files(instance,filename,filetype,mustexist) @@ -4175,15 +4319,6 @@ function input.aux.register_file(files, name, path) end end --- zip:: zip## zip:// --- zip::pathtozipfile::pathinzipfile (also: pathtozipfile/pathinzipfile) --- file::name --- tex::name --- kpse::name --- kpse::format::name --- parent::n::name --- parent::name (default 2) - if not input.finders then input.finders = { } end if not input.openers then input.openers = { } end if not input.loaders then input.loaders = { } end @@ -4193,30 +4328,37 @@ input.openers.notfound = { nil } input.loaders.notfound = { false, nil, 0 } function input.splitmethod(filename) - local method, specification = filename:match("^(.-)##(.+)$") - if method and specification then - return method, specification + if not filename then + return { } -- safeguard + elseif type(filename) == "table" then + return filename -- already split + elseif not filename:find("://") then + return { scheme="file", path = filename, original=filename } -- quick hack else - return 'tex', filename + return url.hashed(filename) end end function input.method_is_file(filename) - local method, specification = input.splitmethod(filename) - return method == 'tex' or method == 'file' + return input.splitmethod(filename).scheme == 'file' +end + +function table.sequenced(t,sep) -- temp here + local s = { } + for k, v in pairs(t) do + s[#s+1] = k .. "=" .. v + end + return table.concat(s, sep or " | ") end function input.methodhandler(what, instance, filename, filetype) -- ... - local method, specification = input.splitmethod(filename) - if method and specification then -- redundant - if input[what][method] then - input.logger('= handler',filename.." -> "..what.." | "..method.." | "..specification) - return input[what][method](instance,specification,filetype) - else - return nil - end + local specification = (type(filename) == "string" and input.splitmethod(filename)) or filename -- no or { }, let it bomb + local scheme = specification.scheme + if input[what][scheme] then + input.logger('= handler',specification.original .." -> " .. what .. " -> " .. table.sequenced(specification)) + return input[what][scheme](instance,filename,filetype) -- todo: specification else - return input[what].tex(instance,filename,filetype) + return input[what].tex(instance,filename,filetype) -- todo: specification end end @@ -4250,6 +4392,8 @@ function input.texdatablob(instance, filename, filetype) return data or "" end +input.loadtexfile = input.texdatablob + function input.openfile(filename) -- brrr texmf.instance here / todo ! ! ! ! ! local fullname = input.findtexfile(texmf.instance, filename) if fullname and (fullname ~= "") then @@ -4828,7 +4972,7 @@ function input.aux.load_data(instance,pathname,dataname,filename) end end --- we will make a better format, maybe something xml or just text +-- we will make a better format, maybe something xml or just text or lua input.automounted = input.automounted or { } @@ -4957,80 +5101,117 @@ if not zip.supported then function zip.openarchive (...) return nil end -- needed ? function zip.closenarchive (...) end -- needed ? - function input.registerzipfile (...) end -- needed ? function input.usezipfile (...) end -- needed ? else - function input.locators.zip(instance,specification) - local name, spec = specification:match("^(.-)##(.-)$") - local f = io.open(name or specification) - if f then -- todo: reuse code - input.logger('! zip locator', specification..' found') - if name and spec then - input.aux.append_hash(instance,'zip',"zip##"..specification,name) - input.aux.extend_texmf_var(instance, "zip##"..specification) + -- zip:///oeps.zip?name=bla/bla.tex + -- zip:///oeps.zip?tree=tex/texmf-local + + local function validzip(str) + if not str:find("^zip://") then + return "zip:///" .. str + else + return str + end + end + + zip.archives = { } + zip.registeredfiles = { } + + function zip.openarchive(instance,name) + if not name or name == "" then + return nil + else + local arch = zip.archives[name] + if arch then + return arch else - input.aux.append_hash(instance,'zip',"zip##"..specification.."##",specification) - input.aux.extend_texmf_var(instance, "zip##"..specification.."##") + local full = input.find_file(instance,name) or "" + local arch = (full ~= "" and zip.open(full)) or false + zip.archives[name] = arch + return arch end - f:close() + end + end + + function zip.closearchive(instance,name) + if not name or name == "" and zip.archives[name] then + zip.close(zip.archives[name]) + zip.archives[name] = nil + end + end + + -- zip:///texmf.zip?tree=/tex/texmf + -- zip:///texmf.zip?tree=/tex/texmf-local + -- zip:///texmf-mine.zip?tree=/tex/texmf-projects + + function input.locators.zip(instance,specification) -- where is this used? startup zips (untested) + specification = input.splitmethod(specification) + local zipfile = specification.path + local zfile = zip.openarchive(instance,name) -- tricky, could be in to be initialized tree + if zfile then + input.logger('! zip locator', specification.original ..' found') else - input.logger('? zip locator', specification..' not found') + input.logger('? zip locator', specification.original ..' not found') end end function input.hashers.zip(instance,tag,name) input.report("loading zip file",name,"as",tag) - input.registerzipfile(instance,name,tag) + input.usezipfile(instance,tag .."?tree=" .. name) end function input.concatinators.zip(tag,path,name) - return tag .. path .. '/' .. name + if not path or path == "" then + return tag .. '?name=' .. name + else + return tag .. '?name=' .. path .. "/" .. name + end end function input.is_readable.zip(name) return true end - function input.finders.zip(instance,filename,filetype) - local archive, dataname = filename:match("^(.+)##/*(.+)$") - if archive and dataname then - local zfile = zip.openarchive(archive) - if not zfile then - archive = input.find_file(instance,archive,filetype) - zfile = zip.openarchive(archive) - end - if zfile then - input.logger('! zip finder',archive) - local dfile = zfile:open(dataname) - if dfile then - dfile = zfile:close() - input.logger('+ zip finder',filename) - return 'zip##' .. filename + function input.finders.zip(instance,specification,filetype) + specification = input.splitmethod(specification) + if specification.path then + local q = url.query(specification.query) + if q.name then + local zfile = zip.openarchive(instance,specification.path) + if zfile then + input.logger('! zip finder',specification.path) + local dfile = zfile:open(q.name) + if dfile then + dfile = zfile:close() + input.logger('+ zip finder',q.name) + return specification.original + end + else + input.logger('? zip finder',specification.path) end - else - input.logger('? zip finder',archive) end end input.logger('- zip finder',filename) return unpack(input.finders.notfound) end - function input.openers.zip(instance,filename) - if filename and filename ~= "" then - local archive, dataname = filename:match("^(.-)##/*(.+)$") - if archive and dataname then - local zfile= zip.openarchive(archive) + function input.openers.zip(instance,specification) + local zipspecification = input.splitmethod(specification) + if zipspecification.path then + local q = url.query(zipspecification.query) + if q.name then + local zfile = zip.openarchive(instance,zipspecification.path) if zfile then - input.logger('+ zip starter',archive) - local dfile = zfile:open(dataname) + input.logger('+ zip starter',zipspecification.path) + local dfile = zfile:open(q.name) if dfile then - input.show_open(filename) - return input.openers.text_opener(filename,dfile,'zip') + input.show_open(specification) + return input.openers.text_opener(specification,dfile,'zip') end else - input.logger('- zip starter',archive) + input.logger('- zip starter',zipspecification.path) end end end @@ -5038,15 +5219,15 @@ else return unpack(input.openers.notfound) end - function input.loaders.zip(instance, filename) -- we could use input.openers.zip - if filename and filename ~= "" then - input.logger('= zip loader',filename) - local archive, dataname = filename:match("^(.+)##/*(.+)$") - if archive and dataname then - local zfile = zip.openarchive(archive) + function input.loaders.zip(instance,specification) + specification = input.splitmethod(specification) + if specification.path then + local q = url.query(specification.query) + if q.name then + local zfile = zip.openarchive(instance,specification.path) if zfile then - input.logger('= zip starter',archive) - local dfile = zfile:open(dataname) + input.logger('+ zip starter',specification.path) + local dfile = zfile:open(q.name) if dfile then input.show_load(filename) input.logger('+ zip loader',filename) @@ -5055,105 +5236,67 @@ else return true, s, #s end else - input.logger('- zip starter',archive) + input.logger('- zip starter',specification.path) end end end input.logger('- zip loader',filename) - return unpack(input.loaders.notfound) - end - - zip.archives = { } - zip.registeredfiles = { } - - function zip.openarchive(name) - if name and name ~= "" and not zip.archives[name] then - zip.archives[name] = zip.open(name) - end - return zip.archives[name] - end - - function zip.closearchive(name) - if zip.archives[name] then - zip.close(archives[name]) - zip.archives[name] = nil - end + return unpack(input.openers.notfound) end - -- aparte register maken voor user (register tex / zip), runtime tree register - -- todo: alleen url syntax toestaan - -- user function: also handle zip::name::path + -- zip:///somefile.zip + -- zip:///somefile.zip?tree=texmf-local -> mount - function input.usezipfile(instance,zipname) -- todo zip:// - zipname = input.normalize_name(zipname) - if not zipname:find("^zip##") then - zipname = "zip##"..zipname - end - input.logger('! zip user','file '..zipname) - if not zipname:find("^zip##(.+)##(.-)$") then - zipname = zipname .. "##" -- dummy spec - end - local tag = zipname - local name = zipname:match("zip##(.+)##.-") - input.aux.prepend_hash(instance,'zip',tag,name) - input.aux.extend_texmf_var(instance, tag) - input.registerzipfile(instance,name,tag) - end - - function input.registerzipfile(instance,zipname,tag) - if not zip.registeredfiles[zipname] then - input.starttiming(instance) - local z = zip.open(zipname) - if not z then - zipname = input.find_file(instance,zipname) - z = zip.open(zipname) - end + function input.usezipfile(instance,zipname) + zipname = validzip(zipname) + input.logger('! zip use','file '..zipname) + local specification = input.splitmethod(zipname) + local zipfile = specification.path + if zipfile and not zip.registeredfiles[zipname] then + local tree = url.query(specification.query).tree or "" + input.logger('! zip register','file '..zipname) + local z = zip.openarchive(instance,zipfile) if z then input.logger("= zipfile","registering "..zipname) + input.starttiming(instance) + input.aux.prepend_hash(instance,'zip',zipname,zipfile) + input.aux.extend_texmf_var(instance,zipname) -- resets hashes too zip.registeredfiles[zipname] = z - input.aux.register_zip_file(instance,zipname,tag) + instance.files[zipname] = input.aux.register_zip_file(z,tree or "") + input.stoptiming(instance) else input.logger("? zipfile","unknown "..zipname) end - input.stoptiming(instance) + else + input.logger('! zip register','no file '..zipname) end end - function input.aux.register_zip_file(instance,zipname,tagname) - if zip.registeredfiles[zipname] then - if not tagname:find("^zip##") then - tagname = "zip##" .. tagname - end - local path, name, n = nil, nil, 0 - if not instance.files[tagname] then - instance.files[tagname] = { } - end - local files, filter = instance.files[tagname], "" - local subtree = tagname:match("^zip##.+##(.+)$") - if subtree then - filter = "^"..subtree.."/(.+)/(.-)$" - else - filter = "^(.+)/(.-)$" - end - input.logger('= zip filter',filter) - -- we can consider putting a files.luc in the file - local register = input.aux.register_file - for i, _ in zip.registeredfiles[zipname]:files() do - path, name = i.filename:match(filter) - if path then - if name and name ~= '' then - register(files, name, path) - n = n + 1 - else - -- directory - end - else - register(files, i.filename, '') + function input.aux.register_zip_file(z,tree) + local files, filter = { }, "" + if tree == "" then + filter = "^(.+)/(.-)$" + else + filter = "^"..tree.."/(.+)/(.-)$" + end + input.logger('= zip filter',filter) + local register, n = input.aux.register_file, 0 + for i in z:files() do + local path, name = i.filename:match(filter) + if path then + if name and name ~= '' then + register(files, name, path) n = n + 1 + else + -- directory end + else + register(files, i.filename, '') + n = n + 1 end - input.report(n, 'entries in', zipname) end + input.report('= zip entries',n) + return files end end @@ -5348,6 +5491,8 @@ if texconfig and not texlua then do texio.write_nl(s .. b .. "\n") end + -- this will become: ctx.install_statistics(fnc() return ..,.. end) etc + function ctx.show_statistics() local function ws(...) ctx.writestatus("mkiv lua stats",string.format(...)) @@ -5383,6 +5528,12 @@ if texconfig and not texlua then do if languages then ws("language load time - %s seconds (n=%s)", input.loadtime(languages), languages.hyphenation.n()) end + if figures then + ws("graphics processing time - %s seconds (n=%s) (including tex)", input.loadtime(figures), figures.n or "?") + end + if metapost then + ws("metapost processing time - %s seconds (+ loading: %s seconds)", input.loadtime(metapost), input.loadtime(mplib)) + end if status.luastate_bytes then ws("current memory usage - %s bytes", status.luastate_bytes) end @@ -5583,7 +5734,7 @@ if texconfig and not texlua then 'hash_extra', 'max_strings', 'pool_free', 'pool_size', 'string_vacancies', 'obj_tab_size', 'pdf_mem_size', 'dest_names_size', 'nest_size', 'param_size', 'save_size', 'stack_size', - 'trie_size', 'hyph_size', + 'trie_size', 'hyph_size', 'max_in_open', 'ocp_stack_size', 'ocp_list_size', 'ocp_buf_size' } @@ -5610,6 +5761,7 @@ if texconfig and not texlua then end texconfig.max_print_line = 100000 + texconfig.max_in_open = 127 end @@ -5637,114 +5789,6 @@ function cs.testcase(b) end end --- This is not the most ideal place, but it will do. Maybe we need to move --- attributes to node-att.lua. - -if node then - - nodes = nodes or { } - - do - - -- just for testing - - local reserved = { } - - function nodes.register(n) - reserved[#reserved+1] = n - end - - function nodes.cleanup_reserved(nofboxes) -- todo - local nr, free = #reserved, node.free - for i=1,nr do - free(reserved[i]) - end - local nl, tb, flush = 0, tex.box, node.flush_list - if nofboxes then - for i=1,nofboxes do - local l = tb[i] - if l then - -- flush(l) - tb[i] = nil - nl = nl + 1 - end - end - end - reserved = { } - return nr, nl, nofboxes - end - - end - - do - - local pdfliteral = node.new("whatsit",8) pdfliteral.next, pdfliteral.prev = nil, nil pdfliteral.mode = 1 - local disc = node.new("disc") disc.next, disc.prev = nil, nil - local kern = node.new("kern",1) kern.next, kern.prev = nil, nil - local penalty = node.new("penalty") penalty.next, penalty.prev = nil, nil - local glue = node.new("glue") glue.next, glue.prev = nil, nil - local glue_spec = node.new("glue_spec") glue_spec.next, glue_spec.prev = nil, nil - - nodes.register(pdfliteral) - nodes.register(disc) - nodes.register(kern) - nodes.register(penalty) - nodes.register(glue) - nodes.register(glue_spec) - - local copy = node.copy - - function nodes.penalty(p) - local n = copy(penalty) - n.penalty = p - return n - end - function nodes.kern(k) - local n = copy(kern) - n.kern = k - return n - end - function nodes.glue(width,stretch,shrink) - local n = copy(glue) - local s = copy(glue_spec) - s.width, s.stretch, s.shrink = width, stretch, shrink - n.spec = s - return n - end - function nodes.glue_spec(width,stretch,shrink) - local s = copy(glue_spec) - s.width, s.stretch, s.shrink = width, stretch, shrink - return s - end - - function nodes.disc() - return copy(disc) - end - - function nodes.pdfliteral(str) - local t = copy(pdfliteral) - t.data = str - return t - end - - end - -end - -if tex then - - function tex.node_mem_status() - -- todo: lpeg - local s = status.node_mem_usage - local t = { } - for n, tag in s:gmatch("(%d+) ([a-z_]+)") do - t[tag] = n - end - return t - end - -end - if not modules then modules = { } end modules ['luat-kps'] = { version = 1.001, @@ -5869,6 +5913,7 @@ own.libs = { -- todo: check which ones are really needed 'l-os.lua', 'l-md5.lua', 'l-file.lua', + 'l-url.lua', 'l-dir.lua', 'l-boolean.lua', 'l-unicode.lua', @@ -5935,7 +5980,8 @@ utils.report = input.report input.defaultlibs = { -- not all are needed 'l-string.lua', 'l-lpeg.lua', 'l-table.lua', 'l-boolean.lua', 'l-number.lua', 'l-set.lua', 'l-unicode.lua', - 'l-md5.lua', 'l-os.lua', 'l-io.lua', 'l-file.lua', 'l-dir.lua', 'l-utils.lua', 'l-tex.lua', + 'l-md5.lua', 'l-os.lua', 'l-io.lua', 'l-file.lua', 'l-url.lua', 'l-dir.lua', 'l-utils.lua', 'l-tex.lua', +'luat-env.lua', 'luat-lib.lua', 'luat-inp.lua', 'luat-tmp.lua', 'luat-zip.lua', 'luat-tex.lua' } diff --git a/scripts/context/lua/mtx-check.lua b/scripts/context/lua/mtx-check.lua new file mode 100644 index 000000000..dd8a71264 --- /dev/null +++ b/scripts/context/lua/mtx-check.lua @@ -0,0 +1,138 @@ +if not modules then modules = { } end modules ['mtx-check'] = { + version = 1.001, + comment = "companion to mtxrun.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +texmf.instance = instance -- we need to get rid of this / maybe current instance in global table + +scripts = scripts or { } +scripts.checker = scripts.checker or { } + +local validator = { } + +do + + validator.n = 1 + validator.errors = { } + validator.trace = false + validator.direct = false + + validator.printer = print + validator.tracer = print + + local message = function(position, kind) + local ve = validator.errors + ve[#ve+1] = { kind, position, validator.n } + if validator.direct then + validator.printer(string.format("%s error at position %s (line %s)", kind, position, validator.n)) + end + end + local progress = function(position, data, kind) + if validator.trace then + validator.tracer(string.format("%s at position %s: %s", kind, position, data or "")) + end + end + + local P, S, V, C, CP, CC = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Cp, lpeg.Cc + + local i_m, d_m = P("$"), P("$$") + local l_s, r_s = P("["), P("]") + local l_g, r_g = P("{"), P("}") + + local esc = P("\\") + local cr = P("\r") + local lf = P("\n") + local crlf = P("\r\n") + local space = S(" \t\f\v") + local newline = crlf + cr + lf + + local line = newline / function() validator.n = validator.n + 1 end + + local grammar = P { "tokens", + ["tokens"] = (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0, + ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0), + ["grouped"] = CP() * C(l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g) * CC("group") / progress, + ["setup"] = CP() * C(l_s * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s) * CC("setup") / progress, + ["display"] = CP() * C(d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m) * CC("display") / progress, + ["inline"] = CP() * C(i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m) * CC("inline") / progress, + ["errors"] = (V("gerror") + V("serror") + V("derror") + V("ierror")) * true, + ["gerror"] = CP() * (l_g + r_g) * CC("grouping") / message, + ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message, + ["derror"] = CP() * d_m * CC("display math error") / message, + ["ierror"] = CP() * i_m * CC("inline math error") / message, + } + + local grammar = P { "tokens", + ["tokens"] = (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0, + ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0), + ["grouped"] = l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g, + ["setup"] = l_s * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s, + ["display"] = d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m, + ["inline"] = i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m, + ["errors"] = (V("gerror")+ V("serror") + V("derror") + V("ierror")), + ["gerror"] = CP() * (l_g + r_g) * CC("grouping") / message, + ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message, + ["derror"] = CP() * d_m * CC("display math error") / message, + ["ierror"] = CP() * i_m * CC("inline math error") / message, + } + + function validator.check(str) + validator.n = 1 + validator.errors = { } + grammar:match(str) + end + +end + +--~ str = [[ +--~ a{oeps {oe\{\}ps} } +--~ test { oeps \} \[\] oeps \setupxxx[oeps=bla]} +--~ test $$ \hbox{$ oeps \} \[\] oeps $} $$ +--~ {$x\$xx$ $ +--~ ]] +--~ str = string.rep(str,10) + +function scripts.checker.check(filename) + local str = io.loaddata(filename) + if str then + validator.check(str) + if #validator.errors > 0 then + for k, v in ipairs(validator.errors) do + local kind, position, line = v[1], v[2], v[3] + local data = str:sub(position-30,position+30) + data = data:gsub("(.)", { + ["\n"] = " ", + ["\r"] = " ", + ["\t"] = " ", + }) + data = data:gsub("^ *","") + print(string.format("% 5i %s %s", line,string.rpadd(kind,10," "),data)) + end + else + print("no error") + end + else + print("no file") + end +end + + +banner = banner .. " | tex check tools " + +messages.help = [[ +--convert check tex file for errors +]] + +input.verbose = true + +if environment.argument("check") then + scripts.checker.check(environment.files[1]) +elseif environment.argument("help") then + input.help(banner,messages.help) +elseif environment.files[1] then + scripts.checker.check(environment.files[1]) +end + diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua index 3abd270aa..e0aa7d086 100644 --- a/scripts/context/lua/mtx-context.lua +++ b/scripts/context/lua/mtx-context.lua @@ -549,6 +549,10 @@ function scripts.context.run(ctxdata) filename = makestub("\\xmlprocess{%s}",filename) end -- + if environment.argument("autopdf") then + os.spawn(string.format('pdfclose --file "%s" 2>&1', file.replacesuffix(filename,"pdf"))) + end + -- local command = "luatex --fmt=" .. string.quote(formatfile) .. " --lua=" .. string.quote(scriptfile) .. " " .. string.quote(filename) local oldhash, newhash = scripts.context.multipass.hashfiles(jobname), { } scripts.context.multipass.makeoptionfile(jobname,ctxdata) @@ -570,6 +574,13 @@ function scripts.context.run(ctxdata) end end end + -- + -- todo: result + -- + if environment.argument("autopdf") then + os.spawn(string.format('pdfopen --file "%s" 2>&1', file.replacesuffix(filename,"pdf"))) + end + -- end else input.error("no format found with name " .. formatname) @@ -578,8 +589,8 @@ function scripts.context.run(ctxdata) end function scripts.context.make() - -- hack, should also be a shared function - for _, name in ipairs( { "cont-en", "cont-nl", "mptopdf" } ) do + local list = (environment.files[1] and environment.files) or { "cont-en", "cont-nl", "mptopdf" } + for _, name in ipairs(list) do local command = "luatools --make --compile " .. name input.report("running command: " .. command) os.spawn(command) @@ -588,7 +599,7 @@ end function scripts.context.generate() -- hack, should also be a shared function - local command = "luatools --generate " .. name + local command = "luatools --generate " input.report("running command: " .. command) os.spawn(command) end @@ -607,8 +618,11 @@ messages.help = [[ --make create context formats formats --generate generate file database etc. --ctx=name use ctx file +--autopdf open pdf file afterwards ]] +input.verbose = true + input.starttiming(scripts.context) if environment.argument("run") then diff --git a/scripts/context/lua/mtx-update.lua b/scripts/context/lua/mtx-update.lua index cfe553731..008ad68e3 100644 --- a/scripts/context/lua/mtx-update.lua +++ b/scripts/context/lua/mtx-update.lua @@ -19,75 +19,105 @@ scripts.update = scripts.update or { } minimals = minimals or { } minimals.config = minimals.config or { } -scripts.update.collections = { +os.setenv("CYGWIN","nontsec") + +scripts.update.formats = { + "cont-en", + "cont-nl", + "cont-cz", + "cont-de", + "cont-fa", + "cont-it", + "cont-ro", + "cont-uk", + "metafun", + "mptopdf", + "plain" +} + +scripts.update.repositories = { + "current", + "experimental" +} + +scripts.update.versions = { + "current", + "latest" +} + +scripts.update.engines = { ["luatex"] = { - { "base/tex/", "texmf" }, - { "base/metapost/", "texmf" }, - { "fonts/new/", "texmf" }, - { "fonts/common/", "texmf" }, - { "fonts/other/", "texmf" }, - { "context/current/", "texmf-context" }, - { "context/img/", "texmf-context" }, - { "misc/setuptex/", "." }, - { "misc/web2c", "texmf" }, - { "bin/common/%s/", "texmf-%s" }, - { "bin/context/%s/", "texmf-%s" }, - { "bin/metapost/%s/", "texmf-%s" }, - { "bin/luatex/%s/", "texmf-%s" }, - { "bin/man/", "texmf-%s" } + { "base/tex/", "texmf" }, + { "base/metapost/", "texmf" }, + { "fonts/new/", "texmf" }, + { "fonts/common/", "texmf" }, + { "fonts/other/", "texmf" }, + { "context//", "texmf-context" }, + { "context/img/", "texmf-context" }, + { "context/config/", "texmf-context" }, + { "misc/setuptex/", "." }, + { "misc/web2c", "texmf" }, + { "bin/common//", "texmf-" }, + { "bin/context//", "texmf-" }, + { "bin/metapost//", "texmf-" }, + { "bin/luatex//", "texmf-" }, + { "bin/man/", "texmf-" } }, ["xetex"] = { - { "base/tex/", "texmf" }, - { "base/metapost/", "texmf" }, - { "base/xetex/", "texmf" }, - { "fonts/new/", "texmf" }, - { "fonts/common/", "texmf" }, - { "fonts/other/", "texmf" }, - { "context/current/", "texmf-context" }, - { "context/img/", "texmf-context" }, - { "misc/setuptex/", "." }, - { "misc/web2c", "texmf" }, - { "bin/common/%s/", "texmf-%s" }, - { "bin/context/%s/", "texmf-%s" }, - { "bin/metapost/%s/", "texmf-%s" }, - { "bin/xetex/%s/", "texmf-%s" }, - { "bin/man/", "texmf-%s" } + { "base/tex/", "texmf" }, + { "base/metapost/", "texmf" }, + { "base/xetex/", "texmf" }, + { "fonts/new/", "texmf" }, + { "fonts/common/", "texmf" }, + { "fonts/other/", "texmf" }, + { "context//", "texmf-context" }, + { "context/img/", "texmf-context" }, + { "context/config/", "texmf-context" }, + { "misc/setuptex/", "." }, + { "misc/web2c", "texmf" }, + { "bin/common//", "texmf-" }, + { "bin/context//", "texmf-" }, + { "bin/metapost//", "texmf-" }, + { "bin/xetex//", "texmf-" }, + { "bin/man/", "texmf-" } }, ["pdftex"] = { - { "base/tex/", "texmf" }, - { "base/metapost/", "texmf" }, - { "fonts/old/", "texmf" }, - { "fonts/common/", "texmf" }, - { "fonts/other/", "texmf" }, - { "context/current/", "texmf-context" }, - { "context/img/", "texmf-context" }, - { "misc/setuptex/", "." }, - { "misc/web2c", "texmf" }, - { "bin/common/%s/", "texmf-%s" }, - { "bin/context/%s/", "texmf-%s" }, - { "bin/metapost/%s/", "texmf-%s" }, - { "bin/pdftex/%s/", "texmf-%s" }, - { "bin/man/", "texmf-%s" } + { "base/tex/", "texmf" }, + { "base/metapost/", "texmf" }, + { "fonts/old/", "texmf" }, + { "fonts/common/", "texmf" }, + { "fonts/other/", "texmf" }, + { "context//", "texmf-context" }, + { "context/img/", "texmf-context" }, + { "context/config/", "texmf-context" }, + { "misc/setuptex/", "." }, + { "misc/web2c", "texmf" }, + { "bin/common//", "texmf-" }, + { "bin/context//", "texmf-" }, + { "bin/metapost//", "texmf-" }, + { "bin/pdftex//", "texmf-" }, + { "bin/man/", "texmf-" } }, ["all"] = { - { "base/tex/", "texmf" }, - { "base/metapost/", "texmf" }, - { "base/xetex/", "texmf" }, - { "fonts/old/", "texmf" }, - { "fonts/new/", "texmf" }, - { "fonts/common/", "texmf" }, - { "fonts/other/", "texmf" }, - { "context/current/", "texmf-context" }, - { "context/img/", "texmf-context" }, - { "misc/setuptex/", "." }, - { "misc/web2c", "texmf" }, - { "bin/common/%s/", "texmf-%s" }, - { "bin/context/%s/", "texmf-%s" }, - { "bin/metapost/%s/", "texmf-%s" }, - { "bin/luatex/%s/", "texmf-%s" }, - { "bin/xetex/%s/", "texmf-%s" }, - { "bin/pdftex/%s/", "texmf-%s" }, - { "bin/man/", "texmf-%s" } + { "base/tex/", "texmf" }, + { "base/metapost/", "texmf" }, + { "base/xetex/", "texmf" }, + { "fonts/old/", "texmf" }, + { "fonts/new/", "texmf" }, + { "fonts/common/", "texmf" }, + { "fonts/other/", "texmf" }, + { "context//", "texmf-context" }, + { "context/img/", "texmf-context" }, + { "context/config/", "texmf-context" }, + { "misc/setuptex/", "." }, + { "misc/web2c", "texmf" }, + { "bin/common//", "texmf-" }, + { "bin/context//", "texmf-" }, + { "bin/metapost//", "texmf-" }, + { "bin/luatex//", "texmf-" }, + { "bin/xetex//", "texmf-" }, + { "bin/pdftex//", "texmf-" }, + { "bin/man/", "texmf-" } }, } @@ -104,73 +134,59 @@ scripts.update.platforms = { ["osx-ppc"] = "osx-ppc", } -scripts.update.rsyncflagspath = "-rpztlv --stats --delete" -scripts.update.rsyncflagsroot = "-rpztlv --stats" - -function scripts.update.prepare() - local texroot = environment.argument("texroot") or "tex" - local engines = environment.argument("engine") - if engines then - engines = engines:split(",") - else - engines = minimals.config.engines or { "all" } - end - local platforms = environment.argument("platform") - if platforms then - platforms = platforms:split(",") - else - platforms = minimals.config.platform or { os.currentplatform() } - end - return texroot, engines, platforms -end - function scripts.update.run(str) - if environment.argument("dryrun") then - logs.report("run", str) - else + logs.report("run", str) + if environment.argument("force") then -- important, otherwise formats fly to a weird place -- (texlua sets luatex as the engine, we need to reset that or to fix texexec :) os.setenv("engine",nil) - os.spawn(str) + os.execute(str) + end +end + +function scripts.update.fullpath(path) + if input.aux.rootbased_path(path) then + return path + else + return lfs.currentdir() .. "/" .. path end end function scripts.update.synchronize() - local texroot, engines, platforms = scripts.update.prepare() - local dryrun = environment.argument("dryrun") - os.setenv("CYGWIN","nontsec") - local rsyncbin = environment.argument("rsync") or "rsync" - local url = environment.argument("url") or "contextgarden.net::" + logs.report("update","start") + local texroot = scripts.update.fullpath(states.get("paths.root")) + local engines = states.get('engines') + local platforms = states.get('platforms') + local repositories = states.get('repositories') + local bin = states.get("rsync.program") + local url = states.get("rsync.server") + local version = states.get("context.version") + local force = environment.argument("force") if not url:find("::$") then url = url .. "::" end local ok = lfs.attributes(texroot,"mode") == "directory" - if not ok and not dryrun then + if not ok and force then dir.mkdirs(texroot) ok = lfs.attributes(texroot,"mode") == "directory" end - if ok or dryrun then - if not dryrun then + if ok or not force then + if force then dir.mkdirs(string.format("%s/%s", texroot, "texmf-cache")) end - local fetched = { } - local individual = { } - local context = environment.argument("context") - for _, engine in ipairs(engines) do - local collections = scripts.update.collections[engine] + local fetched, individual = { }, { } + for engine, _ in pairs(engines) do + local collections = scripts.update.engines[engine] if collections then for _, collection in ipairs(collections) do - for _, platform in ipairs(platforms) do + for platform, _ in pairs(platforms) do platform = scripts.update.platforms[platform] if platform then - local archive = string.format(collection[1], platform) - local destination = string.format("%s/%s", texroot, string.format(collection[2], platform)) + local archive = collection[1]:gsub("", platform) + local destination = string.format("%s/%s", texroot, collection[2]:gsub("", platform)) destination = destination:gsub("\\","/") + archive = archive:gsub("",version) if platform == "windows" or platform == "mswin" then destination = destination:gsub("([a-zA-Z]):/", "/cygdrive/%1/") end - -- if one uses experimental, context=... has no effect - if context and not environment.argument("experimental") then - archive = archive:gsub("/current/", "/" .. context .. "/") - end individual[#individual+1] = { archive, destination } end end @@ -178,20 +194,17 @@ function scripts.update.synchronize() end end local combined = { } - local distributions = { "current" } - -- we need to fetch files from both "current" and "experimental" branch - if environment.argument("experimental") then - distributions = { "experimental", "current" } - end - for _, d in pairs(distributions) do - for _, v in pairs(individual) do - local archive, destination = v[1], v[2] - local cd = combined[destination] - if not cd then - cd = { } - combined[destination] = cd + for _, repository in ipairs(scripts.update.repositories) do + if repositories[repository] then + for _, v in pairs(individual) do + local archive, destination = v[1], v[2] + local cd = combined[destination] + if not cd then + cd = { } + combined[destination] = cd + end + cd[#cd+1] = string.format("%s/%s/%s",states.get('rsync.module'),repository,archive) end - cd[#cd+1] = 'minimals/' .. d .. '/' .. archive end end if input.verbose then @@ -204,10 +217,11 @@ function scripts.update.synchronize() end for destination, archive in pairs(combined) do local archives, command = table.concat(archive," "), "" - if not environment.argument("delete") or destination:find("%.$") then - command = string.format("%s %s %s'%s' %s", rsyncbin, scripts.update.rsyncflagsroot, url, archives, destination) + local normalflags, deleteflags = states.get("rsync.flags.normal"), states.get("rsync.flags.delete") + if true then -- environment.argument("keep") or destination:find("%.$") then + command = string.format("%s %s %s'%s' %s", bin, normalflags, url, archives, destination) else - command = string.format("%s %s %s'%s' %s", rsyncbin, scripts.update.rsyncflagspath, url, archives, destination) + command = string.format("%s %s %s %s'%s' %s", bin, normalflags, deleteflags, url, archives, destination) end logs.report("mtx update", string.format("running command: %s",command)) if not fetched[command] then @@ -218,51 +232,141 @@ function scripts.update.synchronize() else logs.report("mtx update", string.format("no valid texroot: %s",texroot)) end - if environment.argument("make") then - scripts.update.make() + if not force then + logs.report("update", "use --force to really update") + end + logs.report("update","done") +end + +function table.fromhash(t) + local h = { } + for k, v in pairs(t) do -- no ipairs here + if v then h[#h+1] = k end end + return h end + function scripts.update.make() - local texroot, engines, platforms = scripts.update.prepare() + logs.report("make","start") + local force = environment.argument("force") + local texroot = scripts.update.fullpath(states.get("paths.root")) + local engines = states.get('engines') + local platforms = states.get('platforms') + local formats = states.get('formats') input.load_tree(texroot) scripts.update.run("mktexlsr") scripts.update.run("luatools --generate") - engines = (engines[1] and engines[1] == "all" and { "pdftex", "xetex", "luatex" }) or engines - for _, engine in ipairs(engines) do - scripts.update.run(string.format("texexec --make --all --fast --%s",engine)) + local formatlist = table.concat(table.fromhash(formats), " ") + if formatlist ~= "" then + for engine in pairs(engines) do + -- todo: just handle make here or in mtxrun --script context --make +--~ os.execute("set") + scripts.update.run(string.format("texexec --make --all --fast --%s %s",engine,formatlist)) + end + end + if not force then + logs.report("make", "use --force to really make") end + logs.report("make","done") end banner = banner .. " | download tools " -input.runners.save_list = { - "update", "engine", "platform", "url", "rsync", "texroot", "dryrun", "make", "delete", "context" -} - messages.help = [[ ---update update minimal tree ---engine tex engine (luatex, pdftex, xetex) ---platform platform (windows, linux, linux-64, osx-intel, osx-ppc) ---url repository url (rsync://contextgarden.net/minimals) ---rsync rsync binary (rsync) +--platform=string platform (windows, linux, linux-64, osx-intel, osx-ppc) +--server=string repository url (rsync://contextgarden.net) +--module=string repository url (minimals) +--repository=string specify version (current, experimental) +--context=string specify version (current, latest, yyyy.mm.dd) +--rsync=string rsync binary (rsync) --texroot installation directory (not guessed for the moment) ---dryrun just show what will be done +--engine tex engine (luatex, pdftex, xetex) +--force instead of a dryrun, do the real thing +--update update minimal tree --make also make formats and generate file databases ---delete delete unused files ---context=string specify version (current, experimental, yyyy.mm.dd) +--keep don't delete unused or obsolete files ]] input.verbose = true +scripts.savestate = true + +if scripts.savestate then + + states.load("status-of-update.lua") + + -- tag, value, default, persistent + + input.starttiming(states) + + states.set("info.version",0.1) -- ok + states.set("info.count",(states.get("info.count") or 0) + 1,1,false) -- ok + states.set("info.comment","this file contains the settings of the last 'mtxrun --script update ' run",false) -- ok + states.set("info.date",os.date("!%Y-%m-%d %H:%M:%S")) -- ok + + states.set("rsync.program", environment.argument("rsync"), "rsync", true) -- ok + states.set("rsync.server", environment.argument("server"), "contextgarden.net::", true) -- ok + states.set("rsync.module", environment.argument("module"), "minimals", true) -- ok + states.set("rsync.flags.normal", environment.argument("flags"), "-rpztlv --stats", true) -- ok + states.set("rsync.flags.delete", nil, "--delete", true) -- ok + + states.set("paths.root", environment.argument("texroot"), "tex", true) -- ok + + states.set("context.version", environment.argument("context"), "current", true) -- ok + + local valid = table.tohash(scripts.update.repositories) + for r in string.gmatch(environment.argument("repository") or "current","([^, ]+)") do + if valid[r] then states.set("repositories." .. r, true) end + end + local valid = scripts.update.engines + for r in string.gmatch(environment.argument("engine") or "all","([^, ]+)") do + if r == "all" then + for k, v in pairs(valid) do + if k ~= "all" then + states.set("engines." .. k, true) + end + end + elseif valid[r] then + states.set("engines." .. r, true) + end + end + local valid = scripts.update.platforms + for r in string.gmatch(environment.argument("platform") or os.currentplatform(),"([^, ]+)") do + if valid[r] then states.set("platforms." .. r, true) end + end + + local valid = table.tohash(scripts.update.formats) + for r in string.gmatch(environment.argument("formats") or "","([^, ]+)") do + if valid[r] then states.set("formats." .. r, true) end + end + + states.set("formats.cont-en", true) + states.set("formats.cont-nl", true) + states.set("formats.metafun", true) + + -- modules + + logs.report("state","loaded") + +end + if environment.argument("update") then - logs.report("update","start") scripts.update.synchronize() - logs.report("update","done") + if environment.argument("make") then + scripts.update.make() + end elseif environment.argument("make") then - logs.report("make","start") scripts.update.make() - logs.report("make","done") else input.help(banner,messages.help) end + +if scripts.savestate then + input.stoptiming(states) + states.set("info.runtime",tonumber(input.elapsedtime(states))) + if environment.argument("force") then + states.save() + logs.report("state","saved") + end +end diff --git a/scripts/context/lua/mtx-watch.lua b/scripts/context/lua/mtx-watch.lua index 96f6f7eb2..f9e81da42 100644 --- a/scripts/context/lua/mtx-watch.lua +++ b/scripts/context/lua/mtx-watch.lua @@ -11,119 +11,123 @@ texmf.instance = instance -- we need to get rid of this / maybe current instance scripts = scripts or { } scripts.watch = scripts.watch or { } -function scripts.watch.watch() - local delay = environment.argument("delay") or 5 - local logpath = environment.argument("logpath") or "" - local pipe = environment.argument("pipe") or false - if #environment.files > 0 then - for _, path in ipairs(environment.files) do - logs.report("watch", "watching path ".. path) - end - local function glob(files,path) - for name in lfs.dir(path) do - if name:find("^%.") then - -- skip . and .. - else - name = path .. "/" .. name - local a = lfs.attributes(name) - if not a then - -- weird - elseif a.mode == "directory" then - if name:find("graphics$") or name:find("figures$") or name:find("resources$") then - -- skip these too - else - glob(files,name) +do + + function scripts.watch.watch() + local delay = environment.argument("delay") or 5 + local logpath = environment.argument("logpath") or "" + local pipe = environment.argument("pipe") or false + if #environment.files > 0 then + for _, path in ipairs(environment.files) do + logs.report("watch", "watching path ".. path) + end + local function glob(files,path) + for name in lfs.dir(path) do + if name:find("^%.") then + -- skip . and .. + else + name = path .. "/" .. name + local a = lfs.attributes(name) + if not a then + -- weird + elseif a.mode == "directory" then + if name:find("graphics$") or name:find("figures$") or name:find("resources$") then + -- skip these too + else + glob(files,name) + end + elseif name:find(".%luj$") then + files[name] = a.change or a.ctime or a.modification or a.mtime end - elseif name:find(".%luj$") then - files[name] = a.change or a.ctime or a.modification or a.mtime end end end - end - local n = 0 - local function process() - local done = false - for _, path in ipairs(environment.files) do - lfs.chdir(path) - local files = { } - glob(files,path) - table.sort(files) -- what gets sorted here - for name, time in pairs(files) do - --~ local ok, joblog = xpcall(function() return dofile(name) end, function() end ) - local ok, joblog = pcall(dofile,name) - if ok and joblog then - if joblog.status == "processing" then - logs.report("watch",string.format("aborted job, %s added to queue",name)) - joblog.status = "queued" - io.savedata(name, table.serialize(joblog,true)) - elseif joblog.status == "queued" then - local command = joblog.command - if command then - local replacements = { - inputpath = (joblog.paths and joblog.paths.input ) or ".", - outputpath = (joblog.paths and joblog.paths.output) or ".", - filename = joblog.filename or "", - } - command = command:gsub("%%(.-)%%", replacements) - if command ~= "" then - joblog.status = "processing" - joblog.runtime = os.time() -- os.clock() - io.savedata(name, table.serialize(joblog,true)) - logs.report("watch",string.format("running: %s", command)) - local newpath = file.dirname(name) - io.flush() - local result = "" - if newpath ~= "" and newpath ~= "." then - local oldpath = lfs.currentdir() - lfs.chdir(newpath) - if pipe then result = os.resultof(command) else result = os.spawn(command) end - lfs.chdir(oldpath) + local function process() + local done = false + for _, path in ipairs(environment.files) do + lfs.chdir(path) + local files = { } + glob(files,path) + table.sort(files) -- what gets sorted here + for name, time in pairs(files) do + --~ local ok, joblog = xpcall(function() return dofile(name) end, function() end ) + local ok, joblog = pcall(dofile,name) + if ok and joblog then + if joblog.status == "processing" then + logs.report("watch",string.format("aborted job, %s added to queue",name)) + joblog.status = "queued" + io.savedata(name, table.serialize(joblog,true)) + elseif joblog.status == "queued" then + local command = joblog.command + if command then + local replacements = { + inputpath = (joblog.paths and joblog.paths.input ) or ".", + outputpath = (joblog.paths and joblog.paths.output) or ".", + filename = joblog.filename or "", + } + command = command:gsub("%%(.-)%%", replacements) + if command ~= "" then + joblog.status = "processing" + joblog.runtime = os.time() -- os.clock() + io.savedata(name, table.serialize(joblog,true)) + logs.report("watch",string.format("running: %s", command)) + local newpath = file.dirname(name) + io.flush() + local result = "" + if newpath ~= "" and newpath ~= "." then + local oldpath = lfs.currentdir() + lfs.chdir(newpath) + if pipe then result = os.resultof(command) else result = os.spawn(command) end + lfs.chdir(oldpath) + else + if pipe then result = os.resultof(command) else result = os.spawn(command) end + end + logs.report("watch",string.format("return value: %s", result)) + done = true + local path, base = replacements.outputpath, file.basename(replacements.filename) + joblog.runtime = os.time() - joblog.runtime -- os.clock() - joblog.runtime + joblog.result = file.replacesuffix(file.join(path,base),"pdf") + joblog.size = lfs.attributes(joblog.result,"size") + joblog.status = "finished" else - if pipe then result = os.resultof(command) else result = os.spawn(command) end + joblog.status = "invalid command" end - logs.report("watch",string.format("return value: %s", result)) - done = true - local path, base = replacements.outputpath, file.basename(replacements.filename) - joblog.runtime = os.time() - joblog.runtime -- os.clock() - joblog.runtime - joblog.result = file.replacesuffix(file.join(path,base),"pdf") - joblog.size = lfs.attributes(joblog.result,"size") - joblog.status = "finished" else - joblog.status = "invalid command" + joblog.status = "no command" end - else - joblog.status = "no command" - end - -- pcall, when error sleep + again - io.savedata(name, table.serialize(joblog,true)) - if logpath ~= "" then - local name = string.format("%s/%s%04i%09i.lua", logpath, os.time(), math.floor((os.clock()*100)%1000), math.random(99999999)) + -- pcall, when error sleep + again io.savedata(name, table.serialize(joblog,true)) - logs.report("watch", "saving joblog ".. name) + if logpath ~= "" then + local name = string.format("%s/%s%04i%09i.lua", logpath, os.time(), math.floor((os.clock()*100)%1000), math.random(99999999)) + io.savedata(name, table.serialize(joblog,true)) + logs.report("watch", "saving joblog ".. name) + end end end end end end - end - local function wait() - io.flush() - if not done then - n = n + 1 - if n >= 10 then - logs.report("watch", "still sleeping " .. os.clock()) - n = 0 + local n, start = 0, os.clock() + local function wait() + io.flush() + if not done then + n = n + 1 + if n >= 10 then + logs.report("watch", string.format("run time: %i seconds, memory usage: %0.3g MB", os.clock() - start, (status.luastate_bytes/1024)/1000)) + n = 0 + end + os.sleep(delay) end - os.sleep(delay) end + while true do + pcall(process) + pcall(wait) + end + else + logs.report("watch", "no paths to watch") end - while true do - pcall(process) - pcall(wait) - end - else - logs.report("watch", "no paths to watch") end + end function scripts.watch.collect_logs(path) -- clean 'm up too diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index d0c7469e0..a3cbb35e0 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -377,6 +377,31 @@ function string:split_settings() -- no {} handling, see l-aux for lpeg variant end end +local patterns_escapes = { + ["-"] = "%-", + ["."] = "%.", + ["+"] = "%+", + ["*"] = "%*", + ["%"] = "%%", + ["("] = "%)", + [")"] = "%)", + ["["] = "%[", + ["]"] = "%]", +} + + +function string:pattesc() + return (self:gsub(".",patterns_escapes)) +end + +function string:tohash() + local t = { } + for s in self:gmatch("([^, ]+)") do -- lpeg + t[s] = true + end + return t +end + -- filename : l-lpeg.lua -- author : Hans Hagen, PRAGMA-ADE, Hasselt NL @@ -420,7 +445,6 @@ end - -- filename : l-table.lua -- comment : split off from luat-lib -- author : Hans Hagen, PRAGMA-ADE, Hasselt NL @@ -502,7 +526,8 @@ end --~ return t --~ end -function table.merge(t, ...) +function table.merge(t, ...) -- first one is target + t = t or {} local lst = {...} for i=1,#lst do for k, v in pairs(lst[i]) do @@ -1031,6 +1056,14 @@ function table.tohash(t) return h end +function table.fromhash(t) + local h = { } + for k, v in pairs(t) do -- no ipairs here + if v then h[#h+1] = k end + end + return h +end + function table.contains(t, v) if t then for i=1, #t do @@ -1062,6 +1095,22 @@ end --~ return table.serialize(a) == table.serialize(b) --~ end +function table.clone(t,p) -- t is optional or nil or table + if not p then + t, p = { }, t or { } + elseif not t then + t = { } + end + setmetatable(t, { __index = function(_,key) return p[key] end }) + return t +end + + +function table.hexed(t,seperator) + local tt = { } + for i=1,#t do tt[i] = string.format("0x%04X",t[i]) end + return table.concat(tt,seperator or " ") +end -- filename : l-io.lua @@ -1133,38 +1182,10 @@ function io.noflines(f) return n end ---~ t, f, n = os.clock(), io.open("testbed/sample-utf16-bigendian-big.txt",'rb'), 0 ---~ for a in io.characters(f) do n = n + 1 end ---~ print(string.format("characters: %s, time: %s", n, os.clock()-t)) - do local sb = string.byte ---~ local nextchar = { ---~ [ 4] = function(f) ---~ return f:read(1), f:read(1), f:read(1), f:read(1) ---~ end, ---~ [ 2] = function(f) ---~ return f:read(1), f:read(1) ---~ end, ---~ [ 1] = function(f) ---~ return f:read(1) ---~ end, ---~ [-2] = function(f) ---~ local a = f:read(1) ---~ local b = f:read(1) ---~ return b, a ---~ end, ---~ [-4] = function(f) ---~ local a = f:read(1) ---~ local b = f:read(1) ---~ local c = f:read(1) ---~ local d = f:read(1) ---~ return d, c, b, a ---~ end ---~ } - local nextchar = { [ 4] = function(f) return f:read(1,1,1,1) @@ -1488,18 +1509,27 @@ function os.resultof(command) return io.popen(command,"r"):read("*all") end -if not os.exec then -- still not ok - os.exec = os.execute -end -if not os.spawn then -- still not ok - os.spawn = os.execute +if not os.exec then os.exec = os.execute end +if not os.spawn then os.spawn = os.execute end + +--~ os.type : windows | unix (new, we already guessed os.platform) +--~ os.name : windows | msdos | linux | macosx | solaris | .. | generic (new) + +if not io.fileseparator then + if string.find(os.getenv("PATH"),";") then + io.fileseparator, io.pathseparator, os.platform = "\\", ";", os.type or "windows" + else + io.fileseparator, io.pathseparator, os.platform = "/" , ":", os.type or "unix" + end end +os.platform = os.platform or os.type or (io.pathseparator == ";" and "windows") or "unix" + function os.launch(str) if os.platform == "windows" then - os.spawn("start " .. str) + os.execute("start " .. str) -- os.spawn ? else - os.spawn(str .. " &") + os.execute(str .. " &") -- os.spawn ? end end @@ -1514,19 +1544,15 @@ if not os.times then -- cstime = children system time function os.times() return { - utime = os.clock(), -- user - stime = 0, -- system - cutime = 0, -- children user - cstime = 0, -- children system + utime = os.gettimeofday(), -- user + stime = 0, -- system + cutime = 0, -- children user + cstime = 0, -- children system } end end -if os.gettimeofday then - os.clock = os.gettimeofday -else - os.gettimeofday = os.clock -end +os.gettimeofday = os.gettimeofday or os.clock do local startuptime = os.gettimeofday() @@ -1553,11 +1579,11 @@ if not versions then versions = { } end versions['l-file'] = 1.001 if not file then file = { } end function file.removesuffix(filename) - return filename:gsub("%.%a+$", "") + return filename:gsub("%.[%a%d]+$", "") end function file.addsuffix(filename, suffix) - if not filename:find("%.%a-$") then + if not filename:find("%.[%a%d]+$") then return filename .. "." .. suffix else return filename @@ -1565,7 +1591,11 @@ function file.addsuffix(filename, suffix) end function file.replacesuffix(filename, suffix) - return (filename:gsub("%.%a+$", "." .. suffix)) + if not filename:find("%.[%a%d]+$") then + return filename .. "." .. suffix + else + return (filename:gsub("%.[%a%d]+$","."..suffix)) + end end function file.dirname(name) @@ -1584,12 +1614,36 @@ function file.extname(name) return name:match("^.+%.([^/\\]-)$") or "" end +function file.stripsuffix(name) + return (name:gsub("%.[%a%d]+$","")) +end + +--~ function file.join(...) +--~ local t = { ... } +--~ for i=1,#t do +--~ t[i] = (t[i]:gsub("\\","/")):gsub("/+$","") +--~ end +--~ return table.concat(t,"/") +--~ end + +--~ print(file.join("x/","/y")) +--~ print(file.join("http://","/y")) +--~ print(file.join("http://a","/y")) +--~ print(file.join("http:///a","/y")) +--~ print(file.join("//nas-1","/y")) + function file.join(...) - local t = { ... } - for i=1,#t do - t[i] = (t[i]:gsub("\\","/")):gsub("/+$","") + local pth = table.concat({...},"/") + pth = pth:gsub("\\","/") + local a, b = pth:match("^(.*://)(.*)$") + if a and b then + return a .. b:gsub("//+","/") + end + a, b = pth:match("^(//)(.*)$") + if a and b then + return a .. b:gsub("//+","/") end - return table.concat(t,"/") + return (pth:gsub("//+","/")) end function file.is_writable(name) @@ -1888,6 +1942,8 @@ xml.trace_lpath = false xml.trace_print = false xml.trace_remap = false +-- todo: some things per xml file, liek namespace remapping + --[[ldx--

First a hack to enable namespace resolving. A namespace is characterized by a . The following function associates a namespace prefix with a @@ -2506,7 +2562,7 @@ function xml.text(root) return (root and xml.tostring(root)) or "" end -function xml.content(root) +function xml.content(root) -- bugged return (root and root.dt and xml.tostring(root.dt)) or "" end @@ -2837,14 +2893,13 @@ do local t = {...} for i=1,#t do if s == t[i] then return true end end return false end - function xml.traverse(root,pattern,handle,reverse,index,parent,wildcard) + local function traverse(root,pattern,handle,reverse,index,parent,wildcard) if not root then -- error return false elseif pattern == false then -- root handle(root,root.dt,root.ri) return false elseif pattern == true then -- wildcard - local traverse = xml.traverse local rootdt = root.dt if rootdt then local start, stop, step = 1, #rootdt, 1 @@ -2875,7 +2930,7 @@ do elseif command == 11 then -- parent local ep = root.__p__ or parent if index < #pattern then - if not xml.traverse(ep,pattern,handle,reverse,index+1,root) then return false end + if not traverse(ep,pattern,handle,reverse,index+1,root) then return false end elseif handle(root,rootdt,k) then return false end @@ -2890,12 +2945,11 @@ do if command == 11 then -- parent local ep = root.__p__ or parent if index < #pattern then - if not xml.traverse(ep,pattern,handle,reverse,index+1,root) then return false end + if not traverse(ep,pattern,handle,reverse,index+1,root) then return false end elseif handle(root,rootdt,k) then return false end else - local traverse = xml.traverse local rootdt = root.dt local start, stop, step, n, dn = 1, #rootdt, 1, 0, 1 if command == 30 then @@ -2989,6 +3043,7 @@ do if index == #pattern then if handle(root,rootdt,root.ri or k) then return false end if wildcard and multiple then +--~ if wildcard or multiple then if not traverse(e,pattern,handle,reverse,index,root,true) then return false end end else @@ -3049,6 +3104,8 @@ do return true end + xml.traverse = traverse + end --[[ldx-- @@ -3119,7 +3176,7 @@ do traverse(root, lpath(pattern), function(r,d,k) rt,dt,dk = r,d,k return true end, 'reverse') return dt and dt[dk], rt, dt, dk end - function xml.filters.count(root, pattern,everything) + function xml.filters.count(root,pattern,everything) local n = 0 traverse(root, lpath(pattern), function(r,d,t) if everything or type(d[t]) == "table" then @@ -3189,13 +3246,15 @@ do local rt, dt, dk traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end) local ekat = (dt and dt[dk] and dt[dk].at) or (rt and rt.at) - return (ekat and ekat[arguments]) or "" + return (ekat and (ekat[arguments] or ekat[arguments:gsub("^([\"\'])(.*)%1$","%2")])) or "" end - function xml.filters.text(root,pattern,arguments) + function xml.filters.text(root,pattern,arguments) -- ?? why index local dtk, rt, dt, dk = xml.filters.index(root,pattern,arguments) if dtk then local dtkdt = dtk.dt - if #dtkdt == 1 and type(dtkdt[1]) == "string" then + if not dtkdt then + return "", rt, dt, dk + elseif #dtkdt == 1 and type(dtkdt[1]) == "string" then return dtkdt[1], rt, dt, dk else return xml.tostring(dtkdt), rt, dt, dk @@ -3260,7 +3319,7 @@ do

Which will print all the titles in the document. The iterator variant takes - 1.5 times the runtime of the function variant which si due to the overhead in + 1.5 times the runtime of the function variant which is due to the overhead in creating the wrapper. So, instead of:

@@ -3279,6 +3338,10 @@ do return coroutine.wrap(function() traverse(root, lpath(pattern), coroutine.yield, reverse) end) end + function xml.elements_only(root,pattern,reverse) + return coroutine.wrap(function() traverse(root, lpath(pattern), function(r,d,k) coroutine.yield(d[k]) end, reverse) end) + end + function xml.each_element(root, pattern, handle, reverse) local ok traverse(root, lpath(pattern), function(r,d,k) ok = true handle(r,d,k) end, reverse) @@ -3424,10 +3487,20 @@ do end end - function xml.include(xmldata,pattern,attribute,recursive,findfile) + local function load_data(name) -- == io.loaddata + local f, data = io.open(name), "" + if f then + data = f:read("*all",'b') -- 'b' ? + f:close() + end + return data + end + + function xml.include(xmldata,pattern,attribute,recursive,loaddata) -- parse="text" (default: xml), encoding="" (todo) - pattern = pattern or 'include' -- attribute = attribute or 'href' + pattern = pattern or 'include' + loaddata = loaddata or load_data local function include(r,d,k) local ek, name = d[k], nil if not attribute or attribute == "" then @@ -3442,29 +3515,21 @@ do end end end - if name then - name = (findfile and findfile(name)) or name - if name ~= "" then - local f = io.open(name) - if f then - if ek.at["parse"] == "text" then -- for the moment hard coded - d[k] = xml.escaped(f:read("*all")) - else - local xi = xml.load(f) - if recursive then - xml.include(xi,pattern,attribute,recursive,findfile) - end - xml.assign(d,k,xi) - end - f:close() - else - xml.empty(d,k) - end - else + local data = (name and name ~= "" and loaddata(name)) or "" + if data == "" then + xml.empty(d,k) + elseif ek.at["parse"] == "text" then -- for the moment hard coded + d[k] = xml.escaped(data) + else + local xi = xml.convert(data) + if not xi then xml.empty(d,k) + else + if recursive then + xml.include(xi,pattern,attribute,recursive,loaddata) + end + xml.assign(d,k,xi) end - else - xml.empty(d,k) end end xml.each_element(xmldata, pattern, include) @@ -3948,19 +4013,13 @@ os.setlocale(nil,nil) -- useless feature and even dangerous in luatex if not io.fileseparator then if string.find(os.getenv("PATH"),";") then - io.fileseparator, io.pathseparator, os.platform = "\\", ";", "windows" + io.fileseparator, io.pathseparator, os.platform = "\\", ";", os.type or "windows" else - io.fileseparator, io.pathseparator, os.platform = "/" , ":", "unix" + io.fileseparator, io.pathseparator, os.platform = "/" , ":", os.type or "unix" end end -if not os.platform then - if io.pathseparator == ";" then - os.platform = "windows" - else - os.platform = "unix" - end -end +os.platform = os.platform or os.type or (io.pathseparator == ";" and "windows") or "unix" -- arg normalization -- @@ -4159,17 +4218,22 @@ input.formats ['lua'] = 'LUAINPUTS' -- new input.suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } -- here we catch a few new thingies (todo: add these paths to context.tmf) +-- +-- FONTFEATURES = .;$TEXMF/fonts/fea// +-- FONTCIDMAPS = .;$TEXMF/fonts/cid// -function input.checkconfigdata(instance) +function input.checkconfigdata(instance) -- not yet ok, no time for debugging now 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 + local p = instance.environment[proname] + local v = instance.environment[varname] + if not ((p and p ~= "") or (v and v ~= "")) then + instance.variables[varname] = default -- or environment? end end fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") - fix("FONTFEATURES", ".;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") - fix("FONTCIDMAPS" , ".;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") end -- backward compatible ones @@ -4270,6 +4334,11 @@ function input.reset() end +function input.reset_hashes(instance) + instance.lists = { } + instance.found = { } +end + function input.bare_variable(str) -- return string.gsub(string.gsub(string.gsub(str,"%s+$",""),'^"(.+)"$',"%1"),"^'(.+)'$","%1") return (str:gsub("\s*([\"\']?)(.+)%1\s*", "%2")) @@ -4335,7 +4404,7 @@ input.settrace(tonumber(os.getenv("MTX.INPUT.TRACE") or os.getenv("MTX_INPUT_TRA -- loading the database files. do - local clock = os.clock + local clock = os.gettimeofday or os.clock function input.starttiming(instance) if instance then @@ -4609,6 +4678,7 @@ function input.aux.extend_texmf_var(instance,specification) -- crap instance.variables['TEXMF'] = "{" .. instance.variables['TEXMF'] .. "}" end input.expand_variables(instance) + input.reset_hashes(instance) end -- locators @@ -4624,28 +4694,6 @@ function input.locatedatabase(instance,specification) return input.methodhandler('locators', instance, specification) end ---~ poor mans solution, from before we had lfs.isdir ---~ ---~ function input.locators.tex(instance,specification) ---~ if specification and specification ~= '' then ---~ local files = { ---~ file.join(specification,'files'..input.lucsuffix), ---~ file.join(specification,'files'..input.luasuffix), ---~ file.join(specification,input.lsrname) ---~ } ---~ for _, filename in pairs(files) do ---~ local f = io.open(filename) ---~ if f then ---~ input.logger('! tex locator', specification..' found') ---~ input.aux.append_hash(instance,'file',specification,filename) ---~ f:close() ---~ return ---~ end ---~ end ---~ input.logger('? tex locator', specification..' not found') ---~ end ---~ end - function input.locators.tex(instance,specification) if specification and specification ~= '' and lfs.isdir(specification) then input.logger('! tex locator', specification..' found') @@ -5004,8 +5052,6 @@ function input.expand_variables(instance) for k,v in pairs(instance.expansions) do instance.expansions[k] = v:gsub("\\", '/') end - -- ########## - --~ input.splitexpansions(instance) -- better not, fuzzy end function input.aux.expand_vars(instance,lst) -- simple vars @@ -5163,15 +5209,12 @@ do end function input.register_extra_path(instance,paths,subpaths) + local ep = instance.extra_paths or { } + local n = #ep if paths and paths ~= "" then - local ep = instance.extra_paths - if not ep then - ep = { } - instance.extra_paths = ep - end - local n = #ep - if subpath and subpaths ~= "" then + if subpaths and subpaths ~= "" then for p in paths:gmatch("[^,]+") do + -- we gmatch each step again, not that fast, but used seldom for s in subpaths:gmatch("[^,]+") do local ps = p .. "/" .. s if not done[ps] then @@ -5188,10 +5231,24 @@ do end end end - if n < #ep then - instance.lists = { } + elseif subpaths and subpaths ~= "" then + for i=1,n do + -- we gmatch each step again, not that fast, but used seldom + for s in subpaths:gmatch("[^,]+") do + local ps = ep[i] .. "/" .. s + if not done[ps] then + ep[#ep+1] = input.clean_path(ps) + done[ps] = true + end + end end end + if #ep > 0 then + instance.extra_paths = ep -- register paths + end + if #ep > n then + instance.lists = { } -- erase the cache + end end end @@ -5446,7 +5503,7 @@ input.is_readable.tex = input.is_readable.file -- name/name function input.aux.collect_files(instance,names) - local filelist = nil + local filelist = { } for _, fname in pairs(names) do if fname then if input.trace > 2 then @@ -5478,15 +5535,20 @@ function input.aux.collect_files(instance,names) if blobfile then if type(blobfile) == 'string' then if not dname or blobfile:find(dname) then - if not filelist then filelist = { } end - -- input.logger('= collected', blobpath.." | "..blobfile.." | "..bname) - filelist[#filelist+1] = file.join(blobpath,blobfile,bname) + filelist[#filelist+1] = { + hash.type, + file.join(blobpath,blobfile,bname), -- search + input.concatinators[hash.type](blobpath,blobfile,bname) -- result + } end else for _, vv in pairs(blobfile) do if not dname or vv:find(dname) then - if not filelist then filelist = { } end - filelist[#filelist+1] = file.join(blobpath,vv,bname) + filelist[#filelist+1] = { + hash.type, + file.join(blobpath,vv,bname), -- search + input.concatinators[hash.type](blobpath,vv,bname) -- result + } end end end @@ -5497,7 +5559,11 @@ function input.aux.collect_files(instance,names) end end end - return filelist + if #filelist > 0 then + return filelist + else + return nil + end end function input.suffix_of_format(str) @@ -5516,54 +5582,30 @@ function input.suffixes_of_format(str) end end ---~ function input.aux.qualified_path(filename) -- make platform dependent / not good yet ---~ return ---~ filename:find("^%.+/") or ---~ filename:find("^/") or ---~ filename:find("^%a+%:") or ---~ filename:find("^%a+##") ---~ end - ---~ function input.normalize_name(original) ---~ -- internally we use type##spec##subspec ; this hackery slightly slows down searching ---~ local str = original or "" ---~ str = str:gsub("::", "##") -- :: -> ## ---~ str = str:gsub("^(%a+)://" ,"%1##") -- zip:// -> zip## ---~ str = str:gsub("(.+)##(.+)##/(.+)","%1##%2##%3") -- ##/spec -> ##spec ---~ if (input.trace>1) and (original ~= str) then ---~ input.logger('= normalizer',original.." -> "..str) ---~ end ---~ return str ---~ end +do -do -- called about 700 times for an empty doc (font initializations etc) + -- called about 700 times for an empty doc (font initializations etc) -- i need to weed the font files for redundant calls local letter = lpeg.R("az","AZ") - local separator = lpeg.P("##") + local separator = lpeg.P("://") - local qualified = lpeg.P(".")^0 * lpeg.P("/") + letter*lpeg.P(":") + letter^1*separator - local normalized = lpeg.Cs( - (letter^1*(lpeg.P("://")/"##") * (1-lpeg.P(false))^1) + - (lpeg.P("::")/"##" + (1-separator)^1*separator*(1-separator)^1*separator*(lpeg.P("/")/"") + 1)^0 - ) + local qualified = lpeg.P(".")^0 * lpeg.P("/") + letter*lpeg.P(":") + letter^1*separator + local rootbased = lpeg.P("/") + letter*lpeg.P(":") - -- ./name ../name /name c: zip## (todo: use url internally and get rid of ##) + -- ./name ../name /name c: :// function input.aux.qualified_path(filename) return qualified:match(filename) end + function input.aux.rootbased_path(filename) + return rootbased:match(filename) + end - -- zip:// -> zip## ; :: -> ## ; aa##bb##/cc -> aa##bb##cc function input.normalize_name(original) - local str = normalized:match(original or "") - if input.trace > 1 and original ~= str then - input.logger('= normalizer',original.." -> "..str) - end - return str + return original end -end --- split the next one up, better for jit +end function input.aux.register_in_trees(instance,name) if not name:find("^%.") then @@ -5571,11 +5613,13 @@ function input.aux.register_in_trees(instance,name) end end +-- split the next one up, better for jit + function input.aux.find_file(instance,filename) -- todo : plugin (scanners, checkers etc) local result = { } local stamp = nil - filename = input.normalize_name(filename) - filename = file.collapse_path(filename:gsub("\\","/")) + filename = input.normalize_name(filename) -- elsewhere + filename = file.collapse_path(filename:gsub("\\","/")) -- elsewhere -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -5647,7 +5691,7 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec local typespec = input.variable_of_format(filetype) local pathlist = input.expanded_path_list(instance,typespec) if not pathlist or #pathlist == 0 then - -- no pathlist, access check only + -- no pathlist, access check only / todo == wildcard if input.trace > 2 then input.logger('? filename',filename) input.logger('? filetype',filetype or '?') @@ -5662,8 +5706,9 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec end -- this is actually 'other text files' or 'any' or 'whatever' local filelist = input.aux.collect_files(instance,wantedfiles) - filename = filelist and filelist[1] - if filename then + local lf = filelist and filelist[1] + if fl then + filename = fl[3] result[#result+1] = filename done = true end @@ -5673,8 +5718,8 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec local doscan, recurse if input.trace > 2 then input.logger('? filename',filename) - if pathlist then input.logger('? path list',table.concat(pathlist," | ")) end - if filelist then input.logger('? file list',table.concat(filelist," | ")) end + -- if pathlist then input.logger('? path list',table.concat(pathlist," | ")) end + -- if filelist then input.logger('? file list',table.concat(filelist," | ")) end end -- a bit messy ... esp the doscan setting here for _, path in pairs(pathlist) do @@ -5687,16 +5732,18 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec -- compare list entries with permitted pattern pathname = pathname:gsub("([%-%.])","%%%1") -- this also influences pathname = pathname:gsub("/+$", '/.*') -- later usage of pathname - pathname = pathname:gsub("//", '/.-/') + pathname = pathname:gsub("//", '/.-/') -- not ok for /// but harmless local expr = "^" .. pathname -- input.debug('?',expr) - for _, f in pairs(filelist) do + for _, fl in ipairs(filelist) do + local f = fl[2] if f:find(expr) then -- input.debug('T',' '..f) if input.trace > 2 then input.logger('= found in hash',f) end - result[#result+1] = f + --- todo, test for readable + result[#result+1] = fl[3] input.aux.register_in_trees(instance,f) -- for tracing used files done = true if not instance.allresults then break end @@ -5706,7 +5753,7 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec end end if not done and doscan then - -- check if on disk / unchecked / does not work at all + -- check if on disk / unchecked / does not work at all / also zips if input.method_is_file(pathname) then -- ? local pname = pathname:gsub("%.%*$",'') if not pname:find("%*") then @@ -5783,10 +5830,7 @@ end if not input.concatinators then input.concatinators = { } end -function input.concatinators.tex(tag,path,name) - return tag .. '/' .. path .. '/' .. name -end - +input.concatinators.tex = file.join input.concatinators.file = input.concatinators.tex function input.find_files(instance,filename,filetype,mustexist) @@ -5988,15 +6032,6 @@ function input.aux.register_file(files, name, path) end end --- zip:: zip## zip:// --- zip::pathtozipfile::pathinzipfile (also: pathtozipfile/pathinzipfile) --- file::name --- tex::name --- kpse::name --- kpse::format::name --- parent::n::name --- parent::name (default 2) - if not input.finders then input.finders = { } end if not input.openers then input.openers = { } end if not input.loaders then input.loaders = { } end @@ -6006,30 +6041,37 @@ input.openers.notfound = { nil } input.loaders.notfound = { false, nil, 0 } function input.splitmethod(filename) - local method, specification = filename:match("^(.-)##(.+)$") - if method and specification then - return method, specification + if not filename then + return { } -- safeguard + elseif type(filename) == "table" then + return filename -- already split + elseif not filename:find("://") then + return { scheme="file", path = filename, original=filename } -- quick hack else - return 'tex', filename + return url.hashed(filename) end end function input.method_is_file(filename) - local method, specification = input.splitmethod(filename) - return method == 'tex' or method == 'file' + return input.splitmethod(filename).scheme == 'file' +end + +function table.sequenced(t,sep) -- temp here + local s = { } + for k, v in pairs(t) do + s[#s+1] = k .. "=" .. v + end + return table.concat(s, sep or " | ") end function input.methodhandler(what, instance, filename, filetype) -- ... - local method, specification = input.splitmethod(filename) - if method and specification then -- redundant - if input[what][method] then - input.logger('= handler',filename.." -> "..what.." | "..method.." | "..specification) - return input[what][method](instance,specification,filetype) - else - return nil - end + local specification = (type(filename) == "string" and input.splitmethod(filename)) or filename -- no or { }, let it bomb + local scheme = specification.scheme + if input[what][scheme] then + input.logger('= handler',specification.original .." -> " .. what .. " -> " .. table.sequenced(specification)) + return input[what][scheme](instance,filename,filetype) -- todo: specification else - return input[what].tex(instance,filename,filetype) + return input[what].tex(instance,filename,filetype) -- todo: specification end end @@ -6063,6 +6105,8 @@ function input.texdatablob(instance, filename, filetype) return data or "" end +input.loadtexfile = input.texdatablob + function input.openfile(filename) -- brrr texmf.instance here / todo ! ! ! ! ! local fullname = input.findtexfile(texmf.instance, filename) if fullname and (fullname ~= "") then @@ -6641,7 +6685,7 @@ function input.aux.load_data(instance,pathname,dataname,filename) end end --- we will make a better format, maybe something xml or just text +-- we will make a better format, maybe something xml or just text or lua input.automounted = input.automounted or { } @@ -6879,6 +6923,191 @@ logs.set_level('error') logs.set_method('tex') +if not modules then modules = { } end modules ['luat-sta'] = { + version = 1.001, + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +states = states or { } +states.data = states.data or { } +states.hash = states.hash or { } +states.tag = states.tag or "" +states.filename = states.filename or "" + +function states.save(filename,tag) + tag = tag or states.tag + filename = file.addsuffix(filename or states.filename,'lus') + io.savedata(filename, + "-- generator : luat-sta.lua\n" .. + "-- state tag : " .. tag .. "\n\n" .. + table.serialize(states.data[tag or states.tag] or {},true) + ) +end + +function states.load(filename,tag) + states.filename = filename + states.tag = tag or "whatever" + states.filename = file.addsuffix(states.filename,'lus') + states.data[states.tag], states.hash[states.tag] = (io.exists(filename) and dofile(filename)) or { }, { } +end + +function states.set_by_tag(tag,key,value,default,persistent) + local d, h = states.data[tag], states.hash[tag] + if d then + local dkey, hkey = key, key + local pre, post = key:match("(.+)%.([^%.]+)$") + if pre and post then + for k in pre:gmatch("[^%.]+") do + local dk = d[k] + if not dk then + dk = { } + d[k] = dk + end + d = dk + end + dkey, hkey = post, key + end + if type(value) == nil then + value = value or default + elseif persistent then + value = value or d[dkey] or default + else + value = value or default + end + d[dkey], h[hkey] = value, value + end +end + +function states.get_by_tag(tag,key,default) + local h = states.hash[tag] + if h and h[key] then + return h[key] + else + local d = states.data[tag] + if d then + for k in key:gmatch("[^%.]+") do + local dk = d[k] + if dk then + d = dk + else + return default + end + end + return d or default + end + end +end + +function states.set(key,value,default,persistent) + states.set_by_tag(states.tag,key,value,default,persistent) +end + +function states.get(key,default) + return states.get_by_tag(states.tag,key,default) +end + +--~ states.data.update = { +--~ ["version"] = { +--~ ["major"] = 0, +--~ ["minor"] = 1, +--~ }, +--~ ["rsync"] = { +--~ ["server"] = "contextgarden.net", +--~ ["module"] = "minimals", +--~ ["repository"] = "current", +--~ ["flags"] = "-rpztlv --stats", +--~ }, +--~ ["tasks"] = { +--~ ["update"] = true, +--~ ["make"] = true, +--~ ["delete"] = false, +--~ }, +--~ ["platform"] = { +--~ ["host"] = true, +--~ ["other"] = { +--~ ["mswin"] = false, +--~ ["linux"] = false, +--~ ["linux-64"] = false, +--~ ["osx-intel"] = false, +--~ ["osx-ppc"] = false, +--~ ["sun"] = false, +--~ }, +--~ }, +--~ ["context"] = { +--~ ["available"] = {"current", "beta", "alpha", "experimental"}, +--~ ["selected"] = "current", +--~ }, +--~ ["formats"] = { +--~ ["cont-en"] = true, +--~ ["cont-nl"] = true, +--~ ["cont-de"] = false, +--~ ["cont-cz"] = false, +--~ ["cont-fr"] = false, +--~ ["cont-ro"] = false, +--~ }, +--~ ["engine"] = { +--~ ["pdftex"] = { +--~ ["install"] = true, +--~ ["formats"] = { +--~ ["pdftex"] = true, +--~ }, +--~ }, +--~ ["luatex"] = { +--~ ["install"] = true, +--~ ["formats"] = { +--~ }, +--~ }, +--~ ["xetex"] = { +--~ ["install"] = true, +--~ ["formats"] = { +--~ ["xetex"] = false, +--~ }, +--~ }, +--~ ["metapost"] = { +--~ ["install"] = true, +--~ ["formats"] = { +--~ ["mpost"] = true, +--~ ["metafun"] = true, +--~ }, +--~ }, +--~ }, +--~ ["fonts"] = { +--~ }, +--~ ["doc"] = { +--~ }, +--~ ["modules"] = { +--~ ["f-urwgaramond"] = false, +--~ ["f-urwgothic"] = false, +--~ ["t-bnf"] = false, +--~ ["t-chromato"] = false, +--~ ["t-cmscbf"] = false, +--~ ["t-cmttbf"] = false, +--~ ["t-construction-plan"] = false, +--~ ["t-degrade"] = false, +--~ ["t-french"] = false, +--~ ["t-lettrine"] = false, +--~ ["t-lilypond"] = false, +--~ ["t-mathsets"] = false, +--~ ["t-tikz"] = false, +--~ ["t-typearea"] = false, +--~ ["t-vim"] = false, +--~ }, +--~ } + + +--~ states.save("teststate", "update") +--~ states.load("teststate", "update") + +--~ print(states.get_by_tag("update","rsync.server","unknown")) +--~ states.set_by_tag("update","rsync.server","oeps") +--~ print(states.get_by_tag("update","rsync.server","unknown")) +--~ states.save("teststate", "update") +--~ states.load("teststate", "update") +--~ print(states.get_by_tag("update","rsync.server","unknown")) + + -- end library merge own = { } @@ -6906,6 +7135,7 @@ own.libs = { -- todo: check which ones are really needed -- 'luat-kps.lua', 'luat-tmp.lua', 'luat-log.lua', + 'luat-sta.lua', } -- We need this hack till luatex is fixed. @@ -7185,6 +7415,7 @@ input.runners.registered = { if not messages then messages = { } end messages.help = [[ +--script run an mtx script --execute run a script or program --resolve resolve prefixed arguments --ctxlua run internally (using preloaded libs) diff --git a/scripts/context/ruby/ctxtools.rb b/scripts/context/ruby/ctxtools.rb index 4998b21b9..de64679ac 100644 --- a/scripts/context/ruby/ctxtools.rb +++ b/scripts/context/ruby/ctxtools.rb @@ -44,7 +44,7 @@ # it cannot do that (it tries to hyphenate as if the "ffi" was a # character), and the result is wrong hyphenation. -banner = ['CtxTools', 'version 1.3.3', '2004/2006', 'PRAGMA ADE/POD'] +banner = ['CtxTools', 'version 1.3.5', '2004/2008', 'PRAGMA ADE'] $: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq! @@ -866,6 +866,7 @@ class Language @filenames = filenames @remapping = Array.new @demapping = Array.new + @cloning = Array.new @unicode = Hash.new @encoding = encoding @data = '' @@ -895,6 +896,9 @@ class Language def demap(from, to) @demapping.push([from,to]) end + def clone(from, to) + @cloning.push([from,to]) + end def load(filenames=@filenames) found = false @@ -957,6 +961,22 @@ class Language @remapping[$1.to_i][1] end report(" nothing remapped") unless done + @cloning.each_index do |i| + c = 0 + f, s = @cloning[i][0], @cloning[i][1] + str = "#{f}|#{s}" + str.gsub!(/([\[\]])/) do "\\" + "#{$1}" end + reg = /(#{str})/ + content.gsub!(/(\S*(#{str})\S*)/) do + a, b = $1, $1 + a.gsub!(reg, f) + b.gsub!(reg, s) + c = c + 1 + "#{a} #{b}" + end + report("#{c.to_s.rjust(5)} times #{f} cloned to #{s}") + n += c + end report("") content.to_s end @@ -1300,6 +1320,14 @@ class Language remap(/\\a\s*/, "[aeligature]") remap(/\\o\s*/, "[oeligature]") when 'agr' then + # bug fix + remap("a2|", "[greekalphaiotasub]") + remap("h2|", "[greeketaiotasub]") + remap("w2|", "[greekomegaiotasub]") + remap(">2r1<2r", "[2ῤ1ῥ]") + remap(">a2n1wdu'", "[ἀ2ν1ωδύ]") + remap(">e3s2ou'", "[ἐ3σ2ού]") + # main conversion remap(/\<\'a\|/, "[greekalphaiotasubdasiatonos]") # remap(/\<\'a\|/, "[greekdasiatonos][greekAlpha][greekiota]") remap(/\>\'a\|/, "[greekalphaiotasubpsilitonos]") @@ -1399,7 +1427,7 @@ class Language remap(/\<\'u/, "[greekupsilondasiatonos]") remap(/\>\'u/, "[greekupsilonpsilitonos]") remap(/\<\`u/, "[greekupsilondasiavaria]") - remap(/\>\'u/, "[greekupsilonpsilivaria]") + remap(/\>\`u/, "[greekupsilonpsilivaria]") remap(/\<\~u/, "[greekupsilondasiaperispomeni]") remap(/\>\~u/, "[greekupsilonpsiliperispomeni]") remap(/\"\'u/, "[greekupsilondialytikatonos]") @@ -1433,14 +1461,15 @@ class Language remap(/\"\'/, "[greekdialytikatonos]") remap(/\"\`/, "[greekdialytikavaria]") remap(/\"\~/, "[greekdialytikaperispomeni]") - remap(/\/, "[psili]") - remap(/\'/, "[oxia]") + remap(/\/, "[greekpsili]") + remap(/\d.{0,2}''/, "") + remap(/\'/, "[greekoxia]") remap(/\`/, "[greekvaria]") remap(/\~/, "[perispomeni]") - remap(/\"/, "[dialytika]") + remap(/\"/, "[greekdialytika]") # unknown - remap(/\|/, "[greekIotadialytika]") + # remap(/\|/, "[greekIotadialytika]") # next remap(/A/, "[greekAlpha]") remap(/B/, "[greekBeta]") @@ -1491,6 +1520,13 @@ class Language remap(/x/, "[greekxi]") remap(/y/, "[greekpsi]") remap(/z/, "[greekzeta]") + clone("[greekalphatonos]", "[greekalphaoxia]") + clone("[greekepsilontonos]", "[greekepsilonoxia]") + clone("[greeketatonos]", "[greeketaoxia]") + clone("[greekiotatonos]", "[greekiotaoxia]") + clone("[greekomicrontonos]", "[greekomicronoxia]") + clone("[greekupsilontonos]", "[greekupsilonoxia]") + clone("[greekomegatonos]", "[greekomegaoxia]") when 'ru' then remap(/\xC1/, "[cyrillica]") remap(/\xC2/, "[cyrillicb]") diff --git a/tex/context/base/attr-ini.lua b/tex/context/base/attr-ini.lua index b0cb0a10e..c701740e3 100644 --- a/tex/context/base/attr-ini.lua +++ b/tex/context/base/attr-ini.lua @@ -15,6 +15,104 @@ if not modules then modules = { } end modules ['attr-ini'] = { nodes = nodes or { } +-- This is not the most ideal place, but it will do. Maybe we need to move +-- attributes to node-att.lua. + +do + + -- just for testing + + local reserved = { } + + function nodes.register(n) + reserved[#reserved+1] = n + end + + function nodes.cleanup_reserved(nofboxes) -- todo + local nr, free = #reserved, node.free + for i=1,nr do + free(reserved[i]) + end + local nl, tb, flush = 0, tex.box, node.flush_list + if nofboxes then + for i=1,nofboxes do + local l = tb[i] + if l then + -- flush(l) + tb[i] = nil + nl = nl + 1 + end + end + end + reserved = { } + return nr, nl, nofboxes + end + +end + +do + + local pdfliteral = node.new("whatsit",8) pdfliteral.next, pdfliteral.prev = nil, nil pdfliteral.mode = 1 + local disc = node.new("disc") disc.next, disc.prev = nil, nil + local kern = node.new("kern",1) kern.next, kern.prev = nil, nil + local penalty = node.new("penalty") penalty.next, penalty.prev = nil, nil + local glue = node.new("glue") glue.next, glue.prev = nil, nil + local glue_spec = node.new("glue_spec") glue_spec.next, glue_spec.prev = nil, nil + + nodes.register(pdfliteral) + nodes.register(disc) + nodes.register(kern) + nodes.register(penalty) + nodes.register(glue) + nodes.register(glue_spec) + + local copy = node.copy + + function nodes.penalty(p) + local n = copy(penalty) + n.penalty = p + return n + end + function nodes.kern(k) + local n = copy(kern) + n.kern = k + return n + end + function nodes.glue(width,stretch,shrink) + local n = copy(glue) + local s = copy(glue_spec) + s.width, s.stretch, s.shrink = width, stretch, shrink + n.spec = s + return n + end + function nodes.glue_spec(width,stretch,shrink) + local s = copy(glue_spec) + s.width, s.stretch, s.shrink = width, stretch, shrink + return s + end + + function nodes.disc() + return copy(disc) + end + + function nodes.pdfliteral(str) + local t = copy(pdfliteral) + t.data = str + return t + end + +end + +function tex.node_mem_status() + -- todo: lpeg + local s = status.node_mem_usage + local t = { } + for n, tag in s:gmatch("(%d+) ([a-z_]+)") do + t[tag] = n + end + return t +end + -- -- attributes -- @@ -742,13 +840,6 @@ function effects.register(effect,stretch,rulethickness) return effects.registered[stamp] end ---~ backends.pdf.effects = { ---~ normal = 1, ---~ inner = 1, ---~ outer = 2, ---~ both = 3, ---~ hidden = 4, ---~ } backends.pdf.effects = { normal = 0, inner = 0, @@ -757,28 +848,20 @@ backends.pdf.effects = { hidden = 3, } -function effects.reference(effect,stretch,rulethickness) -- will move, test code, we will develop a proper model for that +function effects.reference(effect,stretch,rulethickness) + -- always, no zero test (removed) + rulethickness = number.dimenfactors["bp"]*rulethickness effect = backends.pdf.effects[effect] or backends.pdf.effects['normal'] - if rulethickness > 0 then - rulethickness = number.dimenfactors["bp"]*rulethickness .. " w " - else - rulethickness = "" - end - if stretch > 0 then - stretch = stretch.. " Tc " - else - stretch = "" - end - return backends.pdf.literal(string.format("%s%s%s Tr",stretch,rulethickness,effect)) -- watch order + return backends.pdf.literal(string.format("%s Tc %s w %s Tr",stretch,rulethickness,effect)) -- watch order end -effects.none = effects.reference(effect,0,0) +effects.none = effects.reference(0,0,0) -- faster: backends.pdf.literal("0 Tc 0 w 0 Tr") shipouts.plugins.effect = { namespace = effects, initializer = states.initialize, - finalizer = states.finalize , - processor = states.process , + finalizer = states.finalize, + processor = states.process, } -- layers diff --git a/tex/context/base/attr-ini.tex b/tex/context/base/attr-ini.tex index 80a9e66cb..f7d01b1fd 100644 --- a/tex/context/base/attr-ini.tex +++ b/tex/context/base/attr-ini.tex @@ -157,10 +157,6 @@ {\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} - \def\dotriggereffect {\ctxlua{effects.enabled=true}% \gdef\dotriggereffect##1##2##3% diff --git a/tex/context/base/char-cmp.lua b/tex/context/base/char-cmp.lua index 412f1a073..e995f510f 100644 --- a/tex/context/base/char-cmp.lua +++ b/tex/context/base/char-cmp.lua @@ -195,10 +195,13 @@ function characters.uncompose(n) -- n == string|number, returns string end -- return characters.shape(n) if cdn then - if cdn.shcode then - return utf.char(cdn.shcode) - else + local shcode = cdn.shcode + if not shcode then return characters.uncomposed.both[cdn.contextname] or n + elseif type(shcode) == "table" then + return utf.char(unpack(cdn.shcode)) + else + return utf.char(cdn.shcode) end end return n diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua index 697b33c90..4f55dbed8 100644 --- a/tex/context/base/char-def.lua +++ b/tex/context/base/char-def.lua @@ -1678,6 +1678,7 @@ characters.data={ ["description"]="LATIN CAPITAL LETTER AE", ["lccode"]=0x00E6, ["linebreak"]="al", + ["shcode"]= { 0x0041, 0x0045 }, ["unicodeslot"]=0x00C6, -- Æ }, { @@ -2026,6 +2027,7 @@ characters.data={ ["contextname"]="aeligature", ["description"]="LATIN SMALL LETTER AE", ["linebreak"]="al", + ["shcode"]= { 0x00E6, 0x00EA }, ["uccode"]=0x00C6, ["unicodeslot"]=0x00E6, -- æ }, @@ -2870,6 +2872,7 @@ characters.data={ ["description"]="LATIN CAPITAL LIGATURE IJ", ["lccode"]=0x0133, ["linebreak"]="al", + ["shcode"]={ 0x0049, 0x004A }, ["specials"]={ "compat", 0x0049, 0x004A }, ["unicodeslot"]=0x0132, -- IJ }, @@ -2880,6 +2883,7 @@ characters.data={ ["contextname"]="ijligature", ["description"]="LATIN SMALL LIGATURE IJ", ["linebreak"]="al", + ["shcode"]={ 0x0069, 0x006A }, ["specials"]={ "compat", 0x0069, 0x006A }, ["uccode"]=0x0132, ["unicodeslot"]=0x0133, -- ij @@ -3222,6 +3226,7 @@ characters.data={ ["description"]="LATIN CAPITAL LIGATURE OE", ["lccode"]=0x0153, ["linebreak"]="al", + ["shcode"]={ 0x004F, 0x0045 }, ["unicodeslot"]=0x0152, -- Œ }, { @@ -3231,6 +3236,7 @@ characters.data={ ["contextname"]="oeligature", ["description"]="LATIN SMALL LIGATURE OE", ["linebreak"]="al", + ["shcode"]={ 0x006F, 0x0065 }, ["uccode"]=0x0152, ["unicodeslot"]=0x0153, -- œ }, @@ -4292,6 +4298,7 @@ characters.data={ ["description"]="LATIN CAPITAL LETTER LJ", ["lccode"]=0x01C9, ["linebreak"]="al", + ["shcode"]={ 0x004C, 0x004A }, ["specials"]={ "compat", 0x004C, 0x004A }, ["uccode"]=0x01C8, ["unicodeslot"]=0x01C7, -- LJ @@ -4302,7 +4309,7 @@ characters.data={ ["description"]="LATIN CAPITAL LETTER L WITH SMALL LETTER J", ["lccode"]=0x01C9, ["linebreak"]="al", - ["shcode"]=0x004C, + ["shcode"]={ 0x004C, 0x006A }, ["specials"]={ "compat", 0x004C, 0x006A }, ["uccode"]=0x01C7, ["unicodeslot"]=0x01C8, -- Lj @@ -4312,6 +4319,7 @@ characters.data={ ["contextname"]="ljligature", ["description"]="LATIN SMALL LETTER LJ", ["linebreak"]="al", + ["shcode"]={ 0x006C, 0x006A }, ["specials"]={ "compat", 0x006C, 0x006A }, ["uccode"]=0x01C7, ["unicodeslot"]=0x01C9, -- lj @@ -4322,6 +4330,7 @@ characters.data={ ["description"]="LATIN CAPITAL LETTER NJ", ["lccode"]=0x01CC, ["linebreak"]="al", + ["shcode"]={ 0x004E, 0x004A }, ["specials"]={ "compat", 0x004E, 0x004A }, ["uccode"]=0x01CB, ["unicodeslot"]=0x01CA, -- NJ @@ -4332,6 +4341,7 @@ characters.data={ ["description"]="LATIN CAPITAL LETTER N WITH SMALL LETTER J", ["lccode"]=0x01CC, ["linebreak"]="al", + ["shcode"]={ 0x004E, 0x006A }, ["shcode"]=0x004E, ["specials"]={ "compat", 0x004E, 0x006A }, ["uccode"]=0x01CA, @@ -4342,6 +4352,7 @@ characters.data={ ["contextname"]="njligature", ["description"]="LATIN SMALL LETTER NJ", ["linebreak"]="al", + ["shcode"]={ 0x006E, 0x006A }, ["specials"]={ "compat", 0x006E, 0x006A }, ["uccode"]=0x01CA, ["unicodeslot"]=0x01CC, -- nj @@ -6294,14 +6305,14 @@ characters.data={ ["unicodeslot"]=0x02BB, -- ʻ }, { - ["adobename"]="afii0xE249", + ["adobename"]="afii57929", ["category"]="lm", ["description"]="MODIFIER LETTER APOSTROPHE", ["linebreak"]="al", ["unicodeslot"]=0x02BC, -- ʼ }, { - ["adobename"]="afii0xFDA9", + ["adobename"]="afii64937", ["category"]="lm", ["description"]="MODIFIER LETTER REVERSED COMMA", ["linebreak"]="al", @@ -6362,6 +6373,7 @@ characters.data={ ["contextname"]="textcircumflex", ["description"]="MODIFIER LETTER CIRCUMFLEX ACCENT", ["linebreak"]="al", + ["specials"]={ "compat", 0x0020, 0x0302 }, -- added by hh ["unicodeslot"]=0x02C6, -- ˆ }, { @@ -6371,6 +6383,7 @@ characters.data={ ["contextname"]="textcaron", ["description"]="CARON", ["linebreak"]="ai", + ["specials"]={ "compat", 0x0020, 0x030C }, -- added by hh ["unicodeslot"]=0x02C7, -- ˇ }, { @@ -8264,7 +8277,7 @@ characters.data={ ["unicodeslot"]=0x03C1, -- ρ }, [0x03C2]={ - ["adobename"]="sigma0x0001", + ["adobename"]="sigma1", ["category"]="ll", ["contextname"]="greekfinalsigma", ["description"]="GREEK SMALL LETTER FINAL SIGMA", @@ -8422,7 +8435,7 @@ characters.data={ ["unicodeslot"]=0x03D0, -- ϐ }, [0x03D1]={ - ["adobename"]="theta0x0001", + ["adobename"]="theta1", ["category"]="ll", ["contextname"]="greekthetaalt", ["description"]="GREEK THETA SYMBOL", @@ -8434,7 +8447,7 @@ characters.data={ ["unicodeslot"]=0x03D1, -- ϑ }, [0x03D2]={ - ["adobename"]="Upsilon0x0001", + ["adobename"]="Upsilon1", ["category"]="lu", ["description"]="GREEK UPSILON WITH HOOK SYMBOL", ["linebreak"]="al", @@ -8456,7 +8469,7 @@ characters.data={ ["unicodeslot"]=0x03D4, -- ϔ }, [0x03D5]={ - ["adobename"]="phi0x0001", + ["adobename"]="phi1", ["category"]="ll", ["contextname"]="greekphialt", ["description"]="GREEK PHI SYMBOL", @@ -8467,7 +8480,7 @@ characters.data={ ["unicodeslot"]=0x03D5, -- ϕ }, [0x03D6]={ - ["adobename"]="omega0x0001", + ["adobename"]="omega1", ["category"]="ll", ["contextname"]="greekpialt", ["description"]="GREEK PI SYMBOL", @@ -8789,7 +8802,7 @@ characters.data={ ["unicodeslot"]=0x0400, -- Ѐ }, [0x0401]={ - ["adobename"]="afii0x2727", + ["adobename"]="afii10023", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicYO", @@ -8800,7 +8813,7 @@ characters.data={ ["unicodeslot"]=0x0401, -- Ё }, [0x0402]={ - ["adobename"]="afii0x2743", + ["adobename"]="afii10051", ["category"]="lu", ["contextname"]="cyrillicDJE", ["description"]="CYRILLIC CAPITAL LETTER DJE", @@ -8809,7 +8822,7 @@ characters.data={ ["unicodeslot"]=0x0402, -- Ђ }, [0x0403]={ - ["adobename"]="afii0x2744", + ["adobename"]="afii10052", ["category"]="lu", ["contextname"]="cyrillicGJE", ["description"]="CYRILLIC CAPITAL LETTER GJE", @@ -8819,7 +8832,7 @@ characters.data={ ["unicodeslot"]=0x0403, -- Ѓ }, [0x0404]={ - ["adobename"]="afii0x2745", + ["adobename"]="afii10053", ["category"]="lu", ["contextname"]="cyrillicIE", ["description"]="CYRILLIC CAPITAL LETTER UKRAINIAN IE", @@ -8828,7 +8841,7 @@ characters.data={ ["unicodeslot"]=0x0404, -- Є }, [0x0405]={ - ["adobename"]="afii0x2746", + ["adobename"]="afii10054", ["category"]="lu", ["contextname"]="cyrillicDZE", ["description"]="CYRILLIC CAPITAL LETTER DZE", @@ -8837,7 +8850,7 @@ characters.data={ ["unicodeslot"]=0x0405, -- Ѕ }, [0x0406]={ - ["adobename"]="afii0x2747", + ["adobename"]="afii10055", ["category"]="lu", ["contextname"]="cyrillicII", ["description"]="CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I", @@ -8846,7 +8859,7 @@ characters.data={ ["unicodeslot"]=0x0406, -- І }, [0x0407]={ - ["adobename"]="afii0x2748", + ["adobename"]="afii10056", ["category"]="lu", ["contextname"]="cyrillicYI", ["description"]="CYRILLIC CAPITAL LETTER YI", @@ -8856,7 +8869,7 @@ characters.data={ ["unicodeslot"]=0x0407, -- Ї }, [0x0408]={ - ["adobename"]="afii0x2749", + ["adobename"]="afii10057", ["category"]="lu", ["contextname"]="cyrillicJE", ["description"]="CYRILLIC CAPITAL LETTER JE", @@ -8865,7 +8878,7 @@ characters.data={ ["unicodeslot"]=0x0408, -- Ј }, [0x0409]={ - ["adobename"]="afii0x274A", + ["adobename"]="afii10058", ["category"]="lu", ["contextname"]="cyrillicLJE", ["description"]="CYRILLIC CAPITAL LETTER LJE", @@ -8874,7 +8887,7 @@ characters.data={ ["unicodeslot"]=0x0409, -- Љ }, [0x040A]={ - ["adobename"]="afii0x274B", + ["adobename"]="afii10059", ["category"]="lu", ["contextname"]="cyrillicNJE", ["description"]="CYRILLIC CAPITAL LETTER NJE", @@ -8883,7 +8896,7 @@ characters.data={ ["unicodeslot"]=0x040A, -- Њ }, [0x040B]={ - ["adobename"]="afii0x274C", + ["adobename"]="afii10060", ["category"]="lu", ["contextname"]="cyrillicTSHE", ["description"]="CYRILLIC CAPITAL LETTER TSHE", @@ -8892,7 +8905,7 @@ characters.data={ ["unicodeslot"]=0x040B, -- Ћ }, [0x040C]={ - ["adobename"]="afii0x274D", + ["adobename"]="afii10061", ["category"]="lu", ["contextname"]="cyrillicKJE", ["description"]="CYRILLIC CAPITAL LETTER KJE", @@ -8912,7 +8925,7 @@ characters.data={ ["unicodeslot"]=0x040D, -- Ѝ }, [0x040E]={ - ["adobename"]="afii0x274E", + ["adobename"]="afii10062", ["category"]="lu", ["contextname"]="cyrillicUSHRT", ["description"]="CYRILLIC CAPITAL LETTER SHORT U", @@ -8922,7 +8935,7 @@ characters.data={ ["unicodeslot"]=0x040E, -- Ў }, [0x040F]={ - ["adobename"]="afii0x27A1", + ["adobename"]="afii10145", ["category"]="lu", ["contextname"]="cyrillicDZHE", ["description"]="CYRILLIC CAPITAL LETTER DZHE", @@ -8931,7 +8944,7 @@ characters.data={ ["unicodeslot"]=0x040F, -- Џ }, [0x0410]={ - ["adobename"]="afii0x2721", + ["adobename"]="afii10017", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicA", @@ -8941,7 +8954,7 @@ characters.data={ ["unicodeslot"]=0x0410, -- А }, [0x0411]={ - ["adobename"]="afii0x2722", + ["adobename"]="afii10018", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicB", @@ -8951,7 +8964,7 @@ characters.data={ ["unicodeslot"]=0x0411, -- Б }, [0x0412]={ - ["adobename"]="afii0x2723", + ["adobename"]="afii10019", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicV", @@ -8961,7 +8974,7 @@ characters.data={ ["unicodeslot"]=0x0412, -- В }, [0x0413]={ - ["adobename"]="afii0x2724", + ["adobename"]="afii10020", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicG", @@ -8971,7 +8984,7 @@ characters.data={ ["unicodeslot"]=0x0413, -- Г }, [0x0414]={ - ["adobename"]="afii0x2725", + ["adobename"]="afii10021", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicD", @@ -8981,7 +8994,7 @@ characters.data={ ["unicodeslot"]=0x0414, -- Д }, [0x0415]={ - ["adobename"]="afii0x2726", + ["adobename"]="afii10022", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicE", @@ -8991,7 +9004,7 @@ characters.data={ ["unicodeslot"]=0x0415, -- Е }, [0x0416]={ - ["adobename"]="afii0x2728", + ["adobename"]="afii10024", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicZH", @@ -9001,7 +9014,7 @@ characters.data={ ["unicodeslot"]=0x0416, -- Ж }, [0x0417]={ - ["adobename"]="afii0x2729", + ["adobename"]="afii10025", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicZ", @@ -9011,7 +9024,7 @@ characters.data={ ["unicodeslot"]=0x0417, -- З }, [0x0418]={ - ["adobename"]="afii0x272A", + ["adobename"]="afii10026", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicI", @@ -9021,7 +9034,7 @@ characters.data={ ["unicodeslot"]=0x0418, -- И }, [0x0419]={ - ["adobename"]="afii0x272B", + ["adobename"]="afii10027", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicISHRT", @@ -9032,7 +9045,7 @@ characters.data={ ["unicodeslot"]=0x0419, -- Й }, [0x041A]={ - ["adobename"]="afii0x272C", + ["adobename"]="afii10028", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicK", @@ -9042,7 +9055,7 @@ characters.data={ ["unicodeslot"]=0x041A, -- К }, [0x041B]={ - ["adobename"]="afii0x272D", + ["adobename"]="afii10029", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicL", @@ -9052,7 +9065,7 @@ characters.data={ ["unicodeslot"]=0x041B, -- Л }, [0x041C]={ - ["adobename"]="afii0x272E", + ["adobename"]="afii10030", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicM", @@ -9062,7 +9075,7 @@ characters.data={ ["unicodeslot"]=0x041C, -- М }, [0x041D]={ - ["adobename"]="afii0x272F", + ["adobename"]="afii10031", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicN", @@ -9072,7 +9085,7 @@ characters.data={ ["unicodeslot"]=0x041D, -- Н }, [0x041E]={ - ["adobename"]="afii0x2730", + ["adobename"]="afii10032", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicO", @@ -9082,7 +9095,7 @@ characters.data={ ["unicodeslot"]=0x041E, -- О }, [0x041F]={ - ["adobename"]="afii0x2731", + ["adobename"]="afii10033", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicP", @@ -9092,7 +9105,7 @@ characters.data={ ["unicodeslot"]=0x041F, -- П }, [0x0420]={ - ["adobename"]="afii0x2732", + ["adobename"]="afii10034", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicR", @@ -9102,7 +9115,7 @@ characters.data={ ["unicodeslot"]=0x0420, -- Р }, [0x0421]={ - ["adobename"]="afii0x2733", + ["adobename"]="afii10035", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicS", @@ -9112,7 +9125,7 @@ characters.data={ ["unicodeslot"]=0x0421, -- С }, [0x0422]={ - ["adobename"]="afii0x2734", + ["adobename"]="afii10036", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicT", @@ -9122,7 +9135,7 @@ characters.data={ ["unicodeslot"]=0x0422, -- Т }, [0x0423]={ - ["adobename"]="afii0x2735", + ["adobename"]="afii10037", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicU", @@ -9132,7 +9145,7 @@ characters.data={ ["unicodeslot"]=0x0423, -- У }, [0x0424]={ - ["adobename"]="afii0x2736", + ["adobename"]="afii10038", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicF", @@ -9142,7 +9155,7 @@ characters.data={ ["unicodeslot"]=0x0424, -- Ф }, [0x0425]={ - ["adobename"]="afii0x2737", + ["adobename"]="afii10039", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicH", @@ -9152,7 +9165,7 @@ characters.data={ ["unicodeslot"]=0x0425, -- Х }, [0x0426]={ - ["adobename"]="afii0x2738", + ["adobename"]="afii10040", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicC", @@ -9162,7 +9175,7 @@ characters.data={ ["unicodeslot"]=0x0426, -- Ц }, [0x0427]={ - ["adobename"]="afii0x2739", + ["adobename"]="afii10041", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicCH", @@ -9172,7 +9185,7 @@ characters.data={ ["unicodeslot"]=0x0427, -- Ч }, [0x0428]={ - ["adobename"]="afii0x273A", + ["adobename"]="afii10042", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicSH", @@ -9182,7 +9195,7 @@ characters.data={ ["unicodeslot"]=0x0428, -- Ш }, [0x0429]={ - ["adobename"]="afii0x273B", + ["adobename"]="afii10043", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicSHCH", @@ -9192,7 +9205,7 @@ characters.data={ ["unicodeslot"]=0x0429, -- Щ }, [0x042A]={ - ["adobename"]="afii0x273C", + ["adobename"]="afii10044", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicHRDSN", @@ -9202,7 +9215,7 @@ characters.data={ ["unicodeslot"]=0x042A, -- Ъ }, [0x042B]={ - ["adobename"]="afii0x273D", + ["adobename"]="afii10045", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicERY", @@ -9212,7 +9225,7 @@ characters.data={ ["unicodeslot"]=0x042B, -- Ы }, [0x042C]={ - ["adobename"]="afii0x273E", + ["adobename"]="afii10046", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicSFTSN", @@ -9222,7 +9235,7 @@ characters.data={ ["unicodeslot"]=0x042C, -- Ь }, [0x042D]={ - ["adobename"]="afii0x273F", + ["adobename"]="afii10047", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicEREV", @@ -9232,7 +9245,7 @@ characters.data={ ["unicodeslot"]=0x042D, -- Э }, [0x042E]={ - ["adobename"]="afii0x2740", + ["adobename"]="afii10048", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicYU", @@ -9242,7 +9255,7 @@ characters.data={ ["unicodeslot"]=0x042E, -- Ю }, [0x042F]={ - ["adobename"]="afii0x2741", + ["adobename"]="afii10049", ["category"]="lu", ["cjkwd"]="a", ["contextname"]="cyrillicYA", @@ -9252,7 +9265,7 @@ characters.data={ ["unicodeslot"]=0x042F, -- Я }, [0x0430]={ - ["adobename"]="afii0x2751", + ["adobename"]="afii10065", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillica", @@ -9262,7 +9275,7 @@ characters.data={ ["unicodeslot"]=0x0430, -- а }, [0x0431]={ - ["adobename"]="afii0x2752", + ["adobename"]="afii10066", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicb", @@ -9272,7 +9285,7 @@ characters.data={ ["unicodeslot"]=0x0431, -- б }, [0x0432]={ - ["adobename"]="afii0x2753", + ["adobename"]="afii10067", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicv", @@ -9282,7 +9295,7 @@ characters.data={ ["unicodeslot"]=0x0432, -- в }, [0x0433]={ - ["adobename"]="afii0x2754", + ["adobename"]="afii10068", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicg", @@ -9292,7 +9305,7 @@ characters.data={ ["unicodeslot"]=0x0433, -- г }, [0x0434]={ - ["adobename"]="afii0x2755", + ["adobename"]="afii10069", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicd", @@ -9302,7 +9315,7 @@ characters.data={ ["unicodeslot"]=0x0434, -- д }, [0x0435]={ - ["adobename"]="afii0x2756", + ["adobename"]="afii10070", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillice", @@ -9312,7 +9325,7 @@ characters.data={ ["unicodeslot"]=0x0435, -- е }, [0x0436]={ - ["adobename"]="afii0x2758", + ["adobename"]="afii10072", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrilliczh", @@ -9322,7 +9335,7 @@ characters.data={ ["unicodeslot"]=0x0436, -- ж }, [0x0437]={ - ["adobename"]="afii0x2759", + ["adobename"]="afii10073", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicz", @@ -9332,7 +9345,7 @@ characters.data={ ["unicodeslot"]=0x0437, -- з }, [0x0438]={ - ["adobename"]="afii0x275A", + ["adobename"]="afii10074", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillici", @@ -9342,7 +9355,7 @@ characters.data={ ["unicodeslot"]=0x0438, -- и }, [0x0439]={ - ["adobename"]="afii0x275B", + ["adobename"]="afii10075", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicishrt", @@ -9353,7 +9366,7 @@ characters.data={ ["unicodeslot"]=0x0439, -- й }, [0x043A]={ - ["adobename"]="afii0x275C", + ["adobename"]="afii10076", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillick", @@ -9363,7 +9376,7 @@ characters.data={ ["unicodeslot"]=0x043A, -- к }, [0x043B]={ - ["adobename"]="afii0x275D", + ["adobename"]="afii10077", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicl", @@ -9373,7 +9386,7 @@ characters.data={ ["unicodeslot"]=0x043B, -- л }, [0x043C]={ - ["adobename"]="afii0x275E", + ["adobename"]="afii10078", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicm", @@ -9383,7 +9396,7 @@ characters.data={ ["unicodeslot"]=0x043C, -- м }, [0x043D]={ - ["adobename"]="afii0x275F", + ["adobename"]="afii10079", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicn", @@ -9393,7 +9406,7 @@ characters.data={ ["unicodeslot"]=0x043D, -- н }, [0x043E]={ - ["adobename"]="afii0x2760", + ["adobename"]="afii10080", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillico", @@ -9403,7 +9416,7 @@ characters.data={ ["unicodeslot"]=0x043E, -- о }, [0x043F]={ - ["adobename"]="afii0x2761", + ["adobename"]="afii10081", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicp", @@ -9413,7 +9426,7 @@ characters.data={ ["unicodeslot"]=0x043F, -- п }, [0x0440]={ - ["adobename"]="afii0x2762", + ["adobename"]="afii10082", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicr", @@ -9423,7 +9436,7 @@ characters.data={ ["unicodeslot"]=0x0440, -- р }, [0x0441]={ - ["adobename"]="afii0x2763", + ["adobename"]="afii10083", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillics", @@ -9433,7 +9446,7 @@ characters.data={ ["unicodeslot"]=0x0441, -- с }, [0x0442]={ - ["adobename"]="afii0x2764", + ["adobename"]="afii10084", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillict", @@ -9443,7 +9456,7 @@ characters.data={ ["unicodeslot"]=0x0442, -- т }, [0x0443]={ - ["adobename"]="afii0x2765", + ["adobename"]="afii10085", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicu", @@ -9453,7 +9466,7 @@ characters.data={ ["unicodeslot"]=0x0443, -- у }, [0x0444]={ - ["adobename"]="afii0x2766", + ["adobename"]="afii10086", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicf", @@ -9463,7 +9476,7 @@ characters.data={ ["unicodeslot"]=0x0444, -- ф }, [0x0445]={ - ["adobename"]="afii0x2767", + ["adobename"]="afii10087", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillich", @@ -9473,7 +9486,7 @@ characters.data={ ["unicodeslot"]=0x0445, -- х }, [0x0446]={ - ["adobename"]="afii0x2768", + ["adobename"]="afii10088", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicc", @@ -9483,7 +9496,7 @@ characters.data={ ["unicodeslot"]=0x0446, -- ц }, [0x0447]={ - ["adobename"]="afii0x2769", + ["adobename"]="afii10089", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicch", @@ -9493,7 +9506,7 @@ characters.data={ ["unicodeslot"]=0x0447, -- ч }, [0x0448]={ - ["adobename"]="afii0x276A", + ["adobename"]="afii10090", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicsh", @@ -9503,7 +9516,7 @@ characters.data={ ["unicodeslot"]=0x0448, -- ш }, [0x0449]={ - ["adobename"]="afii0x276B", + ["adobename"]="afii10091", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicshch", @@ -9513,7 +9526,7 @@ characters.data={ ["unicodeslot"]=0x0449, -- щ }, [0x044A]={ - ["adobename"]="afii0x276C", + ["adobename"]="afii10092", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillichrdsn", @@ -9523,7 +9536,7 @@ characters.data={ ["unicodeslot"]=0x044A, -- ъ }, [0x044B]={ - ["adobename"]="afii0x276D", + ["adobename"]="afii10093", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicery", @@ -9533,7 +9546,7 @@ characters.data={ ["unicodeslot"]=0x044B, -- ы }, [0x044C]={ - ["adobename"]="afii0x276E", + ["adobename"]="afii10094", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicsftsn", @@ -9543,7 +9556,7 @@ characters.data={ ["unicodeslot"]=0x044C, -- ь }, [0x044D]={ - ["adobename"]="afii0x276F", + ["adobename"]="afii10095", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicerev", @@ -9553,7 +9566,7 @@ characters.data={ ["unicodeslot"]=0x044D, -- э }, [0x044E]={ - ["adobename"]="afii0x2770", + ["adobename"]="afii10096", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicyu", @@ -9563,7 +9576,7 @@ characters.data={ ["unicodeslot"]=0x044E, -- ю }, [0x044F]={ - ["adobename"]="afii0x2771", + ["adobename"]="afii10097", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicya", @@ -9583,7 +9596,7 @@ characters.data={ ["unicodeslot"]=0x0450, -- ѐ }, [0x0451]={ - ["adobename"]="afii0x2757", + ["adobename"]="afii10071", ["category"]="ll", ["cjkwd"]="a", ["contextname"]="cyrillicyo", @@ -9594,7 +9607,7 @@ characters.data={ ["unicodeslot"]=0x0451, -- ё }, [0x0452]={ - ["adobename"]="afii0x2773", + ["adobename"]="afii10099", ["category"]="ll", ["contextname"]="cyrillicdje", ["description"]="CYRILLIC SMALL LETTER DJE", @@ -9603,7 +9616,7 @@ characters.data={ ["unicodeslot"]=0x0452, -- ђ }, [0x0453]={ - ["adobename"]="afii0x2774", + ["adobename"]="afii10100", ["category"]="ll", ["contextname"]="cyrillicgje", ["description"]="CYRILLIC SMALL LETTER GJE", @@ -9613,7 +9626,7 @@ characters.data={ ["unicodeslot"]=0x0453, -- ѓ }, [0x0454]={ - ["adobename"]="afii0x2775", + ["adobename"]="afii10101", ["category"]="ll", ["contextname"]="cyrillicie", ["description"]="CYRILLIC SMALL LETTER UKRAINIAN IE", @@ -9622,7 +9635,7 @@ characters.data={ ["unicodeslot"]=0x0454, -- є }, [0x0455]={ - ["adobename"]="afii0x2776", + ["adobename"]="afii10102", ["category"]="ll", ["contextname"]="cyrillicdze", ["description"]="CYRILLIC SMALL LETTER DZE", @@ -9631,7 +9644,7 @@ characters.data={ ["unicodeslot"]=0x0455, -- ѕ }, [0x0456]={ - ["adobename"]="afii0x2777", + ["adobename"]="afii10103", ["category"]="ll", ["contextname"]="cyrillicii", ["description"]="CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I", @@ -9640,7 +9653,7 @@ characters.data={ ["unicodeslot"]=0x0456, -- і }, [0x0457]={ - ["adobename"]="afii0x2778", + ["adobename"]="afii10104", ["category"]="ll", ["contextname"]="cyrillicyi", ["description"]="CYRILLIC SMALL LETTER YI", @@ -9650,7 +9663,7 @@ characters.data={ ["unicodeslot"]=0x0457, -- ї }, [0x0458]={ - ["adobename"]="afii0x2779", + ["adobename"]="afii10105", ["category"]="ll", ["contextname"]="cyrillicje", ["description"]="CYRILLIC SMALL LETTER JE", @@ -9659,7 +9672,7 @@ characters.data={ ["unicodeslot"]=0x0458, -- ј }, [0x0459]={ - ["adobename"]="afii0x277A", + ["adobename"]="afii10106", ["category"]="ll", ["contextname"]="cyrilliclje", ["description"]="CYRILLIC SMALL LETTER LJE", @@ -9668,7 +9681,7 @@ characters.data={ ["unicodeslot"]=0x0459, -- љ }, [0x045A]={ - ["adobename"]="afii0x277B", + ["adobename"]="afii10107", ["category"]="ll", ["contextname"]="cyrillicnje", ["description"]="CYRILLIC SMALL LETTER NJE", @@ -9677,7 +9690,7 @@ characters.data={ ["unicodeslot"]=0x045A, -- њ }, [0x045B]={ - ["adobename"]="afii0x277C", + ["adobename"]="afii10108", ["category"]="ll", ["contextname"]="cyrillictshe", ["description"]="CYRILLIC SMALL LETTER TSHE", @@ -9686,7 +9699,7 @@ characters.data={ ["unicodeslot"]=0x045B, -- ћ }, [0x045C]={ - ["adobename"]="afii0x277D", + ["adobename"]="afii10109", ["category"]="ll", ["contextname"]="cyrillickje", ["description"]="CYRILLIC SMALL LETTER KJE", @@ -9706,7 +9719,7 @@ characters.data={ ["unicodeslot"]=0x045D, -- ѝ }, [0x045E]={ - ["adobename"]="afii0x277E", + ["adobename"]="afii10110", ["category"]="ll", ["contextname"]="cyrillicushrt", ["description"]="CYRILLIC SMALL LETTER SHORT U", @@ -9716,7 +9729,7 @@ characters.data={ ["unicodeslot"]=0x045E, -- ў }, [0x045F]={ - ["adobename"]="afii0x27D1", + ["adobename"]="afii10193", ["category"]="ll", ["contextname"]="cyrillicdzhe", ["description"]="CYRILLIC SMALL LETTER DZHE", @@ -9741,7 +9754,7 @@ characters.data={ ["unicodeslot"]=0x0461, -- ѡ }, [0x0462]={ - ["adobename"]="afii0x27A2", + ["adobename"]="afii10146", ["category"]="lu", ["contextname"]="cyrillicYAT", ["description"]="CYRILLIC CAPITAL LETTER YAT", @@ -9750,7 +9763,7 @@ characters.data={ ["unicodeslot"]=0x0462, -- Ѣ }, [0x0463]={ - ["adobename"]="afii0x27D2", + ["adobename"]="afii10194", ["category"]="ll", ["contextname"]="cyrillicyat", ["description"]="CYRILLIC SMALL LETTER YAT", @@ -9871,7 +9884,7 @@ characters.data={ ["unicodeslot"]=0x0471, -- ѱ }, [0x0472]={ - ["adobename"]="afii0x27A3", + ["adobename"]="afii10147", ["category"]="lu", ["contextname"]="cyrillicFITA", ["description"]="CYRILLIC CAPITAL LETTER FITA", @@ -9880,7 +9893,7 @@ characters.data={ ["unicodeslot"]=0x0472, -- Ѳ }, [0x0473]={ - ["adobename"]="afii0x27D3", + ["adobename"]="afii10195", ["category"]="ll", ["contextname"]="cyrillicfita", ["description"]="CYRILLIC SMALL LETTER FITA", @@ -9889,7 +9902,7 @@ characters.data={ ["unicodeslot"]=0x0473, -- ѳ }, [0x0474]={ - ["adobename"]="afii0x27A4", + ["adobename"]="afii10148", ["category"]="lu", ["contextname"]="cyrillicIZHITSA", ["description"]="CYRILLIC CAPITAL LETTER IZHITSA", @@ -9898,7 +9911,7 @@ characters.data={ ["unicodeslot"]=0x0474, -- Ѵ }, [0x0475]={ - ["adobename"]="afii0x27D4", + ["adobename"]="afii10196", ["category"]="ll", ["contextname"]="cyrillicizhitsa", ["description"]="CYRILLIC SMALL LETTER IZHITSA", @@ -10105,7 +10118,7 @@ characters.data={ ["unicodeslot"]=0x048F, -- ҏ }, [0x0490]={ - ["adobename"]="afii0x2742", + ["adobename"]="afii10050", ["category"]="lu", ["contextname"]="cyrillicGHEupturn", ["description"]="CYRILLIC CAPITAL LETTER GHE WITH UPTURN", @@ -10115,7 +10128,7 @@ characters.data={ ["unicodeslot"]=0x0490, -- Ґ }, [0x0491]={ - ["adobename"]="afii0x2772", + ["adobename"]="afii10098", ["category"]="ll", ["contextname"]="cyrillicgheupturn", ["description"]="CYRILLIC SMALL LETTER GHE WITH UPTURN", @@ -10746,7 +10759,7 @@ characters.data={ ["unicodeslot"]=0x04D8, -- Ә }, [0x04D9]={ - ["adobename"]="afii0x2A5E", + ["adobename"]="afii10846", ["category"]="ll", ["contextname"]="cyrillicschwa", ["description"]="CYRILLIC SMALL LETTER SCHWA", @@ -12030,70 +12043,70 @@ characters.data={ ["unicodeslot"]=0x05AF, -- ֯ }, [0x05B0]={ - ["adobename"]="afii0xE1C7", + ["adobename"]="afii57799", ["category"]="mn", ["description"]="HEBREW POINT SHEVA", ["linebreak"]="cm", ["unicodeslot"]=0x05B0, -- ְ }, [0x05B1]={ - ["adobename"]="afii0xE1C9", + ["adobename"]="afii57801", ["category"]="mn", ["description"]="HEBREW POINT HATAF SEGOL", ["linebreak"]="cm", ["unicodeslot"]=0x05B1, -- ֱ }, [0x05B2]={ - ["adobename"]="afii0xE1C8", + ["adobename"]="afii57800", ["category"]="mn", ["description"]="HEBREW POINT HATAF PATAH", ["linebreak"]="cm", ["unicodeslot"]=0x05B2, -- ֲ }, [0x05B3]={ - ["adobename"]="afii0xE1CA", + ["adobename"]="afii57802", ["category"]="mn", ["description"]="HEBREW POINT HATAF QAMATS", ["linebreak"]="cm", ["unicodeslot"]=0x05B3, -- ֳ }, [0x05B4]={ - ["adobename"]="afii0xE1C1", + ["adobename"]="afii57793", ["category"]="mn", ["description"]="HEBREW POINT HIRIQ", ["linebreak"]="cm", ["unicodeslot"]=0x05B4, -- ִ }, [0x05B5]={ - ["adobename"]="afii0xE1C2", + ["adobename"]="afii57794", ["category"]="mn", ["description"]="HEBREW POINT TSERE", ["linebreak"]="cm", ["unicodeslot"]=0x05B5, -- ֵ }, [0x05B6]={ - ["adobename"]="afii0xE1C3", + ["adobename"]="afii57795", ["category"]="mn", ["description"]="HEBREW POINT SEGOL", ["linebreak"]="cm", ["unicodeslot"]=0x05B6, -- ֶ }, [0x05B7]={ - ["adobename"]="afii0xE1C6", + ["adobename"]="afii57798", ["category"]="mn", ["description"]="HEBREW POINT PATAH", ["linebreak"]="cm", ["unicodeslot"]=0x05B7, -- ַ }, [0x05B8]={ - ["adobename"]="afii0xE1C5", + ["adobename"]="afii57797", ["category"]="mn", ["description"]="HEBREW POINT QAMATS", ["linebreak"]="cm", ["unicodeslot"]=0x05B8, -- ָ }, [0x05B9]={ - ["adobename"]="afii0xE1CE", + ["adobename"]="afii57806", ["category"]="mn", ["description"]="HEBREW POINT HOLAM", ["linebreak"]="cm", @@ -12106,63 +12119,63 @@ characters.data={ ["unicodeslot"]=0x05BA, -- ֺ }, [0x05BB]={ - ["adobename"]="afii0xE1C4", + ["adobename"]="afii57796", ["category"]="mn", ["description"]="HEBREW POINT QUBUTS", ["linebreak"]="cm", ["unicodeslot"]=0x05BB, -- ֻ }, [0x05BC]={ - ["adobename"]="afii0xE1CF", + ["adobename"]="afii57807", ["category"]="mn", ["description"]="HEBREW POINT DAGESH OR MAPIQ", ["linebreak"]="cm", ["unicodeslot"]=0x05BC, -- ּ }, [0x05BD]={ - ["adobename"]="afii0xE1EF", + ["adobename"]="afii57839", ["category"]="mn", ["description"]="HEBREW POINT METEG", ["linebreak"]="cm", ["unicodeslot"]=0x05BD, -- ֽ }, [0x05BE]={ - ["adobename"]="afii0xE12D", + ["adobename"]="afii57645", ["category"]="po", ["description"]="HEBREW PUNCTUATION MAQAF", ["linebreak"]="ba", ["unicodeslot"]=0x05BE, -- ־ }, [0x05BF]={ - ["adobename"]="afii0xE1F1", + ["adobename"]="afii57841", ["category"]="mn", ["description"]="HEBREW POINT RAFE", ["linebreak"]="cm", ["unicodeslot"]=0x05BF, -- ֿ }, [0x05C0]={ - ["adobename"]="afii0xE1F2", + ["adobename"]="afii57842", ["category"]="po", ["description"]="HEBREW PUNCTUATION PASEQ", ["linebreak"]="al", ["unicodeslot"]=0x05C0, -- ׀ }, [0x05C1]={ - ["adobename"]="afii0xE1CC", + ["adobename"]="afii57804", ["category"]="mn", ["description"]="HEBREW POINT SHIN DOT", ["linebreak"]="cm", ["unicodeslot"]=0x05C1, -- ׁ }, [0x05C2]={ - ["adobename"]="afii0xE1CB", + ["adobename"]="afii57803", ["category"]="mn", ["description"]="HEBREW POINT SIN DOT", ["linebreak"]="cm", ["unicodeslot"]=0x05C2, -- ׂ }, [0x05C3]={ - ["adobename"]="afii0xE13A", + ["adobename"]="afii57658", ["category"]="po", ["description"]="HEBREW PUNCTUATION SOF PASUQ", ["linebreak"]="al", @@ -12193,7 +12206,7 @@ characters.data={ ["unicodeslot"]=0x05C7, -- ׇ }, [0x05D0]={ - ["adobename"]="afii0xE140", + ["adobename"]="afii57664", ["category"]="lo", ["contextname"]="hebrewAlef", ["description"]="HEBREW LETTER ALEF", @@ -12201,7 +12214,7 @@ characters.data={ ["unicodeslot"]=0x05D0, -- א }, [0x05D1]={ - ["adobename"]="afii0xE141", + ["adobename"]="afii57665", ["category"]="lo", ["contextname"]="hebrewBet", ["description"]="HEBREW LETTER BET", @@ -12209,7 +12222,7 @@ characters.data={ ["unicodeslot"]=0x05D1, -- ב }, [0x05D2]={ - ["adobename"]="afii0xE142", + ["adobename"]="afii57666", ["category"]="lo", ["contextname"]="hebrewGimel", ["description"]="HEBREW LETTER GIMEL", @@ -12217,7 +12230,7 @@ characters.data={ ["unicodeslot"]=0x05D2, -- ג }, [0x05D3]={ - ["adobename"]="afii0xE143", + ["adobename"]="afii57667", ["category"]="lo", ["contextname"]="hebrewDalet", ["description"]="HEBREW LETTER DALET", @@ -12225,7 +12238,7 @@ characters.data={ ["unicodeslot"]=0x05D3, -- ד }, [0x05D4]={ - ["adobename"]="afii0xE144", + ["adobename"]="afii57668", ["category"]="lo", ["contextname"]="hebrewHe", ["description"]="HEBREW LETTER HE", @@ -12233,7 +12246,7 @@ characters.data={ ["unicodeslot"]=0x05D4, -- ה }, [0x05D5]={ - ["adobename"]="afii0xE145", + ["adobename"]="afii57669", ["category"]="lo", ["contextname"]="hebrewVav", ["description"]="HEBREW LETTER VAV", @@ -12241,7 +12254,7 @@ characters.data={ ["unicodeslot"]=0x05D5, -- ו }, [0x05D6]={ - ["adobename"]="afii0xE146", + ["adobename"]="afii57670", ["category"]="lo", ["contextname"]="hebrewZayin", ["description"]="HEBREW LETTER ZAYIN", @@ -12249,7 +12262,7 @@ characters.data={ ["unicodeslot"]=0x05D6, -- ז }, [0x05D7]={ - ["adobename"]="afii0xE147", + ["adobename"]="afii57671", ["category"]="lo", ["contextname"]="hebrewHet", ["description"]="HEBREW LETTER HET", @@ -12257,7 +12270,7 @@ characters.data={ ["unicodeslot"]=0x05D7, -- ח }, [0x05D8]={ - ["adobename"]="afii0xE148", + ["adobename"]="afii57672", ["category"]="lo", ["contextname"]="hebrewTet", ["description"]="HEBREW LETTER TET", @@ -12265,7 +12278,7 @@ characters.data={ ["unicodeslot"]=0x05D8, -- ט }, [0x05D9]={ - ["adobename"]="afii0xE149", + ["adobename"]="afii57673", ["category"]="lo", ["contextname"]="hebrewYod", ["description"]="HEBREW LETTER YOD", @@ -12273,7 +12286,7 @@ characters.data={ ["unicodeslot"]=0x05D9, -- י }, [0x05DA]={ - ["adobename"]="afii0xE14A", + ["adobename"]="afii57674", ["category"]="lo", ["contextname"]="hebrewKaffinal", ["description"]="HEBREW LETTER FINAL KAF", @@ -12281,7 +12294,7 @@ characters.data={ ["unicodeslot"]=0x05DA, -- ך }, [0x05DB]={ - ["adobename"]="afii0xE14B", + ["adobename"]="afii57675", ["category"]="lo", ["contextname"]="hebrewKaf", ["description"]="HEBREW LETTER KAF", @@ -12289,7 +12302,7 @@ characters.data={ ["unicodeslot"]=0x05DB, -- כ }, [0x05DC]={ - ["adobename"]="afii0xE14C", + ["adobename"]="afii57676", ["category"]="lo", ["contextname"]="hebrewLamed", ["description"]="HEBREW LETTER LAMED", @@ -12297,7 +12310,7 @@ characters.data={ ["unicodeslot"]=0x05DC, -- ל }, [0x05DD]={ - ["adobename"]="afii0xE14D", + ["adobename"]="afii57677", ["category"]="lo", ["contextname"]="hebrewMemfinal", ["description"]="HEBREW LETTER FINAL MEM", @@ -12305,7 +12318,7 @@ characters.data={ ["unicodeslot"]=0x05DD, -- ם }, [0x05DE]={ - ["adobename"]="afii0xE14E", + ["adobename"]="afii57678", ["category"]="lo", ["contextname"]="hebrewMem", ["description"]="HEBREW LETTER MEM", @@ -12313,7 +12326,7 @@ characters.data={ ["unicodeslot"]=0x05DE, -- מ }, [0x05DF]={ - ["adobename"]="afii0xE14F", + ["adobename"]="afii57679", ["category"]="lo", ["contextname"]="hebrewNunfinal", ["description"]="HEBREW LETTER FINAL NUN", @@ -12321,7 +12334,7 @@ characters.data={ ["unicodeslot"]=0x05DF, -- ן }, [0x05E0]={ - ["adobename"]="afii0xE150", + ["adobename"]="afii57680", ["category"]="lo", ["contextname"]="hebrewNun", ["description"]="HEBREW LETTER NUN", @@ -12329,7 +12342,7 @@ characters.data={ ["unicodeslot"]=0x05E0, -- נ }, [0x05E1]={ - ["adobename"]="afii0xE151", + ["adobename"]="afii57681", ["category"]="lo", ["contextname"]="hebrewSamekh", ["description"]="HEBREW LETTER SAMEKH", @@ -12337,7 +12350,7 @@ characters.data={ ["unicodeslot"]=0x05E1, -- ס }, [0x05E2]={ - ["adobename"]="afii0xE152", + ["adobename"]="afii57682", ["category"]="lo", ["contextname"]="hebrewAyin", ["description"]="HEBREW LETTER AYIN", @@ -12345,7 +12358,7 @@ characters.data={ ["unicodeslot"]=0x05E2, -- ע }, [0x05E3]={ - ["adobename"]="afii0xE153", + ["adobename"]="afii57683", ["category"]="lo", ["contextname"]="hebrewPefinal", ["description"]="HEBREW LETTER FINAL PE", @@ -12353,7 +12366,7 @@ characters.data={ ["unicodeslot"]=0x05E3, -- ף }, [0x05E4]={ - ["adobename"]="afii0xE154", + ["adobename"]="afii57684", ["category"]="lo", ["contextname"]="hebrewPe", ["description"]="HEBREW LETTER PE", @@ -12361,7 +12374,7 @@ characters.data={ ["unicodeslot"]=0x05E4, -- פ }, [0x05E5]={ - ["adobename"]="afii0xE155", + ["adobename"]="afii57685", ["category"]="lo", ["contextname"]="hebrewTsadifinal", ["description"]="HEBREW LETTER FINAL TSADI", @@ -12369,7 +12382,7 @@ characters.data={ ["unicodeslot"]=0x05E5, -- ץ }, [0x05E6]={ - ["adobename"]="afii0xE156", + ["adobename"]="afii57686", ["category"]="lo", ["contextname"]="hebrewTsadi", ["description"]="HEBREW LETTER TSADI", @@ -12377,7 +12390,7 @@ characters.data={ ["unicodeslot"]=0x05E6, -- צ }, [0x05E7]={ - ["adobename"]="afii0xE157", + ["adobename"]="afii57687", ["category"]="lo", ["contextname"]="hebrewQof", ["description"]="HEBREW LETTER QOF", @@ -12385,7 +12398,7 @@ characters.data={ ["unicodeslot"]=0x05E7, -- ק }, [0x05E8]={ - ["adobename"]="afii0xE158", + ["adobename"]="afii57688", ["category"]="lo", ["contextname"]="hebrewResh", ["description"]="HEBREW LETTER RESH", @@ -12393,7 +12406,7 @@ characters.data={ ["unicodeslot"]=0x05E8, -- ר }, [0x05E9]={ - ["adobename"]="afii0xE159", + ["adobename"]="afii57689", ["category"]="lo", ["contextname"]="hebrewShin", ["description"]="HEBREW LETTER SHIN", @@ -12401,7 +12414,7 @@ characters.data={ ["unicodeslot"]=0x05E9, -- ש }, [0x05EA]={ - ["adobename"]="afii0xE15A", + ["adobename"]="afii57690", ["category"]="lo", ["contextname"]="hebrewTav", ["description"]="HEBREW LETTER TAV", @@ -12409,21 +12422,21 @@ characters.data={ ["unicodeslot"]=0x05EA, -- ת }, [0x05F0]={ - ["adobename"]="afii0xE174", + ["adobename"]="afii57716", ["category"]="lo", ["description"]="HEBREW LIGATURE YIDDISH DOUBLE VAV", ["linebreak"]="al", ["unicodeslot"]=0x05F0, -- װ }, [0x05F1]={ - ["adobename"]="afii0xE175", + ["adobename"]="afii57717", ["category"]="lo", ["description"]="HEBREW LIGATURE YIDDISH VAV YOD", ["linebreak"]="al", ["unicodeslot"]=0x05F1, -- ױ }, [0x05F2]={ - ["adobename"]="afii0xE176", + ["adobename"]="afii57718", ["category"]="lo", ["description"]="HEBREW LIGATURE YIDDISH DOUBLE YOD", ["linebreak"]="al", @@ -12472,7 +12485,7 @@ characters.data={ ["unicodeslot"]=0x060B, -- ؋ }, [0x060C]={ - ["adobename"]="afii0xE02C", + ["adobename"]="afii57388", ["category"]="po", ["description"]="ARABIC COMMA", ["linebreak"]="ex", @@ -12533,7 +12546,7 @@ characters.data={ ["unicodeslot"]=0x0615, -- ؕ }, [0x061B]={ - ["adobename"]="afii0xE03B", + ["adobename"]="afii57403", ["category"]="po", ["description"]="ARABIC SEMICOLON", ["linebreak"]="ex", @@ -12546,21 +12559,21 @@ characters.data={ ["unicodeslot"]=0x061E, -- ؞ }, [0x061F]={ - ["adobename"]="afii0xE03F", + ["adobename"]="afii57407", ["category"]="po", ["description"]="ARABIC QUESTION MARK", ["linebreak"]="ex", ["unicodeslot"]=0x061F, -- ؟ }, [0x0621]={ - ["adobename"]="afii0xE041", + ["adobename"]="afii57409", ["category"]="lo", ["description"]="ARABIC LETTER HAMZA", ["linebreak"]="al", ["unicodeslot"]=0x0621, -- ء }, [0x0622]={ - ["adobename"]="afii0xE042", + ["adobename"]="afii57410", ["category"]="lo", ["description"]="ARABIC LETTER ALEF WITH MADDA ABOVE", ["linebreak"]="al", @@ -12569,7 +12582,7 @@ characters.data={ ["unicodeslot"]=0x0622, -- آ }, [0x0623]={ - ["adobename"]="afii0xE043", + ["adobename"]="afii57411", ["category"]="lo", ["description"]="ARABIC LETTER ALEF WITH HAMZA ABOVE", ["linebreak"]="al", @@ -12578,7 +12591,7 @@ characters.data={ ["unicodeslot"]=0x0623, -- أ }, [0x0624]={ - ["adobename"]="afii0xE044", + ["adobename"]="afii57412", ["category"]="lo", ["description"]="ARABIC LETTER WAW WITH HAMZA ABOVE", ["linebreak"]="al", @@ -12587,7 +12600,7 @@ characters.data={ ["unicodeslot"]=0x0624, -- ؤ }, [0x0625]={ - ["adobename"]="afii0xE045", + ["adobename"]="afii57413", ["category"]="lo", ["description"]="ARABIC LETTER ALEF WITH HAMZA BELOW", ["linebreak"]="al", @@ -12596,7 +12609,7 @@ characters.data={ ["unicodeslot"]=0x0625, -- إ }, [0x0626]={ - ["adobename"]="afii0xE046", + ["adobename"]="afii57414", ["category"]="lo", ["description"]="ARABIC LETTER YEH WITH HAMZA ABOVE", ["linebreak"]="al", @@ -12605,273 +12618,273 @@ characters.data={ ["unicodeslot"]=0x0626, -- ئ }, [0x0627]={ - ["adobename"]="afii0xE047", + ["adobename"]="afii57415", ["category"]="lo", ["description"]="ARABIC LETTER ALEF", ["linebreak"]="al", ["unicodeslot"]=0x0627, -- ا }, [0x0628]={ - ["adobename"]="afii0xE048", + ["adobename"]="afii57416", ["category"]="lo", ["description"]="ARABIC LETTER BEH", ["linebreak"]="al", ["unicodeslot"]=0x0628, -- ب }, [0x0629]={ - ["adobename"]="afii0xE049", + ["adobename"]="afii57417", ["category"]="lo", ["description"]="ARABIC LETTER TEH MARBUTA", ["linebreak"]="al", ["unicodeslot"]=0x0629, -- ة }, [0x062A]={ - ["adobename"]="afii0xE04A", + ["adobename"]="afii57418", ["category"]="lo", ["description"]="ARABIC LETTER TEH", ["linebreak"]="al", ["unicodeslot"]=0x062A, -- ت }, [0x062B]={ - ["adobename"]="afii0xE04B", + ["adobename"]="afii57419", ["category"]="lo", ["description"]="ARABIC LETTER THEH", ["linebreak"]="al", ["unicodeslot"]=0x062B, -- ث }, [0x062C]={ - ["adobename"]="afii0xE04C", + ["adobename"]="afii57420", ["category"]="lo", ["description"]="ARABIC LETTER JEEM", ["linebreak"]="al", ["unicodeslot"]=0x062C, -- ج }, [0x062D]={ - ["adobename"]="afii0xE04D", + ["adobename"]="afii57421", ["category"]="lo", ["description"]="ARABIC LETTER HAH", ["linebreak"]="al", ["unicodeslot"]=0x062D, -- ح }, [0x062E]={ - ["adobename"]="afii0xE04E", + ["adobename"]="afii57422", ["category"]="lo", ["description"]="ARABIC LETTER KHAH", ["linebreak"]="al", ["unicodeslot"]=0x062E, -- خ }, [0x062F]={ - ["adobename"]="afii0xE04F", + ["adobename"]="afii57423", ["category"]="lo", ["description"]="ARABIC LETTER DAL", ["linebreak"]="al", ["unicodeslot"]=0x062F, -- د }, [0x0630]={ - ["adobename"]="afii0xE050", + ["adobename"]="afii57424", ["category"]="lo", ["description"]="ARABIC LETTER THAL", ["linebreak"]="al", ["unicodeslot"]=0x0630, -- ذ }, [0x0631]={ - ["adobename"]="afii0xE051", + ["adobename"]="afii57425", ["category"]="lo", ["description"]="ARABIC LETTER REH", ["linebreak"]="al", ["unicodeslot"]=0x0631, -- ر }, [0x0632]={ - ["adobename"]="afii0xE052", + ["adobename"]="afii57426", ["category"]="lo", ["description"]="ARABIC LETTER ZAIN", ["linebreak"]="al", ["unicodeslot"]=0x0632, -- ز }, [0x0633]={ - ["adobename"]="afii0xE053", + ["adobename"]="afii57427", ["category"]="lo", ["description"]="ARABIC LETTER SEEN", ["linebreak"]="al", ["unicodeslot"]=0x0633, -- س }, [0x0634]={ - ["adobename"]="afii0xE054", + ["adobename"]="afii57428", ["category"]="lo", ["description"]="ARABIC LETTER SHEEN", ["linebreak"]="al", ["unicodeslot"]=0x0634, -- ش }, [0x0635]={ - ["adobename"]="afii0xE055", + ["adobename"]="afii57429", ["category"]="lo", ["description"]="ARABIC LETTER SAD", ["linebreak"]="al", ["unicodeslot"]=0x0635, -- ص }, [0x0636]={ - ["adobename"]="afii0xE056", + ["adobename"]="afii57430", ["category"]="lo", ["description"]="ARABIC LETTER DAD", ["linebreak"]="al", ["unicodeslot"]=0x0636, -- ض }, [0x0637]={ - ["adobename"]="afii0xE057", + ["adobename"]="afii57431", ["category"]="lo", ["description"]="ARABIC LETTER TAH", ["linebreak"]="al", ["unicodeslot"]=0x0637, -- ط }, [0x0638]={ - ["adobename"]="afii0xE058", + ["adobename"]="afii57432", ["category"]="lo", ["description"]="ARABIC LETTER ZAH", ["linebreak"]="al", ["unicodeslot"]=0x0638, -- ظ }, [0x0639]={ - ["adobename"]="afii0xE059", + ["adobename"]="afii57433", ["category"]="lo", ["description"]="ARABIC LETTER AIN", ["linebreak"]="al", ["unicodeslot"]=0x0639, -- ع }, [0x063A]={ - ["adobename"]="afii0xE05A", + ["adobename"]="afii57434", ["category"]="lo", ["description"]="ARABIC LETTER GHAIN", ["linebreak"]="al", ["unicodeslot"]=0x063A, -- غ }, [0x0640]={ - ["adobename"]="afii0xE060", + ["adobename"]="afii57440", ["category"]="lm", ["description"]="ARABIC TATWEEL", ["linebreak"]="al", ["unicodeslot"]=0x0640, -- ـ }, [0x0641]={ - ["adobename"]="afii0xE061", + ["adobename"]="afii57441", ["category"]="lo", ["description"]="ARABIC LETTER FEH", ["linebreak"]="al", ["unicodeslot"]=0x0641, -- ف }, [0x0642]={ - ["adobename"]="afii0xE062", + ["adobename"]="afii57442", ["category"]="lo", ["description"]="ARABIC LETTER QAF", ["linebreak"]="al", ["unicodeslot"]=0x0642, -- ق }, [0x0643]={ - ["adobename"]="afii0xE063", + ["adobename"]="afii57443", ["category"]="lo", ["description"]="ARABIC LETTER KAF", ["linebreak"]="al", ["unicodeslot"]=0x0643, -- ك }, [0x0644]={ - ["adobename"]="afii0xE064", + ["adobename"]="afii57444", ["category"]="lo", ["description"]="ARABIC LETTER LAM", ["linebreak"]="al", ["unicodeslot"]=0x0644, -- ل }, [0x0645]={ - ["adobename"]="afii0xE065", + ["adobename"]="afii57445", ["category"]="lo", ["description"]="ARABIC LETTER MEEM", ["linebreak"]="al", ["unicodeslot"]=0x0645, -- م }, [0x0646]={ - ["adobename"]="afii0xE066", + ["adobename"]="afii57446", ["category"]="lo", ["description"]="ARABIC LETTER NOON", ["linebreak"]="al", ["unicodeslot"]=0x0646, -- ن }, [0x0647]={ - ["adobename"]="afii0xE07E", + ["adobename"]="afii57470", ["category"]="lo", ["description"]="ARABIC LETTER HEH", ["linebreak"]="al", ["unicodeslot"]=0x0647, -- ه }, [0x0648]={ - ["adobename"]="afii0xE068", + ["adobename"]="afii57448", ["category"]="lo", ["description"]="ARABIC LETTER WAW", ["linebreak"]="al", ["unicodeslot"]=0x0648, -- و }, [0x0649]={ - ["adobename"]="afii0xE069", + ["adobename"]="afii57449", ["category"]="lo", ["description"]="ARABIC LETTER ALEF MAKSURA", ["linebreak"]="al", ["unicodeslot"]=0x0649, -- ى }, [0x064A]={ - ["adobename"]="afii0xE06A", + ["adobename"]="afii57450", ["category"]="lo", ["description"]="ARABIC LETTER YEH", ["linebreak"]="al", ["unicodeslot"]=0x064A, -- ي }, [0x064B]={ - ["adobename"]="afii0xE06B", + ["adobename"]="afii57451", ["category"]="mn", ["description"]="ARABIC FATHATAN", ["linebreak"]="cm", ["unicodeslot"]=0x064B, -- ً }, [0x064C]={ - ["adobename"]="afii0xE06C", + ["adobename"]="afii57452", ["category"]="mn", ["description"]="ARABIC DAMMATAN", ["linebreak"]="cm", ["unicodeslot"]=0x064C, -- ٌ }, [0x064D]={ - ["adobename"]="afii0xE06D", + ["adobename"]="afii57453", ["category"]="mn", ["description"]="ARABIC KASRATAN", ["linebreak"]="cm", ["unicodeslot"]=0x064D, -- ٍ }, [0x064E]={ - ["adobename"]="afii0xE06E", + ["adobename"]="afii57454", ["category"]="mn", ["description"]="ARABIC FATHA", ["linebreak"]="cm", ["unicodeslot"]=0x064E, -- َ }, [0x064F]={ - ["adobename"]="afii0xE06F", + ["adobename"]="afii57455", ["category"]="mn", ["description"]="ARABIC DAMMA", ["linebreak"]="cm", ["unicodeslot"]=0x064F, -- ُ }, [0x0650]={ - ["adobename"]="afii0xE070", + ["adobename"]="afii57456", ["category"]="mn", ["description"]="ARABIC KASRA", ["linebreak"]="cm", ["unicodeslot"]=0x0650, -- ِ }, [0x0651]={ - ["adobename"]="afii0xE071", + ["adobename"]="afii57457", ["category"]="mn", ["description"]="ARABIC SHADDA", ["linebreak"]="cm", ["unicodeslot"]=0x0651, -- ّ }, [0x0652]={ - ["adobename"]="afii0xE072", + ["adobename"]="afii57458", ["category"]="mn", ["description"]="ARABIC SUKUN", ["linebreak"]="cm", @@ -12950,77 +12963,77 @@ characters.data={ ["unicodeslot"]=0x065E, -- ٞ }, [0x0660]={ - ["adobename"]="afii0xE030", + ["adobename"]="afii57392", ["category"]="nd", ["description"]="ARABIC-INDIC DIGIT ZERO", ["linebreak"]="nu", ["unicodeslot"]=0x0660, -- ٠ }, [0x0661]={ - ["adobename"]="afii0xE031", + ["adobename"]="afii57393", ["category"]="nd", ["description"]="ARABIC-INDIC DIGIT ONE", ["linebreak"]="nu", ["unicodeslot"]=0x0661, -- ١ }, [0x0662]={ - ["adobename"]="afii0xE032", + ["adobename"]="afii57394", ["category"]="nd", ["description"]="ARABIC-INDIC DIGIT TWO", ["linebreak"]="nu", ["unicodeslot"]=0x0662, -- ٢ }, [0x0663]={ - ["adobename"]="afii0xE033", + ["adobename"]="afii57395", ["category"]="nd", ["description"]="ARABIC-INDIC DIGIT THREE", ["linebreak"]="nu", ["unicodeslot"]=0x0663, -- ٣ }, [0x0664]={ - ["adobename"]="afii0xE034", + ["adobename"]="afii57396", ["category"]="nd", ["description"]="ARABIC-INDIC DIGIT FOUR", ["linebreak"]="nu", ["unicodeslot"]=0x0664, -- ٤ }, [0x0665]={ - ["adobename"]="afii0xE035", + ["adobename"]="afii57397", ["category"]="nd", ["description"]="ARABIC-INDIC DIGIT FIVE", ["linebreak"]="nu", ["unicodeslot"]=0x0665, -- ٥ }, [0x0666]={ - ["adobename"]="afii0xE036", + ["adobename"]="afii57398", ["category"]="nd", ["description"]="ARABIC-INDIC DIGIT SIX", ["linebreak"]="nu", ["unicodeslot"]=0x0666, -- ٦ }, [0x0667]={ - ["adobename"]="afii0xE037", + ["adobename"]="afii57399", ["category"]="nd", ["description"]="ARABIC-INDIC DIGIT SEVEN", ["linebreak"]="nu", ["unicodeslot"]=0x0667, -- ٧ }, [0x0668]={ - ["adobename"]="afii0xE038", + ["adobename"]="afii57400", ["category"]="nd", ["description"]="ARABIC-INDIC DIGIT EIGHT", ["linebreak"]="nu", ["unicodeslot"]=0x0668, -- ٨ }, [0x0669]={ - ["adobename"]="afii0xE039", + ["adobename"]="afii57401", ["category"]="nd", ["description"]="ARABIC-INDIC DIGIT NINE", ["linebreak"]="nu", ["unicodeslot"]=0x0669, -- ٩ }, [0x066A]={ - ["adobename"]="afii0xE025", + ["adobename"]="afii57381", ["category"]="po", ["description"]="ARABIC PERCENT SIGN", ["linebreak"]="ex", @@ -13039,7 +13052,7 @@ characters.data={ ["unicodeslot"]=0x066C, -- ٬ }, [0x066D]={ - ["adobename"]="afii0xF6BF", + ["adobename"]="afii63167", ["category"]="po", ["description"]="ARABIC FIVE POINTED STAR", ["linebreak"]="al", @@ -13119,7 +13132,7 @@ characters.data={ ["unicodeslot"]=0x0678, -- ٸ }, [0x0679]={ - ["adobename"]="afii0xE0A7", + ["adobename"]="afii57511", ["category"]="lo", ["description"]="ARABIC LETTER TTEH", ["linebreak"]="al", @@ -13152,7 +13165,7 @@ characters.data={ ["unicodeslot"]=0x067D, -- ٽ }, [0x067E]={ - ["adobename"]="afii0xE0A2", + ["adobename"]="afii57506", ["category"]="lo", ["description"]="ARABIC LETTER PEH", ["linebreak"]="al", @@ -13204,7 +13217,7 @@ characters.data={ ["unicodeslot"]=0x0685, -- څ }, [0x0686]={ - ["adobename"]="afii0xE0A3", + ["adobename"]="afii57507", ["category"]="lo", ["description"]="ARABIC LETTER TCHEH", ["linebreak"]="al", @@ -13217,7 +13230,7 @@ characters.data={ ["unicodeslot"]=0x0687, -- ڇ }, [0x0688]={ - ["adobename"]="afii0xE0A8", + ["adobename"]="afii57512", ["category"]="lo", ["description"]="ARABIC LETTER DDAL", ["linebreak"]="al", @@ -13277,7 +13290,7 @@ characters.data={ ["unicodeslot"]=0x0690, -- ڐ }, [0x0691]={ - ["adobename"]="afii0xE0A9", + ["adobename"]="afii57513", ["category"]="lo", ["description"]="ARABIC LETTER RREH", ["linebreak"]="al", @@ -13326,7 +13339,7 @@ characters.data={ ["unicodeslot"]=0x0697, -- ڗ }, [0x0698]={ - ["adobename"]="afii0xE0A4", + ["adobename"]="afii57508", ["category"]="lo", ["description"]="ARABIC LETTER JEH", ["linebreak"]="al", @@ -13409,7 +13422,7 @@ characters.data={ ["unicodeslot"]=0x06A3, -- ڣ }, [0x06A4]={ - ["adobename"]="afii0xE0A1", + ["adobename"]="afii57505", ["category"]="lo", ["description"]="ARABIC LETTER VEH", ["linebreak"]="al", @@ -13482,7 +13495,7 @@ characters.data={ ["unicodeslot"]=0x06AE, -- ڮ }, [0x06AF]={ - ["adobename"]="afii0xE0A5", + ["adobename"]="afii57509", ["category"]="lo", ["description"]="ARABIC LETTER GAF", ["linebreak"]="al", @@ -13557,7 +13570,7 @@ characters.data={ ["unicodeslot"]=0x06B9, -- ڹ }, [0x06BA]={ - ["adobename"]="afii0xE0AA", + ["adobename"]="afii57514", ["category"]="lo", ["description"]="ARABIC LETTER NOON GHUNNA", ["linebreak"]="al", @@ -13714,7 +13727,7 @@ characters.data={ ["unicodeslot"]=0x06D1, -- ۑ }, [0x06D2]={ - ["adobename"]="afii0xE0AF", + ["adobename"]="afii57519", ["category"]="lo", ["description"]="ARABIC LETTER YEH BARREE", ["linebreak"]="al", @@ -13734,7 +13747,7 @@ characters.data={ ["unicodeslot"]=0x06D4, -- ۔ }, [0x06D5]={ - ["adobename"]="afii0xE0BE", + ["adobename"]="afii57534", ["category"]="lo", ["description"]="ARABIC LETTER AE", ["linebreak"]="al", @@ -42607,28 +42620,28 @@ characters.data={ ["unicodeslot"]=0x200B, -- ​ }, [0x200C]={ - ["adobename"]="afii0xF0E0", + ["adobename"]="afii61664", ["category"]="cf", ["description"]="ZERO WIDTH NON-JOINER", ["linebreak"]="cm", ["unicodeslot"]=0x200C, -- ‌ }, [0x200D]={ - ["adobename"]="afii0x012D", + ["adobename"]="afii301", ["category"]="cf", ["description"]="ZERO WIDTH JOINER", ["linebreak"]="cm", ["unicodeslot"]=0x200D, -- ‍ }, [0x200E]={ - ["adobename"]="afii0x012B", + ["adobename"]="afii299", ["category"]="cf", ["description"]="LEFT-TO-RIGHT MARK", ["linebreak"]="cm", ["unicodeslot"]=0x200E, -- ‎ }, [0x200F]={ - ["adobename"]="afii0x012C", + ["adobename"]="afii300", ["category"]="cf", ["description"]="RIGHT-TO-LEFT MARK", ["linebreak"]="cm", @@ -42671,11 +42684,11 @@ characters.data={ ["cjkwd"]="a", ["contextname"]="emdash", ["description"]="EM DASH", - ["linebreak"]="b0x0002", + ["linebreak"]="b2", ["unicodeslot"]=0x2014, -- — }, [0x2015]={ - ["adobename"]="afii0x00D0", + ["adobename"]="afii208", ["category"]="pd", ["cjkwd"]="a", ["contextname"]="texthorizontalbar", @@ -42856,21 +42869,21 @@ characters.data={ ["unicodeslot"]=0x202B, -- ‫ }, [0x202C]={ - ["adobename"]="afii0xF085", + ["adobename"]="afii61573", ["category"]="cf", ["description"]="POP DIRECTIONAL FORMATTING", ["linebreak"]="cm", ["unicodeslot"]=0x202C, -- ‬ }, [0x202D]={ - ["adobename"]="afii0xF086", + ["adobename"]="afii61574", ["category"]="cf", ["description"]="LEFT-TO-RIGHT OVERRIDE", ["linebreak"]="cm", ["unicodeslot"]=0x202D, -- ‭ }, [0x202E]={ - ["adobename"]="afii0xF087", + ["adobename"]="afii61575", ["category"]="cf", ["description"]="RIGHT-TO-LEFT OVERRIDE", ["linebreak"]="cm", @@ -43571,7 +43584,7 @@ characters.data={ ["unicodeslot"]=0x20A9, -- ₩ }, [0x20AA]={ - ["adobename"]="afii0xE124", + ["adobename"]="afii57636", ["category"]="sc", ["description"]="NEW SHEQEL SIGN", ["linebreak"]="pr", @@ -43876,7 +43889,7 @@ characters.data={ ["unicodeslot"]=0x2104, -- ℄ }, [0x2105]={ - ["adobename"]="afii0xEF40", + ["adobename"]="afii61248", ["category"]="so", ["cjkwd"]="a", ["description"]="CARE OF", @@ -43977,7 +43990,7 @@ characters.data={ ["unicodeslot"]=0x2112, -- ℒ }, [0x2113]={ - ["adobename"]="afii0xEF69", + ["adobename"]="afii61289", ["category"]="ll", ["cjkwd"]="a", ["description"]="SCRIPT SMALL L", @@ -44001,7 +44014,7 @@ characters.data={ ["unicodeslot"]=0x2115, -- ℕ }, [0x2116]={ - ["adobename"]="afii0xEFA8", + ["adobename"]="afii61352", ["category"]="so", ["cjkwd"]="a", ["contextname"]="textnumero", @@ -50251,7 +50264,7 @@ characters.data={ ["unicodeslot"]=0x24FF, -- ⓿ }, [0x2500]={ - ["adobename"]="SF0x186A0", + ["adobename"]="SF100000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT HORIZONTAL", @@ -50266,7 +50279,7 @@ characters.data={ ["unicodeslot"]=0x2501, -- ━ }, [0x2502]={ - ["adobename"]="SF0x1ADB0", + ["adobename"]="SF110000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT VERTICAL", @@ -50337,7 +50350,7 @@ characters.data={ ["unicodeslot"]=0x250B, -- ┋ }, [0x250C]={ - ["adobename"]="SF0x2710", + ["adobename"]="SF10000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT DOWN AND RIGHT", @@ -50366,7 +50379,7 @@ characters.data={ ["unicodeslot"]=0x250F, -- ┏ }, [0x2510]={ - ["adobename"]="SF0x7530", + ["adobename"]="SF30000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT DOWN AND LEFT", @@ -50395,7 +50408,7 @@ characters.data={ ["unicodeslot"]=0x2513, -- ┓ }, [0x2514]={ - ["adobename"]="SF0x4E20", + ["adobename"]="SF20000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT UP AND RIGHT", @@ -50424,7 +50437,7 @@ characters.data={ ["unicodeslot"]=0x2517, -- ┗ }, [0x2518]={ - ["adobename"]="SF0x9C40", + ["adobename"]="SF40000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT UP AND LEFT", @@ -50453,7 +50466,7 @@ characters.data={ ["unicodeslot"]=0x251B, -- ┛ }, [0x251C]={ - ["adobename"]="SF0x13880", + ["adobename"]="SF80000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT VERTICAL AND RIGHT", @@ -50510,7 +50523,7 @@ characters.data={ ["unicodeslot"]=0x2523, -- ┣ }, [0x2524]={ - ["adobename"]="SF0x15F90", + ["adobename"]="SF90000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT VERTICAL AND LEFT", @@ -50567,7 +50580,7 @@ characters.data={ ["unicodeslot"]=0x252B, -- ┫ }, [0x252C]={ - ["adobename"]="SF0xEA60", + ["adobename"]="SF60000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT DOWN AND HORIZONTAL", @@ -50624,7 +50637,7 @@ characters.data={ ["unicodeslot"]=0x2533, -- ┳ }, [0x2534]={ - ["adobename"]="SF0x11170", + ["adobename"]="SF70000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT UP AND HORIZONTAL", @@ -50681,7 +50694,7 @@ characters.data={ ["unicodeslot"]=0x253B, -- ┻ }, [0x253C]={ - ["adobename"]="SF0xC350", + ["adobename"]="SF50000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL", @@ -50818,7 +50831,7 @@ characters.data={ ["unicodeslot"]=0x254F, -- ╏ }, [0x2550]={ - ["adobename"]="SF0x68FB0", + ["adobename"]="SF430000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE HORIZONTAL", @@ -50826,7 +50839,7 @@ characters.data={ ["unicodeslot"]=0x2550, -- ═ }, [0x2551]={ - ["adobename"]="SF0x3A980", + ["adobename"]="SF240000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE VERTICAL", @@ -50834,7 +50847,7 @@ characters.data={ ["unicodeslot"]=0x2551, -- ║ }, [0x2552]={ - ["adobename"]="SF0x7C830", + ["adobename"]="SF510000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE", @@ -50842,7 +50855,7 @@ characters.data={ ["unicodeslot"]=0x2552, -- ╒ }, [0x2553]={ - ["adobename"]="SF0x7EF40", + ["adobename"]="SF520000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE", @@ -50850,7 +50863,7 @@ characters.data={ ["unicodeslot"]=0x2553, -- ╓ }, [0x2554]={ - ["adobename"]="SF0x5F370", + ["adobename"]="SF390000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE DOWN AND RIGHT", @@ -50858,7 +50871,7 @@ characters.data={ ["unicodeslot"]=0x2554, -- ╔ }, [0x2555]={ - ["adobename"]="SF0x35B60", + ["adobename"]="SF220000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE", @@ -50866,7 +50879,7 @@ characters.data={ ["unicodeslot"]=0x2555, -- ╕ }, [0x2556]={ - ["adobename"]="SF0x33450", + ["adobename"]="SF210000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE", @@ -50874,7 +50887,7 @@ characters.data={ ["unicodeslot"]=0x2556, -- ╖ }, [0x2557]={ - ["adobename"]="SF0x3D090", + ["adobename"]="SF250000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE DOWN AND LEFT", @@ -50882,7 +50895,7 @@ characters.data={ ["unicodeslot"]=0x2557, -- ╗ }, [0x2558]={ - ["adobename"]="SF0x7A120", + ["adobename"]="SF500000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE", @@ -50890,7 +50903,7 @@ characters.data={ ["unicodeslot"]=0x2558, -- ╘ }, [0x2559]={ - ["adobename"]="SF0x77A10", + ["adobename"]="SF490000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE", @@ -50898,7 +50911,7 @@ characters.data={ ["unicodeslot"]=0x2559, -- ╙ }, [0x255A]={ - ["adobename"]="SF0x5CC60", + ["adobename"]="SF380000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE UP AND RIGHT", @@ -50906,7 +50919,7 @@ characters.data={ ["unicodeslot"]=0x255A, -- ╚ }, [0x255B]={ - ["adobename"]="SF0x445C0", + ["adobename"]="SF280000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS UP SINGLE AND LEFT DOUBLE", @@ -50914,7 +50927,7 @@ characters.data={ ["unicodeslot"]=0x255B, -- ╛ }, [0x255C]={ - ["adobename"]="SF0x41EB0", + ["adobename"]="SF270000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS UP DOUBLE AND LEFT SINGLE", @@ -50922,7 +50935,7 @@ characters.data={ ["unicodeslot"]=0x255C, -- ╜ }, [0x255D]={ - ["adobename"]="SF0x3F7A0", + ["adobename"]="SF260000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE UP AND LEFT", @@ -50930,7 +50943,7 @@ characters.data={ ["unicodeslot"]=0x255D, -- ╝ }, [0x255E]={ - ["adobename"]="SF0x57E40", + ["adobename"]="SF360000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE", @@ -50938,7 +50951,7 @@ characters.data={ ["unicodeslot"]=0x255E, -- ╞ }, [0x255F]={ - ["adobename"]="SF0x5A550", + ["adobename"]="SF370000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE", @@ -50946,7 +50959,7 @@ characters.data={ ["unicodeslot"]=0x255F, -- ╟ }, [0x2560]={ - ["adobename"]="SF0x668A0", + ["adobename"]="SF420000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE VERTICAL AND RIGHT", @@ -50954,7 +50967,7 @@ characters.data={ ["unicodeslot"]=0x2560, -- ╠ }, [0x2561]={ - ["adobename"]="SF0x2E630", + ["adobename"]="SF190000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE", @@ -50962,7 +50975,7 @@ characters.data={ ["unicodeslot"]=0x2561, -- ╡ }, [0x2562]={ - ["adobename"]="SF0x30D40", + ["adobename"]="SF200000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE", @@ -50970,7 +50983,7 @@ characters.data={ ["unicodeslot"]=0x2562, -- ╢ }, [0x2563]={ - ["adobename"]="SF0x38270", + ["adobename"]="SF230000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE VERTICAL AND LEFT", @@ -50978,7 +50991,7 @@ characters.data={ ["unicodeslot"]=0x2563, -- ╣ }, [0x2564]={ - ["adobename"]="SF0x72BF0", + ["adobename"]="SF470000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE", @@ -50986,7 +50999,7 @@ characters.data={ ["unicodeslot"]=0x2564, -- ╤ }, [0x2565]={ - ["adobename"]="SF0x75300", + ["adobename"]="SF480000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE", @@ -50994,7 +51007,7 @@ characters.data={ ["unicodeslot"]=0x2565, -- ╥ }, [0x2566]={ - ["adobename"]="SF0x64190", + ["adobename"]="SF410000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL", @@ -51002,7 +51015,7 @@ characters.data={ ["unicodeslot"]=0x2566, -- ╦ }, [0x2567]={ - ["adobename"]="SF0x6DDD0", + ["adobename"]="SF450000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE", @@ -51010,7 +51023,7 @@ characters.data={ ["unicodeslot"]=0x2567, -- ╧ }, [0x2568]={ - ["adobename"]="SF0x704E0", + ["adobename"]="SF460000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE", @@ -51018,7 +51031,7 @@ characters.data={ ["unicodeslot"]=0x2568, -- ╨ }, [0x2569]={ - ["adobename"]="SF0x61A80", + ["adobename"]="SF400000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE UP AND HORIZONTAL", @@ -51026,7 +51039,7 @@ characters.data={ ["unicodeslot"]=0x2569, -- ╩ }, [0x256A]={ - ["adobename"]="SF0x83D60", + ["adobename"]="SF540000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE", @@ -51034,7 +51047,7 @@ characters.data={ ["unicodeslot"]=0x256A, -- ╪ }, [0x256B]={ - ["adobename"]="SF0x81650", + ["adobename"]="SF530000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE", @@ -51042,7 +51055,7 @@ characters.data={ ["unicodeslot"]=0x256B, -- ╫ }, [0x256C]={ - ["adobename"]="SF0x6B6C0", + ["adobename"]="SF440000", ["category"]="so", ["cjkwd"]="a", ["description"]="BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL", @@ -51399,7 +51412,7 @@ characters.data={ ["unicodeslot"]=0x25A0, -- ■ }, [0x25A1]={ - ["adobename"]="H0x5639", + ["adobename"]="H22073", ["category"]="so", ["cjkwd"]="a", ["description"]="WHITE SQUARE", @@ -51462,14 +51475,14 @@ characters.data={ ["unicodeslot"]=0x25A9, -- ▩ }, [0x25AA]={ - ["adobename"]="H0x486F", + ["adobename"]="H18543", ["category"]="so", ["description"]="BLACK SMALL SQUARE", ["linebreak"]="al", ["unicodeslot"]=0x25AA, -- ▪ }, [0x25AB]={ - ["adobename"]="H0x4877", + ["adobename"]="H18551", ["category"]="so", ["description"]="WHITE SMALL SQUARE", ["linebreak"]="al", @@ -51706,7 +51719,7 @@ characters.data={ ["unicodeslot"]=0x25CE, -- ◎ }, [0x25CF]={ - ["adobename"]="H0x4865", + ["adobename"]="H18533", ["category"]="so", ["cjkwd"]="a", ["description"]="BLACK CIRCLE", @@ -81796,14 +81809,14 @@ characters.data={ ["category"]="lo", ["cjkwd"]="w", ["description"]="", - ["linebreak"]="h0x0002", + ["linebreak"]="h2", ["unicodeslot"]=0xAC00, -- 가 }, [0xD7A3]={ ["category"]="lo", ["cjkwd"]="w", ["description"]="", - ["linebreak"]="h0x0003", + ["linebreak"]="h3", ["unicodeslot"]=0xD7A3, -- 힣 }, [0xD800]={ @@ -85591,6 +85604,7 @@ characters.data={ ["contextname"]="filigature", ["description"]="LATIN SMALL LIGATURE FI", ["linebreak"]="al", + ["shcode"]={ 0x0066, 0x0069 }, ["specials"]={ "compat", 0x0066, 0x0069 }, ["unicodeslot"]=0xFB01, -- fi }, @@ -85599,6 +85613,7 @@ characters.data={ ["contextname"]="flligature", ["description"]="LATIN SMALL LIGATURE FL", ["linebreak"]="al", + ["shcode"]={ 0x0066, 0x006C }, ["specials"]={ "compat", 0x0066, 0x006C }, ["unicodeslot"]=0xFB02, -- fl }, @@ -85607,6 +85622,7 @@ characters.data={ ["contextname"]="ffiligature", ["description"]="LATIN SMALL LIGATURE FFI", ["linebreak"]="al", + ["shcode"]={ 0x0066, 0x0069 }, ["specials"]={ "compat", 0x0066, 0x0066, 0x0069 }, ["unicodeslot"]=0xFB03, -- ffi }, @@ -85615,6 +85631,7 @@ characters.data={ ["contextname"]="fflligature", ["description"]="LATIN SMALL LIGATURE FFL", ["linebreak"]="al", + ["shcode"]={ 0x0066, 0x006C }, ["specials"]={ "compat", 0x0066, 0x0066, 0x006C }, ["unicodeslot"]=0xFB04, -- ffl }, @@ -85630,6 +85647,7 @@ characters.data={ ["contextname"]="stligature", ["description"]="LATIN SMALL LIGATURE ST", ["linebreak"]="al", + ["shcode"]={ 0x0073, 0x0074 }, ["specials"]={ "compat", 0x0073, 0x0074 }, ["unicodeslot"]=0xFB06, -- st }, diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua index 8f8f8dc26..4750e929a 100644 --- a/tex/context/base/char-ini.lua +++ b/tex/context/base/char-ini.lua @@ -94,14 +94,15 @@ table we derive a few more.

-- used ? -characters.context.unicodes = characters.context.unicodes or { } -characters.context.utfcodes = characters.context.utfcodes or { } -characters.context.enccodes = characters.context.enccodes or { } +characters.context.unicodes = characters.context.unicodes or { } +characters.context.utfcodes = characters.context.utfcodes or { } +characters.context.enccodes = characters.context.enccodes or { } +characters.context.fallbacks = characters.context.fallbacks or { } function characters.context.rehash() - local unicodes, utfcodes, enccodes, utfchar = characters.context.unicodes, characters.context.utfcodes, characters.context.enccodes, utf.char + local unicodes, utfcodes, enccodes, fallbacks, utfchar = characters.context.unicodes, characters.context.utfcodes, characters.context.enccodes, characters.context.fallbacks, utf.char for k,v in pairs(characters.data) do - local contextname, adobename = v.contextname, v.adobename + local contextname, adobename, specials = v.contextname, v.adobename, v.specials if contextname then local slot = v.unicodeslot unicodes[contextname] = slot @@ -111,6 +112,11 @@ function characters.context.rehash() if encname then enccodes[encname] = k end + if specials and specials[1] == "compat" and specials[2] == 0x0020 and specials[3] then + local s = specials[3] + fallbacks[k] = s + fallbacks[s] = k + end end for name,code in pairs(characters.synonyms) do if not enccodes[name] then enccodes[name] = code end @@ -319,15 +325,23 @@ function characters.uccode(n) return characters.data[n].uccode or n end function characters.lccode(n) return characters.data[n].lccode or n end function characters.flush(n) - if characters.data[n].contextname then - tex.sprint(tex.texcatcodes, "\\"..characters.data[n].contextname) + local c = characters.data[n] + if c and c.contextname then + tex.sprint(tex.texcatcodes, "\\"..c.contextname) else tex.sprint(unicode.utf8.char(n)) end end function characters.shape(n) - return characters.data[n].shcode or n + local shcode = characters.data[n].shcode + if not shcode then + return n, nil + elseif type(shcode) == "table" then + return shcode[1], shcode[#shcode] + else + return shcode, nil + end end --[[ldx-- @@ -358,12 +372,12 @@ unicode reference tables.

--ldx]]-- function characters.setpdfunicodes() - local flush, tc, sf = tex.sprint, tex.ctxcatcodes, string.format - for _,v in pairs(characters.data) do - if v.adobename then - flush(tc,sf("\\pdfglyphtounicode{%s}{%04X}", v.adobename, v.unicodeslot)) - end - end +--~ local flush, tc, sf = tex.sprint, tex.ctxcatcodes, string.format +--~ for _,v in pairs(characters.data) do +--~ if v.adobename then +--~ flush(tc,sf("\\pdfglyphtounicode{%s}{%04X}", v.adobename, v.unicodeslot)) +--~ end +--~ end end --[[ldx-- @@ -377,21 +391,21 @@ characters.pdftex.make_pdf_to_unicodetable("pdfr-def.tex") characters.pdftex = characters.pdftex or { } function characters.pdftex.make_pdf_to_unicodetable(filename) - local sf = string.format - f = io.open(filename,'w') - if f then - f:write("% This file is generated with Luatex using the\n") - f:write("% character tables that come with ConTeXt MkIV.\n") - f:write("%\n") - f:write("\\ifx\\pdfglyphtounicode\\undefined\\endinput\\fi\n") -- just to be sure - for _, v in pairs(characters.data) do - if v.adobename then - f:write(sf("\\pdfglyphtounicode{%s}{%04X}", v.adobename, v.unicodeslot)) - end - end - f:write("%\n") - f:write("%\n") - f:write("\\endinput") - f:close() - end +--~ local sf = string.format +--~ f = io.open(filename,'w') +--~ if f then +--~ f:write("% This file is generated with Luatex using the\n") +--~ f:write("% character tables that come with ConTeXt MkIV.\n") +--~ f:write("%\n") +--~ f:write("\\ifx\\pdfglyphtounicode\\undefined\\endinput\\fi\n") -- just to be sure +--~ for _, v in pairs(characters.data) do +--~ if v.adobename then +--~ f:write(sf("\\pdfglyphtounicode{%s}{%04X}", v.adobename, v.unicodeslot)) +--~ end +--~ end +--~ f:write("%\n") +--~ f:write("%\n") +--~ f:write("\\endinput") +--~ f:close() +--~ end end diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv index 14472000f..550a96ea9 100644 --- a/tex/context/base/cont-new.mkiv +++ b/tex/context/base/cont-new.mkiv @@ -73,6 +73,12 @@ \def\elapsedtime {\ctxlua{tex.sprint(os.clock()-environment.starttime)}} \let\elapsedseconds \elapsedtime +\resettimer + +% \appendtoks +% \resettimer +% \to \everyjob + %D For me. \def\traceluausage diff --git a/tex/context/base/cont-sys.ori b/tex/context/base/cont-sys.ori index b90662cc3..335a7d984 100644 --- a/tex/context/base/cont-sys.ori +++ b/tex/context/base/cont-sys.ori @@ -121,6 +121,7 @@ % When you have your own fonts installed, you may want to predefine: % % \usetypescriptfile[type-buy] +% \usetypescriptfile [type-gyr] % Some styles default to Lucida Bright. You can overload % Lucida by Times cum suis. Watch out, the pos collection diff --git a/tex/context/base/context-characters.lmx b/tex/context/base/context-characters.lmx new file mode 100644 index 000000000..b992d30b8 --- /dev/null +++ b/tex/context/base/context-characters.lmx @@ -0,0 +1,104 @@ + + + <?lua pv('title') ?> + + + + +
+ +
+
+ +
+ + +
+ + +
     
+
characters     
+
unicodes     
+
indices     
+
fonts     
+ + +
     
+
before utf     
+
after utf     
+
before hex     
+
after hex     
+
after hex     
+
after dec     
+
filename     
+ + + + +
+
     
+
     
+
     
+
     
+
     
+
     
+
     
+ + + + +
+ + + + + + + + +

Processed Words

+ + + + + + + +
+
+ +
+
+ Job Name:     + ConTeXt Version:     +
+ + diff --git a/tex/context/base/context-debug.lmx b/tex/context/base/context-debug.lmx index 88ca0b450..593f35672 100644 --- a/tex/context/base/context-debug.lmx +++ b/tex/context/base/context-debug.lmx @@ -43,7 +43,7 @@
- +

Scratch Variables

@@ -52,12 +52,12 @@ - + - - - + + +
   count    toks
                  
@@ -72,26 +72,26 @@ -
-
-
+
+
+
- +

Internal Variables

- +

- +

ConTeXt Variables

- +
@@ -101,8 +101,8 @@
Job Name:     ConTeXt Version:     - Real Page:     - Page:     + Real Page:     + Page:    
diff --git a/tex/context/base/context-error.lmx b/tex/context/base/context-error.lmx index 075c43073..df3ad9090 100644 --- a/tex/context/base/context-error.lmx +++ b/tex/context/base/context-error.lmx @@ -48,8 +48,8 @@
Job Name:     ConTeXt Version:     - Real Page:     - Page:     + Real Page:     + Page:    
diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex index 449d667f4..d90783726 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{2008.01.28 21:28} +\edef\contextversion{2008.03.10 23:20} %D For those who want to use this: @@ -469,6 +469,7 @@ \loadcorefile{core-mis.tex} \loadcorefile{core-trf.tex} +\loadcorefile{core-inc.tex} \loadcorefile{core-fig.tex} \loadcorefile{core-par.tex} diff --git a/tex/context/base/core-buf.lua b/tex/context/base/core-buf.lua index 081655a72..384a5608e 100644 --- a/tex/context/base/core-buf.lua +++ b/tex/context/base/core-buf.lua @@ -58,6 +58,10 @@ function buffers.grab(name,begintag,endtag,data) cs.testcase(more) end +function buffers.exists(name) + return buffers.data[name] ~= nil +end + function buffers.doifelsebuffer(name) cs.testcase(buffers.data[name] ~= nil) end diff --git a/tex/context/base/core-fig.tex b/tex/context/base/core-fig.tex index 975d9429a..f701c0c9f 100644 --- a/tex/context/base/core-fig.tex +++ b/tex/context/base/core-fig.tex @@ -11,171 +11,10 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% todo: directory : system -> \allinputpaths (so that we can \usesubpath) - -%D It may be that some functionality got lost. If it concerns -%D defined features, let me know and it will be sorted out. - -\writestatus{loading}{Context Core Macros / Figure Inclusion} - -%D This is a reimplementation of the original module, which -%D over time had evolved into a pretty complex whole. This -%D was partly due to the fact that we needed to handle many -%D formats, deal with substitute graphics, handle fallbacks -%D and driver specifics (objects), etc. In the meantime we -%D have more clever backends, moved away from texutil to -%D rlxtools, can use runtime or betweentime runs etc. Also, -%D more memory permits a cleaner implementation. Time to -%D move on. We can now also assume that scaling is available. -%D -%D Another mess that can go is the llx/lly handling since -%D drivers now automatically can determine such things. - -%D Messages 3 and 5 needs to be translated! +\writestatus{loading}{Context Core Macros / Figure Handling} \unprotect -\startmessages dutch library: figures - title: figuren - 1: figuur -- is niet te vinden - 2: figuur -- wordt niet preset - 3: maten van -- worden extern vastgesteld - 4: maten van -- geladen uit figuurfile zelf - 5: maten van -- zijn onbekend - 6: maten van -- berekend door rlxtools - 8: figuurobject -- wordt opnieuw gebruikt -\stopmessages - -\startmessages english library: figures - title: figures - 1: figure -- can not be found - 2: figure -- is not preset - 3: dimensions of -- are determined externally - 4: dimensions of -- loaded from figurefile itself - 5: dimensions of -- are unknown - 6: dimensions of -- calculated by rlxtools - 8: figureobject -- is reused -\stopmessages - -\startmessages german library: figures - title: Abbildungen - 1: Abbildung -- kann nicht gefunden werden - 2: Abbildung -- wird nicht erstellt - 3: dimensions of -- are determined externally - 4: Dimensionen von -- geladen aus der Abbildungsdatei selbst - 5: Dimensions of -- are unknown - 6: Dimensionen von -- ausgerechnet durch rlxtools - 8: Abbildungobjekt -- wurde wiederverwandt -\stopmessages - -\startmessages czech library: figures - title: obrazy - 1: obraz -- nelze nalezt - 2: obraz -- nepritomen - 3: dimensions of -- are determined externally - 4: dimenze obrazu -- nacteny primo z jeho souboru - 5: dimensions of -- are unknown - 6: dimenze obrazu -- spocteny programem rlxtools - 8: obrazovy objekt -- je znovu pouzit -\stopmessages - -\startmessages italian library: figures - title: figure - 1: figura -- non trovata - 2: la figura -- non è preimpostata - 3: dimensions of -- are determined externally - 4: dimensioni di -- caricate dal file di immagini stesso - 5: dimensions of -- are unknown - 6: dimensioni di -- calcolate da rlxtools - 8: oggetto-figura -- riutilizzato -\stopmessages - -\startmessages romanian library: figures - title: figuri - 1: figura -- nu poate fi gasita - 2: figura -- nu este presetata - 3: dimensions of -- are determined externally - 4: dimensiunea figurii -- se incarca din fisierul insusi - 5: dimensions of -- are unknown - 6: dimensiunea figurii -- este calculata de rlxtools - 8: obiectul figura -- este refolosit -\stopmessages - -\startmessages french library: figures - title: figures - 1: la figure -- ne peut être trouvée - 2: la figure -- n'est pas pré-sélectionnée - 3: dimensions of -- are determined externally - 4: les dimensions de -- chargées implicitement à partir du fichier de figure - 5: dimensions of -- are unknown - 6: les dimensions de -- calculées par rlxtools - 8: figureobject -- est réutilisé -\stopmessages - -%D Due to the mere fact that \DVI|/|\PDF\ drivers differ in their -%D needs for figure dimensions, we have to provide the width, -%D height, horizontal and vertical scale. Also we want to -%D specify at the user level either width and|/|or height, scale, -%D or a factor related to the current document bodyfont size. -%D Even better: we can also specify isometric scaling and -%D automatically let \CONTEXT\ calculate the maximum possible -%D dimensions. Whatever we calculate, the results will come -%D available in the next registers. - -\letempty \@@DriverImageBox -\letempty \@@DriverImageOptions -\letempty \@@DriverImageWidth -\letempty \@@DriverImageHeight -\letempty \@@DriverImageFile -\letempty \@@DriverImageLabel -\letempty \@@DriverImageType -\letempty \@@DriverImageMethod -\letempty \@@DriverImagePage - -%D Because looking for dimensions can take many steps (locating -%D the figure, maybe on more directories, scanning the figure -%D on dimension, or when not found, trying to find them in the -%D utility file, and again when not found, trying to generate -%D such a file, and, as a last resort, trying to use the -%D dimensions. Now when things do not work out the way we want, -%D we can set a switch and get some information on what takes -%D place. - -\newif\iftraceexternalfigures - -\let\traceexternalfigures\traceexternalfigurestrue - -\def\doshowfigurestate - {\iftraceexternalfigures - \expandafter\writestatus\expandafter\m!figures - \else - \expandafter\gobbleoneargument - \fi} - -\def\doshowfiguremessage - {\iftraceexternalfigures - \expandafter\gobbletwoarguments - \else - \expandafter\showmessage\expandafter\m!figures - \fi} - -%D Another switch tells \CONTEXT\ to locate and calculate a -%D figure, but does not actually insert it. Especially when we -%D use \PDFTEX\ this saves a lot of time on trialruns. (Keep -%D in mind that \PDFTEX\ is both a \TEX\ pre|| and postprocessor.) - -\newif\ifskipexternalfigures % can be set elsewhere - -% \newif\ifrunutilityfile -% \newif\ifconsultutilityfile -% -% Let's save two hash entries: - -\let\runutilityfiletrue \relax \let\runutilityfilefalse \relax -\let\consultutilityfiletrue\relax \let\consultutilityfilefalse\relax - -%D The basic setup. - \def\setupexternalfigures {\dosingleempty\dosetupexternalfigures} @@ -184,663 +23,24 @@ \getparameters[\??ex][#1]% global settings \setfigurepathlist} % the path may be used elsewhere too (as in x-res-04) -%D Intermediate, private. - -\newdimen\determinedfigurewidth -\newdimen\determinedfigureheight - -\let\naturalfigureheight\!!zeropoint -\let\naturalfigurewidth \!!zeropoint - -\def\defaultfigurewidth {8\lineheight} -\def\defaultfigureheight{6\lineheight} - -\def\defaultfigurepathsignal{(\v!default)} - -\def\checknaturalfiguredimensions - {\edef\naturalfigurewidth{\the\dimexpr\ifzeropt\determinedfigurewidth - \defaultfigurewidth \else\determinedfigurewidth \fi\relax}% - \edef\naturalfigureheight{\the\dimexpr\ifzeropt\determinedfigureheight - \defaultfigureheight\else\determinedfigureheight\fi\relax}} - -%D Locating figures. Dilemma: we do support eps and svg parsing but drivers -%D don't always support it. - -\def\figuretypes{\c!mps,\c!pdf,\c!eps,\c!svg,\c!svg z,\c!png,\c!tif,jb2,\c!jpg} - -\def\supportedfiguretypes{\figuretypes} - -\def\checksupportedfiguretypes - {\begingroup - \global\let\supportedfiguretypes\empty - \def\docommand##1% - {\doiffileinsertionsupportedelse{##1} - {\doglobal\addtocommalist{##1}\supportedfiguretypes} - \donothing}% - \processcommacommand[\figuretypes]\docommand - \gdef\checksupportedfiguretypes{\let\figuretypes\supportedfiguretypes}% - \endgroup - \checksupportedfiguretypes} - -%D The next box is used to store the graphic. It's globally assigned. - -\newbox\foundexternalfigure - -\chardef\figurestatus\zerocount % nothing found - -\def\noffigurepages{\nofinsertpages} - -%D Variables. - -\newtoks\everyexternalfigureresets - -\def\resetfigurevariables - {\the\everyexternalfigureresets} - -%D Example usage: - -\appendtoks - \global\let\externalfigurelog\empty -\to\everyexternalfigureresets - -%D Intermediate, private - -\def\resetprivatefigurevariables - {\let \wantedfigurefull \empty - \let \wantedfigurepath \empty - \let \wantedfigurename \empty - \let \wantedfigurebase \empty - \let \wantedfiguretype \empty - \let \wantedfigurefullname \empty - \let \wantedfiguretypespec \empty - \let \wantedfiguremethod \empty - \let \wantedfigurepage \empty - \let \wantedfigureoptions \empty - \let \wantedfigureconversion\empty - \let \wantedfigureprefix \empty - \let \wantedfiguretypelist \figuretypes - \let \figurepathlist \empty - \chardef \figurestatus \zerocount - \let \expandedfigurename \empty - \global\let \analyzedfigurewidth \!!zeropoint % set by indentifying code - \global\let \analyzedfigureheight \!!zeropoint % set by indentifying code - \global\setbox\foundexternalfigure \emptybox - \def \frozenfigurestamp {\externalfigurestamp}} % no edef - -\resetprivatefigurevariables - -\appendtoks - \resetprivatefigurevariables -\to\everyexternalfigureresets - -%D Private/public. - -\def\resetpublicfigurevariables - {\let\figurewidth \!!zeropoint - \let\figureheight \!!zeropoint - \let\figurenaturalwidth \!!zeropoint - \let\figurenaturalheight \!!zeropoint - \let\figurelabel \empty - \let\figurefileoriginal \empty - \let\figurefileoptions \empty - \let\figurefilename \empty - \let\figurefiletype \empty - \let\figurefilepage \!!zerocount - \let\figurefileconversion\empty - \let\figurefileprefix \empty - \let\figurefilepath \empty - \let\figurefilecache \empty} - -\resetpublicfigurevariables - -\appendtoks - \resetpublicfigurevariables -\to\everyexternalfigureresets - -\newcounter\figurenestinglevel - -\def\pushpublicfigurevariables - {\ifcase\figurenestinglevel\else - \doshowfigurestate{variables : push}% - \globalpushmacro\figurewidth - \globalpushmacro\figureheight - \globalpushmacro\figurenaturalwidth - \globalpushmacro\figurenaturalheight - \globalpushmacro\figurelabel - \globalpushmacro\figurefileoriginal - \globalpushmacro\figurefileoptions - \globalpushmacro\figurefilename - \globalpushmacro\figurefiletype - \globalpushmacro\figurefilepage - \globalpushmacro\figurefileconversion - \globalpushmacro\figurefileprefix - \globalpushmacro\figurefilepath - \globalpushmacro\figurefilecache - \fi} - -\def\poppublicfigurevariables - {\ifcase\figurenestinglevel\else - \doshowfigurestate{variables : pop}% - \globalpopmacro\figurefilecache - \globalpopmacro\figurefilepath - \globalpopmacro\figurefileprefix - \globalpopmacro\figurefileconversion - \globalpopmacro\figurefilepage - \globalpopmacro\figurefiletype - \globalpopmacro\figurefilename - \globalpopmacro\figurefileoptions - \globalpopmacro\figurefileoriginal - \globalpopmacro\figurelabel - \globalpopmacro\figurenaturalheight - \globalpopmacro\figurenaturalwidth - \globalpopmacro\figureheight - \globalpopmacro\figurewidth - \fi} - -\def\setpublicfigurevariables % todo: type vs typespec - {\xdef\figurewidth {\the\wd\foundexternalfigure}% - \xdef\figureheight {\the\ht\foundexternalfigure}% - \xdef\figurenaturalwidth {\naturalfigurewidth}% - \xdef\figurenaturalheight {\naturalfigureheight}% - \xdef\figurelabel {\wantedfigurelabel}% - \xdef\figurefilepath {\wantedfigurepath}% - \xdef\figurefilename {\wantedfigurename}% - \xdef\figurefiletype {\wantedfiguretypespec}% - \xdef\figurefilepage {\wantedfigurepage}% - \xdef\figurefileoptions {\wantedfigureoptions}% - \xdef\figurefileconversion{\wantedfigureconversion}% - \xdef\figurefilecache {\wantedconversioncache}% - \xdef\figurefileprefix {\wantedconversionprefix}% - \xdef\figurefileoriginal {\wantedconversionname}% - \xdef\figurefullname {\wantedfigurepath/\wantedfigurename.\wantedfiguretypespec}% - \ifcase\figurestatus - \let\figurefiletype\empty % ? - \fi} - -\def\setpublicfigurescalevariables - {\edef\figurescalewidth {\finalscaleboxwidth }% - \edef\figurescaleheight {\finalscaleboxheight}% - \edef\figurescalexscale {\finalscaleboxxscale}% - \edef\figurescaleyscale {\finalscaleboxyscale}} - -\def\resetpublicfigurescalevariables - {\let\figurescalewidth \!!zeropoint - \let\figurescaleheight \!!zeropoint - \let\figurescalexscale \!!plusone - \let\figurescaleyscale \!!plusone} - -\resetpublicfigurescalevariables - -\appendtoks - \resetpublicfigurescalevariables -\to \everyexternalfigureresets - -%D The next one is for instance used in symbols. Since -%D we only need to reset some parameters, we can -%D better use the fast alternative: -%D -%D \starttyping -%D \def\resetexternalfigures -%D {\getparameters[\??ef] -%D [\c!option=,\c!maxwidth=,\c!maxheight=, -%D \c!foregroundcolor=,\c!color=, -%D %\c!conversion=,\c!prefix=,\c!splitcolor=, -%D \c!frame=\v!off,\c!background=]} -%D \stoptyping -%D -%D This one dropped the runtime of the \MAPS\ bibliography -%D from over 110 seconds down to less than 105 seconds. The -%D tremendously faster (but uglier) implementation is: - -\def\resetexternalfigures - {\let\@@efoption \empty % \let\@@efprefix\empty - \let\@@efmaxwidth \empty % \let\@@efcache \empty - \let\@@efmaxheight \empty % \let\@@efframe \v!off - \let\@@efforegroundcolor\empty - \let\@@efcolor \empty - \let\@@efconversion \empty - \let\@@efbackground \empty} - -%D The following code will move: - -\appendtoks \resetexternalfigures \to \everyoverlay -\appendtoks \resetexternalfigures \to \everybeforepagebody % not really needed -%appendtoks \resetexternalfigures \to \everysymbol - -%D We need this one for bookkeeping: - -\newcounter\forcedMPSobject % better something \every - -%D Features: - -% converted -> prefix, suffix -% alternative -> other suffix -% buffer -> prefix - -%D Still messy: - -\newtoks\everyfiguretypepresets - -\def\presetfiguretypeprocessing - {\the\everyfiguretypepresets} - -\def\presetspecialfigure#1% - {\doif\wantedfiguretype{#1}% - {\let\@@efobject\v!no - \let\@@efpreset\v!no - \ifx\@@efwidth \empty\def\@@efwidth {\defaultfigurewidth }\fi - \ifx\@@efheight\empty\def\@@efheight{\defaultfigureheight}\fi}} - -\appendtoks - \presetspecialfigure\c!mov - \presetspecialfigure\c!avi -\to \everyfiguretypepresets - -\def\checkformpsfigurefiles % to be checked - {\doif\wantedfigurename{mprun} - {\doshowfigurestate{type check : forcing mps (mprun)}% - \doifnotinstring{^\bufferprefix}{^\wantedfigurename} - {\edef\wantedfigurename{\bufferprefix\wantedfigurename}}% - \let\wantedfiguremethod \c!mps - \let\wantedfiguretypespec\c!mps}% - \doifnumberelse\wantedfiguretype - {\doshowfigurestate{type check : forcing mps (number)}% - \let\wantedfiguremethod \c!mps - \let\wantedfiguretypespec\c!mps} - \donothing - \doif\wantedfiguretypespec\c!mps - {\let\wantedfiguretypelist\wantedfiguretypespec - \ifcase\EPSspecial\else\ifinobject\else - \doglobal\increment\forcedMPSobject - \edef\externalfigurestamp{\c!mps::\forcedMPSobject}% - \let\@@efobject\v!yes - \fi\fi}} - -\appendtoks - \checkformpsfigurefiles -\to \everyfiguretypepresets - -\def\checkfortexfigurefiles % to be checked (brrr: c!) / brrr: eftype - {\doifinset\wantedfiguretype{\c!tex,\c!tmp} - {\let\wantedfiguretypespec \wantedfiguretype}% - \doifinset\wantedfiguretypespec{\c!tex,\c!tmp,\v!buffer} - {\doshowfigurestate{type check : forcing tex (\wantedfiguretypespec)}% - \let\wantedfiguretypelist\wantedfiguretypespec - \let\wantedfiguremethod \c!tex - \let\@@efobject\v!no - \doifnothing\wantedfiguretype{\let\wantedfiguretype\c!tmp}% - % there can be a non buffer \jobname.tmp (made by texexec) - \doifnotinstring{^\bufferprefix}{^\wantedfigurename} - {\edef\wantedfigurename{\bufferprefix\wantedfigurename}}}} - -\appendtoks - \checkfortexfigurefiles -\to \everyfiguretypepresets - -\def\checkforunknownfigurefiles - {\doifnothing\wantedfiguretype - {\dogetcommacommandelement\plusone\from\@@eftype\to\commalistelement - \edef\wantedfigurefullname{\wantedfigurename.\commalistelement}}} - -\appendtoks - \checkforunknownfigurefiles -\to \everyfiguretypepresets - -% note * : this is needed because reusable graphics -% combined with funny page aspect aspect ratio's can lead to -% strange side effects of preceding factor=max specs. This -% surfaced in the metafun manual, where the two side by -% side clipped cow heads [the second one was a reused object] -% where the second one inherited some characteristics from -% the factor=max one some 30 pages back. Sigh. - -\chardef\splitexternalfigure\zerocount % 0 nosplit 1 split/yes 2 split/no - -\def\checkfigurecolorsettings - {% seperation, seldom used - \doifseparatingcolorselse - {\let\@@efforegroundcolor\empty - \doifelsenothing\@@efsplit - {\chardef\splitexternalfigure\zerocount} - {\doifcolorchannelelse\@@efsplit - {\let\@@efobject\v!no % why? - \chardef\splitexternalfigure\plusone} - {\chardef\splitexternalfigure\plustwo}}} - {\chardef\splitexternalfigure\zerocount}% - % fake color in gray bitmaps, assumes that - % a transparent color is used - \doifsomething\@@efforegroundcolor - {\def\@@efbackground{\v!foreground,\v!color}% - \def\@@efbackgroundcolor{\@@efforegroundcolor}}% - \doifsomething\@@efcolor - {\doifcolorelse\@@efcolor - {\checkpredefinedcolor[\@@efcolor]% - \doregisterfigurecolor\@@efcolor}}% - \donothing} - -\def\setextrafiguredriveroptions - {\let\@@DriverImageOptions\empty - \doifsomething\@@efpage {\addtocommalist\@@efpage \@@DriverImageOptions}% - \doif \@@efpreview \v!yes{\addtocommalist\v!preview \@@DriverImageOptions}% - \doif \@@efcontrols\v!yes{\addtocommalist\v!controls\@@DriverImageOptions}% - \doif \@@efrepeat \v!yes{\addtocommalist\v!repeat \@@DriverImageOptions}% - \doifinsetelse\@@efsize{mediabox,cropbox,artbox,bleedbox,trimbox} - {\let \@@DriverImageBox \@@efsize}% - {\doifinsetelse\@@efsize{media,crop,art,bleed,trim} - {\edef\@@DriverImageBox{\@@efsize box}}% - {\let \@@DriverImageBox \empty}}% - \let\wantedfigureoptions\@@DriverImageOptions} - -\def\checkiffigureobjectpresent - {\doifnot\@@efobject\v!no - {\doifobjectssupportedelse - {\doifobjectfoundelse{FIG}\externalfigurestamp - {\doshowfigurestate{object found : \externalfigurestamp}% - \getobjectdimensions{FIG}\externalfigurestamp - \edef\frozenfigurestamp{\externalfigurestamp}% - \xdef\analyzedfigurewidth {\the\dimexpr\objectwidth \relax}% - \xdef\analyzedfigureheight{\the\dimexpr\objectheight\relax}% - \setanalyzedfiguredimensions\plusone} - {\doshowfigurestate{unknown object: \externalfigurestamp}}} - {}}} - -\def\checkifknownfigureobjectpresent - {\ifx\wantedfiguretype\empty - \let\savedwantedfiguretype\wantedfiguretype - \def\docommand##1% - {\ifcase\figurestatus - \edef\wantedfiguretype{##1}% - \checkiffigureobjectpresent - \fi}% - \processcommacommand[\figuretypes]\docommand - \ifcase\figurestatus - \let\wantedfiguretype\savedwantedfiguretype - \fi - \fi} +\presetlocalframed[\??ef] -\def\checkforfigurefile - {\ifcase\figurestatus - \ifconditional\externalfigureflush - \analyzefigurefiles - \fi - \fi} +\newconditional\externalfigurelevel % true=background false=normal +\newconditional\externalfigureflush % true=place false=ignore -\def\externalfigurestamp % needs \edef'd macros! - {\wantedfigurename - \ifx\wantedfiguretype\empty\else - \ifx\wantedfiguretype\s!unknown\else - -\wantedfiguretype - \fi - \fi - \ifx\wantedfiguretypespec\empty\else - \ifx\wantedfiguretypespec\s!unknown\else - \ifx\wantedfiguretypespec\wantedfiguretype\else - -\wantedfiguretypespec - \fi - \fi - \fi - \ifnum\wantedfigurepage>\zeropoint - -\wantedfigurepage - \fi} +\setfalse\externalfigurelevel +\settrue \externalfigureflush -\def\checkfigurerenderingoptions - {\ifcase\figurestatus - \let\@@efframe\v!on - \fi - \doif\@@exoption\v!frame - {\let\@@efframe\v!on}% - \doif\@@exoption\v!empty - {\skipexternalfigurestrue - \let\@@efframe\v!off}} - -\newtoks\externalfigurepostprocessors - -\def\resetfigureusersettings - {\let\@@eftype \s!unknown \let\@@efmethod \empty \let\@@efpreset\v!yes - \let\@@eflabel \empty \let\@@efsize \empty \let\@@efpage \!!zerocount - \let\@@efobject \@@exobject \let\@@efdisplay \empty - \let\@@efsplit \empty \let\@@efcolor \empty \let\@@efsymbol\v!no - \let\@@efcontrols \v!no \let\@@efpreview \v!no \let\@@efrepeat\v!no - \let\@@efhfactor \empty \let\@@efwfactor \empty \let\@@effactor\empty - \let\@@efmaxwidth \@@exmaxwidth \let\@@efmaxheight\@@exmaxheight - \let\@@efxscale \empty \let\@@efyscale \empty \let\@@efscale \empty - \let\@@efsx \!!plusone \let\@@efsy \!!plusone - \let\@@efwidth \empty \let\@@efheight \empty - \let\@@eflines \empty \let\@@efgrid \empty - \let\@@efconversion\@@exconversion \let\@@efprefix \@@exprefix \let\@@efcache \@@excache} - -%D Types and Methods are a bit history. Anyhow, user scan use the -%D type to force the handler. So, what to do with the method. We can -%D use that one to force a handler with a given suffix, so when no -%D type is given, but a suffix is part of the name, the method will -%D determine the handler. - -\def\checkfigureusersettings - {\doif\@@efreset\v!yes\resetexternalfigures - \doifelsenothing\@@eflabel - {\doifnothing\wantedfigurelabel{\let\wantedfigurelabel\wantedfigurename}}% - {\let\wantedfigurelabel\@@eflabel}% - \doifsomething\@@eftype - {\doifnot\@@eftype\s!unknown - {\edef\wantedfiguretypespec{\@@eftype} - \let\wantedfiguremethod\wantedfiguretypespec}}% - \doifnothing\wantedfigurepage % can be set by plug in - {\let\wantedfigurepage\@@efpage}% - \doif\wantedfigurepage\empty - {\let\wantedfigurepage\!!zerocount}% 0 is signal ! - \doifsomething\@@efmethod % rather untested misusage of the remapper - {\doifsomething\wantedfiguretype - {\definegraphictypesynonym[\wantedfiguretype][\@@method]}}} - -% #1 is now obsolete - -\def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% \cmd label filename parent_id preset current - {\doshowfigurestate{begin}% - \dontcomplain - % let's limit the search, which means that e.g. svg has to be given explicitly - \checksupportedfiguretypes - % recently added; we presume local use - \restorecatcodes - % collected resets (token list) - \resetfigurevariables -\resetwantedconversionvariables % new here - % analyze filename and set wanted variables - \analyzefigurefilename{#3}{#2}% - \doanalyzefiguredimensionsfromfile - % handle user settings - \resetfigureusersettings - \dosetefparameters{#4}{#5}{#6}% - \checkfigureusersettings - \checkfigurecolorsettings - % adapt settings based on suffix and/or type - \presetfiguretypeprocessing - % now we really start - \checkiffigureobjectpresent % first guess, we may not yet know the typespec - \checkifknownfigureobjectpresent - \checkforfigurefilepresence - \checkiffigureobjectpresent % to be sure, in case we now know the typespec - \checkfigurerenderingoptions % was later, moved here - \checknaturalfiguredimensions % inherit from global values and/or fallbacks - % by now we know what we're dealing with (put in box and scale) - \setextrafiguredriveroptions - \prepackageexternalfigureobject - % set public variables in case postprocessing needs them - \pushpublicfigurevariables - \setpublicfigurevariables - \setpublicfigureconversionvariables - \setpublicfigurescalevariables - % package final graphic, only now we can apply backgrounds and such - \doglobal\increment\figurenestinglevel - \finishexternalfigure - \doglobal\decrement\figurenestinglevel - % restore variables - \poppublicfigurevariables - \doshowfigurestate{end}} - -\def\checkforfigurefilepresence - {\checkforconvertedfigure - \checkforfigurefile} - -%D Figure objects. - -\def\setfigureobject - {\doshowfigurestate{object set : \externalfigurestamp}% - \setobject{FIG}\externalfigurestamp} - -% \def\getfigureobject -% {\doshowfigurestate{object used : \externalfigurestamp}% -% \getobject{FIG}\externalfigurestamp} - -\def\getfigureobject - {\doshowfigurestate{object used : \frozenfigurestamp}% - \getobject{FIG}\frozenfigurestamp} - -\def\prepackageexternalfigureobject - {\ifcase\figurestatus - \doshowfiguremessage1\expandedfigurename - \doshowfigurestate{state : figure not found (\expandedfigurename)}% - \global\setbox\foundexternalfigure\naturalvbox - {\doscalebox\??ef{\blackrule[\c!width=\naturalfigurewidth,\c!height=\naturalfigureheight]}}% - \or - \doshowfiguremessage8\expandedfigurename - \doshowfigurestate{state : reusing existing figure}% - \global\setbox\foundexternalfigure\naturalvbox - {\doscalebox\??ef{\dowithfigure{\getfigureobject}}}% - \xdef\noffigurepages{\number\getvalue{\externalfigurestamp\c!n}}% - \or - \doshowfiguremessage2\expandedfigurename - \doshowfigurestate{state : using special figure}% - \setbox\scratchbox\naturalvbox % make a dummy - {\doscalebox\??ef{\blackrule[\c!width=\naturalfigurewidth,\c!height=\naturalfigureheight]}}% - \global\setbox\foundexternalfigure\naturalvbox to \finalscaleboxheight - {\vfill - \hsize\finalscaleboxwidth - \dowithfigure{\insertscaledfiguredriverdata}}% - \xdef\noffigurepages{\number\nofinsertpages}% - \else - \ifdim\naturalfigurewidth>\zeropoint - \ifnum\figurestatus>\!!ten\relax - \doshowfiguremessage3\expandedfigurename - \else - \doshowfiguremessage4\expandedfigurename - \fi - \else - \doshowfiguremessage5\expandedfigurename - \fi - \doshowfigurestate{state : using found figure}% 3=self 4=rlx - \doifelse\@@efobject\v!no - {\donefalse} - {\doifobjectssupportedelse\donetrue\donefalse}% - \ifdone - % make an object and use it - \packageexternalfigureobject - \setfigureobject\vbox{\box\foundexternalfigure}% - \setxvalue{\externalfigurestamp\c!n}{\number\nofinsertpages}% - \global\setbox\foundexternalfigure\naturalvbox - {\doscalebox\??ef{\dowithfigure{\getfigureobject}}}% - \xdef\noffigurepages{\number\getvalue{\externalfigurestamp\c!n}}% - \else - % maybe a tex figure - \global\setbox\foundexternalfigure\naturalvbox - {\doscalebox\??ef{\dowithfigure{\box\foundexternalfigure}}}% - \xdef\noffigurepages{\number\nofinsertpages}% - \fi - \fi - \global\wd\foundexternalfigure\finalscaleboxwidth - \global\ht\foundexternalfigure\finalscaleboxheight - \global\let\lastfigureobjectname\externalfigurestamp - \doresetobjects} % clean up driver left overs - -\def\packageexternalfigureobject - {\global\setbox\foundexternalfigure\vbox to \naturalfigureheight - {\vfill - \ifdim\wd\foundexternalfigure=\zeropoint - \setextrafiguredriveroptions - \insertunscaledfiguredriverdata - \else\ifskipexternalfigures - \ruledhbox{\backgroundline[\@@efsplitcolor]{\fakebox\foundexternalfigure}}% - \else - \box\foundexternalfigure - \fi\fi}% - \wd\foundexternalfigure\naturalfigurewidth - \ht\foundexternalfigure\naturalfigureheight} - -\def\finishexternalfigure % here we use \figurevariables - {\global\setbox\foundexternalfigure\vbox - {\forgetall - \ifcase\figurestatus - \resetsystemmode\v!figure % todo, also: \v!resource - \else - \setsystemmode \v!figure % todo, also: \v!resource - \fi - \ifconditional\externalfigureflush - \ifconditional\externalfigurelevel % probably background - \ifskipexternalfigures - % nothing - \fakebox\foundexternalfigure - \else\ifcase\figurestatus - % nothing - \else\ifnum\splitexternalfigure=\plustwo\else - \the\externalfigurepostprocessors - \box\foundexternalfigure - \fi\fi\fi - \else - \iftrialtypesetting \else \feedbackexternalfigure \fi - \settrue\externalfigurelevel - \ifskipexternalfigures - \ifcase\figurestatus - \externalfigurereplacement\figurelabel\figurefilename{unknown}% - \else - \externalfigurereplacement\figurelabel\figurefullname{skipped}% - \fi - \else\ifcase\figurestatus - \externalfigurereplacement\figurelabel\figurefilename{unknown}% - \else\ifnum\splitexternalfigure=\plustwo - \backgroundline[\@@efsplitcolor]{\fakebox\foundexternalfigure}% - \else - \the\externalfigurepostprocessors - \doifelse\@@efreset\v!yes - {\wd\foundexternalfigure\figurewidth - \ht\foundexternalfigure\figureheight - \dp\foundexternalfigure\zeropoint - \box\foundexternalfigure} - {\localframed % should also be applied to high res ! - [\??ef] - [\c!offset=\v!overlay, - \c!width=\figurewidth, - \c!height=\figureheight] - {\vfilll - \ifnum\splitexternalfigure=\plusone - % hm, eigenlijk in dit geval achtergrondkleur - \hidesplitcolorfalse % really needed - \backgroundline[\@@efsplitcolor]{\box\foundexternalfigure}% - \else % = 0, no split mode - \box\foundexternalfigure - \fi}}% - \fi\fi\fi - \fi - \else - % maybe also \the\externalfigurepostprocessors - \iftrialtypesetting \else \feedbackexternalfigure \fi - \fi}} - -\def\insertfiguredriverdata#1#2% - {\lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec - \lowercasestring\wantedfiguremethod \to\lcwantedfiguremethod - \edef\@@DriverImageWidth {\the\dimexpr#1\relax}% - \edef\@@DriverImageHeight{\the\dimexpr#2\relax}% - \let \@@DriverImageFile \wantedfigurefullname - \let \@@DriverImageType \lcwantedfiguretypespec - \let \@@DriverImageMethod \lcwantedfiguremethod - \let \@@DriverImageLabel \wantedfigurelabel - \let \@@DriverImagePage \wantedfigurepage - \doinsertfile} - -\def\insertunscaledfiguredriverdata - {\insertfiguredriverdata\naturalfigurewidth\naturalfigureheight} - -\def\insertscaledfiguredriverdata - {\insertfiguredriverdata\finalscaleboxwidth\finalscaleboxheight} +\def\doplaceexternalfigure[#1][#2][#3][#4][#5]% + {\doifsomething{#2}% catches \defineexternalfigure dummies + {\bgroup + \pushmacro\textunderscore + \edef\textunderscore{\string_}% brrr, temp hack, still needed? + \calculateexternalfigure [][#1][#2][#3][#4][#5]% [] is dummy dwcomp + \calculateexternalscreenfigure[][#1][#2][#3][#4][#5]% [] is dummy dwcomp + \popmacro\textunderscore + \box\foundexternalfigure + \egroup}} \def\externalfigurereplacement#1#2#3% {\setupcolors @@ -867,518 +67,6 @@ name: \expanded{\verbatimstring{#1}}\\% state: \expanded{\verbatimstring{placeholder}}}} -\def\registerexternalfigure % no placement, handy for preprocessing - {\dotripleempty\doregisterexternalfigure} - -\def\doregisterexternalfigure[#1][#2][#3]% - {\bgroup - \setfalse\externalfigureflush - \externalfigure[#1][#2][#3]% or \doexternalfigure - \egroup} - -\let\feedbackexternalfigure\relax % \gobblefourarguments -\let\dowithfigure \relax - -%D Conversion stuff: - -\newcount\nofconversionfigures - -\def\resetwantedconversionvariables - {\let\wantedconversionpath \empty % these point to the to be converted graphic - \let\wantedconversionname \empty - \let\wantedconversiontype \empty - \let\wantedconversioncache \empty - \let\wantedconversionprefix\empty} - -\resetwantedconversionvariables - -\def\checkforconvertedfigure - {\ifcase\figurestatus - \resetwantedconversionvariables - \doifsomething\@@efconversion - {\global\advance\nofconversionfigures\plusone - \doshowfigurestate{n-of-conversions : \number\nofconversionfigures}% - \edef\wantedfigureconversion{\@@efconversion}% - \edef\wantedconversioncache {\@@efcache}% - \edef\wantedconversionprefix{\@@efprefix}% - \doshowfigurestate{checking paths : \figurepathlist}% - \processcommacommand[\figurepathlist]\dolocatefigureconversionfile - \ifcase\figurestatus - \doshowfigurestate{remark : no conversion file found}% - \else - \doshowfigurestate{remark : conversion file found}% - \chardef\figurestatus\zerocount - \fi - \let\wantedconversionname\wantedfigurename - \edef\wantedfigurename{\wantedconversionprefix\wantedfigurename}% - \ifx\wantedconversioncache\empty - \let \wantedfigurepath \wantedconversionpath - \else - \checkfilename\@@efcache - \ifnum\kindoffile=\plusone - \let\wantedfigurepath\@@efcache % root related path - \else % brrr - \edef\wantedfigurepath{\@@efcache,\wantedconversionpath/\@@efcache}% in case of explicit paths, what a mess - \fi - \fi - \let\wantedfiguretype \empty - \let\wantedfiguretypelist\figuretypes % hm, why needed - \ifx\figurepathlist\empty - \let\figurepathlist\wantedfigurepath - \else - \edef\figurepathlist{\wantedfigurepath,\figurepathlist}% - \fi - \doshowfigurestate{conversion path : \wantedconversionpath}% - \doshowfigurestate{conversion name : \wantedconversionname}}% - \doshowfigurestate{new figure path : \wantedfigurepath}% - \fi} - -\def\dolocatefigureconversionfile#1% - {\ifcase\figurestatus - \setwantedfigurefullname{#1}\wantedfigurename\wantedfiguretype - \doshowfigurestate{locating original : \wantedfigurefullname}% - \doiffile\wantedfigurefullname - {\def\wantedconversionpath{#1}% - \let\wantedconversionname\wantedfigurename - \let\wantedconversiontype\wantedfiguretype - \chardef\figurestatus\plusfive}% - \fi} - -\def\setpublicfigureconversionvariables % also prefix, cache - {\doifsomething\@@efconversion - {\doifmode{\systemmodeprefix\v!first} - {\let\figurefilepath\wantedconversionpath - \let\figurefilename\wantedconversionname - \let\figurefiletype\wantedconversiontype - \let\figurefileconversion\wantedfigureconversion - \def\figurefullname - {\ifx\wantedconversionpath\empty\else\wantedconversionpath/\fi - \wantedconversionname - \ifx\wantedconversiontype\empty\else.\wantedconversiontype\fi}}}} - -%D In \PDF\ one can specify an alternative graphic. This means -%D that for instance a low resolution graphic can be used for -%D viewing and a high res one for printing. Because this -%D feature depends much on the driver, here we only take care -%D of perparations. It is up to the special driver to handle -%D the inclusion. The driver routines can change the content of -%D box \type {\foundexternalfigure} if suitable. -%D -%D One complication is for instance that an alternative may -%D not itself have an alternative, and these kind of situations -%D are best handled by the driver. - -\let\lastfigureobjectname\empty - -%D The next macro does not work well with figure bases yet. - -\def\calculateexternalscreenfigure[#1][#2][#3][#4][#5][#6]% - {\ifx\@@efdisplay\empty\else - \doifnot\@@efobject\v!no - {\doifobjectssupportedelse - {\doifspecialavailableelse\doregisterfigure - {\doshowfigurestate{screen alternative : start}% - \bgroup - \dosetefparameters{#4}{#5}{#6}% - \doregisterfigure{FIG}{\lastfigureobjectname}% - \let\@@ef@@scherm\@@efdisplay - \calculateexternalfigure[#1][\@@ef@@scherm][\@@ef@@scherm][#4,\c!display=][#5][#6]% - \doshowfigurestate{screen alternative : stop}% - \egroup} - {}} - {}}% - \fi} - -\def\getfiguredimensions - {\dodoubleempty\dogetfiguredimensions} - -\def\dogetfiguredimensions[#1][#2]% - {{\let\immediate\relax % very dirty but prevents flushing, will change - \setbox0\hbox{\externalfigure[#1][#2,\c!display=,\c!object=\v!no]}}} - -% use the next one when the object must be forgotten (xobj -% nums can migrate to the next object; maybe it should -% always be done; todo .... - -\def\getfiguredimensionsonly - {\dodoubleempty\dogetfiguredimensionsonly} - -\def\dogetfiguredimensionsonly[#1][#2]% - {\dogetfiguredimensions[#1][#2]% - \doresetobjects} - -\def\doiffigureelse#1% - {\getfiguredimensions[#1]% - \ifcase\figurewidth - \expandafter\secondoftwoarguments - \else - \expandafter\firstoftwoarguments - \fi} - -%D Size determination. -%D -%D An analyzer must set the following dimensions (global macros): -%D -%D \starttyping -%D \analyzedfigurewidth -%D \analyzedfigureheight -%D \stoptyping -%D -%D And afterwards, when succeeded, call: -%D -%D \starttyping -%D \setanalyzedfiguredimensions{number>=10} -%D \stoptyping -%D -%D Numbers upto 9 are reserved for special purposes: -%D -%D \starttabulate -%D \NC 0 \NC not found \NC \NR -%D \NC 1 \NC object (will be reused) \NC \NR -%D \NC 2 \NC found but no dimensions (e.g. special annotation) \NC \NR -%D \stoptabulate - -\let\doanalyzefiguredimensionsfromfile\relax % hook for figuredatabase -\let\doanalyzefiguredimensionsinternal\relax -\let\doanalyzefiguredimensionsexternal\relax % hook for rli support (see later) -\let\doanalyzefiguredimensionsfallback\relax - -\def\doanalyzefiguredimensions - {\lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec - \doiffileinsertionsupportedelse\lcwantedfiguretypespec - {\doiffileelse\wantedfigurefullname - {\doshowfigurestate{analyzing : \wantedfigurefullname}% - \doanalyzefiguredimensionsinternal - \doanalyzefiguredimensionsexternal - \doanalyzefiguredimensionsfallback} - {\doshowfigurestate{not found : \wantedfigurefullname}}} - {}} - -\def\setanalyzedfiguredimensions#1% - {\ifdim\analyzedfigurewidth>\zeropoint - \ifdim\analyzedfigureheight>\zeropoint - \determinedfigurewidth \analyzedfigurewidth - \determinedfigureheight\analyzedfigureheight - \chardef\figurestatus #1\relax - \doshowfigurestate{dimensions : - \the\dimexpr\analyzedfigurewidth\relax\space x\space - \the\dimexpr\analyzedfigureheight\relax}% - \else - \determinedfigurewidth \zeropoint - \determinedfigureheight\zeropoint - \chardef\figurestatus \zerocount - \fi - \else - \determinedfigurewidth \zeropoint - \determinedfigureheight\zeropoint - \chardef\figurestatus \zerocount - \fi} - -%D We can remap types. This is to be dealt with in the driver files. - -\def\definegraphictypesynonym - {\dodoubleargument\dodefinegraphictypesynonym} - -\def\dodefinegraphictypesynonym[#1][#2]% - {\setvalue{\??ef:\??ex:#1}{#2}} - -\def\truegraphictype#1% - {\ifcsname\??ef:\??ex:#1\endcsname - \expandafter\truegraphictype\csname\??ef:\??ex:#1\endcsname\else#1% - \fi} - -\definegraphictypesynonym[epdf] [pdf] -\definegraphictypesynonym[jpeg] [jpg] -\definegraphictypesynonym[jp2] [jpg] -\definegraphictypesynonym[jbig] [jb2] -\definegraphictypesynonym[jbig2][jb2] -\definegraphictypesynonym[jbg] [jb2] - -%D The self method (mostly used) uses the driver. - -% todo: when zero width mps, ok -% -% analyzer must set the analyzed dimensions - -\def\doanalyzefiguredimensionsinternal - {\ifcase\figurestatus - \lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec - \let\@@DriverImageFile \wantedfigurefullname - \let\@@DriverImagePage \wantedfigurepage - \let\@@DriverImageType\lcwantedfiguretypespec - % use internal when available, otherwise try driver (\dogetfiguresize) - \executeifdefined{dogetfiguresize\@@DriverImageType}\dogetfiguresize - \setanalyzedfiguredimensions\!!ten - \fi} - -%D The tex method. - -\def\dogetfiguresizetex - {\ifcase\figurestatus - \global\setbox\foundexternalfigure\vbox - {\insidefloattrue - \forgetall - \blank[\v!disable]% niet meer weg ! - \startreadingfile - \readfile\wantedfigurefullname \donothing \donothing - \stopreadingfile - \endgraf - \removelastskip}% - \global\setbox\foundexternalfigure\hbox - {\raise\dp\foundexternalfigure\box\foundexternalfigure}% - \xdef\analyzedfigurewidth {\the\wd\foundexternalfigure}% - \xdef\analyzedfigureheight{\the\ht\foundexternalfigure}% - \fi} - -\let\dogetfiguresizetmp \dogetfiguresizetex -\let\dogetfiguresizebuffer\dogetfiguresizetex - -%D The eps, mps and svg files are read directly. - -\def\dogetfiguresizeeps - {\dogetEPSboundingbox\wantedfigurefullname\!!widtha\!!heighta\!!widthb\!!heightb - \xdef\analyzedfigurewidth {\the\!!widthb}% - \xdef\analyzedfigureheight{\the\!!heightb}} - -\let\dogetfiguresizemps\dogetfiguresizeeps - -\def\dogetfiguresizesvg - {\doifinset\wantedfiguretypespec\c!svg - {\startnointerference - \startXMLignore - \defineXMLcommand[svg][width=100,height=75] - {\doifdimensionelse{\XMLop{width}} - {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{width}\relax}} - {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{width}\onebasepoint\relax}}% - \doifdimensionelse{\XMLop{height}} - {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{height}\relax}} - {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{height}\onebasepoint\relax}}% - \endinput}% - \processXMLfilegrouped\wantedfigurefullname - \stopXMLignore - \stopnointerference}} - -%D Do some checking on the filename. - -\newconditional \figurefileisqualified - -\def\setfigurepathlist - {\let\figurepathlist\empty - \expanded{\doifinset{\v!global }{\@@exlocation}} - {\let\figurepathlist\@@exdirectory}% - \expanded{\doifinset{\v!local }{\@@exlocation}} - {\prependtocommalist\f!currentpath\figurepathlist}% - \expanded{\doifinset{\v!default}{\@@exlocation}} - {\appendtocommalist\defaultfigurepathsignal\figurepathlist}} - -% \def\analyzefigurefilename#1#2% -% {\sanitizefilename#1\to\expandedfigurename -% \expanded{\checkfilename{\expandedfigurename}}% -% \ifcase\kindoffile -% \splitfigurefilename -% \ifcase\splitoffkind -% \let\wantedfigurepath\empty % no . either -% \setfigurepathlist -% \setfalse\figurefileisqualified -% \else -% \splitfigurefilename -% \let\figurepathlist\wantedfigurepath -% \let\wantedfigurepath\empty -% \settrue\figurefileisqualified -% \fi -% \else % fully qualified -% \splitfigurefilename -% \let\figurepathlist\wantedfigurepath -% \let\wantedfigurepath\empty -% \settrue\figurefileisqualified -% \fi -% \ifx\figurepathlist\empty -% \let\figurepathlist\defaultfigurepathsignal % will prepend no path -% \fi -% \doifelsenothing\wantedfiguretype -% {\doifparentfileelse\wantedfigurename -% {\@EA\removefromcommalist\@EA{\jobsuffix }\wantedfiguretypelist -% \@EA\removefromcommalist\@EA{\jobfilesuffix}\wantedfiguretypelist} -% {}} -% {\let\wantedfiguretypelist\empty -% \let\wantedfiguretypespec\wantedfiguretype}% -% \edef\wantedfigurelabel{#2}% -% \doshowfigurestate{type check : \ifx\wantedfiguretypelist\empty forced type \wantedfiguretypespec\else\wantedfiguretypelist\fi}% -% \doshowfigurestate{file specs : \wantedfigurefull\space [\wantedfigurepath] [\wantedfigurename] [\wantedfiguretype]}% -% \doshowfigurestate{file type : \ifconditional\figurefileisqualified qualified\else simple\fi}} - -% The combined path and qualified path hack is dedicated to Onno Tomson, -% our partner in fighting inconsistent and faulty image specifications in -% user files. - -\def\analyzefigurefilename#1#2% - {\sanitizefilename#1\to\expandedfigurename - \expanded{\checkfilename{\expandedfigurename}}% - \ifcase\kindoffile - \splitfigurefilename - \ifcase\splitoffkind - \let\wantedfigurepath\empty % no . either - \setfigurepathlist - \setfalse\figurefileisqualified - \else - \splitfigurefilename - % will become splitoffkind 3 ! ! ! ! - \setfalse\figurefileisqualified - \doifinstring{$$/}{$$\wantedfigurepath}{\settrue\figurefileisqualified}% - \doifinstring {:} {\wantedfigurepath}{\settrue\figurefileisqualified}% - \ifconditional\figurefileisqualified - \let\figurepathlist\wantedfigurepath - \let\wantedfigurepath\empty - \settrue\figurefileisqualified - \else - \let\figurepathlist\@@exdirectory - \let\oldfigurepathlist\figurepathlist - \let\figurepathlist\wantedfigurepath - \def\docommand##1{\edef\figurepathlist{\figurepathlist,##1/\wantedfigurepath}}% - \processcommacommand[\oldfigurepathlist]\docommand - \fi - \fi - \else % fully qualified - \splitfigurefilename - \let\wantedfigurepath\empty - \settrue\figurefileisqualified - \fi - \ifx\figurepathlist\empty - \let\figurepathlist\defaultfigurepathsignal % will prepend no path - \fi - \doifelsenothing\wantedfiguretype - {\doifparentfileelse\wantedfigurename - {\@EA\removefromcommalist\@EA{\jobsuffix }\wantedfiguretypelist - \@EA\removefromcommalist\@EA{\jobfilesuffix}\wantedfiguretypelist} - {}} - {\let\wantedfiguretypelist\empty - \let\wantedfiguretypespec\wantedfiguretype}% - \edef\wantedfigurelabel{#2}% - \doshowfigurestate{type check : \ifx\wantedfiguretypelist\empty forced type \wantedfiguretypespec\else\wantedfiguretypelist\fi}% - \doshowfigurestate{file specs : \wantedfigurefull\space [\wantedfigurepath] [\wantedfigurename] [\wantedfiguretype]}% - \doshowfigurestate{file type : \ifconditional\figurefileisqualified qualified\else simple\fi}} - -\def\setwantedfigurefullname#1#2#3% path name spec - {\ifx\wantedfiguremethod\empty - % the either explicit or gambled typespec determines the method - \edef\wantedfiguretypespec{#3}% - \doifelse{#1}\defaultfigurepathsignal - {\edef\wantedfigurefullname {#2.\wantedfiguretypespec}} - {\edef\wantedfigurefullname{#1/#2.\wantedfiguretypespec}}% - \else\ifx\wantedfiguretype\empty % - % the typespec (probably the same as the method) determines the suffix - \doifelse{#1}\defaultfigurepathsignal - {\edef\wantedfigurefullname {#2.\wantedfiguretypespec}} - {\edef\wantedfigurefullname{#1/#2.\wantedfiguretypespec}}% - \let\wantedfiguretypespec\wantedfiguremethod - \else - % the given suffix is used - \let\wantedfiguretypespec\wantedfiguremethod - \doifelse{#1}\defaultfigurepathsignal - {\edef\wantedfigurefullname {#2.\wantedfiguretype}} - {\edef\wantedfigurefullname{#1/#2.\wantedfiguretype}}% - \fi\fi} - -\def\splitfigurefilename - {\splitfilename\expandedfigurename - \let\wantedfigurefull\splitofffull - \let\wantedfigurepath\splitoffpath - \let\wantedfigurename\splitoffname - \let\wantedfigurebase\splitoffbase - \let\wantedfiguretype\splitofftype} - -\def\analyzefigurefiles - {\ifconditional\figurefileisqualified - \ifx\wantedfiguretype\empty - \doshowfigurestate{locating : unknown type}% - \doanalyzeunknownfiguretype - \else - % this file or none - \doshowfigurestate{locating : known type}% - \doanalyzequalifiedfigure - \fi - \else - \ifx\wantedfiguretype\empty - % locate best fit / check support - \doshowfigurestate{locating : best fit}% - \doanalyzeunknownfiguretype - \else - % only check on paths - \doshowfigurestate{locating : known types}% - \doanalyzeknownfiguretype - \fi - \fi} - -\def\doanalyzequalifiedfigure - {\let\wantedfigurefullname\wantedfigurefull - \let\wantedfiguretypespec\wantedfiguretype - \doshowfigurestate{forced type : \wantedfiguretype}% - \doshowfigurestate{identifying : \wantedfigurefullname}% - \doanalyzefiguredimensions} - -\def\doanalyzeknownfiguretype - {\doshowfigurestate{using paths : \figurepathlist}% - \doshowfigurestate{known type : \wantedfiguretype}% - \doshowfigurestate{identifying : \wantedfigurename}% - \let\wantedfiguretypespec\wantedfiguretype - \processcommacommand[\figurepathlist]\dodoanalyzeknownfiguretype} - -\def\dodoanalyzeknownfiguretype#1% path - {\ifcase\figurestatus - \setwantedfigurefullname{#1}\wantedfigurename\wantedfiguretype - \doanalyzefiguredimensions - \fi} - -\def\doanalyzeunknownfiguretype - {\doshowfigurestate{using paths : \figurepathlist}% - \doshowfigurestate{using types : \wantedfiguretypelist}% - \doshowfigurestate{identifying : \wantedfigurename}% - \processcommacommand[\wantedfiguretypelist]\dodoanalyzeunknownfiguretype} - -\def\dodoanalyzeunknownfiguretype#1% - {\processcommacommand[\figurepathlist]{\dododoanalyzeunknownfiguretype{#1}}} - -\def\dododoanalyzeunknownfiguretype#1#2% type path - {\ifcase\figurestatus - \setwantedfigurefullname{#2}\wantedfigurename{#1}% path spec - \doanalyzefiguredimensions - \fi} - -%D Some files, take for instance movies, cannot easilly be -%D parsed on dimensions, that is, not yet. Although the current -%D mechanism has no problems with this, as long as the user -%D specified width and height reflect the right aspect ratio. -%D Nevertheless, when one does not want any scanning done, one -%D can disable \type{preset}. When no preset is needed, we only -%D locate the file. - -\def\doanalyzefiguredimensionsfallback - {\ifcase\figurestatus - \doshowfigurestate{warning : assuming adaptive figure}% - \xdef\analyzedfigurewidth {\the\dimexpr\@@efwidth +\zeropoint\relax}% - \xdef\analyzedfigureheight{\the\dimexpr\@@efheight+\zeropoint\relax}% - \setanalyzedfiguredimensions\plustwo - \fi} - -\presetlocalframed[\??ef] - -\newconditional\externalfigurelevel % true=background false=normal -\newconditional\externalfigureflush % true=place false=ignore - -\setfalse\externalfigurelevel -\settrue \externalfigureflush - -\def\doplaceexternalfigure[#1][#2][#3][#4][#5]% - {\doifsomething{#2}% catches \defineexternalfigure dummies - {\bgroup - \pushmacro\textunderscore - \edef\textunderscore{\string_}% brrr, temp hack, still needed? - \calculateexternalfigure [][#1][#2][#3][#4][#5]% [] is dummy dwcomp - \calculateexternalscreenfigure[][#1][#2][#3][#4][#5]% [] is dummy dwcomp - \popmacro\textunderscore - \box\foundexternalfigure - \egroup}} - % new: more convenient/efficient than % % \use..[a][a][setting] \externalfigure[b][a] @@ -1489,7 +177,7 @@ \def\overlayfigure#1% {\externalfigure[#1][\c!width=\overlaywidth,\c!height=\overlayheight]} -%D Still undocumented! +%D Still undocumented! No one uses it I think, better be done with layers. \newcount\efreference \newdimen\efxsteps @@ -1778,7 +466,7 @@ \externalfigure[\bufferprefix typeset-\noftypesetbuffers.pdf][#2]% \egroup} -% for me only (manuals and sucn) +% for me only (manuals and such) \definesystemvariable{tz} diff --git a/tex/context/base/core-inc.lua b/tex/context/base/core-inc.lua new file mode 100644 index 000000000..c86078cdd --- /dev/null +++ b/tex/context/base/core-inc.lua @@ -0,0 +1,819 @@ +if not modules then modules = { } end modules ['core-inc'] = { + version = 1.001, + comment = "companion to core-inc.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- lowercase types +-- mps tex tmp svg +-- partly qualified +-- dimensions +-- consult rlx + +--[[ +The ConTeXt figure inclusion mechanisms are among the oldest code +in ConTeXt and evolve dinto a complex whole. One reason is that we +deal with backend in an abstract way. What complicates matters is +that we deal with internal graphics as well: TeX code, MetaPost code, +etc. Later on figure databases were introduced, which resulted in +a plug in model for locating images. On top of that runs a conversion +mechanism (with caching) and resource logging. + +Porting that to Lua is not that trivial because quite some +status information is kept between al these stages. Of course, image +reuse also has some price, and so I decided to implement the graphics +inclusion in several layers: detection, loading, inclusion, etc. + +Object sharing and scaling can happen at each stage, depending on the +way the resource is dealt with. + +The TeX-Lua mix is suboptimal. This has to do with the fact that we cannot +run TeX code from within Lua. Some more functionality will move to Lua. +]]-- + +backends = backends or { } +backends.pdf = backends.pdf or { } + +--~ function backends.pdf.startscaling(sx,sy) +--~ return nodes.pdfliteral(string.format("q %s 0 0 %s 0 0 cm",(sx ~= 0 and sx) or .0001,(sy ~= 0 and sy) or .0001)) +--~ end +--~ function backends.pdf.stopscaling() +--~ return nodes.pdfliteral("%Q") +--~ end + +function backends.pdf.insertmovie(data) + data = data or figures.current() + local dr, du, ds = data.request, data.used, data.status + local width, height, factor = du.width or dr.width, du.height or dr.height, number.dimenfactors.bp + local options, actions = "", "" + if dr["repeat"] then + actions = actions .. "/Mode /Repeat " + end + if dr.controls then + actions = actions .. "/ShowControls true " + else + actions = actions .. "/ShowControls false " + end + if dr.preview then + options = options .. "/Poster true " + end + if actions ~= "" then + actions= "/A <<" .. actions .. ">>" + end + tex.sprint(tex.ctxcatcodes, string.format( + "\\doPDFannotation{%ssp}{%ssp}{/Subtype /Movie /Border [0 0 0] /T (movie %s) /Movie << /F (%s) /Aspect [%s %s] %s>> %s}", + width, height, dr.label, du.foundname, factor * width, factor * height, options, actions + )) + return data +end + +--~ if node then do +--~ local n = node.new(0,0) +--~ local m = getmetatable(n) +--~ m.__concat = function(a,b) +--~ local t = node.slide(a) +--~ t.next, b.prev = b, t +--~ return a +--~ end +--~ node.free(n) +--~ end end + +--- some extra img functions --- + +function img.totable(i) + local t = { } + for _, v in ipairs(img.keys()) do + t[v] = i[v] + end + return t +end + +function img.serialize(i) + return table.serialize(img.totable(i)) +end + +function img.clone(i,data) + i.width = data.width or i.width + i.height = data.height or i.height + -- attr etc + return i +end + +local validsizes = table.tohash(img.boxes()) +local validtypes = table.tohash(img.types()) + +function img.check_size(size) + if size then + size = size:gsub("box","") + return (validsizes[size] and size) or "crop" + else + return "crop" + end +end + +--- + +figures = figures or { } +figures.loaded = figures.loaded or { } +figures.used = figures.used or { } +figures.found = figures.found or { } +figures.suffixes = figures.suffixes or { } +figures.patterns = figures.patterns or { } +figures.boxnumber = figures.boxid or 0 +figures.trace = false +figures.defaultsearch = true +figures.defaultwidth = 0 +figures.defaultheight = 0 +figures.defaultdepth = 0 +figures.n = 0 + +figures.localpaths = { + ".", "..", "../.." +} +figures.cachepaths = { + prefix = "", + path = ".", + subpath = ".", +} + +figures.paths = table.copy(figures.localpaths) + +figures.order = { + "pdf", "mps", "jpg", "png", "jbig", "svg", "eps", "mov", "buffer", "tex" +} + +figures.formats = { + ["pdf"] = { }, + ["mps"] = { patterns = { "%d+" } }, + ["jpg"] = { list = { "jpg", "jpeg" } }, + ["png"] = { } , + ["jbig"] = { list = { "jbig", "jbig2", "jb2" } }, + ["svg"] = { list = { "svg", "svgz" } }, + ["eps"] = { list = { "eps", "ai" } }, + ["mov"] = { list = { "mov", "avi" } }, + ["buffer"] = { list = { "tmp", "buffer", "buf" } }, + ["tex"] = { }, +} + +function figures.setlookups() + figures.suffixes, figures.patterns = { }, { } + for _, format in pairs(figures.order) do + local data = figures.formats[format] + local fs, fp = figures.suffixes, figures.patterns + if data.list then + for _, s in ipairs(data.list) do + fs[s] = format -- hash + end + else + fs[format] = format + end + if data.patterns then + for _, s in ipairs(data.patterns) do + fp[#fp+1] = { s, format } -- array + end + end + end +end + +figures.setlookups() + +local function register(tag,target,what) + local data = figures.formats[target] + if data then + local d = data[tag] + if d and not table.contains(d,what) then + d[#d+1] = what + else + data[tag] = { what } + end + else + figures.formats[target] = { } + end + figures.setlookups() +end + +function figures.registersuffix (suffix, target) register('list', target,suffix ) end +function figures.registerpattern(pattern,target) register('pattern',target,pattern) end + +local pathhash = { } + +function figures.setpaths(locationset,pathlist) + local ph, iv, t = pathhash[locationset], interfaces.variables, nil + if ph then + ph = ph[pathlist] + if ph then + figures.paths = ph + return + end + end + if not ph then + ph = { } + pathhash[locationset] = ph + end + local h = locationset:tohash() + t = (h[iv["local"]] and figures.localpaths) or { } + if h[iv["global"]] then + for s in pathlist:gmatch("([^, ]+)") do + t[#t+1] = s + end + end + figures.defaultsearch = h[iv["default"]] + ph[pathlist] = t + figures.paths = t +end + +-- check conversions and handle it here + +--~ local keys = img.keys() + +--~ function figures.hash(data) +--~ local i = data.status.private +--~ local t = { } +--~ for _, v in ipairs(keys) do +--~ local iv = i[v] +--~ if iv then +--~ t[#t+1] = v .. '=' .. iv +--~ end +--~ end +--~ return table.concat(t,"+") +--~ end + +function figures.hash(data) + return data.status.fullname .. "+".. (data.request.page or 1) -- img is still not perfect +end + +-- interfacing to tex + +do + + local figuredata = { } + local callstack = { } + + function figures.new() + figuredata = { + request = { + name = false, + label = false, + format = false, + page = false, + width = false, + height = false, + preview = false, + ["repeat"] = false, + controls = false, + display = false, + conversion = false, + cache = false, + prefix = false, + size = false, + }, + used = { + fullname = false, + format = false, + name = false, + path = false, + suffix = false, + width = false, + height = false, + }, + status = { + status = 0, + converted = false, + cached = false, + fullname = false, + format = false, + }, + } + return figuredata + end + + function figures.push(request) + input.starttiming(figures) + local figuredata = figures.new() + if request then + local iv = interfaces.variables + local w, h = tonumber(request.width), tonumber(request.heiht) + request.page = math.max(tonumber(request.page) or 1,1) + request.size = img.check_size(request.size) + request.object = iv[request.object] == "yes" + request["repeat"] = iv[request["repeat"]] == "yes" + request.preview = iv[request.preview] == "yes" + request.cache = request.cache ~= "" and request.cache + request.prefix = request.prefix ~= "" and request.prefix + request.format = request.format ~= "" and request.format + request.width = (w and w > 0) or false + request.height = (h and h > 0) or false + table.merge(figuredata.request,request) + end + callstack[#callstack+1] = figuredata + return figuredata + end + function figures.pop() + figuredata = callstack[#callstack] + callstack[#callstack] = nil + input.stoptiming(figures) + end + -- maybe move tex.sprint to tex + function figures.get(category,tag,default) + local value = figuredata[category][tag] + if not value or value == "" or value == true then + return default or "" + else + return value + end + end + function figures.tprint(category,tag,default) + tex.sprint(tex.ctxcatcodes,figures.get(category,tag,default)) + end + function figures.current() + return callstack[#callstack] + end + +end + +do + + local function register(askedname,specification) + if specification then + local format = specification.format + if format then + local converter = figures.converters[format] + if converter then + local oldname = specification.fullname + local newpath = file.dirname(oldname) + local newbase = file.replacesuffix(file.basename(oldname),"pdf") -- todo + local fc = specification.cache or figures.cachepaths.path + if fc and fc ~= "" and fc ~= "." then + newpath = fc + end + local subpath = specification.subpath or figures.cachepaths.subpath + if subpath and subpath ~= "" and subpath ~= "." then + newpath = newpath .. "/" .. subpath + end + local prefix = specification.prefix or figures.cachepaths.prefix + if prefix and prefix ~= "" then + newbase = prefix .. newbase + end + local newname = file.join(newpath,newbase) + dir.makedirs(newpath) + local oldtime = lfs.attributes(oldname,'modification') or 0 + local newtime = lfs.attributes(newname,'modification') or 0 + if oldtime > newtime then + converter(oldname,newname) + end + if io.exists(newname) then + specification.foundname = oldname + specification.fullname = newname + specification.prefix = prefix + specification.subpath = subpath + specification.converted = true + elseif exists(oldname) then + specification.fullname = newname + specification.converted = false + end + end + end + specification.found = true -- ? + else + specification = { } + end + specification.foundname = specification.foundname or specification.fullname + figures.found[askedname] = specification + return specification + end + + local function locate(request) -- name, format, cache + local askedname = input.clean_path(request.name) + if figures.found[askedname] then + return figures.found[askedname] + end + local askedpath= file.dirname(askedname) + local askedbase = file.basename(askedname) + local askedformat = (request.format ~= "" and request.format ~= "unknown" and request.format) or file.extname(askedname) + local askedcache = request.cache + if askedformat ~= "" then + askedformat = askedformat:lower() + local format = figures.suffixes[askedformat] + if not format then + for _, pattern in ipairs(figures.patterns) do + if askedformat:find(pattern[1]) then + format = pattern[2] + break + end + end + end + if format then + local foundname = figures.exists(askedname,askedformat) + if foundname then + return register(askedname, { + askedname = askedname, + fullname = askedname, + format = format, + cache = askedcache, + foundname = foundname, + }) + end + end + if askedpath ~= "" then + -- path and type given, todo: strip pieces of path + if figures.exists(askedname,askedformat) then + return register(askedname, { + askedname = askedname, + fullname = askedname, + format = askedformat, + cache = askedcache, + }) + end + else + -- type given + for _, path in ipairs(figures.paths) do + local check = path .. "/" .. askedname + if figures.exists(askedname,askedformat) then + return register(check, { + askedname = askedname, + fullname = check, + format = askedformat, + cache = askedcache, + }) + end + end + if figures.defaultsearch then + local check = input.find_file(texmf.instance,askedname) + if check and check ~= "" then + return register(askedname, { + askedname = askedname, + fullname = check, + format = askedformat, + cache = askedcache, + }) + end + end + end + elseif askedpath ~= "" then + for _, format in ipairs(figures.order) do + local list = figures.formats[format].list or { format } + for _, suffix in ipairs(list) do + local check = file.addsuffix(askedname,suffix) + if figures.exists(check,format) then + return register(askedname, { + askedname = askedname, + fullname = check, + format = format, + cache = askedcache, + }) + end + end + end + else + for _, format in ipairs(figures.order) do + local list = figures.formats[format].list or { format } + for _, suffix in ipairs(list) do + local name = file.replacesuffix(askedbase,suffix) + for _, path in ipairs(figures.paths) do + local check = path .. "/" .. name + if figures.exists(check,format) then + return register(askedname, { + askedname = askedname, + fullname = check, + format = format, + cache = askedcache, + }) + end + end + if figures.defaultsearch then + local check = input.find_file(texmf.instance,file.replacesuffix(askedname,suffix)) + if check and check ~= "" then + return register(askedname, { + askedname = askedname, + fullname = check, + format = format, + cache = askedcache, + }) + end + end + end + end + end + return register(askedname) + end + + -- -- -- plugins -- -- -- + + figures.existers = figures.existers or { } + figures.checkers = figures.checkers or { } + figures.includers = figures.includers or { } + figures.converters = figures.converters or { } + figures.identifiers = figures.identifiers or { } + + figures.identifiers.list = { + figures.identifiers.default + } + + function figures.identifiers.default(data) + local dr, du, ds = data.request, data.used, data.status + local l = locate(dr) + local foundname = l.foundname + local fullname = l.fullname or foundname + if fullname then + du.format = l.format or false + du.fullname = fullname -- can be cached + ds.fullname = foundname -- original + ds.format = l.format + ds.status = (l.found and 10) or 0 + end + return data + end + + function figures.identify(data) + data = data or figures.current() + for _, identifier in ipairs(figures.identifiers.list) do + data = identifier(data) + if data.status.status > 0 then + break + end + end + return data + end + function figures.exists(askedname,format) + return (figures.existers[format] or figures.existers.generic)(askedname) + end + function figures.check(data) + data = data or figures.current() + local dr, du, ds = data.request, data.used, data.status + return (figures.checkers[ds.format] or figures.checkers.generic)(data) + end + function figures.include(data) + data = data or figures.current() + local dr, du, ds = data.request, data.used, data.status + return (figures.includers[ds.format] or figures.includers.generic)(data) + end + function figures.scale(data) -- will become lua code + tex.sprint(tex.ctxcatcodes,"\\doscalefigure") + return data + end + function figures.done(data) + figures.n = figures.n + 1 + data = data or figures.current() + local dr, du, ds = data.request, data.used, data.status + ds.width = tex.wd[figures.boxnumber] + ds.height = tex.ht[figures.boxnumber] + ds.xscale = ds.width/(du.width or 1) + ds.yscale = ds.height/(du.height or 1) + return data + end + + function figures.dummy(data) -- fails +--~ data = data or figures.current() +--~ local dr, du, ds = data.request, data.used, data.status +--~ local r = node.new("rule") +--~ r.width = du.width or figures.defaultwidth +--~ r.height = du.height or figures.defaultheight +--~ r.depth = du.depth or figures.defaultdepth +--~ tex.box[figures.boxnumber] = node.write(r) + tex.sprint(tex.ctxcatcodes,"\\emptyfoundexternalfigure") + end + +end + +-- -- -- generic -- -- -- + +function figures.existers.generic(askedname) +--~ local result = io.exists(askedname) +--~ result = (result==true and askedname) or result +--~ local result = input.find_file(texmf.instance,askedname) or "" + local result = input.findbinfile(texmf.instance,askedname) or "" + if result == "" then result = false end + if figures.trace then + if result then + logs.report("figures", "found:" .. askedname .. " ->" .. result) + else + logs.report("figures", "not found:" .. askedname) + end + end + return result +end +function figures.checkers.generic(data) + local dr, du, ds = data.request, data.used, data.status + local name, page = du.fullname or "unknown generic", dr.page + local hash = name .. "->" .. page + local figure = figures.loaded[hash] + if figure == nil then + figure = img.new { filename = name, page = page } + figure = (figure and img.scan(figure)) or false + figures.loaded[hash] = figure + end + if figure then + du.width = figure.width + du.height = figure.height + du.pages = figure.pages + ds.private = figure + end + return data +end +function figures.includers.generic(data) + local dr, du, ds = data.request, data.used, data.status + dr.width = dr.width or du.width + dr.height = dr.height or du.height + local hash = figures.hash(data) + local figure = figures.used[hash] + if figure == nil then + figure = ds.private + if figure then +--~ figure.page = dr.page or '1' + figure = img.copy(figure) + figure = (figure and img.clone(figure,data.request)) or false + end + figures.used[hash] = figure + end + if figure then + tex.box[figures.boxnumber] = img.node(figure) -- img.write(figure) + ds.objectnumber = figure.objnum + end + return data +end + +-- -- -- nongeneric -- -- -- + +function figures.checkers.nongeneric(data,command) + local dr, du, ds = data.request, data.used, data.status + local name = du.fullname or "unknown nongeneric" + local hash = name + if dr.object then + if not job.objects["FIG::"..hash] then + tex.sprint(tex.ctxcatcodes,command) + tex.sprint(tex.ctxcatcodes,string.format("\\setobject{FIG}{%s}\\vbox{\\box\\foundexternalfigure}",hash)) + end + tex.sprint(tex.ctxcatcodes,string.format("\\global\\setbox\\foundexternalfigure\\vbox{\\getobject{FIG}{%s}}",hash)) + else + tex.sprint(tex.ctxcatcodes,command) + end + return data +end +function figures.includers.nongeneric(data) + return data +end + +-- -- -- mov -- -- -- + +function figures.checkers.mov(data) + local dr, du, ds = data.request, data.used, data.status + du.width = dr.width or figures.defaultwidth + du.height = dr.height or figures.defaultheight + du.foundname = du.fullname + tex.sprint(tex.ctxcatcodes,string.format("\\startfoundexternalfigure{%ssp}{%ssp}",du.width,du.height)) + data = backends.pdf.insertmovie(data) + tex.sprint(tex.ctxcatcodes,"\\stopfoundexternalfigure") + return data +end +figures.includers.mov = figures.includers.nongeneric + +-- -- -- mps -- -- -- + +function figures.checkers.mps(data) + return figures.checkers.nongeneric(data,string.format("\\docheckfiguremps{%s}",data.used.fullname)) +end +figures.includers.mps = figures.includers.nongeneric + +-- -- -- buffer -- -- -- + +function figures.existers.buffer(askedname) + askedname = file.nameonly(askedname) + return buffers.exists(askedname) and askedname +end +function figures.checkers.buffer(data) + return figures.checkers.nongeneric(data,string.format("\\docheckfigurebuffer{%s}", file.nameonly(data.used.fullname))) +end +figures.includers.buffers = figures.includers.nongeneric + +-- -- -- tex -- -- -- + +function figures.existers.tex(askedname) + askedname = input.find_file(texmf.instance,askedname) + return (askedname ~= "" and askedname) or false +end +function figures.checkers.tex(data) + return figures.checkers.nongeneric(data,string.format("\\docheckfiguretex{%s}", data.used.fullname)) +end +figures.includers.tex = figures.includers.nongeneric + +-- -- -- eps -- -- -- + +function figures.converters.eps(oldname,newname) + -- hack, we need a lua based converter script, or better, we should use + -- rlx as alternative + local outputpath = file.dirname(newname) + local outputbase = file.basename(newname) + local command = string.format("mtxrun bin:pstopdf --outputpath=%s %s",outputpath,oldname) + os.spawn(command) +end + +figures.converters.svg = figures.converters.eps + +-- -- -- lowres -- -- -- + +--~ function figures.converters.pdf(oldname,newname) +--~ local outputpath = file.dirname(newname) +--~ local outputbase = file.basename(newname) +--~ local command = string.format("mtxrun bin:pstopdf --method=4 --outputpath=%s %s",outputpath,oldname) +--~ os.spawn(command) +--~ end + + +figures.bases = { } +figures.bases.list = { } -- index => { basename, fullname, xmlroot } +figures.bases.used = { } -- [basename] => { basename, fullname, xmlroot } -- pointer to list +figures.bases.found = { } +figures.bases.enabled = false + +function figures.bases.use(basename) + if basename == "reset" then + figures.bases.list = { } + figures.bases.used = { } + figures.bases.found = { } + figures.bases.enabled = false + else + basename = file.addsuffix(basename,"xml") + if not figures.bases.used[basename] then + local t = { basename, nil, nil } + figures.bases.used[basename] = t + figures.bases.list[#figures.bases.list+1] = t + if not figures.bases.enabled then + figures.bases.enabled = true + xml.registerns("rlx","http://www.pragma-ade.com/schemas/rlx") -- we should be able to do this per xml file + end + end + end +end + +function figures.bases.find(basename,askedlabel) + basename = file.addsuffix(basename,"xml") + local t = figures.bases.found[askedlabel] + if t == nil then + local base = figures.bases.used[basename] + local page = 0 + if base[2] == nil then + -- no yet located + for _, path in ipairs(figures.paths) do + local xmlfile = path .. "/" .. basename + if io.exists(xmlfile) then + base[2] = xmlfile + base[3] = xml.load(xmlfile) + break + end + end + end + t = false + if base[2] and base[3] then + for e, d, k in xml.elements(base[3],"/(rlx:library|figurelibrary)/*:figure/*:label") do + page = page + 1 + if xml.content(d[k]) == askedlabel then + t = { + base = file.replacesuffix(base[2],"pdf"), + format = "pdf", + name = xml.filters.text(e,"*:file"), + page = page, + } + figures.bases.found[askedlabel] = t + break + end + end + end + figures.bases.found[askedlabel] = t + end + return t +end + +-- we can access sequential or by name + +function figures.bases.locate(askedlabel) + for _, entry in ipairs(figures.bases.list) do + local t = figures.bases.find(entry[1],askedlabel) + if t then + return t + end + end + return false +end + +function figures.identifiers.base(data) + if figures.bases.enabled then + local dr, du, ds = data.request, data.used, data.status + local fbl = figures.bases.locate(dr.name or dr.label) + if fbl then + du.page = fbl.page + du.format = fbl.format + du.fullname = fbl.base + ds.fullname = fbl.name + ds.format = fbl.format + ds.status = 10 + end + end + return data +end + +figures.identifiers.list = { + figures.identifiers.base, + figures.identifiers.default +} diff --git a/tex/context/base/core-inc.mkii b/tex/context/base/core-inc.mkii new file mode 100644 index 000000000..fe3894d57 --- /dev/null +++ b/tex/context/base/core-inc.mkii @@ -0,0 +1,1326 @@ +%D \module +%D [ file=core-inc, % moved from core-fig +%D version=2006.08.26, % overhaul of 1997.03.31 +%D title=\CONTEXT\ Core Macros, +%D subtitle=Figure Inclusion, +%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. + +% todo: directory : system -> \allinputpaths (so that we can \usesubpath) + +%D This is a reimplementation of the original module, which +%D over time had evolved into a pretty complex whole. This +%D was partly due to the fact that we needed to handle many +%D formats, deal with substitute graphics, handle fallbacks +%D and driver specifics (objects), etc. In the meantime we +%D have more clever backends, moved away from texutil to +%D rlxtools, can use runtime or betweentime runs etc. Also, +%D more memory permits a cleaner implementation. Time to +%D move on. We can now also assume that scaling is available. +%D +%D Another mess that can go is the llx/lly handling since +%D drivers now automatically can determine such things. + +%D Messages 3 and 5 needs to be translated! + +\unprotect + +\startmessages dutch library: figures + title: figuren + 1: figuur -- is niet te vinden + 2: figuur -- wordt niet preset + 3: maten van -- worden extern vastgesteld + 4: maten van -- geladen uit figuurfile zelf + 5: maten van -- zijn onbekend + 6: maten van -- berekend door rlxtools + 8: figuurobject -- wordt opnieuw gebruikt +\stopmessages + +\startmessages english library: figures + title: figures + 1: figure -- can not be found + 2: figure -- is not preset + 3: dimensions of -- are determined externally + 4: dimensions of -- loaded from figurefile itself + 5: dimensions of -- are unknown + 6: dimensions of -- calculated by rlxtools + 8: figureobject -- is reused +\stopmessages + +\startmessages german library: figures + title: Abbildungen + 1: Abbildung -- kann nicht gefunden werden + 2: Abbildung -- wird nicht erstellt + 3: dimensions of -- are determined externally + 4: Dimensionen von -- geladen aus der Abbildungsdatei selbst + 5: Dimensions of -- are unknown + 6: Dimensionen von -- ausgerechnet durch rlxtools + 8: Abbildungobjekt -- wurde wiederverwandt +\stopmessages + +\startmessages czech library: figures + title: obrazy + 1: obraz -- nelze nalezt + 2: obraz -- nepritomen + 3: dimensions of -- are determined externally + 4: dimenze obrazu -- nacteny primo z jeho souboru + 5: dimensions of -- are unknown + 6: dimenze obrazu -- spocteny programem rlxtools + 8: obrazovy objekt -- je znovu pouzit +\stopmessages + +\startmessages italian library: figures + title: figure + 1: figura -- non trovata + 2: la figura -- non è preimpostata + 3: dimensions of -- are determined externally + 4: dimensioni di -- caricate dal file di immagini stesso + 5: dimensions of -- are unknown + 6: dimensioni di -- calcolate da rlxtools + 8: oggetto-figura -- riutilizzato +\stopmessages + +\startmessages romanian library: figures + title: figuri + 1: figura -- nu poate fi gasita + 2: figura -- nu este presetata + 3: dimensions of -- are determined externally + 4: dimensiunea figurii -- se incarca din fisierul insusi + 5: dimensions of -- are unknown + 6: dimensiunea figurii -- este calculata de rlxtools + 8: obiectul figura -- este refolosit +\stopmessages + +\startmessages french library: figures + title: figures + 1: la figure -- ne peut être trouvée + 2: la figure -- n'est pas pré-sélectionnée + 3: dimensions of -- are determined externally + 4: les dimensions de -- chargées implicitement à partir du fichier de figure + 5: dimensions of -- are unknown + 6: les dimensions de -- calculées par rlxtools + 8: figureobject -- est réutilisé +\stopmessages + +%D Due to the mere fact that \DVI|/|\PDF\ drivers differ in their +%D needs for figure dimensions, we have to provide the width, +%D height, horizontal and vertical scale. Also we want to +%D specify at the user level either width and|/|or height, scale, +%D or a factor related to the current document bodyfont size. +%D Even better: we can also specify isometric scaling and +%D automatically let \CONTEXT\ calculate the maximum possible +%D dimensions. Whatever we calculate, the results will come +%D available in the next registers. + +\letempty \@@DriverImageBox +\letempty \@@DriverImageOptions +\letempty \@@DriverImageWidth +\letempty \@@DriverImageHeight +\letempty \@@DriverImageFile +\letempty \@@DriverImageLabel +\letempty \@@DriverImageType +\letempty \@@DriverImageMethod +\letempty \@@DriverImagePage + +%D Because looking for dimensions can take many steps (locating +%D the figure, maybe on more directories, scanning the figure +%D on dimension, or when not found, trying to find them in the +%D utility file, and again when not found, trying to generate +%D such a file, and, as a last resort, trying to use the +%D dimensions. Now when things do not work out the way we want, +%D we can set a switch and get some information on what takes +%D place. + +\newif\iftraceexternalfigures + +\let\traceexternalfigures\traceexternalfigurestrue + +\def\doshowfigurestate + {\iftraceexternalfigures + \expandafter\writestatus\expandafter\m!figures + \else + \expandafter\gobbleoneargument + \fi} + +\def\doshowfiguremessage + {\iftraceexternalfigures + \expandafter\gobbletwoarguments + \else + \expandafter\showmessage\expandafter\m!figures + \fi} + +%D Another switch tells \CONTEXT\ to locate and calculate a +%D figure, but does not actually insert it. Especially when we +%D use \PDFTEX\ this saves a lot of time on trialruns. (Keep +%D in mind that \PDFTEX\ is both a \TEX\ pre|| and postprocessor.) + +\newif\ifskipexternalfigures % can be set elsewhere + +% \newif\ifrunutilityfile +% \newif\ifconsultutilityfile +% +% Let's save two hash entries: + +\let\runutilityfiletrue \relax \let\runutilityfilefalse \relax +\let\consultutilityfiletrue\relax \let\consultutilityfilefalse\relax + +%D Intermediate, private. + +\newdimen\determinedfigurewidth +\newdimen\determinedfigureheight + +\let\naturalfigureheight\!!zeropoint +\let\naturalfigurewidth \!!zeropoint + +\def\defaultfigurewidth {8\lineheight} +\def\defaultfigureheight{6\lineheight} + +\def\defaultfigurepathsignal{(\v!default)} + +\def\checknaturalfiguredimensions + {\edef\naturalfigurewidth{\the\dimexpr\ifzeropt\determinedfigurewidth + \defaultfigurewidth \else\determinedfigurewidth \fi\relax}% + \edef\naturalfigureheight{\the\dimexpr\ifzeropt\determinedfigureheight + \defaultfigureheight\else\determinedfigureheight\fi\relax}} + +%D Locating figures. Dilemma: we do support eps and svg parsing but drivers +%D don't always support it. + +\def\figuretypes{\c!mps,\c!pdf,\c!eps,\c!svg,\c!svg z,\c!png,\c!tif,jb2,\c!jpg} + +\def\supportedfiguretypes{\figuretypes} + +\def\checksupportedfiguretypes + {\begingroup + \global\let\supportedfiguretypes\empty + \def\docommand##1% + {\doiffileinsertionsupportedelse{##1} + {\doglobal\addtocommalist{##1}\supportedfiguretypes} + \donothing}% + \processcommacommand[\figuretypes]\docommand + \gdef\checksupportedfiguretypes{\let\figuretypes\supportedfiguretypes}% + \endgroup + \checksupportedfiguretypes} + +%D The next box is used to store the graphic. It's globally assigned. + +\newbox\foundexternalfigure + +\chardef\figurestatus\zerocount % nothing found + +\def\noffigurepages{\nofinsertpages} + +%D Variables. + +\newtoks\everyexternalfigureresets + +\def\resetfigurevariables + {\the\everyexternalfigureresets} + +%D Example usage: + +\appendtoks + \global\let\externalfigurelog\empty +\to\everyexternalfigureresets + +%D Intermediate, private + +\def\resetprivatefigurevariables + {\let \wantedfigurefull \empty + \let \wantedfigurepath \empty + \let \wantedfigurename \empty + \let \wantedfigurebase \empty + \let \wantedfiguretype \empty + \let \wantedfigurefullname \empty + \let \wantedfiguretypespec \empty + \let \wantedfiguremethod \empty + \let \wantedfigurepage \empty + \let \wantedfigureoptions \empty + \let \wantedfigureconversion\empty + \let \wantedfigureprefix \empty + \let \wantedfiguretypelist \figuretypes + \let \figurepathlist \empty + \chardef \figurestatus \zerocount + \let \expandedfigurename \empty + \global\let \analyzedfigurewidth \!!zeropoint % set by indentifying code + \global\let \analyzedfigureheight \!!zeropoint % set by indentifying code + \global\setbox\foundexternalfigure \emptybox + \def \frozenfigurestamp {\externalfigurestamp}} % no edef + +\resetprivatefigurevariables + +\appendtoks + \resetprivatefigurevariables +\to\everyexternalfigureresets + +%D Private/public. + +\def\resetpublicfigurevariables + {\let\figurewidth \!!zeropoint + \let\figureheight \!!zeropoint + \let\figurenaturalwidth \!!zeropoint + \let\figurenaturalheight \!!zeropoint + \let\figurelabel \empty + \let\figurefileoriginal \empty + \let\figurefileoptions \empty + \let\figurefilename \empty + \let\figurefiletype \empty + \let\figurefilepage \!!zerocount + \let\figurefileconversion\empty + \let\figurefileprefix \empty + \let\figurefilepath \empty + \let\figurefilecache \empty} + +\resetpublicfigurevariables + +\appendtoks + \resetpublicfigurevariables +\to\everyexternalfigureresets + +\newcounter\figurenestinglevel + +\def\pushpublicfigurevariables + {\ifcase\figurenestinglevel\else + \doshowfigurestate{variables : push}% + \globalpushmacro\figurewidth + \globalpushmacro\figureheight + \globalpushmacro\figurenaturalwidth + \globalpushmacro\figurenaturalheight + \globalpushmacro\figurelabel + \globalpushmacro\figurefileoriginal + \globalpushmacro\figurefileoptions + \globalpushmacro\figurefilename + \globalpushmacro\figurefiletype + \globalpushmacro\figurefilepage + \globalpushmacro\figurefileconversion + \globalpushmacro\figurefileprefix + \globalpushmacro\figurefilepath + \globalpushmacro\figurefilecache + \fi} + +\def\poppublicfigurevariables + {\ifcase\figurenestinglevel\else + \doshowfigurestate{variables : pop}% + \globalpopmacro\figurefilecache + \globalpopmacro\figurefilepath + \globalpopmacro\figurefileprefix + \globalpopmacro\figurefileconversion + \globalpopmacro\figurefilepage + \globalpopmacro\figurefiletype + \globalpopmacro\figurefilename + \globalpopmacro\figurefileoptions + \globalpopmacro\figurefileoriginal + \globalpopmacro\figurelabel + \globalpopmacro\figurenaturalheight + \globalpopmacro\figurenaturalwidth + \globalpopmacro\figureheight + \globalpopmacro\figurewidth + \fi} + +\def\setpublicfigurevariables % todo: type vs typespec + {\xdef\figurewidth {\the\wd\foundexternalfigure}% + \xdef\figureheight {\the\ht\foundexternalfigure}% + \xdef\figurenaturalwidth {\naturalfigurewidth}% + \xdef\figurenaturalheight {\naturalfigureheight}% + \xdef\figurelabel {\wantedfigurelabel}% + \xdef\figurefilepath {\wantedfigurepath}% + \xdef\figurefilename {\wantedfigurename}% + \xdef\figurefiletype {\wantedfiguretypespec}% + \xdef\figurefilepage {\wantedfigurepage}% + \xdef\figurefileoptions {\wantedfigureoptions}% + \xdef\figurefileconversion{\wantedfigureconversion}% + \xdef\figurefilecache {\wantedconversioncache}% + \xdef\figurefileprefix {\wantedconversionprefix}% + \xdef\figurefileoriginal {\wantedconversionname}% + \xdef\figurefullname {\wantedfigurepath/\wantedfigurename.\wantedfiguretypespec}% + \ifcase\figurestatus + \let\figurefiletype\empty % ? + \fi} + +\def\setpublicfigurescalevariables + {\edef\figurescalewidth {\finalscaleboxwidth }% + \edef\figurescaleheight {\finalscaleboxheight}% + \edef\figurescalexscale {\finalscaleboxxscale}% + \edef\figurescaleyscale {\finalscaleboxyscale}} + +\def\resetpublicfigurescalevariables + {\let\figurescalewidth \!!zeropoint + \let\figurescaleheight \!!zeropoint + \let\figurescalexscale \!!plusone + \let\figurescaleyscale \!!plusone} + +\resetpublicfigurescalevariables + +\appendtoks + \resetpublicfigurescalevariables +\to \everyexternalfigureresets + +%D The next one is for instance used in symbols. Since +%D we only need to reset some parameters, we can +%D better use the fast alternative: +%D +%D \starttyping +%D \def\resetexternalfigures +%D {\getparameters[\??ef] +%D [\c!option=,\c!maxwidth=,\c!maxheight=, +%D \c!foregroundcolor=,\c!color=, +%D %\c!conversion=,\c!prefix=,\c!splitcolor=, +%D \c!frame=\v!off,\c!background=]} +%D \stoptyping +%D +%D This one dropped the runtime of the \MAPS\ bibliography +%D from over 110 seconds down to less than 105 seconds. The +%D tremendously faster (but uglier) implementation is: + +\def\resetexternalfigures + {\let\@@efoption \empty % \let\@@efprefix\empty + \let\@@efmaxwidth \empty % \let\@@efcache \empty + \let\@@efmaxheight \empty % \let\@@efframe \v!off + \let\@@efforegroundcolor\empty + \let\@@efcolor \empty + \let\@@efconversion \empty + \let\@@efbackground \empty} + +%D The following code will move: + +\appendtoks \resetexternalfigures \to \everyoverlay +\appendtoks \resetexternalfigures \to \everybeforepagebody % not really needed +%appendtoks \resetexternalfigures \to \everysymbol + +%D We need this one for bookkeeping: + +\newcounter\forcedMPSobject % better something \every + +%D Features: + +% converted -> prefix, suffix +% alternative -> other suffix +% buffer -> prefix + +%D Still messy: + +\newtoks\everyfiguretypepresets + +\def\presetfiguretypeprocessing + {\the\everyfiguretypepresets} + +\def\presetspecialfigure#1% + {\doif\wantedfiguretype{#1}% + {\let\@@efobject\v!no + \let\@@efpreset\v!no + \ifx\@@efwidth \empty\def\@@efwidth {\defaultfigurewidth }\fi + \ifx\@@efheight\empty\def\@@efheight{\defaultfigureheight}\fi}} + +\appendtoks + \presetspecialfigure\c!mov + \presetspecialfigure\c!avi +\to \everyfiguretypepresets + +\def\checkformpsfigurefiles % to be checked + {\doif\wantedfigurename{mprun} + {\doshowfigurestate{type check : forcing mps (mprun)}% + \doifnotinstring{^\bufferprefix}{^\wantedfigurename} + {\edef\wantedfigurename{\bufferprefix\wantedfigurename}}% + \let\wantedfiguremethod \c!mps + \let\wantedfiguretypespec\c!mps}% + \doifnumberelse\wantedfiguretype + {\doshowfigurestate{type check : forcing mps (number)}% + \let\wantedfiguremethod \c!mps + \let\wantedfiguretypespec\c!mps} + \donothing + \doif\wantedfiguretypespec\c!mps + {\let\wantedfiguretypelist\wantedfiguretypespec + \ifcase\EPSspecial\else\ifinobject\else + \doglobal\increment\forcedMPSobject + \edef\externalfigurestamp{\c!mps::\forcedMPSobject}% + \let\@@efobject\v!yes + \fi\fi}} + +\appendtoks + \checkformpsfigurefiles +\to \everyfiguretypepresets + +\def\checkfortexfigurefiles % to be checked (brrr: c!) / brrr: eftype + {\doifinset\wantedfiguretype{\c!tex,\c!tmp} + {\let\wantedfiguretypespec \wantedfiguretype}% + \doifinset\wantedfiguretypespec{\c!tex,\c!tmp,\v!buffer} + {\doshowfigurestate{type check : forcing tex (\wantedfiguretypespec)}% + \let\wantedfiguretypelist\wantedfiguretypespec + \let\wantedfiguremethod \c!tex + \let\@@efobject\v!no + \doifnothing\wantedfiguretype{\let\wantedfiguretype\c!tmp}% + % there can be a non buffer \jobname.tmp (made by texexec) + \doifnotinstring{^\bufferprefix}{^\wantedfigurename} + {\edef\wantedfigurename{\bufferprefix\wantedfigurename}}}} + +\appendtoks + \checkfortexfigurefiles +\to \everyfiguretypepresets + +\def\checkforunknownfigurefiles + {\doifnothing\wantedfiguretype + {\dogetcommacommandelement\plusone\from\@@eftype\to\commalistelement + \edef\wantedfigurefullname{\wantedfigurename.\commalistelement}}} + +\appendtoks + \checkforunknownfigurefiles +\to \everyfiguretypepresets + +% note * : this is needed because reusable graphics +% combined with funny page aspect aspect ratio's can lead to +% strange side effects of preceding factor=max specs. This +% surfaced in the metafun manual, where the two side by +% side clipped cow heads [the second one was a reused object] +% where the second one inherited some characteristics from +% the factor=max one some 30 pages back. Sigh. + +\chardef\splitexternalfigure\zerocount % 0 nosplit 1 split/yes 2 split/no + +\def\checkfigurecolorsettings + {% seperation, seldom used + \doifseparatingcolorselse + {\let\@@efforegroundcolor\empty + \doifelsenothing\@@efsplit + {\chardef\splitexternalfigure\zerocount} + {\doifcolorchannelelse\@@efsplit + {\let\@@efobject\v!no % why? + \chardef\splitexternalfigure\plusone} + {\chardef\splitexternalfigure\plustwo}}} + {\chardef\splitexternalfigure\zerocount}% + % fake color in gray bitmaps, assumes that + % a transparent color is used + \doifsomething\@@efforegroundcolor + {\def\@@efbackground{\v!foreground,\v!color}% + \def\@@efbackgroundcolor{\@@efforegroundcolor}}% + \doifsomething\@@efcolor + {\doifcolorelse\@@efcolor + {\checkpredefinedcolor[\@@efcolor]% + \doregisterfigurecolor\@@efcolor}}% + \donothing} + +\def\setextrafiguredriveroptions + {\let\@@DriverImageOptions\empty + \doifsomething\@@efpage {\addtocommalist\@@efpage \@@DriverImageOptions}% + \doif \@@efpreview \v!yes{\addtocommalist\v!preview \@@DriverImageOptions}% + \doif \@@efcontrols\v!yes{\addtocommalist\v!controls\@@DriverImageOptions}% + \doif \@@efrepeat \v!yes{\addtocommalist\v!repeat \@@DriverImageOptions}% + \doifinsetelse\@@efsize{mediabox,cropbox,artbox,bleedbox,trimbox} + {\let \@@DriverImageBox \@@efsize}% + {\doifinsetelse\@@efsize{media,crop,art,bleed,trim} + {\edef\@@DriverImageBox{\@@efsize box}}% + {\let \@@DriverImageBox \empty}}% + \let\wantedfigureoptions\@@DriverImageOptions} + +\def\checkiffigureobjectpresent + {\doifnot\@@efobject\v!no + {\doifobjectssupportedelse + {\doifobjectfoundelse{FIG}\externalfigurestamp + {\doshowfigurestate{object found : \externalfigurestamp}% + \getobjectdimensions{FIG}\externalfigurestamp + \edef\frozenfigurestamp{\externalfigurestamp}% + \xdef\analyzedfigurewidth {\the\dimexpr\objectwidth \relax}% + \xdef\analyzedfigureheight{\the\dimexpr\objectheight\relax}% + \setanalyzedfiguredimensions\plusone} + {\doshowfigurestate{unknown object: \externalfigurestamp}}} + {}}} + +\def\checkifknownfigureobjectpresent + {\ifx\wantedfiguretype\empty + \let\savedwantedfiguretype\wantedfiguretype + \def\docommand##1% + {\ifcase\figurestatus + \edef\wantedfiguretype{##1}% + \checkiffigureobjectpresent + \fi}% + \processcommacommand[\figuretypes]\docommand + \ifcase\figurestatus + \let\wantedfiguretype\savedwantedfiguretype + \fi + \fi} + +\def\checkforfigurefile + {\ifcase\figurestatus + \ifconditional\externalfigureflush + \analyzefigurefiles + \fi + \fi} + +\def\externalfigurestamp % needs \edef'd macros! + {\wantedfigurename + \ifx\wantedfiguretype\empty\else + \ifx\wantedfiguretype\s!unknown\else + -\wantedfiguretype + \fi + \fi + \ifx\wantedfiguretypespec\empty\else + \ifx\wantedfiguretypespec\s!unknown\else + \ifx\wantedfiguretypespec\wantedfiguretype\else + -\wantedfiguretypespec + \fi + \fi + \fi + \ifnum\wantedfigurepage>\zeropoint + -\wantedfigurepage + \fi} + +\def\checkfigurerenderingoptions + {\ifcase\figurestatus + \let\@@efframe\v!on + \fi + \doif\@@exoption\v!frame + {\let\@@efframe\v!on}% + \doif\@@exoption\v!empty + {\skipexternalfigurestrue + \let\@@efframe\v!off}} + +\newtoks\externalfigurepostprocessors + +\def\resetfigureusersettings + {\let\@@eftype \s!unknown \let\@@efmethod \empty \let\@@efpreset\v!yes + \let\@@eflabel \empty \let\@@efsize \empty \let\@@efpage \!!zerocount + \let\@@efobject \@@exobject \let\@@efdisplay \empty + \let\@@efsplit \empty \let\@@efcolor \empty \let\@@efsymbol\v!no + \let\@@efcontrols \v!no \let\@@efpreview \v!no \let\@@efrepeat\v!no + \let\@@efhfactor \empty \let\@@efwfactor \empty \let\@@effactor\empty + \let\@@efmaxwidth \@@exmaxwidth \let\@@efmaxheight\@@exmaxheight + \let\@@efxscale \empty \let\@@efyscale \empty \let\@@efscale \empty + \let\@@efsx \!!plusone \let\@@efsy \!!plusone + \let\@@efwidth \empty \let\@@efheight \empty + \let\@@eflines \empty \let\@@efgrid \empty + \let\@@efconversion\@@exconversion \let\@@efprefix \@@exprefix \let\@@efcache \@@excache} + +%D Types and Methods are a bit history. Anyhow, user scan use the +%D type to force the handler. So, what to do with the method. We can +%D use that one to force a handler with a given suffix, so when no +%D type is given, but a suffix is part of the name, the method will +%D determine the handler. + +\def\checkfigureusersettings + {\doif\@@efreset\v!yes\resetexternalfigures + \doifelsenothing\@@eflabel + {\doifnothing\wantedfigurelabel{\let\wantedfigurelabel\wantedfigurename}}% + {\let\wantedfigurelabel\@@eflabel}% + \doifsomething\@@eftype + {\doifnot\@@eftype\s!unknown + {\edef\wantedfiguretypespec{\@@eftype}% + \let\wantedfiguremethod\wantedfiguretypespec}}% + \doifnothing\wantedfigurepage % can be set by plug in + {\let\wantedfigurepage\@@efpage}% + \doif\wantedfigurepage\empty + {\let\wantedfigurepage\!!zerocount}% 0 is signal ! + \doifsomething\@@efmethod % rather untested misusage of the remapper + {\doifsomething\wantedfiguretype + {\definegraphictypesynonym[\wantedfiguretype][\@@method]}}} + +% #1 is now obsolete + +\def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% \cmd label filename parent_id preset current + {\doshowfigurestate{begin}% + \dontcomplain + % let's limit the search, which means that e.g. svg has to be given explicitly + \checksupportedfiguretypes + % recently added; we presume local use + \restorecatcodes + % collected resets (token list) + \resetfigurevariables +\resetwantedconversionvariables % new here + % analyze filename and set wanted variables + \analyzefigurefilename{#3}{#2}% + \doanalyzefiguredimensionsfromfile + % handle user settings + \resetfigureusersettings + \dosetefparameters{#4}{#5}{#6}% + \checkfigureusersettings + \checkfigurecolorsettings + % adapt settings based on suffix and/or type + \presetfiguretypeprocessing + % now we really start + \checkiffigureobjectpresent % first guess, we may not yet know the typespec + \checkifknownfigureobjectpresent + \checkforfigurefilepresence + \checkiffigureobjectpresent % to be sure, in case we now know the typespec + \checkfigurerenderingoptions % was later, moved here + \checknaturalfiguredimensions % inherit from global values and/or fallbacks + % by now we know what we're dealing with (put in box and scale) + \setextrafiguredriveroptions + \prepackageexternalfigureobject + % set public variables in case postprocessing needs them + \pushpublicfigurevariables + \setpublicfigurevariables + \setpublicfigureconversionvariables + \setpublicfigurescalevariables + % package final graphic, only now we can apply backgrounds and such + \doglobal\increment\figurenestinglevel + \finishexternalfigure + \doglobal\decrement\figurenestinglevel + % restore variables + \poppublicfigurevariables + \doshowfigurestate{end}} + +\def\checkforfigurefilepresence + {\checkforconvertedfigure + \checkforfigurefile} + +%D Figure objects. + +\def\setfigureobject + {\doshowfigurestate{object set : \externalfigurestamp}% + \setobject{FIG}\externalfigurestamp} + +% \def\getfigureobject +% {\doshowfigurestate{object used : \externalfigurestamp}% +% \getobject{FIG}\externalfigurestamp} + +\def\getfigureobject + {\doshowfigurestate{object used : \frozenfigurestamp}% + \getobject{FIG}\frozenfigurestamp} + +\def\prepackageexternalfigureobject + {\ifcase\figurestatus + \doshowfiguremessage1\expandedfigurename + \doshowfigurestate{state : figure not found (\expandedfigurename)}% + \global\setbox\foundexternalfigure\naturalvbox + {\doscalebox\??ef{\blackrule[\c!width=\naturalfigurewidth,\c!height=\naturalfigureheight]}}% + \or + \doshowfiguremessage8\expandedfigurename + \doshowfigurestate{state : reusing existing figure}% + \global\setbox\foundexternalfigure\naturalvbox + {\doscalebox\??ef{\dowithfigure{\getfigureobject}}}% + \xdef\noffigurepages{\number\getvalue{\externalfigurestamp\c!n}}% + \or + \doshowfiguremessage2\expandedfigurename + \doshowfigurestate{state : using special figure}% + \setbox\scratchbox\naturalvbox % make a dummy + {\doscalebox\??ef{\blackrule[\c!width=\naturalfigurewidth,\c!height=\naturalfigureheight]}}% + \global\setbox\foundexternalfigure\naturalvbox to \finalscaleboxheight + {\vfill + \hsize\finalscaleboxwidth + \dowithfigure{\insertscaledfiguredriverdata}}% + \xdef\noffigurepages{\number\nofinsertpages}% + \else + \ifdim\naturalfigurewidth>\zeropoint + \ifnum\figurestatus>\!!ten\relax + \doshowfiguremessage3\expandedfigurename + \else + \doshowfiguremessage4\expandedfigurename + \fi + \else + \doshowfiguremessage5\expandedfigurename + \fi + \doshowfigurestate{state : using found figure}% 3=self 4=rlx + \doifelse\@@efobject\v!no + {\donefalse} + {\doifobjectssupportedelse\donetrue\donefalse}% + \ifdone + % make an object and use it + \packageexternalfigureobject + \setfigureobject\vbox{\box\foundexternalfigure}% + \setxvalue{\externalfigurestamp\c!n}{\number\nofinsertpages}% + \global\setbox\foundexternalfigure\naturalvbox + {\doscalebox\??ef{\dowithfigure{\getfigureobject}}}% + \xdef\noffigurepages{\number\getvalue{\externalfigurestamp\c!n}}% + \else + % maybe a tex figure + \global\setbox\foundexternalfigure\naturalvbox + {\doscalebox\??ef{\dowithfigure{\box\foundexternalfigure}}}% + \xdef\noffigurepages{\number\nofinsertpages}% + \fi + \fi + \global\wd\foundexternalfigure\finalscaleboxwidth + \global\ht\foundexternalfigure\finalscaleboxheight + \global\let\lastfigureobjectname\externalfigurestamp + \doresetobjects} % clean up driver left overs + +\def\packageexternalfigureobject + {\global\setbox\foundexternalfigure\vbox to \naturalfigureheight + {\vfill + \ifdim\wd\foundexternalfigure=\zeropoint + \setextrafiguredriveroptions + \insertunscaledfiguredriverdata + \else\ifskipexternalfigures + \ruledhbox{\backgroundline[\@@efsplitcolor]{\fakebox\foundexternalfigure}}% + \else + \box\foundexternalfigure + \fi\fi}% + \wd\foundexternalfigure\naturalfigurewidth + \ht\foundexternalfigure\naturalfigureheight} + +\def\finishexternalfigure % here we use \figurevariables + {\global\setbox\foundexternalfigure\vbox + {\forgetall + \ifcase\figurestatus + \resetsystemmode\v!figure % todo, also: \v!resource + \else + \setsystemmode \v!figure % todo, also: \v!resource + \fi + \ifconditional\externalfigureflush + \ifconditional\externalfigurelevel % probably background + \ifskipexternalfigures + % nothing + \fakebox\foundexternalfigure + \else\ifcase\figurestatus + % nothing + \else\ifnum\splitexternalfigure=\plustwo\else + \the\externalfigurepostprocessors + \box\foundexternalfigure + \fi\fi\fi + \else + \iftrialtypesetting \else \feedbackexternalfigure \fi + \settrue\externalfigurelevel + \ifskipexternalfigures + \ifcase\figurestatus + \externalfigurereplacement\figurelabel\figurefilename{unknown}% + \else + \externalfigurereplacement\figurelabel\figurefullname{skipped}% + \fi + \else\ifcase\figurestatus + \externalfigurereplacement\figurelabel\figurefilename{unknown}% + \else\ifnum\splitexternalfigure=\plustwo + \backgroundline[\@@efsplitcolor]{\fakebox\foundexternalfigure}% + \else + \the\externalfigurepostprocessors + \doifelse\@@efreset\v!yes + {\wd\foundexternalfigure\figurewidth + \ht\foundexternalfigure\figureheight + \dp\foundexternalfigure\zeropoint + \box\foundexternalfigure} + {\localframed % should also be applied to high res ! + [\??ef] + [\c!offset=\v!overlay, + \c!width=\figurewidth, + \c!height=\figureheight] + {\vfilll + \ifnum\splitexternalfigure=\plusone + % hm, eigenlijk in dit geval achtergrondkleur + \hidesplitcolorfalse % really needed + \backgroundline[\@@efsplitcolor]{\box\foundexternalfigure}% + \else % = 0, no split mode + \box\foundexternalfigure + \fi}}% + \fi\fi\fi + \fi + \else + % maybe also \the\externalfigurepostprocessors + \iftrialtypesetting \else \feedbackexternalfigure \fi + \fi}} + +\def\insertfiguredriverdata#1#2% + {\lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec + \lowercasestring\wantedfiguremethod \to\lcwantedfiguremethod + \edef\@@DriverImageWidth {\the\dimexpr#1\relax}% + \edef\@@DriverImageHeight{\the\dimexpr#2\relax}% + \let \@@DriverImageFile \wantedfigurefullname + \let \@@DriverImageType \lcwantedfiguretypespec + \let \@@DriverImageMethod \lcwantedfiguremethod + \let \@@DriverImageLabel \wantedfigurelabel + \let \@@DriverImagePage \wantedfigurepage + \doinsertfile} + +\def\insertunscaledfiguredriverdata + {\insertfiguredriverdata\naturalfigurewidth\naturalfigureheight} + +\def\insertscaledfiguredriverdata + {\insertfiguredriverdata\finalscaleboxwidth\finalscaleboxheight} + +\ifx\externalfigurereplacement\undefined\let\externalfigurereplacement\gobblethrearguments\fi +\ifx\externalfigureplaceholder\undefined\let\externalfigureplaceholder\gobblethrearguments\fi + +\def\registerexternalfigure % no placement, handy for preprocessing + {\dotripleempty\doregisterexternalfigure} + +\def\doregisterexternalfigure[#1][#2][#3]% + {\bgroup + \setfalse\externalfigureflush + \externalfigure[#1][#2][#3]% or \doexternalfigure + \egroup} + +\let\feedbackexternalfigure\relax % \gobblefourarguments +\let\dowithfigure \relax + +%D Conversion stuff: + +\newcount\nofconversionfigures + +\def\resetwantedconversionvariables + {\let\wantedconversionpath \empty % these point to the to be converted graphic + \let\wantedconversionname \empty + \let\wantedconversiontype \empty + \let\wantedconversioncache \empty + \let\wantedconversionprefix\empty} + +\resetwantedconversionvariables + +\def\checkforconvertedfigure + {\ifcase\figurestatus + \resetwantedconversionvariables + \doifsomething\@@efconversion + {\global\advance\nofconversionfigures\plusone + \doshowfigurestate{n-of-conversions : \number\nofconversionfigures}% + \edef\wantedfigureconversion{\@@efconversion}% + \edef\wantedconversioncache {\@@efcache}% + \edef\wantedconversionprefix{\@@efprefix}% + \doshowfigurestate{checking paths : \figurepathlist}% + \processcommacommand[\figurepathlist]\dolocatefigureconversionfile + \ifcase\figurestatus + \doshowfigurestate{remark : no conversion file found}% + \else + \doshowfigurestate{remark : conversion file found}% + \chardef\figurestatus\zerocount + \fi + \let\wantedconversionname\wantedfigurename + \edef\wantedfigurename{\wantedconversionprefix\wantedfigurename}% + \ifx\wantedconversioncache\empty + \let \wantedfigurepath \wantedconversionpath + \else + \checkfilename\@@efcache + \ifnum\kindoffile=\plusone + \let\wantedfigurepath\@@efcache % root related path + \else % brrr + \edef\wantedfigurepath{\@@efcache,\wantedconversionpath/\@@efcache}% in case of explicit paths, what a mess + \fi + \fi + \let\wantedfiguretype \empty + \let\wantedfiguretypelist\figuretypes % hm, why needed + \ifx\figurepathlist\empty + \let\figurepathlist\wantedfigurepath + \else + \edef\figurepathlist{\wantedfigurepath,\figurepathlist}% + \fi + \doshowfigurestate{conversion path : \wantedconversionpath}% + \doshowfigurestate{conversion name : \wantedconversionname}}% + \doshowfigurestate{new figure path : \wantedfigurepath}% + \fi} + +\def\dolocatefigureconversionfile#1% + {\ifcase\figurestatus + \setwantedfigurefullname{#1}\wantedfigurename\wantedfiguretype + \doshowfigurestate{locating original : \wantedfigurefullname}% + \doiffile\wantedfigurefullname + {\def\wantedconversionpath{#1}% + \let\wantedconversionname\wantedfigurename + \let\wantedconversiontype\wantedfiguretype + \chardef\figurestatus\plusfive}% + \fi} + +\def\setpublicfigureconversionvariables % also prefix, cache + {\doifsomething\@@efconversion + {\doifmode{\systemmodeprefix\v!first} + {\let\figurefilepath\wantedconversionpath + \let\figurefilename\wantedconversionname + \let\figurefiletype\wantedconversiontype + \let\figurefileconversion\wantedfigureconversion + \def\figurefullname + {\ifx\wantedconversionpath\empty\else\wantedconversionpath/\fi + \wantedconversionname + \ifx\wantedconversiontype\empty\else.\wantedconversiontype\fi}}}} + +%D In \PDF\ one can specify an alternative graphic. This means +%D that for instance a low resolution graphic can be used for +%D viewing and a high res one for printing. Because this +%D feature depends much on the driver, here we only take care +%D of perparations. It is up to the special driver to handle +%D the inclusion. The driver routines can change the content of +%D box \type {\foundexternalfigure} if suitable. +%D +%D One complication is for instance that an alternative may +%D not itself have an alternative, and these kind of situations +%D are best handled by the driver. + +\let\lastfigureobjectname\empty + +%D The next macro does not work well with figure bases yet. + +\def\calculateexternalscreenfigure[#1][#2][#3][#4][#5][#6]% + {\ifx\@@efdisplay\empty\else + \doifnot\@@efobject\v!no + {\doifobjectssupportedelse + {\doifspecialavailableelse\doregisterfigure + {\doshowfigurestate{screen alternative : start}% + \bgroup + \dosetefparameters{#4}{#5}{#6}% + \doregisterfigure{FIG}{\lastfigureobjectname}% + \let\@@ef@@scherm\@@efdisplay + \calculateexternalfigure[#1][\@@ef@@scherm][\@@ef@@scherm][#4,\c!display=][#5][#6]% + \doshowfigurestate{screen alternative : stop}% + \egroup} + {}} + {}}% + \fi} + +\def\getfiguredimensions + {\dodoubleempty\dogetfiguredimensions} + +\def\dogetfiguredimensions[#1][#2]% + {{\let\immediate\relax % very dirty but prevents flushing, will change + \setbox0\hbox{\externalfigure[#1][#2,\c!display=,\c!object=\v!no]}}} + +% use the next one when the object must be forgotten (xobj +% nums can migrate to the next object; maybe it should +% always be done; todo .... + +\def\getfiguredimensionsonly + {\dodoubleempty\dogetfiguredimensionsonly} + +\def\dogetfiguredimensionsonly[#1][#2]% + {\dogetfiguredimensions[#1][#2]% + \doresetobjects} + +\def\doiffigureelse#1% + {\getfiguredimensions[#1]% + \ifcase\figurewidth + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +%D Size determination. +%D +%D An analyzer must set the following dimensions (global macros): +%D +%D \starttyping +%D \analyzedfigurewidth +%D \analyzedfigureheight +%D \stoptyping +%D +%D And afterwards, when succeeded, call: +%D +%D \starttyping +%D \setanalyzedfiguredimensions{number>=10} +%D \stoptyping +%D +%D Numbers upto 9 are reserved for special purposes: +%D +%D \starttabulate +%D \NC 0 \NC not found \NC \NR +%D \NC 1 \NC object (will be reused) \NC \NR +%D \NC 2 \NC found but no dimensions (e.g. special annotation) \NC \NR +%D \stoptabulate + +\let\doanalyzefiguredimensionsfromfile\relax % hook for figuredatabase +\let\doanalyzefiguredimensionsinternal\relax +\let\doanalyzefiguredimensionsexternal\relax % hook for rli support (see later) +\let\doanalyzefiguredimensionsfallback\relax + +\def\doanalyzefiguredimensions + {\lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec + \doiffileinsertionsupportedelse\lcwantedfiguretypespec + {\doiffileelse\wantedfigurefullname + {\doshowfigurestate{analyzing : \wantedfigurefullname}% + \doanalyzefiguredimensionsinternal + \doanalyzefiguredimensionsexternal + \doanalyzefiguredimensionsfallback} + {\doshowfigurestate{not found : \wantedfigurefullname}}} + {}} + +\def\setanalyzedfiguredimensions#1% + {\ifdim\analyzedfigurewidth>\zeropoint + \ifdim\analyzedfigureheight>\zeropoint + \determinedfigurewidth \analyzedfigurewidth + \determinedfigureheight\analyzedfigureheight + \chardef\figurestatus #1\relax + \doshowfigurestate{dimensions : + \the\dimexpr\analyzedfigurewidth\relax\space x\space + \the\dimexpr\analyzedfigureheight\relax}% + \else + \determinedfigurewidth \zeropoint + \determinedfigureheight\zeropoint + \chardef\figurestatus \zerocount + \fi + \else + \determinedfigurewidth \zeropoint + \determinedfigureheight\zeropoint + \chardef\figurestatus \zerocount + \fi} + +%D We can remap types. This is to be dealt with in the driver files. + +\def\definegraphictypesynonym + {\dodoubleargument\dodefinegraphictypesynonym} + +\def\dodefinegraphictypesynonym[#1][#2]% + {\setvalue{\??ef:\??ex:#1}{#2}} + +\def\truegraphictype#1% + {\ifcsname\??ef:\??ex:#1\endcsname + \expandafter\truegraphictype\csname\??ef:\??ex:#1\endcsname\else#1% + \fi} + +\definegraphictypesynonym[epdf] [pdf] +\definegraphictypesynonym[jpeg] [jpg] +\definegraphictypesynonym[jp2] [jpg] +\definegraphictypesynonym[jbig] [jb2] +\definegraphictypesynonym[jbig2][jb2] +\definegraphictypesynonym[jbg] [jb2] + +%D The self method (mostly used) uses the driver. + +% todo: when zero width mps, ok +% +% analyzer must set the analyzed dimensions + +\def\doanalyzefiguredimensionsinternal + {\ifcase\figurestatus + \lowercasestring\wantedfiguretypespec\to\lcwantedfiguretypespec + \let\@@DriverImageFile \wantedfigurefullname + \let\@@DriverImagePage \wantedfigurepage + \let\@@DriverImageType\lcwantedfiguretypespec + % use internal when available, otherwise try driver (\dogetfiguresize) + \executeifdefined{dogetfiguresize\@@DriverImageType}\dogetfiguresize + \setanalyzedfiguredimensions\!!ten + \fi} + +%D The tex method. + +\def\dogetfiguresizetex + {\ifcase\figurestatus + \global\setbox\foundexternalfigure\vbox + {\insidefloattrue + \forgetall + \blank[\v!disable]% niet meer weg ! + \startreadingfile + \readfile\wantedfigurefullname \donothing \donothing + \stopreadingfile + \endgraf + \removelastskip}% + \global\setbox\foundexternalfigure\hbox + {\raise\dp\foundexternalfigure\box\foundexternalfigure}% + \xdef\analyzedfigurewidth {\the\wd\foundexternalfigure}% + \xdef\analyzedfigureheight{\the\ht\foundexternalfigure}% + \fi} + +\let\dogetfiguresizetmp \dogetfiguresizetex +\let\dogetfiguresizebuffer\dogetfiguresizetex + +%D The eps, mps and svg files are read directly. + +\def\dogetfiguresizeeps + {\dogetEPSboundingbox\wantedfigurefullname\!!widtha\!!heighta\!!widthb\!!heightb + \xdef\analyzedfigurewidth {\the\!!widthb}% + \xdef\analyzedfigureheight{\the\!!heightb}} + +\let\dogetfiguresizemps\dogetfiguresizeeps + +\def\dogetfiguresizesvg + {\doifinset\wantedfiguretypespec\c!svg + {\startnointerference + \startXMLignore + \defineXMLcommand[svg][width=100,height=75] + {\doifdimensionelse{\XMLop{width}} + {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{width}\relax}} + {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{width}\onebasepoint\relax}}% + \doifdimensionelse{\XMLop{height}} + {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{height}\relax}} + {\xdef\analyzedfigurewidth {\the\dimexpr\XMLop{height}\onebasepoint\relax}}% + \endinput}% + \processXMLfilegrouped\wantedfigurefullname + \stopXMLignore + \stopnointerference}} + +%D Do some checking on the filename. + +\newconditional \figurefileisqualified + +\def\setfigurepathlist + {\let\figurepathlist\empty + \expanded{\doifinset{\v!global }{\@@exlocation}} + {\let\figurepathlist\@@exdirectory}% + \expanded{\doifinset{\v!local }{\@@exlocation}} + {\prependtocommalist\f!currentpath\figurepathlist}% + \expanded{\doifinset{\v!default}{\@@exlocation}} + {\appendtocommalist\defaultfigurepathsignal\figurepathlist}} + +% \def\analyzefigurefilename#1#2% +% {\sanitizefilename#1\to\expandedfigurename +% \expanded{\checkfilename{\expandedfigurename}}% +% \ifcase\kindoffile +% \splitfigurefilename +% \ifcase\splitoffkind +% \let\wantedfigurepath\empty % no . either +% \setfigurepathlist +% \setfalse\figurefileisqualified +% \else +% \splitfigurefilename +% \let\figurepathlist\wantedfigurepath +% \let\wantedfigurepath\empty +% \settrue\figurefileisqualified +% \fi +% \else % fully qualified +% \splitfigurefilename +% \let\figurepathlist\wantedfigurepath +% \let\wantedfigurepath\empty +% \settrue\figurefileisqualified +% \fi +% \ifx\figurepathlist\empty +% \let\figurepathlist\defaultfigurepathsignal % will prepend no path +% \fi +% \doifelsenothing\wantedfiguretype +% {\doifparentfileelse\wantedfigurename +% {\@EA\removefromcommalist\@EA{\jobsuffix }\wantedfiguretypelist +% \@EA\removefromcommalist\@EA{\jobfilesuffix}\wantedfiguretypelist} +% {}} +% {\let\wantedfiguretypelist\empty +% \let\wantedfiguretypespec\wantedfiguretype}% +% \edef\wantedfigurelabel{#2}% +% \doshowfigurestate{type check : \ifx\wantedfiguretypelist\empty forced type \wantedfiguretypespec\else\wantedfiguretypelist\fi}% +% \doshowfigurestate{file specs : \wantedfigurefull\space [\wantedfigurepath] [\wantedfigurename] [\wantedfiguretype]}% +% \doshowfigurestate{file type : \ifconditional\figurefileisqualified qualified\else simple\fi}} + +% The combined path and qualified path hack is dedicated to Onno Tomson, +% our partner in fighting inconsistent and faulty image specifications in +% user files. + +\def\analyzefigurefilename#1#2% + {\sanitizefilename#1\to\expandedfigurename + \expanded{\checkfilename{\expandedfigurename}}% + \ifcase\kindoffile + \splitfigurefilename + \ifcase\splitoffkind + \let\wantedfigurepath\empty % no . either + \setfigurepathlist + \setfalse\figurefileisqualified + \else + \splitfigurefilename + % will become splitoffkind 3 ! ! ! ! + \setfalse\figurefileisqualified + \doifinstring{$$/}{$$\wantedfigurepath}{\settrue\figurefileisqualified}% + \doifinstring {:} {\wantedfigurepath}{\settrue\figurefileisqualified}% + \ifconditional\figurefileisqualified + \let\figurepathlist\wantedfigurepath + \let\wantedfigurepath\empty + \settrue\figurefileisqualified + \else + \let\figurepathlist\@@exdirectory + \let\oldfigurepathlist\figurepathlist + \let\figurepathlist\wantedfigurepath + \def\docommand##1{\edef\figurepathlist{\figurepathlist,##1/\wantedfigurepath}}% + \processcommacommand[\oldfigurepathlist]\docommand + \fi + \fi + \else % fully qualified + \splitfigurefilename + \let\wantedfigurepath\empty + \settrue\figurefileisqualified + \fi + \ifx\figurepathlist\empty + \let\figurepathlist\defaultfigurepathsignal % will prepend no path + \fi + \doifelsenothing\wantedfiguretype + {\doifparentfileelse\wantedfigurename + {\@EA\removefromcommalist\@EA{\jobsuffix }\wantedfiguretypelist + \@EA\removefromcommalist\@EA{\jobfilesuffix}\wantedfiguretypelist} + {}} + {\let\wantedfiguretypelist\empty + \let\wantedfiguretypespec\wantedfiguretype}% + \edef\wantedfigurelabel{#2}% + \doshowfigurestate{type check : \ifx\wantedfiguretypelist\empty forced type \wantedfiguretypespec\else\wantedfiguretypelist\fi}% + \doshowfigurestate{file specs : \wantedfigurefull\space [\wantedfigurepath] [\wantedfigurename] [\wantedfiguretype]}% + \doshowfigurestate{file type : \ifconditional\figurefileisqualified qualified\else simple\fi}} + +\def\setwantedfigurefullname#1#2#3% path name spec + {\ifx\wantedfiguremethod\empty + % the either explicit or gambled typespec determines the method + \edef\wantedfiguretypespec{#3}% + \doifelse{#1}\defaultfigurepathsignal + {\edef\wantedfigurefullname {#2.\wantedfiguretypespec}} + {\edef\wantedfigurefullname{#1/#2.\wantedfiguretypespec}}% + \else\ifx\wantedfiguretype\empty % + % the typespec (probably the same as the method) determines the suffix + \doifelse{#1}\defaultfigurepathsignal + {\edef\wantedfigurefullname {#2.\wantedfiguretypespec}} + {\edef\wantedfigurefullname{#1/#2.\wantedfiguretypespec}}% + \let\wantedfiguretypespec\wantedfiguremethod + \else + % the given suffix is used + \let\wantedfiguretypespec\wantedfiguremethod + \doifelse{#1}\defaultfigurepathsignal + {\edef\wantedfigurefullname {#2.\wantedfiguretype}} + {\edef\wantedfigurefullname{#1/#2.\wantedfiguretype}}% + \fi\fi} + +\def\splitfigurefilename + {\splitfilename\expandedfigurename + \let\wantedfigurefull\splitofffull + \let\wantedfigurepath\splitoffpath + \let\wantedfigurename\splitoffname + \let\wantedfigurebase\splitoffbase + \let\wantedfiguretype\splitofftype} + +\def\analyzefigurefiles + {\ifconditional\figurefileisqualified + \ifx\wantedfiguretype\empty + \doshowfigurestate{locating : unknown type}% + \doanalyzeunknownfiguretype + \else + % this file or none + \doshowfigurestate{locating : known type}% + \doanalyzequalifiedfigure + \fi + \else + \ifx\wantedfiguretype\empty + % locate best fit / check support + \doshowfigurestate{locating : best fit}% + \doanalyzeunknownfiguretype + \else + % only check on paths + \doshowfigurestate{locating : known types}% + \doanalyzeknownfiguretype + \fi + \fi} + +\def\doanalyzequalifiedfigure + {\let\wantedfigurefullname\wantedfigurefull + \let\wantedfiguretypespec\wantedfiguretype + \doshowfigurestate{forced type : \wantedfiguretype}% + \doshowfigurestate{identifying : \wantedfigurefullname}% + \doanalyzefiguredimensions} + +\def\doanalyzeknownfiguretype + {\doshowfigurestate{using paths : \figurepathlist}% + \doshowfigurestate{known type : \wantedfiguretype}% + \doshowfigurestate{identifying : \wantedfigurename}% + \let\wantedfiguretypespec\wantedfiguretype + \processcommacommand[\figurepathlist]\dodoanalyzeknownfiguretype} + +\def\dodoanalyzeknownfiguretype#1% path + {\ifcase\figurestatus + \setwantedfigurefullname{#1}\wantedfigurename\wantedfiguretype + \doanalyzefiguredimensions + \fi} + +\def\doanalyzeunknownfiguretype + {\doshowfigurestate{using paths : \figurepathlist}% + \doshowfigurestate{using types : \wantedfiguretypelist}% + \doshowfigurestate{identifying : \wantedfigurename}% + \processcommacommand[\wantedfiguretypelist]\dodoanalyzeunknownfiguretype} + +\def\dodoanalyzeunknownfiguretype#1% + {\processcommacommand[\figurepathlist]{\dododoanalyzeunknownfiguretype{#1}}} + +\def\dododoanalyzeunknownfiguretype#1#2% type path + {\ifcase\figurestatus + \setwantedfigurefullname{#2}\wantedfigurename{#1}% path spec + \doanalyzefiguredimensions + \fi} + +%D Some files, take for instance movies, cannot easilly be +%D parsed on dimensions, that is, not yet. Although the current +%D mechanism has no problems with this, as long as the user +%D specified width and height reflect the right aspect ratio. +%D Nevertheless, when one does not want any scanning done, one +%D can disable \type{preset}. When no preset is needed, we only +%D locate the file. + +\def\doanalyzefiguredimensionsfallback + {\ifcase\figurestatus + \doshowfigurestate{warning : assuming adaptive figure}% + \xdef\analyzedfigurewidth {\the\dimexpr\@@efwidth +\zeropoint\relax}% + \xdef\analyzedfigureheight{\the\dimexpr\@@efheight+\zeropoint\relax}% + \setanalyzedfiguredimensions\plustwo + \fi} + +\protect \endinput diff --git a/tex/context/base/core-inc.mkiv b/tex/context/base/core-inc.mkiv new file mode 100644 index 000000000..ff4ab3e6b --- /dev/null +++ b/tex/context/base/core-inc.mkiv @@ -0,0 +1,399 @@ +%D \module +%D [ file=core-inc, % moved from core-fig +%D version=2006.08.26, % overhaul of 1997.03.31 +%D title=\CONTEXT\ Core Macros, +%D subtitle=Figure Inclusion, +%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. + +%D todo: +%D +%D - color conversion +%D - color separation +%D - alternative images +%D - a few more obscure things + +\registerctxluafile{core-inc}{1.001} + +\unprotect + +%D The following registers are used (if only to be downward compatible). + +\newbox \foundexternalfigure +\newif \iftraceexternalfigures +\newif \ifskipexternalfigures +\newtoks \everyexternalfigureresets +\newtoks \everyexternalfigurechecks +\newtoks \externalfigurepostprocessors +\chardef \splitexternalfigure \zerocount % 0 nosplit 1 split/yes 2 split/no + +\let\traceexternalfigures \traceexternalfigurestrue + +\def\resetfigurevariables {\the\everyexternalfigureresets} +\def\checkfigurevariables {\the\everyexternalfigurechecks} + +%D Historic feature: + +\appendtoks + \global\let\externalfigurelog\empty +\to \everyexternalfigureresets + +\let\runutilityfiletrue \relax \let\runutilityfilefalse \relax +\let\consultutilityfiletrue\relax \let\consultutilityfilefalse\relax + +%D You can register additional suffixes with the following command: +%D +%D \starttyping +%D \definegraphictypesynonym[jbig] [jb2] +%D \definegraphictypesynonym[jbig2][jb2] +%D \definegraphictypesynonym[jbg] [jb2] +%D \stoptyping + +\def\definegraphictypesynonym + {\dodoubleargument\dodefinegraphictypesynonym} + +\def\dodefinegraphictypesynonym[#1][#2]% + {\ctxlua{figures.registersuffix("#1","#2")}} + +%D Additional paths can be installed with the regular setup command. The next +%D macro picks up the list. + +\def\setfigurepathlist + {\ctxlua{figures.setpaths("\@@exlocation","\@@exdirectory")}} + +%D Variables: + +\def\defaultfigurewidth {8\lineheight} +\def\defaultfigureheight {6\lineheight} + +\def\figurestatus {\numexpr\ctxlua{figures.tprint("status","status",0)}\relax} % number: 0 = not found +\def\figurewidth {\ctxlua{figures.tprint("status","width",0)}sp} +\def\figureheight {\ctxlua{figures.tprint("status","height",0)}sp} +\def\figurexscale {\ctxlua{figures.tprint("status","xscale",1)}} +\def\figureyscale {\ctxlua{figures.tprint("status","yscale",1)}} + +\def\figurelabel {\ctxlua{figures.tprint("request","label")}} +\def\figurefileoriginal {\ctxlua{figures.tprint("request","name")}} +\def\figurefilepage {\ctxlua{figures.tprint("request","page",1)}} +\def\figurefileoptions {\ctxlua{figures.tprint("request","options")}} +\def\figurefileconversion{\ctxlua{figures.tprint("request","conversion")}} +\def\figurefilecache {\ctxlua{figures.tprint("request","cache")}} +\def\figurefileprefix {\ctxlua{figures.tprint("request","prefix")}} + +\def\figurenaturalwidth {\ctxlua{figures.tprint("used","width",\number\dimexpr\defaultfigurewidth\relax)}sp} +\def\figurenaturalheight {\ctxlua{figures.tprint("used","height",\number\dimexpr\defaultfigureheight\relax)}sp} + +\def\figurefilepath {\ctxlua{tex.sprint(tex.ctxcatcodes,file.dirname (figures.get("used","fullname")))}} +\def\figurefilename {\ctxlua{tex.sprint(tex.ctxcatcodes,file.nameonly(figures.get("used","fullname")))}} +\def\figurefiletype {\ctxlua{tex.sprint(tex.ctxcatcodes,file.extname (figures.get("used","fullname")))}} +\def\figurefullname {\ctxlua{figures.tprint("used","fullname")}} + +\def\noffigurepages {\ctxlua{figures.tprint("used","pages",0)}} + +\let\naturalfigurewidth \figurenaturalwidth +\let\naturalfigureheight \figurenaturalheight + +\let\figurescalewidth \figurewidth +\let\figurescaleheight \figureheight +\let\figurescalexscale \figurexscale +\let\figurescaleyscale \figureyscale + +\appendtoks + \ctxlua { + figures.setpaths("\@@exlocation","\@@exdirectory") ; + figures.defaultwidth = \number\dimexpr\defaultfigurewidth \relax ; + figures.defaultheight = \number\dimexpr\defaultfigureheight\relax ; + figures.boxnumber = \number\foundexternalfigure ; + }% +\to \everyexternalfigureresets + +%D In some situations we need to make sure that the figure related variables +%D are reset. This is especially important when we are nesting. Is this still +%D needed in \MKIV. + +\def\resetexternalfigures + {\let\@@efoption \empty % \let\@@efprefix\empty + \let\@@efmaxwidth \empty % \let\@@efcache \empty + \let\@@efmaxheight \empty % \let\@@efframe \v!off + \let\@@efforegroundcolor\empty + \let\@@efcolor \empty + \let\@@efconversion \empty + \let\@@efbackground \empty} + +\appendtoks \resetexternalfigures \to \everyoverlay +\appendtoks \resetexternalfigures \to \everybeforepagebody % not really needed + +\def\resetfigureusersettings + {% + \let\@@efmethod \empty + \let\@@eflabel \empty + \let\@@efsize \empty + \let\@@efconversion\@@exconversion + \let\@@efprefix \@@exprefix + \let\@@efcache \@@excache + \let\@@efpage \!!zerocount + \let\@@efobject \@@exobject + \let\@@efdisplay \empty + % + \let\@@efpreset \v!yes + \let\@@efsplit \empty + \let\@@efcolor \empty + % + \let\@@efsymbol \v!no + % + \let\@@efcontrols \v!no + \let\@@efpreview \v!no + \let\@@efrepeat \v!no + % + \let\@@efhfactor \empty + \let\@@efwfactor \empty + \let\@@effactor \empty + \let\@@efmaxwidth \@@exmaxwidth + \let\@@efmaxheight \@@exmaxheight + \let\@@efxscale \empty + \let\@@efyscale \empty + \let\@@efscale \empty + \let\@@efsx \!!plusone + \let\@@efsy \!!plusone + \let\@@efwidth \empty + \let\@@efheight \empty + \let\@@eflines \empty + \let\@@efgrid \empty} + +\appendtoks + \resetfigureusersettings +\to \everyexternalfigureresets + +\def\checkfigureusersettings + {% old features + \doif\@@exoption\v!frame + {\let\@@efframe\v!on}% + \doif\@@exoption\v!empty + {\skipexternalfigurestrue + \let\@@efframe\v!off}% + % seperation, seldom used + \doifseparatingcolorselse + {\let\@@efforegroundcolor\empty + \doifelsenothing\@@efsplit + {\chardef\splitexternalfigure\zerocount} + {\doifcolorchannelelse\@@efsplit + {\let\@@efobject\v!no % why? + \chardef\splitexternalfigure\plusone} + {\chardef\splitexternalfigure\plustwo}}} + {\chardef\splitexternalfigure\zerocount}% + % fake color in gray bitmaps, assumes that + % a transparent color is used + \doifsomething\@@efforegroundcolor + {\def\@@efbackground{\v!foreground,\v!color}% + \def\@@efbackgroundcolor{\@@efforegroundcolor}}% + \doifsomething\@@efcolor + {\doifcolorelse\@@efcolor + {\checkpredefinedcolor[\@@efcolor]% + \doregisterfigurecolor\@@efcolor}}% + \donothing} + +\appendtoks + \checkfigureusersettings +\to \everyexternalfigurechecks + +%D Internal graphics are handled at the \TEX\ end: + +\def\doprocesstexlikefigure#1% retrofit into mkii + {\global\setbox\foundexternalfigure\vbox\framed + [\c!strut=\v!no,\c!align=\v!normal,\c!frame=\v!off, + \c!offset=\v!overlay,\c!width=\v!fit,\c!height=\v!fit] + {\blank[\v!disable]#1\endgraf\removelastskip}} % disable should stay here! + +\def\doprocessmpslikefigure#1% retrofit into mkii + {\global\setbox\foundexternalfigure\vbox{\convertMPtoPDF{#1}11}} + +\def\docheckfigurebuffer#1{\doprocesstexlikefigure{\getbuffer[#1]}} +\def\docheckfiguretex #1{\doprocesstexlikefigure{\input#1\relax}} +\def\docheckfiguremps #1{\doprocessmpslikefigure{#1}} + +\def\doscalefigure + {\global\setbox\foundexternalfigure\vbox{\doscalebox\??ef{\dowithfigure{\box\foundexternalfigure}}}} + +\newconditional\testexternalfigureonly + +\def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% \cmd label filename parent_id preset current + {\dontcomplain + \restorecatcodes + \forgetall + \resetfigurevariables + \dosetefparameters{#4}{#5}{#6}% + \checkfigurevariables + \ctxlua{figures.push { + name="#3", + label="#2", % todo: \@eflabel + page="\@@efpage", + size="\@@efsize", + object="\@@efobject", + prefix="\@@efprefix", + cache="\@@efcache", + format="\@@efmethod", + preset="\@@efprefix", + controls="\@@efcontrols", + preview="\@@efpreview", + display="\@@efdisplay", + ["repeat"]="\@@efrepeat", + width="\@@efwidth", % can be crap + height="\@@efheight", % can be crap + } }% + \ctxlua{figures.identify()}% + \ifconditional\testexternalfigureonly + \signalexternalfigure + \else + \ifcase\figurestatus + \ctxlua{figures.dummy()}% + \ctxlua{figures.scale()}% + \else + \ctxlua{figures.check()}% + \ctxlua{figures.include()}% + \ctxlua{figures.scale()}% + \fi + \ctxlua{figures.done()}% + \signalexternalfigure + \finishexternalfigure + \fi + \ctxlua{figures.pop()}} + +\def\signalexternalfigure + {\ifcase\figurestatus + \resetsystemmode\v!figure % todo, also: \v!resource + \else + \setsystemmode \v!figure % todo, also: \v!resource + \fi} + +\def\startfoundexternalfigure#1#2% + {\global\setbox\foundexternalfigure\vbox to #2\bgroup\vss\hbox to #1\bgroup} + +\def\stopfoundexternalfigure + {\hss\egroup\egroup} + +\def\emptyfoundexternalfigure + {\startfoundexternalfigure\defaultfigurewidth\defaultfigureheight + \stopfoundexternalfigure} + +\def\finishexternalfigure % here we use \figurevariables + {\global\setbox\foundexternalfigure\vbox + {\ifcase\figurestatus + \let\@@efframe\v!on + \fi + \ifconditional\externalfigureflush + \ifconditional\externalfigurelevel % probably background + \ifskipexternalfigures + % nothing + \fakebox\foundexternalfigure + \else\ifcase\figurestatus + % nothing + \else\ifnum\splitexternalfigure=\plustwo\else + \the\externalfigurepostprocessors + \box\foundexternalfigure + \fi\fi\fi + \else + \iftrialtypesetting \else \feedbackexternalfigure \fi + \settrue\externalfigurelevel + \ifskipexternalfigures + \ifcase\figurestatus + \externalfigurereplacement\figurelabel\figurefileoriginal{unknown}% + \else + \externalfigurereplacement\figurelabel\figurefullname{skipped}% + \fi + \else\ifcase\figurestatus + \externalfigurereplacement\figurelabel\figurefileoriginal{unknown}% + \else\ifnum\splitexternalfigure=\plustwo + \backgroundline[\@@efsplitcolor]{\fakebox\foundexternalfigure}% + \else + \the\externalfigurepostprocessors + \doifelse\@@efreset\v!yes + {\wd\foundexternalfigure\figurewidth + \ht\foundexternalfigure\figureheight + \dp\foundexternalfigure\zeropoint + \box\foundexternalfigure} + {\localframed % should also be applied to high res ! + [\??ef] + [\c!offset=\v!overlay, + \c!width=\figurewidth, + \c!height=\figureheight] + {\vfilll + \ifnum\splitexternalfigure=\plusone + % hm, eigenlijk in dit geval achtergrondkleur + \hidesplitcolorfalse % really needed + \backgroundline[\@@efsplitcolor]{\box\foundexternalfigure}% + \else % = 0, no split mode + \box\foundexternalfigure + \fi}}% + \fi\fi\fi + \fi + \else + % maybe also \the\externalfigurepostprocessors + \iftrialtypesetting \else \feedbackexternalfigure \fi + \fi}} + +\ifx\externalfigurereplacement\undefined\let\externalfigurereplacement\gobblethrearguments\fi +\ifx\externalfigureplaceholder\undefined\let\externalfigureplaceholder\gobblethrearguments\fi + +\let\feedbackexternalfigure\relax % \gobblefourarguments +\let\dowithfigure \relax + +% \let\lastfigureobjectname\empty + +\def\calculateexternalscreenfigure[#1][#2][#3][#4][#5][#6]% + {\ifx\@@efdisplay\empty\else +% \doifnot\@@efobject\v!no +% {\doifobjectssupportedelse +% {\doifspecialavailableelse\doregisterfigure +% {\doshowfigurestate{screen alternative : start}% +% \bgroup +% \dosetefparameters{#4}{#5}{#6}% +% \doregisterfigure{FIG}{\lastfigureobjectname}% +% \let\@@ef@@scherm\@@efdisplay +% \calculateexternalfigure[#1][\@@ef@@scherm][\@@ef@@scherm][#4,\c!display=][#5][#6]% +% \doshowfigurestate{screen alternative : stop}% +% \egroup} +% {}} +% {}}% + \fi} + +\def\getfiguredimensions + {\dodoubleempty\dogetfiguredimensions} + +\def\dogetfiguredimensions[#1][#2]% + {\startnointerference + \testexternalfigureonly + \externalfigure[#1][#2,\c!display=,\c!object=\v!no] + \stopnointerference} + +\let\getfiguredimensionsonly\getfiguredimensions + +\def\doiffigureelse#1% + {\getfiguredimensions[#1]% + \ifcase\figurewidth % todo: \figurestatus + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\def\registerexternalfigure % no placement, handy for preprocessing + {\dotripleempty\doregisterexternalfigure} + +\def\doregisterexternalfigure[#1][#2][#3]% + {\startnointerference + \testexternalfigureonly + \setfalse\externalfigureflush % == test ? + \externalfigure[#1][#2][#3]% or \doexternalfigure + \externalfigure[#1][#2,\c!display=,\c!object=\v!no] + \stopnointerference} + +% figurebases + +\def\usefigurebase[#1]% + {\ctxlua{figures.bases.use("#1")}} + +\protect \endinput diff --git a/tex/context/base/core-inc.tex b/tex/context/base/core-inc.tex new file mode 100644 index 000000000..88d52e746 --- /dev/null +++ b/tex/context/base/core-inc.tex @@ -0,0 +1,18 @@ +%D \module +%D [ file=core-inc, % moved from core-fig +%D version=2006.08.26, % overhaul of 1997.03.31 +%D title=\CONTEXT\ Core Macros, +%D subtitle=Figure Inclusion, +%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 Core Macros / Figure Inclusion} + +\loadmarkfile{core-inc} + +\endinput diff --git a/tex/context/base/core-job.lua b/tex/context/base/core-job.lua index aa3ff9a0e..8454d3d51 100644 --- a/tex/context/base/core-job.lua +++ b/tex/context/base/core-job.lua @@ -8,68 +8,135 @@ if not modules then modules = { } end modules ['core-job'] = { -- will move +commands.writestatus = ctx.writestatus + function commands.doifelse(b) - if b then - tex.sprint(tex.texcatcodes,"\\firstoftwoarguments") - else - tex.sprint(tex.texcatcodes,"\\secondoftwoarguments") - end + tex.sprint(tex.texcatcodes,(b and "\\firstoftwoarguments") or "\\secondoftwoarguments") end function commands.doif(b) - if b then - tex.sprint(tex.texcatcodes,"\\firstoftwoarguments") - end + tex.sprint(tex.texcatcodes,(b and "\\firstofoneargument") or "\\gobbleoneargument") end function commands.doifnot(b) - if not b then - tex.sprint(tex.texcatcodes,"\\firstoftwoarguments") - end + tex.sprint(tex.texcatcodes,(b and "\\gobbleoneargument") or "\\firstofoneargument") end cs.testcase = commands.doifelse --- main code +function commands. def(cs,value) tex.sprint(tex.ctxcatcodes, "\\def\\"..cs.."{"..value.."}") end +function commands.edef(cs,value) tex.sprint(tex.ctxcatcodes,"\\edef\\"..cs.."{"..value.."}") end +function commands.gdef(cs,value) tex.sprint(tex.ctxcatcodes,"\\gdef\\"..cs.."{"..value.."}") end +function commands.xdef(cs,value) tex.sprint(tex.ctxcatcodes,"\\xdef\\"..cs.."{"..value.."}") end -do +-- main code - local function find(name,maxreadlevel) - local n = "./" .. name +local function find_file(name,maxreadlevel) + local function exists(n) if io.exists(n) then return n else - n = file.addsuffix(name,'tex') + n = file.addsuffix(n,'tex') + if io.exists(n) then + return n + end + end + return nil + end + if input.aux.qualified_path(name) then + return name + else + -- not that efficient, too many ./ lookups + local n = "./" .. name + local found = exists(n) + if found then + return found + else for i=1,maxreadlevel or 0 do n = "../" .. n - if io.exists(n) then - return n + found = exists(n) + if found then + return found end end end return input.find_file(texmf.instance,name) or "" end +end - function commands.processfile(name,maxreadlevel) - name = find(name,maxreadlevel) - if name ~= "" then - tex.sprint(tex.ctxcatcodes,string.format("\\input %s\\relax",name)) - end +function commands.processfile(name,maxreadlevel) + name = find_file(name,maxreadlevel) + if name ~= "" then + tex.sprint(tex.ctxcatcodes,string.format("\\input %s\\relax",name)) end +end - function commands.doifinputfileelse(name,maxreadlevel) - commands.doifelse(find(name,maxreadlevel) ~= "") - end +function commands.doifinputfileelse(name,maxreadlevel) + commands.doifelse(find_file(name,maxreadlevel) ~= "") +end - function commands.locatefilepath(name,maxreadlevel) - tex.sprint(tex.texcatcodes,file.dirname(find(name,maxreadlevel))) - end +function commands.locatefilepath(name,maxreadlevel) + tex.sprint(tex.texcatcodes,file.dirname(find_file(name,maxreadlevel))) +end + +function commands.usepath(paths,maxreadlevel) + input.register_extra_path(texmf.instance,paths) + tex.sprint(tex.texcatcodes,table.concat(texmf.instance.extra_paths or {}, "")) +end + +function commands.usesubpath(subpaths,maxreadlevel) + input.register_extra_path(texmf.instance,nil,subpaths) + tex.sprint(tex.texcatcodes,table.concat(texmf.instance.extra_paths or {}, "")) +end - function commands.usepath(paths,maxreadlevel) - input.register_extra_path(texmf.instance,paths) - tex.sprint(tex.texcatcodes,table.concat(texmf.instance.extra_paths or {}, "")) +function commands.usezipfile(name,tree) + if tree and tree ~= "" then + input.usezipfile(texmf.instance,string.format("zip:///%s?tree=%s",name,tree)) + else + input.usezipfile(texmf.instance,string.format("zip:///%s",name)) end +end + +-- for the moment here, maybe a module - function commands.usesubpath(subpaths,maxreadlevel) - input.register_extra_path(texmf.instance,nil,subpaths) - tex.sprint(tex.texcatcodes,table.concat(texmf.instance.extra_paths or {}, "")) +--~ +--~ +--~ nee +--~ standaard +--~ + +local function convertexamodes(str) + local x, t = xml.convert(str), { } + for e, d, k in xml.elements(x,"exa:variable") do + local dk = d[k] + local label = dk.at and dk.at.label + if label and label ~= "" then + local data = xml.content(dk) + local mode = label:match("^mode:(.+)$") + if mode then + tex.sprint(tex.ctxcatcodes,string.format("\\enablemode[%s:%s]",mode,data)) + end + if data:find("{}") then + t[#t+1] = string.format("%s={%s}",mode,data) + else + t[#t+1] = string.format("%s=%s",mode,data) + end + end + end + if #t > 0 then + tex.sprint(tex.ctxcatcodes,string.format("\\setvariables[exa:variables][%s]",table.concat(t,","))) end +end + +-- we need a system file option: ,. .. etc + path sbut no tex lookup so input.find_file is wrong here +function commands.loadexamodes(filename) + if not filename or filename == "" then + filename = file.stripsuffix(tex.jobname) + end + filename = input.find_file(texmf.instance,file.addsuffix(filename,'ctm')) or "" + if filename ~= "" then + commands.writestatus("examodes","loading " .. filename) -- todo: message system + convertexamodes(io.loaddata(filename)) + else + commands.writestatus("examodes","no mode file " .. filename) -- todo: message system + end end + diff --git a/tex/context/base/core-job.mkiv b/tex/context/base/core-job.mkiv index 82ee878aa..c49063b86 100644 --- a/tex/context/base/core-job.mkiv +++ b/tex/context/base/core-job.mkiv @@ -19,4 +19,10 @@ \def\usepath [#1]{\edef\allinputpaths{\ctxlua{commands.usepath("#1")}}} \def\usesubpath [#1]{\edef\allinputpaths{\ctxlua{commands.usesubpath("#1")}}} +\def\usezipfile {\dodoubleempty\dousezipfile} +\def\dousezipfile[#1][#2]{\ctxlua{commands.usezipfile("#1","#2")}} % [filename] [optional subtree] + +\def\loadexamodes {\dosingleempty\doloadexamodes} +\def\doloadexamodes [#1]{\ctxlua{commands.loadexamodes("#1")}} + \endinput diff --git a/tex/context/base/core-mat.tex b/tex/context/base/core-mat.tex index da4ba9a58..465e8d50b 100644 --- a/tex/context/base/core-mat.tex +++ b/tex/context/base/core-mat.tex @@ -155,6 +155,9 @@ \def\formuladistance{\formulaparameter\c!distance} +\def\doformulareference#1#2% + {\doifsomething{#1}{\doifnotinset{#1}{+,-}{\rawreference\s!for{#1}{#2}}}} + \def\dododoformulanumber#1#2#3#4% (#1,#2)=outer(ref,sub) (#3,#4)=inner(ref,sub) {\hbox\bgroup \ifconditional\handleformulanumber @@ -168,12 +171,12 @@ \else \let\hetsubnummer\empty \fi - \doifsomething{#1}{\rawreference{\s!for}{#1}{\composedsectionnumber\hetsubnummer}}% + \doformulareference{#1}{\composedsectionnumber\hetsubnummer}% \setbox0\hbox{\ignorespaces#4\unskip}% \ifdim\wd0>\zeropoint \edef\hetsubnummer{\@@fnseparator#4}%AM: was \edef\hetsubnummer{#4}% \fi - \doifsomething{#3}{\rawreference\s!for{#3}{\composedsectionnumber\hetsubnummer}}% + \doformulareference{#3}{\composedsectionnumber\hetsubnummer}% \doflushformulalistentry{\composedsectionnumber\hetsubnummer}% \rm % nodig ? \doif{\formulaparameter\c!location}\v!right{\hskip\formuladistance}% @@ -571,7 +574,7 @@ {\incrementnumber[\v!formula]% \makesectionnumber[\v!formula]% \doflushformulalistentry{\composedsectionnumber}% - \doifsomething{#1}{\rawreference\s!for{#1}\composedsectionnumber}% + \doformulareference{#1}\composedsectionnumber \expanded{\setupnumber [\v!formula*] [\c!start={\rawnumber[\v!formula]}, diff --git a/tex/context/base/core-ntb.tex b/tex/context/base/core-ntb.tex index 7d5a04d13..63e4bea10 100644 --- a/tex/context/base/core-ntb.tex +++ b/tex/context/base/core-ntb.tex @@ -454,6 +454,9 @@ \let\eTR\relax % handy in \expanded \iffirstargument\setTABLEparameters[\c!y\number\maximumrow][#1]\fi} +\def\settblref#1#2{\expandafter\xdef\csname\@@tblprefix\number#1:\number#2:x\endcsname} +\def\gettblref#1#2{\ifcsname\@@tblprefix\number#1:\number#2:x\endcsname\csname\@@tblprefix\number#1:\number#2:x\endcsname\fi} + \long\def\parseTD[#1][#2]#3\eTD % [#2] is dummy that kills spaces {\def\tblny{\tblnr}% \def\tblnx{\tblnc}% @@ -461,7 +464,9 @@ \let\tblnr\plusone \let\tbln\currentcol \let\tblm\empty - \iffirstargument\getparameters[\@@tbl][#1]\fi + \iffirstargument + \getparameters[\@@tbl][#1]% + \fi % goto first cell % NEW, n/m=cellnumber \edef\@@tblnindeed{\csname\@@tbl\c!n\endcsname}% \ifx\@@tblnindeed\empty @@ -503,6 +508,7 @@ \lettbltag\maximumrow\currentcol\tblcell \settblcol\maximumrow\currentcol{\number\tblnx}% \settblrow\maximumrow\currentcol{\number\tblny}% + \settblref\maximumrow\currentcol{\ifcsname\@@tbl\c!action\endcsname\csname\@@tbl\c!action\endcsname\fi}% % save text \edef\celltag{{\number\maximumrow}{\number\currentcol}}% \@EA\settbltxt\@EA\maximumrow\@EA\currentcol\@EA{\@EA\handleTBLcell\celltag[#1]{#3}}} @@ -952,6 +958,12 @@ \ht\scratchbox\scratchdimen \fi \dp\scratchbox\zeropoint + \edef\!!stringa{\gettblref{#1}{#2}}% + \ifx\!!stringa\empty + \box\scratchbox + \else + \expanded{\gotobox{\box\scratchbox}[\!!stringa]}% + \fi \box\scratchbox} \def\inTBLcell#1#2% hm, do we need #1 #2 ? we use tblcol anyway @@ -985,6 +997,7 @@ \let\makeTBL\domakeTBLone \let\handleTBLcell\dohandleTBLcellA \setbox0\vbox{\trialtypesettingtrue \flushtbltoks}% +% \setbox\scratchbox\vbox{\trialtypesettingtrue \flushtbltoks}% \lettbldis\maximumcol\zeropoint \ifautoTBLspread % experimental, stretch non fixed cells to \hsize @@ -1020,13 +1033,13 @@ \let\handleTBLcell\dohandleTBLcellE \chardef\tblpass\plusthree \let\makeTBL\domakeTBLthree - \ifnum\TBLlevel>\plusone - \@EA\notsplittblbox - \else\ifenableTBLbreak - \@EAEAEA\splittblbox - \else - \@EAEAEA\notsplittblbox - \fi\fi{\flushtbltoks}} + \ifnum\TBLlevel>\plusone + \@EA\notsplittblbox + \else\ifenableTBLbreak + \@EAEAEA\splittblbox + \else + \@EAEAEA\notsplittblbox + \fi\fi{\flushtbltoks}} \def\stretchtblwidths {\ifcase\maximumcol\else % else division by zero diff --git a/tex/context/base/core-reg.mkii b/tex/context/base/core-reg.mkii index ef52ca475..bd925d568 100644 --- a/tex/context/base/core-reg.mkii +++ b/tex/context/base/core-reg.mkii @@ -27,7 +27,7 @@ \def\mksaveregistervariable#1#2#3% class type value {\expanded{\immediatewriteutility{r #2 {#1} {#3}}}} -\def\mkloadregister#1% class - {\doutilities{#1}{\registerparameter\c!file}{#1}\relax\par} % par needed for hanging indentation +\def\mkloadregister#1#2#3% class before after + {\doutilities{#1}{\registerparameter\c!file}{#1}{#2}{#3}} \protect \endinput diff --git a/tex/context/base/core-reg.mkiv b/tex/context/base/core-reg.mkiv index f4c2cc64c..d6407612f 100644 --- a/tex/context/base/core-reg.mkiv +++ b/tex/context/base/core-reg.mkiv @@ -47,10 +47,10 @@ % Beware, we have no filename support here. For that we need to save the resulting % tex code in a file. No big deal. -\def\mkloadregister#1% class, todo: loader macro just like mkii +\def\mkloadregister#1#2#3% class, todo: loader macro just like mkii {\bgroup - \getvalue{\s!set#1}% - \ctxlua{job.loadregister('#1')}\par % par needed for hanging indentation + \getvalue{\s!set#1}% smells like a hack + #2\ctxlua{job.loadregister('#1')}#3% par needed for hanging indentation \getvalue{\s!reset#1}% \egroup} diff --git a/tex/context/base/core-reg.tex b/tex/context/base/core-reg.tex index f183c12bd..18ce09830 100644 --- a/tex/context/base/core-reg.tex +++ b/tex/context/base/core-reg.tex @@ -375,6 +375,35 @@ \global\let\c!entryletter\relax \global\let\c!entryreference\relax} +% \def\dodosetpageregisterpageB#1#2#3#4#5#6% +% {\iffirstregisterpage +% \expandafter\hskip\getvalue{\??id#2\c!distance}\relax +% \else\ifnum#1=3 +% \strut|--|\relax % -- ! +% \else +% % \relax after space needed because | looks ahead +% \strut\registerpageseparator|\space|\relax +% \fi\fi +% \iftrue % \iftrue ...\fi to preserve indentation, can be folded out +% \begingroup +% % +% \doifelsevalue{\??id#2\c!prefix}\v!none % default v!both +% {\chardef\pageprefixmode\zerocount}% +% {\doifvalue{\??id#2\c!prefix}\v!first % only first in range (1.2-4) +% {\ifnum#1=3 \chardef\pageprefixmode\zerocount \fi}}% +% % +% \doifelsevalue{\??id#2\c!interaction}\v!pagenumber +% {\bgroup +% \setbox0\hbox{\showlocation{\doregisterpage{#2}[#5]\ifnum#1=2\/\fi}}% +% \gotonextinternal{\s!ind}{#4}{#6}{\box0}%{\copy0}% +% \egroup} +% {\hbox{\doregisterpage{#2}[#5]\ifnum#1=2\/\fi}}% +% \endgroup +% \ignorespaces +% \relax +% \fi +% \global\firstregisterpagefalse} + \def\dodosetpageregisterpageB#1#2#3#4#5#6% {\iffirstregisterpage \expandafter\hskip\getvalue{\??id#2\c!distance}\relax @@ -382,19 +411,23 @@ \strut|--|\relax % -- ! \else % \relax after space needed because | looks ahead - \strut\registerpageseparator|\space|\relax +% TH: next line replaced +% \strut\registerpageseparator|\space|\relax + \strut \registerpageseparator{ }% +% /TH \fi\fi \iftrue % \iftrue ...\fi to preserve indentation, can be folded out \begingroup % \doifelsevalue{\??id#2\c!prefix}\v!none % default v!both {\chardef\pageprefixmode\zerocount}% - {\doifvalue{\??id#2\c!prefix}\v!first % only first in range (1.2-4) + {\doifvalue{\??id#2\c!prefix}\v!first % {\ifnum#1=3 \chardef\pageprefixmode\zerocount \fi}}% % \doifelsevalue{\??id#2\c!interaction}\v!pagenumber {\bgroup - \setbox0\hbox{\showlocation{\doregisterpage{#2}[#5]\ifnum#1=2\/\fi}}% + \setbox0 + \hbox{\showlocation{\doregisterpage{#2}[#5]\ifnum#1=2\/\fi}}% \gotonextinternal{\s!ind}{#4}{#6}{\box0}%{\copy0}% \egroup} {\hbox{\doregisterpage{#2}[#5]\ifnum#1=2\/\fi}}% @@ -855,7 +888,7 @@ \let\dosetregister\doloadregisterlinks \def\currentregister{#1}% \setupregister[#1][#2]% - \mkloadregister\currentregister + \mkloadregister\currentregister\dobeforeplaceregister\doafterplaceregister \endgroup \ifautoregisterhack \doinitializeautoregister{#1}% @@ -1064,19 +1097,21 @@ \doifelse{\registerparameter\c!compress}\v!yes % new {\chardef\collapseregisterpages\plusone} {\chardef\collapseregisterpages\zerocount}% - \raggedright +% TH: disable next line +% \raggedright +% /TH \startcolumns [\c!n=\registerparameter\c!n, \c!balance=\registerparameter\c!balance, - \c!align=\registerparameter\c!align]% + \c!align=\registerparameter\c!align, + tolerance=stretch]% \dontcomplain \startpacked[\v!blank]% - \mkloadregister\currentregister + \mkloadregister\currentregister\dobeforeplaceregister\doafterplaceregister \stoppacked \stopcolumns \endgroup \fi} - \def\dobeforeplaceregister {\resetseenregisterpage \relax} @@ -1107,7 +1142,7 @@ {\setupregister[#1]% [\c!n=2, \c!balance=\v!yes, % \v!no komt niet zo vaak voor - \c!align=\v!no, + \c!align=\v!flushleft, \c!before=\blank, % binnen kolommen: \blank[\v!line] \c!after=, \c!symbol=, @@ -1167,7 +1202,7 @@ \global\utilitydonetrue} {}}% \doglobal\newcounter\utilityregisterlength - \setbox0\vbox{\mkloadregister\currentregister}% + \setbox0\vbox{\mkloadregister\currentregister\dobeforeplaceregister\doafterplaceregister}% \endgroup \ifregistergeplaatst \setsystemmode \v!register diff --git a/tex/context/base/core-rul.tex b/tex/context/base/core-rul.tex index b481ab49c..ebb624476 100644 --- a/tex/context/base/core-rul.tex +++ b/tex/context/base/core-rul.tex @@ -1753,6 +1753,10 @@ %D of a centered box automatically (\type {fit}). When %D doing so, we need to reshape the box: +% The next implementation is frozen! It preserves the depth, +% otherwise we get problems with framed display math and auto +% width. + \newcount\framednoflines \newdimen\framedlastlength @@ -1760,10 +1764,6 @@ {\framednoflines \zerocount \framedlastlength\zeropoint} -% The next implementation is frozen! It preserves the depth, -% otherwise we get problems with framed display math and auto -% width. - \chardef\reshapeframeboxmethod\plusone % 0=no flush, 1=old method 2=no depth messing \let\framedboxwidth \!!zeropoint @@ -1812,7 +1812,7 @@ \dp\framebox\framedboxdepth % \strutdp otherwise problem with math \fi \fi - \ifdim\framedlastlength=\zeropoint\global\framednoflines\wd\framebox\fi + \ifdim\framedlastlength=\zeropoint\global\framedlastlength\wd\framebox\fi \ifcase\framednoflines\global\framednoflines\plusone\fi \fi} diff --git a/tex/context/base/core-spa.lua b/tex/context/base/core-spa.lua index 4942c7ae1..22b392d4d 100644 --- a/tex/context/base/core-spa.lua +++ b/tex/context/base/core-spa.lua @@ -514,8 +514,13 @@ end do - local has_attribute = node.has_attribute - local unset = node.unset_attribute + local has_attribute = node.has_attribute + local unset_attribute = node.unset_attribute + local set_attribute = node.set_attribute + +--~ local function unset_attribute(n,attribute) +--~ set_attribute(n,attribute,0) +--~ end local glyph = node.id("glyph") local kern = node.id("kern") @@ -550,11 +555,11 @@ do local done, mapping, fontids = false, spacings.mapping, fonts.tfm.id for start in node.traverse_id(glyph,head) do -- tricky since we inject local attr = has_attribute(start,attribute) - if attr then + if attr and attr > 0 then local map = mapping[attr] if map then map = map[start.char] - unset(start,attribute) + unset_attribute(start,attribute) if map then local kern, prev = map.left, start.prev if kern and kern ~= 0 and prev and prev.id == glyph then @@ -599,8 +604,8 @@ do while start do -- faster to test for attr first local attr = has_attribute(start,attribute) - if attr then - unset(start,attribute) + if attr and attr > 0 then + unset_attribute(start,attribute) local krn = mapping[attr] if krn and krn ~= 0 then local id = start.id @@ -843,8 +848,8 @@ do local done, actions = false, cases.actions for start in node.traverse_id(glyph,head) do local attr = has_attribute(start,attribute) - if attr then - unset(start,attribute) + if attr and attr > 0 then + unset_attribute(start,attribute) local action = actions[attr] if action then local _, ok = action(start) @@ -935,8 +940,8 @@ do local id = start.id if id == glyph then local attr = has_attribute(start,attribute) - if attr then - unset(start,attribute) -- maybe test for subtype > 256 (faster) + if attr and attr > 0 then + unset_attribute(start,attribute) -- maybe test for subtype > 256 (faster) -- look ahead and back n chars local map = mapping[attr] if map then diff --git a/tex/context/base/core-spa.tex b/tex/context/base/core-spa.tex index 4c13568f3..d4cda2431 100644 --- a/tex/context/base/core-spa.tex +++ b/tex/context/base/core-spa.tex @@ -1101,7 +1101,7 @@ \fi} \defineindentingmethod [\v!reset] {\indentfirstparagraphtrue - \parindent\zerocount + \parindent\zeropoint \chardef\indentingtoggle\zerocount} \def\noindenting{\indenting[\v!no, \v!next ]} @@ -1503,7 +1503,7 @@ \newskip\ctxparskip \ctxparskip\zeropoint -\settrue\flexiblewhitespace +\newconditional \flexiblewhitespace \settrue\flexiblewhitespace \def\blankokleinmaat {\smallskipamount} \def\blankomiddelmaat {\medskipamount} diff --git a/tex/context/base/core-tsp.tex b/tex/context/base/core-tsp.tex index 1338b79f1..ead8fde18 100644 --- a/tex/context/base/core-tsp.tex +++ b/tex/context/base/core-tsp.tex @@ -130,14 +130,14 @@ \egroup \ifconditional\somenextplitofffloat \doifelsenothing\@@siinbetween - {\ifconditional\tsplitfirstdone\else\page\fi} + {\ifconditional\splitfloatfirstdone\else\page\fi} \@@siinbetween \else \@@siafter \dopopsavedfloats \doflushsavedfloats \fi - \global\settrue\tsplitfirstdone}% + \global\settrue\splitfloatfirstdone}% \vbox} \def\nodowithsplitofffloat @@ -145,7 +145,7 @@ {\forgetall \dontcomplain \box\nextbox % maybe an option to unvbox - \global\settrue\tsplitfirstdone}% + \global\settrue\splitfloatfirstdone}% \vbox} \def\dochecksplitofffloat#1% box @@ -222,11 +222,11 @@ % todo: keep tail to rest, so we need a lookahead -\newconditional\tsplitfirstdone +\newconditional\splitfloatfirstdone \def\handletsplit {\analyzesplitfloatcaption\tsplitcontent - \global\setfalse\tsplitfirstdone + \global\setfalse\splitfloatfirstdone \testpagesync % new, sync, but still tricky [\tsplitminimumfreelines] [\dimexpr\tsplitminimumfreespace+\extrasplitfloatlines\lineheight\relax]% @@ -236,11 +236,11 @@ \doloop {\ifinsidecolumns % brrr, assumes empty columns - \global\setfalse\tsplitfirstdone + \global\setfalse\splitfloatfirstdone \scratchdimen\textheight \!!donectrue \else - \ifconditional\tsplitfirstdone + \ifconditional\splitfloatfirstdone \scratchdimen\textheight \!!donectrue \else\ifdim\pagegoal<\maxdimen @@ -331,7 +331,8 @@ \else \doifnotinsidesplitfloat\page \fi - \fi}} + \fi}% + \global\setfalse\splitfloatfirstdone} % we can use this one for tests \protect \endinput diff --git a/tex/context/base/core-two.mkii b/tex/context/base/core-two.mkii index 234080d97..a14586dc4 100644 --- a/tex/context/base/core-two.mkii +++ b/tex/context/base/core-two.mkii @@ -15,27 +15,21 @@ %D We save two pass information in the utility file. -\def\resettwopassentries - {\let\twopassentry\gobblethreearguments} - \addutilityreset{twopassentries} -\resettwopassentries +\def\immediatesavetwopassdata #1#2#3{\immediatewriteutilitycommand{\twopassentry{#1}{#2}{#3}}} +\def\savetwopassdata #1#2#3{\writeutilitycommand{\twopassentry{#1}{#2}{#3}}} +\def\lazysavetwopassdata #1#2#3{\expanded{\writeutilitycommand{\noexpand\twopassentry{#1}{#2}{#3}}}} % expanded ! +\def\savetaggedtwopassdata #1#2#3#4{\immediatewriteutilitycommand{\twopassentry{#1}{#2}{#3::#4}}} +\def\lazysavetaggedtwopassdata#1#2#3#4{\expanded{\writeutilitycommand{\noexpand\twopassentry{#1}{#2}{#3::#4}}}} % expanded ! + +\def\resettwopassentries + {\let\twopassentry\gobblethreearguments} \def\settwopassentries {\def\twopassentry##1{\executeifdefined{@@##1\s!pass}\gobbletwoarguments}} -\def\savetwopassdata#1#2#3% - {\immediatewriteutilitycommand{\twopassentry{#1}{#2}{#3}}} - -\def\lazysavetwopassdata#1#2#3% expanded ! - {\expanded{\writeutilitycommand{\noexpand\twopassentry{#1}{#2}{#3}}}} - -\def\savetaggedtwopassdata#1#2#3#4% - {\immediatewriteutilitycommand{\twopassentry{#1}{#2}{#3::#4}}} - -\def\lazysavetaggedtwopassdata#1#2#3#4% expanded ! - {\expanded{\writeutilitycommand{\noexpand\twopassentry{#1}{#2}{#3::#4}}}} +\resettwopassentries \def\appendtwopasselement#1#2#3% can sometimes become a large list {%\debuggerinfo{\m!systems}{twopass data #1 - #2 = #3}% diff --git a/tex/context/base/core-two.mkiv b/tex/context/base/core-two.mkiv index d4641e024..bbdc6d489 100644 --- a/tex/context/base/core-two.mkiv +++ b/tex/context/base/core-two.mkiv @@ -20,10 +20,19 @@ \immediatewriteutilitytua{local tp = job.twopass}% \to \everyopenutilities +%D I'm not that sure if this behaves exactly like mkii. This needs a cleanup. + +% \def\immediatesavetwopassdata #1#2#3{\immediatewriteutilitycommand{\twopassentry{#1}{#2}{#3}}} +% \def\savetwopassdata #1#2#3{\writeutilitycommand{\twopassentry{#1}{#2}{#3}}} +% \def\lazysavetwopassdata #1#2#3{\expanded{\writeutilitycommand{\noexpand\twopassentry{#1}{#2}{#3}}}} % expanded ! +% \def\savetaggedtwopassdata #1#2#3#4{\immediatewriteutilitycommand{\twopassentry{#1}{#2}{#3::#4}}} +% \def\lazysavetaggedtwopassdata#1#2#3#4{\expanded{\writeutilitycommand{\noexpand\twopassentry{#1}{#2}{#3::#4}}}} % expanded ! + \def\immediatesavetwopassdata #1#2#3{\expanded{\immediatewriteutilitytua{ti(tp['#1'],"#3")}}} \def\savetwopassdata #1#2#3{\expanded{\writeutilitytua {ti(tp['#1'],"#3")}}} -\def\immediatesavetaggedtwopassdata#1#2#3#4{\expanded{\immediatewriteutilitytua{tp['#1']['#3']="#4"}}} -\def\savetaggedtwopassdata #1#2#3#4{\expanded{\writeutilitytua {tp['#1']['#3']="#4"}}} +\def\lazysavetwopassdata #1#2#3{\expanded{\writeutilitytua {ti(tp['#1'],"#3")}}} +\def\savetaggedtwopassdata #1#2#3#4{\expanded{\immediatewriteutilitytua{tp['#1']['#3']="#4"}}} +\def\lazysavetaggedtwopassdata #1#2#3#4{\expanded{\writeutilitytua {tp['#1']['#3']="#4"}}} % temp hack: needs a proper \starteverytimeluacode diff --git a/tex/context/base/core-two.tex b/tex/context/base/core-two.tex index ebe601f19..5a845c614 100644 --- a/tex/context/base/core-two.tex +++ b/tex/context/base/core-two.tex @@ -79,6 +79,7 @@ \newif\iftwopassdatafound \let\savetwopassdata \gobblethreearguments +\let\immediatesavetwopassdata \gobblethreearguments \let\lazysavetwopassdata \gobblethreearguments \let\savetaggedtwopassdata \gobblefourarguments \let\lazysavetaggedtwopassdata\gobblefourarguments diff --git a/tex/context/base/core-uti.tex b/tex/context/base/core-uti.tex index 4ad12c31f..b564347c1 100644 --- a/tex/context/base/core-uti.tex +++ b/tex/context/base/core-uti.tex @@ -288,6 +288,7 @@ {\showmessage\m!systems9{{#3}}% \doifconcepttracing {\blank + \setmessagetext\m!systems9{{#3}}% \type{[\currentmessagetext]}% \blank}}% \fi diff --git a/tex/context/base/enco-utf.tex b/tex/context/base/enco-utf.tex index eac1b78b0..f0be5b4d2 100644 --- a/tex/context/base/enco-utf.tex +++ b/tex/context/base/enco-utf.tex @@ -3039,16 +3039,20 @@ \def\greekOmegaiotasub {ῼ} % GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI \def\greekoxia {´} % GREEK OXIA \def\greekdasia {῾} % GREEK DASIA +\def\enspace { } % EN SPACE +\def\emspace { } % EM SPACE +\def\thinspace { } % THIN SPACE +\def\hairspace { } % HAIR SPACE \def\textminus {‒} % FIGURE DASH \def\endash {–} % EN DASH \def\emdash {—} % EM DASH \def\texthorizontalbar {―} % HORIZONTAL BAR \def\quoteleft {‘} % LEFT SINGLE QUOTATION MARK \def\quoteright {’} % RIGHT SINGLE QUOTATION MARK -\def\quotesinglebase {‚} % SINGLE LOW-9 QUOTATION MARK +\def\quotesinglebase {‚} % SINGLE LOW-0x0009 QUOTATION MARK \def\quotedblleft {“} % LEFT DOUBLE QUOTATION MARK \def\quotedblright {”} % RIGHT DOUBLE QUOTATION MARK -\def\quotedblbase {„} % DOUBLE LOW-9 QUOTATION MARK +\def\quotedblbase {„} % DOUBLE LOW-0x0009 QUOTATION MARK \def\textdag {†} % DAGGER \def\textddag {‡} % DOUBLE DAGGER \def\textbullet {•} % BULLET diff --git a/tex/context/base/font-afm.lua b/tex/context/base/font-afm.lua index cbba9cbb7..d31b1d155 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.23 -- incrementing this number one up will force a re-cache +fonts.afm.version = 1.24 -- 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 @@ -281,12 +281,17 @@ function fonts.afm.load(filename) end function fonts.afm.unify(data, filename) - local unicode, private, unicodes = containers.content(fonts.enc.cache,'unicode').hash, 0x0F0000, { } + local unicode, private, unicodes = fonts.enc.load('unicode').hash, 0x0F0000, { } for name, blob in pairs(data.characters) do local code = unicode[name] -- or characters.name_to_unicode[name] if not code then - code = private - private = private + 1 + local u = name:match("^uni(%x+)$") + code = u and tonumber(u,16) + if not code then + code = private + private = private + 1 + logs.report("afm glyph", string.format("assigning private slot 0x%04X for unknown glyph name %s", code, name)) + end end blob.unicode = code unicodes[name] = code @@ -486,7 +491,7 @@ end function fonts.afm.set_features(tfmdata) local shared = tfmdata.shared local afmdata = shared.afmdata - shared.features = fonts.define.check(shared.features,fonts.afm.features.default) + -- elsewhere: shared.features = fonts.define.check(shared.features,fonts.afm.features.default) local features = shared.features --~ texio.write_nl(table.serialize(features)) if not table.is_empty(features) then @@ -510,6 +515,7 @@ function fonts.afm.set_features(tfmdata) end initialize(fonts.triggers) initialize(fonts.afm.features.list) + initialize(fonts.manipulators) end local fm = fonts.methods[mode] if fm and fm.afm then @@ -531,6 +537,14 @@ function fonts.afm.set_features(tfmdata) end end +function fonts.afm.check_features(specification) + local features, done = fonts.define.check(specification.features.normal,fonts.afm.features.default) + if done then + specification.features.normal = features + fonts.tfm.hash_instance(specification,true) + end +end + function fonts.afm.afm_to_tfm(specification) local afmname = specification.filename or specification.name local encoding, filename = afmname:match("^(.-)%-(.*)$") -- context: encoding-name.* @@ -556,6 +570,7 @@ function fonts.afm.afm_to_tfm(specification) if afmname == "" then return nil else + fonts.afm.check_features(specification) local features = specification.features.normal local cache_id = specification.hash local tfmdata = containers.read(fonts.tfm.cache, cache_id) -- cache with features applied @@ -670,21 +685,12 @@ function fonts.afm.features.prepare_kerns(tfmdata,kerns,value) end end -function fonts.initializers.base.afm.ligatures(tfmdata,value) - fonts.afm.features.prepare_ligatures(tfmdata,'ligatures',value) -end - -function fonts.initializers.base.afm.texligatures(tfmdata,value) - fonts.afm.features.prepare_ligatures(tfmdata,'texligatures',value) -end +-- hm, register? -function fonts.initializers.base.afm.kerns(tfmdata,value) - fonts.afm.features.prepare_kerns(tfmdata,'kerns',value) -end - -function fonts.initializers.base.afm.extrakerns(tfmdata,value) - fonts.afm.features.prepare_kerns(tfmdata,'extrakerns',value) -end +function fonts.initializers.base.afm.ligatures (tfmdata,value) fonts.afm.features.prepare_ligatures(tfmdata,'ligatures', value) end +function fonts.initializers.base.afm.texligatures(tfmdata,value) fonts.afm.features.prepare_ligatures(tfmdata,'texligatures',value) end +function fonts.initializers.base.afm.kerns (tfmdata,value) fonts.afm.features.prepare_kerns (tfmdata,'kerns', value) end +function fonts.initializers.base.afm.extrakerns (tfmdata,value) fonts.afm.features.prepare_kerns (tfmdata,'extrakerns', value) end fonts.afm.features.register('liga',true) fonts.afm.features.register('kerns',true) @@ -703,7 +709,8 @@ fonts.initializers.node.afm.tlig = fonts.initializers.base.afm.texligatu fonts.initializers.base.afm.trep = fonts.tfm.replacements fonts.initializers.node.afm.trep = fonts.tfm.replacements -fonts.afm.features.register('trep') -- todo: also proper features for afm +fonts.afm.features.register('tlig',true) -- todo: also proper features for afm +fonts.afm.features.register('trep',true) -- todo: also proper features for afm -- tfm features diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index 7bf595842..c9a3144f5 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -162,9 +162,9 @@ when we get rid of base mode we can optimize even further by sharing, but then w loose our testcases for .

--ldx]]-- -function fonts.tfm.hash_instance(specification) +function fonts.tfm.hash_instance(specification,force) local hash, size = specification.hash, specification.size - if not hash then + if force or not hash then hash = fonts.tfm.hash_features(specification) specification.hash = hash end @@ -568,17 +568,18 @@ fonts.define.register_split('*',fonts.define.specify.starred) a helper function.

--ldx]]-- -function fonts.define.check(features,defaults) +function fonts.define.check(features,defaults) -- nb adapts features ! + local done = false if table.is_empty(features) then - features = table.fastcopy(defaults) -- we could do without copy + features, done = table.fastcopy(defaults), true else for k,v in pairs(defaults) do if features[k] == nil then - features[k] = v + features[k], done = v, true end end end - return features + return features, done -- done signals a change end --[[ldx-- diff --git a/tex/context/base/font-enc.lua b/tex/context/base/font-enc.lua index 2d1005ad2..73b4ae5d8 100644 --- a/tex/context/base/font-enc.lua +++ b/tex/context/base/font-enc.lua @@ -52,42 +52,48 @@ will be used.

function fonts.enc.load(filename) local name = file.removesuffix(filename) local data = containers.read(fonts.enc.cache,name) - 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 - for ch in vec:gmatch("/([%a%d%.]+)") do - if ch ~= ".notdef" then - vector[i] = ch - if not hash[ch] then - hash[ch] = i - else - -- duplicate, play safe for tex ligs and take first - end - if enccodes[ch] then - unicodes[enccodes[ch]] = i - end + if data then + return data + end + if name == "unicode" then + data = fonts.enc.make_unicode_vector() -- special case, no tex file for this + end + if data then + return data + end + 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 + for ch in vec:gmatch("/([%a%d%.]+)") do + if ch ~= ".notdef" then + vector[i] = ch + if not hash[ch] then + hash[ch] = i + else + -- duplicate, play safe for tex ligs and take first + end + if enccodes[ch] then + unicodes[enccodes[ch]] = i end - i = i + 1 end + i = i + 1 end end - local data = { - name=name, - tag=tag, - vector=vector, - hash=hash, - unicodes=unicodes - } - data = containers.write(fonts.enc.cache, name, data) end - return data + local data = { + name=name, + tag=tag, + vector=vector, + hash=hash, + unicodes=unicodes + } + return containers.write(fonts.enc.cache, name, data) end --[[ldx-- @@ -110,5 +116,5 @@ function fonts.enc.make_unicode_vector() for name, code in pairs(characters.synonyms) do vector[code], hash[name] = name, code end - containers.write(fonts.enc.cache, 'unicode', { name='unicode', tag='unicode', vector=vector, hash=hash }) + return containers.write(fonts.enc.cache, 'unicode', { name='unicode', tag='unicode', vector=vector, hash=hash }) end diff --git a/tex/context/base/font-ext.lua b/tex/context/base/font-ext.lua new file mode 100644 index 000000000..28d96057e --- /dev/null +++ b/tex/context/base/font-ext.lua @@ -0,0 +1,225 @@ +if not modules then modules = { } end modules ['font-ext'] = { + version = 1.001, + comment = "companion to font-ini.tex and hand-ini.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local byte = string.byte + +-- -- -- -- -- -- +-- expansion (hz) +-- -- -- -- -- -- + +fonts.expansions = fonts.expansions or { } +fonts.expansions.classes = fonts.expansions.classes or { } +fonts.expansions.vectors = fonts.expansions.vectors or { } + +-- beware, pdftex itself uses percentages * 10 + +fonts.expansions.classes.preset = { stretch = 2, shrink = 2, step = .5, factor = 1 } + +function commands.setupfontexpansion(class,settings) + aux.getparameters(fonts.expansions.classes,class,'preset',settings) +end + +fonts.expansions.classes['quality'] = { + stretch = 2, shrink = 2, step = .5, vector = 'default', factor = 1 +} + +fonts.expansions.vectors['default'] = { + [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7, + [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7, + [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7, + [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7, + [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7, + [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7, + [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7, + [byte('w')] = 0.7, [byte('z')] = 0.7, + [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7, +} + +function fonts.initializers.common.expansion(tfmdata,value) + if value then + local class = fonts.expansions.classes[value] + if class then + local vector = fonts.expansions.vectors[class.vector] + if vector then + tfmdata.stretch = (class.stretch or 0) * 10 + tfmdata.shrink = (class.shrink or 0) * 10 + tfmdata.step = (class.step or 0) * 10 + tfmdata.auto_expand = true + local factor = class.factor or 1 + local data = characters.data + for i, chr in pairs(tfmdata.characters) do + local v = vector[i] + if not v then + local d = data[i] + if d then + local s = d.shcode + if not s then + -- sorry + elseif type(s) == "table" then + v = ((vector[s[1]] or 0) + (vector[s[#s]] or 0)) / 2 + else + v = vector[s] or 0 + end + end + end + if v and v ~= 0 then + chr.expansion_factor = v*factor + else -- can be option + chr.expansion_factor = factor + end + end + end + end + end +end + +table.insert(fonts.manipulators,"expansion") + +fonts.initializers.base.otf.expansion = fonts.initializers.common.expansion +fonts.initializers.node.otf.expansion = fonts.initializers.common.expansion + +fonts.initializers.base.afm.expansion = fonts.initializers.common.expansion +fonts.initializers.node.afm.expansion = fonts.initializers.common.expansion + +-- -- -- -- -- -- +-- protrusion +-- -- -- -- -- -- + +fonts.protrusions = fonts.protrusions or { } +fonts.protrusions.classes = fonts.protrusions.classes or { } +fonts.protrusions.vectors = fonts.protrusions.vectors or { } + +-- the values need to be revisioned + +fonts.protrusions.classes.preset = { factor = 1 } + +function commands.setupfontprotrusion(class,settings) + aux.getparameters(fonts.protrusions.classes,class,'preset',settings) +end + +fonts.protrusions.classes['pure'] = { + vector = 'pure', factor = 1 +} +fonts.protrusions.classes['punctuation'] = { + vector = 'punctuation', factor = 1 +} +fonts.protrusions.classes['alpha'] = { + vector = 'alpha', factor = 1 +} +fonts.protrusions.classes['quality'] = { + vector = 'quality', factor = 1 +} + +fonts.protrusions.vectors['pure'] = { + + [0x002C] = { 0, 1 }, -- comma + [0x002E] = { 0, 1 }, -- period + [0x003A] = { 0, 1 }, -- colon + [0x003B] = { 0, 1 }, -- semicolon + [0x002D] = { 0, 1 }, -- hyphen + [0x2013] = { 0, 0.50 }, -- endash + [0x2014] = { 0, 0.33 }, -- emdash + +} + +fonts.protrusions.vectors['punctuation'] = { + + [0x003F] = { 0, 0.20 }, -- ? + [0x00BF] = { 0, 0.20 }, -- ¿ + [0x0021] = { 0, 0.20 }, -- ! + [0x00A1] = { 0, 0.20 }, -- ¡ + [0x0028] = { 0.05, 0 }, -- ( + [0x0029] = { 0, 0.05 }, -- ) + [0x005B] = { 0.05, 0 }, -- [ + [0x005D] = { 0, 0.05 }, -- ] + [0x002C] = { 0, 0.70 }, -- comma + [0x002E] = { 0, 0.70 }, -- period + [0x003A] = { 0, 0.50 }, -- colon + [0x003B] = { 0, 0.50 }, -- semicolon + [0x002D] = { 0, 0.70 }, -- hyphen + [0x2013] = { 0, 0.30 }, -- endash + [0x2014] = { 0, 0.20 }, -- emdash + + -- todo: left and right quotes: .5 double, .7 single + +} + +fonts.protrusions.vectors['alpha'] = { + + [byte("A")] = { .05, .05 }, + [byte("F")] = { 0, .05 }, + [byte("J")] = { .05, 0 }, + [byte("K")] = { 0, .05 }, + [byte("L")] = { 0, .05 }, + [byte("T")] = { .05, .05 }, + [byte("V")] = { .05, .05 }, + [byte("W")] = { .05, .05 }, + [byte("X")] = { .05, .05 }, + [byte("Y")] = { .05, .05 }, + + [byte("k")] = { 0, .05 }, + [byte("r")] = { 0, .05 }, + [byte("t")] = { 0, .05 }, + [byte("v")] = { .05, .05 }, + [byte("w")] = { .05, .05 }, + [byte("x")] = { .05, .05 }, + [byte("y")] = { .05, .05 }, + +} + +fonts.protrusions.vectors['quality'] = table.merge( {}, + fonts.protrusions.vectors['punctuation'], + fonts.protrusions.vectors['alpha'] +) + +function fonts.initializers.common.protrusion(tfmdata,value) + if value then + local class = fonts.protrusions.classes[value] + if class then + local vector = fonts.protrusions.vectors[class.vector] + if vector then + local factor = class.factor or 1 + local data = characters.data + local emwidth = tfmdata.parameters[6] + for i, chr in pairs(tfmdata.characters) do + local v, pl, pr = vector[i], nil, nil + if v then + pl, pr = v[1], v[2] + else + local d = data[i] + if d then + local s = d.shcode + if not s then + -- sorry + elseif type(s) == "table" then + local vl, vr = vector[s[1]], vector[s[#s]] + if vl then pl = vl[1] end + if vr then pr = vr[2] end + else + v = vector[s] + if v then + pl, pr = v[1], v[2] + end + end + end + end + if pl and pl ~= 0 then chr.left_protruding = pl*factor end + if pr and pr ~= 0 then chr.right_protruding = pr*factor end + end + end + end + end +end + +table.insert(fonts.manipulators,"protrusion") + +fonts.initializers.base.otf.protrusion = fonts.initializers.common.protrusion +fonts.initializers.node.otf.protrusion = fonts.initializers.common.protrusion + +fonts.initializers.base.afm.protrusion = fonts.initializers.common.protrusion +fonts.initializers.node.afm.protrusion = fonts.initializers.common.protrusion diff --git a/tex/context/base/font-fbk.lua b/tex/context/base/font-fbk.lua index ffe9bea41..50650b60f 100644 --- a/tex/context/base/font-fbk.lua +++ b/tex/context/base/font-fbk.lua @@ -107,154 +107,6 @@ end fonts.vf.aux.combine.force_composed = false ---~ fonts.vf.aux.combine.commands["complete-composed-characters"] = function(g,v) ---~ local chars = g.characters ---~ local xchar = chars[string.byte("X")] ---~ if xchar.boundingbox then ---~ local cap_lly = xchar.boundingbox[4] ---~ local ita_cor = math.cos(math.rad(90+g.italicangle)) ---~ local force = fonts.vf.aux.combine.force_composed ---~ local special, red, green, blue, black = fonts.vf.aux.combine.initialize_trace() ---~ for i,c in pairs(characters.data) do ---~ if force or not chars[i] then ---~ local s = c.specials ---~ if s and s[1] == 'char' then ---~ local chr = s[2] ---~ if chars[chr] then ---~ local cc = c.category ---~ if (cc == 'll') or (cc == 'lu') or (cc == 'lt') then ---~ local acc = s[3] ---~ local t = table.fastcopy(chars[chr]) ---~ t.name = "" ---~ t.index = i ---~ t.unicode = i ---~ if chars[acc] then ---~ local cb = chars[chr].boundingbox ---~ local ab = chars[acc].boundingbox ---~ if cd and ab then ---~ local c_llx, c_lly, c_urx, c_ury = cb[1], cb[2], cb[3], cb[4] ---~ local a_llx, a_lly, a_urx, a_ury = ab[1], ab[2], ab[3], ab[4] ---~ local dx = (c_urx - a_urx - a_llx + c_llx)/2 ---~ local dd = (c_urx-c_llx)*ita_cor ---~ if a_ury < 0 then ---~ local dy = cap_lly-a_lly ---~ t.commands = { ---~ {"push"}, ---~ {"right", dx-dd}, ---~ {"down", -dy}, -- added ---~ {special, red}, ---~ {"slot", 1, acc}, ---~ {special, black}, ---~ {"pop"}, ---~ {"slot", 1, chr}, ---~ } ---~ elseif c_ury > a_lly then ---~ local dy = cap_lly-a_lly ---~ t.commands = { ---~ {"push"}, ---~ {"right", dx+dd}, ---~ {"down", -dy}, ---~ {special, green}, ---~ {"slot", 1, acc}, ---~ {special, black}, ---~ {"pop"}, ---~ {"slot", 1, chr}, ---~ } ---~ else ---~ t.commands = { ---~ {"push"}, ---~ {"right", dx+dd}, ---~ {special, blue}, ---~ {"slot", 1, acc}, ---~ {special, black}, ---~ {"pop"}, ---~ {"slot", 1, chr}, ---~ } ---~ end ---~ end ---~ end ---~ chars[i] = t ---~ end ---~ end ---~ end ---~ end ---~ end ---~ end ---~ end - ---~ fonts.vf.aux.combine.commands["complete-composed-characters"] = function(g,v) ---~ local chars = g.characters ---~ local xchar = chars[string.byte("X")] ---~ if xchar then ---~ local xheight = xchar.height ---~ local ita_cor = math.cos(math.rad(90+g.italicangle)) ---~ local force = fonts.vf.aux.combine.force_composed ---~ local special, red, green, blue, black = fonts.vf.aux.combine.initialize_trace() ---~ for i,c in pairs(characters.data) do ---~ if force or not chars[i] then ---~ local s = c.specials ---~ if s and s[1] == 'char' then ---~ local chr = s[2] ---~ if chars[chr] then ---~ local cc = c.category ---~ if (cc == 'll') or (cc == 'lu') or (cc == 'lt') then ---~ local acc = s[3] ---~ local t = table.fastcopy(chars[chr]) ---~ t.name = "" ---~ t.index = i ---~ t.unicode = i ---~ if chars[acc] then ---~ local c = chars[chr] ---~ local a = chars[acc] ---~ if c and a then ---~ local dx = (c.width-a.width)/2 ---~ local dd = c.width*ita_cor ---~ if a.height < 0 then ---~ local dy = xheight+a.depth ---~ t.commands = { ---~ {"push"}, ---~ {"right", dx-dd}, ---~ {"down", -dy}, -- added ---~ {special, red}, ---~ {"slot", 1, acc}, ---~ {special, black}, ---~ {"pop"}, ---~ {"slot", 1, chr}, ---~ } ---~ elseif c.height > -a.depth then ---~ local dy = xheight+a.depth ---~ t.commands = { ---~ {"push"}, ---~ {"right", dx+dd}, ---~ {"down", -dy}, ---~ {special, green}, ---~ {"slot", 1, acc}, ---~ {special, black}, ---~ {"pop"}, ---~ {"slot", 1, chr}, ---~ } ---~ else ---~ t.commands = { ---~ {"push"}, ---~ {"right", dx+dd}, ---~ {special, blue}, ---~ {"slot", 1, acc}, ---~ {special, black}, ---~ {"pop"}, ---~ {"slot", 1, chr}, ---~ } ---~ end ---~ end ---~ end ---~ chars[i] = t ---~ end ---~ end ---~ end ---~ end ---~ end ---~ end ---~ end - function fonts.vf.aux.compose_characters(g) -- todo: scaling depends on call location local chars = g.characters local xchar = chars[string.byte("X")] @@ -262,23 +114,30 @@ function fonts.vf.aux.compose_characters(g) -- todo: scaling depends on call loc local cap_lly = xchar.description.boundingbox[4] local ita_cor = math.cos(math.rad(90+g.italicangle)) local force = fonts.vf.aux.combine.force_composed + local fallbacks = characters.context.fallbacks local special, red, green, blue, black = fonts.vf.aux.combine.initialize_trace() for i,c in pairs(characters.data) do if force or not chars[i] then local s = c.specials if s and s[1] == 'char' then local chr = s[2] - if chars[chr] then + local charschr = chars[chr] + if charschr then local cc = c.category - if (cc == 'll') or (cc == 'lu') or (cc == 'lt') then + if cc == 'll' or cc == 'lu' or cc == 'lt' then local acc = s[3] - local t = table.fastcopy(chars[chr]) - t.name = "" - t.index = i - t.unicode = i - if chars[acc] then - local cb = chars[chr].description.boundingbox - local ab = chars[acc].description.boundingbox + local t = table.fastcopy(charschr) + local d = t.description + d.name = c.adobename or "unknown" + d.unicode = i + local charsacc = chars[acc] + if not charsacc then + acc = fallbacks[acc] + charsacc = acc and chars[acc] + end + if charsacc then + local cb = charschr.description.boundingbox + local ab = charsacc.description.boundingbox if cb and ab then local c_llx, c_lly, c_urx, c_ury = cb[1], cb[2], cb[3], cb[4] local a_llx, a_lly, a_urx, a_ury = ab[1], ab[2], ab[3], ab[4] diff --git a/tex/context/base/font-ini.mkiv b/tex/context/base/font-ini.mkiv index 9e96f3c13..7d9a8e850 100644 --- a/tex/context/base/font-ini.mkiv +++ b/tex/context/base/font-ini.mkiv @@ -21,10 +21,11 @@ \registerctxluafile{font-vf} {1.001} \registerctxluafile{font-def}{1.001} \registerctxluafile{font-fbk}{1.001} +\registerctxluafile{font-ext}{1.001} -\startruntimectxluacode - fonts.enc.make_unicode_vector() -\stopruntimectxluacode +% \startruntimectxluacode +% fonts.enc.make_unicode_vector() -- each time, brrr +% \stopruntimectxluacode \unprotect @@ -113,8 +114,7 @@ \edef\@@fontskewchar{\truefontdata\fontfile \s!skewchar}} \def\setfontcharacteristics - {\fastenablehandling{\ifx\@@fonthandling\empty\s!default\else\@@fonthandling\fi}\lastfontidentifier - \the\everyfont} + {\the\everyfont} %D Predefined: diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua index d283c5543..00eb8e4b8 100644 --- a/tex/context/base/font-otf.lua +++ b/tex/context/base/font-otf.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['font-otf'] = { + if not modules then modules = { } end modules ['font-otf'] = { version = 1.001, comment = "companion to font-ini.tex", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -6,10 +6,13 @@ if not modules then modules = { } end modules ['font-otf'] = { license = "see context related readme files" } +-- once we have all features working, i will redo this module .. caching lookups and such + -- the flattening code is a prelude to a more compact table format (so, we're now --- at the fourth version) +-- at the fourth version); maybe we will go unicode, although that will mean that we +-- miss some glyphs (unicode -1) ---- todo: featuredata is now indexed by kind,lookup but probably lookup is okay too +-- todo: featuredata is now indexed by kind,lookup but probably lookup is okay too -- todo: now that we pack ... resolve strings to unicode points -- todo: unpack already in tmc file, i.e. save tables and return ref''d version @@ -20,6 +23,51 @@ if not modules then modules = { } end modules ['font-otf'] = { -- mset opbd palt pwid qwid rand rtbd rtla ruby size tjmo twid valt vatu vert -- vhal vjmo vkna vkrn vpal vrt2 +-- The specification of OpenType is vague, very vague. Apart from a lack of proper +-- specifications (a free one) there's also the problem that Microsoft and Adobe +-- may have their own rules. Anyhow, the following is from Adobe's feature file +-- specification: +-- +-- http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html#6.h +-- +-- The following is a reference summary of the algorithm used by an OpenType layout +-- (OTL) engine to perform substitutions and positionings. The important aspect of +-- this for a feature file editor is that each lookup corresponds to one "pass" over +-- the glyph run (see step 4 below). Thus, each lookup has as input the accumulated +-- result of all previous lookups in the LookupList (whether in the same feature or +-- in other features). +-- 1. All glyphs in the client's glyph run must belong to the same language +-- system. Glyph sequence matching may not occur across language +-- systems. Do the following first for the GSUB and then for the GPOS: +-- 2. Assemble all features (including any required feature) for the glyph +-- run's language system. +-- 3. Assemble all lookups in these features, in LookupList order, removing +-- any duplicates. All features and thus all lookups needn't be applied to +-- every glyph in the run. +-- 4. For each lookup: +-- 5. For each glyph in the glyph run: +-- 6. If the lookup is applied to that glyph and the lookupflag doesn't +-- indicate that that glyph is to be ignored: +-- 7. For each subtable in the lookup: +-- 8. If the subtable's target context is matched: +-- 9. Do the glyph substitution or positioning, +-- --- OR: --- +-- If this is a (chain) contextual lookup do the following +-- [(10)-(11)] in the subtable's Subst/PosLookupRecord order: +-- 10. For each (sequenceIndex, lookupListIndex) pair: +-- 11. Apply lookup[lookupListIndex] at input sequence[sequenceIndex] +-- [steps (7)-(11)] +-- 12. Goto the glyph after the input sequence matched in (8) +-- (i.e. skip any remaining subtables in the lookup). +-- The "target context" in step 8 above comprises the input sequence and any +-- backtrack and lookahead sequences. +-- The input sequence must be matched entirely within the lookup's "application +-- range" at that glyph (that contiguous subrun of glyphs including and around +-- the current glyph on which the lookup is applied). There is no such restriction +-- on the backtrack and lookahead sequences. +-- "Matching" includes matching any glyphs designated to be skipped in the +-- lookup's LookupFlag. + --[[ldx--

This module is sparsely documented because it is a moving target. The table format of the reader changes and we experiment a lot with @@ -40,7 +88,7 @@ number by one when there's a fix in the library or fonts = fonts or { } fonts.otf = fonts.otf or { } -fonts.otf.version = 2.05 +fonts.otf.version = 2.08 fonts.otf.pack = true fonts.otf.tables = fonts.otf.tables or { } fonts.otf.meanings = fonts.otf.meanings or { } @@ -58,9 +106,19 @@ fonts.otf.trace_contexts = false fonts.otf.trace_anchors = false fonts.otf.trace_ligatures = false fonts.otf.trace_kerns = false +fonts.otf.trace_cursive = false fonts.otf.notdef = false fonts.otf.cache = containers.define("fonts", "otf", fonts.otf.version, true) +function fonts.otf.trace_process() + fonts.otf.trace_replacements = true + fonts.otf.trace_contexts = true + fonts.otf.trace_anchors = true + fonts.otf.trace_ligatures = true + fonts.otf.trace_kerns = true + fonts.otf.trace_cursive = true +end + --[[ldx--

We start with a lot of tables and related functions.

--ldx]]-- @@ -724,7 +782,7 @@ do function fonts.otf.meanings.normalize(features) local h = { } for k,v in pairs(features) do - k = (k:lower()):gsub("[^a-z0-9%-]","") + k = k:lower() -- :gsub("[^a-z0-9%-%.]" -- not needed if k == "language" or k == "lang" then v = (v:lower()):gsub("[^a-z0-9%-]","") k = language @@ -744,7 +802,7 @@ do if type(v) == "string" then local b = v:is_boolean() if type(b) == "nil" then - v = (v:lower()):gsub("[^a-z0-9%-]","") + v = v:lower() -- gsub("[^a-z0-9%-]") -- too dangerous, e.g. featurefiles else v = b end @@ -801,7 +859,7 @@ function fonts.otf.load(filename,format,sub,featurefile) if ff then local function load_featurefile(featurefile) if featurefile then - featurefile = input.find_file(texmf.instance,file.addsuffix(featurefile,'fea'),"FONTFEATURES") + featurefile = input.find_file(texmf.instance,file.addsuffix(featurefile,'fea')) -- "FONTFEATURES" if featurefile and featurefile ~= "" then logs.report("load otf", "featurefile: " .. featurefile) fontforge.apply_featurefile(ff, featurefile) @@ -850,6 +908,16 @@ end -- memory saver .. +function table.reverse(t) + local tt = { } + if #t > 0 then + for i=#t,1,-1 do + tt[#tt+1] = t[i] + end + end + return tt +end + function fonts.otf.enhance.pack(data) if data then local h, t = { }, { } @@ -1208,13 +1276,24 @@ function fonts.otf.enhance.before(data,filename) table.compact(subfont.glyphs) end end - + -- we prefer the before lookups in a normal order + if data.lookups then + for _, v in pairs(data.lookups) do + if v.rules then + for _, vv in pairs(v.rules) do + local c = vv.coverage + if c and c.before then + c.before = table.reverse(c.before) + end + end + end + end + end --~ for index, glyph in pairs(data.glyphs) do --~ for k,v in pairs(glyph) do --~ if v == 0 then glyph[k] = nil end --~ end --~ end - end function fonts.otf.enhance.after(data,filename) -- to be split @@ -1952,19 +2031,6 @@ end fonts.otf.default_language = 'latn' fonts.otf.default_script = 'dflt' ---~ function fonts.otf.valid_feature(otfdata,kind,script,language) -- return hash is faster ---~ if otfdata.luatex.ctx_always[kind] then ---~ script, language = 'dflt', 'dflt' ---~ else ---~ script = script or fonts.otf.default_script ---~ language = language or fonts.otf.default_language ---~ end ---~ script, language = script:lower(), language:lower() -- will go away, we will lowercase values ---~ local ft = otfdata.luatex.subtables[kind] ---~ local st = ft[script] ---~ return false, otfdata.luatex.always_valid, st and st[language] and st[language].valid ---~ end - function fonts.otf.valid_feature(otfdata,kind,script,language) -- return hash is faster if otfdata.luatex.ctx_always[kind] then script, language = 'dflt', 'dflt' @@ -1979,22 +2045,6 @@ function fonts.otf.valid_feature(otfdata,kind,script,language) -- return hash is return false, otfdata.luatex.always_valid, lt.valid end ---~ function fonts.otf.some_valid_feature(otfdata,kind,script,language) ---~ if otfdata.luatex.ctx_always[kind] then ---~ script, language = 'dflt', 'dflt' ---~ else ---~ script = script or fonts.otf.default_script ---~ language = language or fonts.otf.default_language ---~ script, language = script:lower(), language:lower() -- will go away, we will lowercase values ---~ end ---~ local t = otfdata.luatex.subtables[kind] ---~ if t and t[script] and t[script][language] and t[script][language].valid then ---~ return t[script][language].valid ---~ else ---~ return { } ---~ end ---~ end - function fonts.otf.some_valid_feature(otfdata,kind,script,language) if otfdata.luatex.ctx_always[kind] then script, language = 'dflt', 'dflt' @@ -2456,7 +2506,11 @@ do end lookuptype = types[lookups[1]] end - for unic, _ in pairs(sequence[1]) do + -- this may be wrong; we cannot copy inside the for loop (out of memory with hz); + -- so we may end up with a different usage of sequence in the chainproc handlers + sequence = table.copy(sequence) + -- we trigger on the first character in current + for unic, _ in pairs(sequence[start]) do local t = contexts[unic] if not t then contexts[unic] = { lookups={}, flags=flags[lookupname] } @@ -2753,6 +2807,12 @@ do local context_setups = fonts.define.specify.context_setups local context_numbers = fonts.define.specify.context_numbers + -- 1 loop over glyphs loop over lookups, quit at match + -- 2 loop over glyphs loop over lookups, continue at match + -- 3 loop over lookups loop over glyphs + + fonts.otf.strategy = 2 + function fonts.otf.features.process.feature(head,font,attr,kind,attribute) tfmdata = fontdata[font] local shared = tfmdata.shared @@ -2771,6 +2831,7 @@ do local fullkind = kind .. script .. language local lookuptable = shared.lookuptable[fullkind] if lookuptable then + local strategy = fonts.otf.strategy local types = otfdata.luatex.name_to_type local start, done, ok = head, false, false local processes = shared.processes[fullkind] @@ -2808,23 +2869,68 @@ do start = start.next end end + elseif strategy == 3 then + for i=1,#processes do local p = processes[i] + local pp = p[3] + start = head + while start do + if start.id == glyph then + if start.subtype<256 and start.font == font and + (not attr or has_attribute(start,0,attr)) and -- dynamic feature + (not attribute or has_attribute(start,state,attribute)) then + local pc = pp[start.char] + if pc then + start, ok = p[1](start,kind,p[2],pc,pp,p[4]) + if ok then + done = true + end -- else + if start then start = start.next end + else + start = start.next + end + else + start = start.next + end + elseif start.id == glue then + if p[5] then -- chain + local pc = pp[32] + if pc then + start, ok = p[1](start,kind,p[2],pc,p[3],p[4]) + if ok then + done = true + end + if start then start = start.next end + else + start = start.next + end + else + start = start.next + end + else + start = start.next + end + end + end else while start do if start.id == glyph then if start.subtype<256 and start.font == font and (not attr or has_attribute(start,0,attr)) and -- dynamic feature (not attribute or has_attribute(start,state,attribute)) then - local chr = start.char + local chr = start.char -- used ? for i=1,#processes do local p = processes[i] local pp = p[3] - -- local pc = pp[start.char] -- var maken - local pc = pp[chr] +--~ local pc = pp[chr] + local pc = pp[start.char] if pc then start, ok = p[1](start,kind,p[2],pc,pp,p[4]) if ok then done = true - break - elseif not start then + if strategy == 1 then + break + end + end -- else + if not start then break end end @@ -2839,8 +2945,11 @@ do start, ok = p[1](start,kind,p[2],pc,pp,p[4]) if ok then done = true - break - elseif not start then + if strategy == 1 then + break + end + end + if not start then break end end @@ -2909,26 +3018,7 @@ do end end local next = start.next ---~ while true do ---~ if next == stop or deletemarks or marks[next.char] then ---~ local crap = next ---~ next.prev.next = next.next ---~ if next.next then ---~ next.next.prev = next.prev ---~ end ---~ if next == stop then ---~ stop = crap.prev ---~ node.free(crap) ---~ break ---~ else ---~ next = next.next ---~ node.free(crap) ---~ end ---~ else ---~ next = next.next ---~ end ---~ end - while true do + while next do if next == stop or deletemarks or marks[next.char] then local crap = next local np, nn = next.prev, next.next @@ -2955,10 +3045,10 @@ do function fonts.otf.features.process.gsub_single(start,kind,lookupname,replacements) if replacements then - start.char = replacements if fonts.otf.trace_replacements then - report("otf process",format("%s:%s replacing %s by %s",kind,lookupname,start.char,replacements)) + report("otf process",format("%s:%s replacing 0x%04X by 0x%04X",kind,lookupname,start.char,replacements)) end + start.char = replacements return start, true else return start, false @@ -2967,10 +3057,10 @@ do function fonts.otf.features.process.gsub_alternate(start,kind,lookupname,alternatives) if alternatives then - start.char = alternatives[1] -- will be preference if fonts.otf.trace_replacements then - report("otf process",format("%s:%s alternative %s => %s",kind,lookupname,start.char,table.concat(alternatives,"|"))) + report("otf process",format("%s:%s alternative 0x%04X => %s",kind,lookupname,start.char,table.hexed(alternatives))) end + start.char = alternatives[1] -- will be preference return start, true else return start, false @@ -2979,6 +3069,9 @@ do function fonts.otf.features.process.gsub_multiple(start,kind,lookupname,multiples) if multiples then + if fonts.otf.trace_replacements then + report("otf process",format("%s:%s multiple 0x%04X => %s",kind,lookupname,start.char,table.hexed(multiples))) + end start.char = multiples[1] if #multiples > 1 then for k=2,#multiples do @@ -2994,9 +3087,6 @@ do start = n end end - if fonts.otf.trace_replacements then - report("otf process",format("%s:%s alternative %s => %s",kind,lookupname,start.char,table.concat(multiples," "))) - end return start, true else return start, false @@ -3034,186 +3124,163 @@ do if stop and ligatures[2] then start = toligature(start,stop,ligatures[2],flags[1],discfound) if fonts.otf.trace_ligatures then - report("otf process",format("%s: inserting ligature %s (%s)",kind,start.char,utf.char(start.char))) + report("otf process",format("%s: inserting ligature 0x%04X (%s)",kind,start.char,utf.char(start.char))) end return start, true end return start, false end - -- again, using copies is more efficient than sharing code - - function fonts.otf.features.process.gpos_mark2base(start,kind,lookupname,baseanchors,anchors) -- maybe use copies - local bases = baseanchors['basechar'] - if bases then - local component = start.next - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - local trace = fonts.otf.trace_anchors - local last, done = start, false - local factor = tfmdata.factor - while true do - local markanchors = anchors[component.char] - if markanchors then - local marks = markanchors['mark'] - if marks then - for anchor,data in pairs(marks) do - local ba = bases[anchor] - if ba then - local dx = scale(ba[1]-data[1], factor) - local dy = scale(ba[2]-data[2], factor) - component.xoffset = start.xoffset - dx - component.yoffset = start.yoffset + dy - if trace then - report("otf process",format("%s: anchoring mark %s to basechar %s => (%s,%s) => (%s,%s)",kind,component.char,start.char,dx,dy,component.xoffset,component.yoffset)) + function fonts.otf.features.process.gpos_mark2base(start,kind,lookupname,m_anchors,b_anchors) + local markchar = start.char + if marks[markchar] then + local markanchors = m_anchors['mark'] + if markanchors then + local component = start.prev + while component and component.id == glyph and component.subtype<256 and component.font == currentfont do + local basechar = component.char + if marks[basechar] then + component = component.prev + else + local baseanchors = b_anchors[basechar] + if baseanchors then + baseanchors = baseanchors['basechar'] + if baseanchors then + for anchor, ma in pairs(markanchors) do + local ba = baseanchors[anchor] + if ba then + local factor = tfmdata.factor + local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor) + start.xoffset, start.yoffset = component.xoffset - dx, component.yoffset + dy + if fonts.otf.trace_anchors then + report("otf process",format("%s: anchoring mark 0x%04X to basechar 0x%04X => (%s,%s) => (%s,%s)", + kind,markchar,basechar,dx,dy,start.xoffset,start.yoffset)) + end + return start, true end - done = true - break end end end - last = component - end - component = component.next ---~ if component and component.id == kern then ---~ component = component.next ---~ end - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - -- ok - else break end end - return last, done end end return start, false end - function fonts.otf.features.process.gpos_mark2ligature(start,kind,lookupname,baseanchors,anchors) - local bases = baseanchors['baselig'] - if bases then - local component = start.next - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - local trace = fonts.otf.trace_anchors - local last, done = start, false - local factor = tfmdata.factor - while true do - local markanchors = anchors[component.char] - if markanchors then - local marks = markanchors['mark'] - if marks then - for anchor,data in pairs(marks) do - local ba = bases[anchor] - if ba then - local n = has_attribute(component,marknumber) - local ban = ba[n] - if ban then - local dx = scale(ban[1]-data[1], factor) - local dy = scale(ban[2]-data[2], factor) - component.xoffset = start.xoffset - dx - component.yoffset = start.yoffset + dy - if trace then - report("otf process",format("%s:%s:%s anchoring mark %s to baselig %s => (%s,%s) => (%s,%s)",kind,anchor,n,component.char,start.char,dx,dy,component.xoffset,component.yoffset)) + function fonts.otf.features.process.gpos_mark2ligature(start,kind,lookupname,m_anchors,b_anchors) -- maybe use copies + local markchar = start.char + if marks[markchar] then + local markanchors = m_anchors['mark'] + if markanchors then + local component = start.prev + while component and component.id == glyph and component.subtype<256 and component.font == currentfont do + local basechar = component.char + if marks[basechar] then + component = component.prev + else + local baseanchors = b_anchors[basechar] + if baseanchors then + baseanchors = baseanchors['baselig'] + if baseanchors then + for anchor, ma in pairs(markanchors) do + local ba = baseanchors[anchor] + if ba then + local n = has_attribute(start,marknumber) + ba = ba[n] + if ba then + local factor = tfmdata.factor + local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor) + start.xoffset, start.yoffset = component.xoffset - dx, component.yoffset + dy + if fonts.otf.trace_anchors then + report("otf process",format("%s: anchoring mark 0x%04X to baseligature 0x%04X => (%s,%s) => (%s,%s)", + kind,markchar,basechar,dx,dy,component.xoffset,component.yoffset)) + end + return start, true end - done = true - break end end end end - end - last = component - component = component.next ---~ if component and component.id == kern then ---~ component = component.next ---~ end - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - -- ok - else break end end - return last, done + return start, done end end return start, false end - function fonts.otf.features.process.gpos_mark2mark(start,kind,lookupname,baseanchors,anchors) - -- we can stay in the loop for all anchors - local bases = baseanchors['basemark'] - if bases then - local component = start.next - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - local baseattr = has_attribute(start,marknumber) or 1 - local trace = fonts.otf.trace_anchors - local last, done = start, false - local factor = tfmdata.factor - while true do - local markattr = has_attribute(component,marknumber) or 1 - if baseattr == markattr then - local markanchors = anchors[component.char] - if markanchors then - local marks = markanchors['mark'] - if marks then - for anchor,data in pairs(marks) do - local ba = bases[anchor] - if ba then - local dx = scale(ba[1]-data[1], factor) - local dy = scale(ba[2]-data[2], factor) - component.xoffset = start.xoffset - dx - component.yoffset = start.yoffset + dy - if trace then - report("otf process",format("%s:%s:%s anchoring mark %s to basemark %s => (%s,%s) => (%s,%s)",kind,anchor,markattr,start.char,component.char,dx,dy,component.xoffset,component.yoffset)) + function fonts.otf.features.process.gpos_mark2mark(start,kind,lookupname,b_anchors,m_anchors) + local markchar = start,char + if marks[markchar] then + local baseanchors = b_anchors['basemark'] + if baseanchors then + local component = start.next + while component and component.id == glyph and component.subtype<256 and component.font == currentfont do + local basechar = component.char + if not marks[basechar] then + break + else + local markattr = has_attribute(start, marknumber) or 1 + local baseattr = has_attribute(component,marknumber) or 1 + if baseattr == markattr then -- still needed? + local markanchors = m_anchors[basechar] + if markanchors then + local markanchor = markanchors['mark'] + if markanchor then + for anchor,ma in pairs(markanchor) do + local ba = baseanchors[anchor] + if ba then + local factor = tfmdata.factor + local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor) + component.xoffset, component.yoffset = start.xoffset - dx, start.yoffset + dy + if fonts.otf.trace_anchors then + report("otf process",format("%s:%s:%s anchoring mark 0x%04X to basemark 0x%04X => (%s,%s) => (%s,%s)", + kind,anchor,markattr,markchar,basechar,dx,dy,component.xoffset,component.yoffset)) + end + return start, true end - done = true - break end end end + component = component.next end - last = component - component = component.next ---~ if component and component.id == kern then ---~ component = component.next ---~ end - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - -- ok - else - break - end - else - break end end - return last, done + return start, done end end return start, false end + -- the following can be optimized, also, we can share the table (no need to collect) + function fonts.otf.features.process.gpos_cursive(start,kind,lookupname,exitanchors,anchors) local trace = fonts.otf.trace_anchors - local next, done, x, y, total, t, first = start.next, false, 0, 0, 0, { }, nil + local next, done, x, y, total_x, total_y, tx, ty, first = start.next, false, 0, 0, 0, 0, { }, { }, nil + local factor = tfmdata.factor local function finish() local i = 0 - local factor = tfmdata.factor - while first do - if characters[first.char].description.class == 'mark' then + while first and first.id == glyph do + if marks[first.char] then first = first.next else - first.yoffset = scale(total, factor) - -- first.yoffset = factor*total + i = i + 1 + first.yoffset = scale(total_y, factor) + if fonts.otf.trace_cursive then + report("otf process",format("%s:%s move 0x%04X cursive (%s,%s)",kind,lookupname,first.char,"?",total_y)) + end if first == next then break else - i = i + 1 - total = total - (t[i] or 0) + total_y = total_y - (ty[i] or 0) first = first.next end end end - x, y, total, t, first = 0, 0, 0, { }, nil + x, y, total_x, total_y, tx, ty, first = 0, 0, 0, 0, { }, { }, nil end while next do if next.id == glyph and next.subtype<256 and next.font == currentfont then @@ -3229,8 +3296,9 @@ do local exit = cexit[anchor] if exit then if not first then first = start end - t[#t+1] = exit[2] + entry[2] - total = total + t[#t] + local dx, dy = exit[1] + entry[1], -exit[2] + entry[2] + tx[#tx+1], ty[#ty+1] = dx, dy + total_x, total_y = total_x + dx, total_y + dy done = true break end @@ -3288,7 +3356,7 @@ do else -- todo, just start, next = node.insert_before(head,next,nodes.kern(scale(kern,factor))) if fonts.otf.trace_kerns then - report("otf process",format("%s: inserting kern %s between %s and %s",kind,krn,prev.char,next.char)) + report("otf process",format("%s: inserting kern %s between 0x%04X and 0x%04X",kind,krn,prev.char,next.char)) end local k = nodes.kern(scale(krn,factor)) k.next = next @@ -3309,38 +3377,54 @@ do -- are stored in the featurecache, because we don't want to loop over all characters -- in order to locate them. - -- We had a version that shared code, but it was too much a slow down - -- todo n x n. - function chainprocs.gsub_single(start,stop,kind,lookupname,sequence,f,l,lookups) - local char = start.char - local cacheslot = sequence[f] -- [1] - local replacement = cacheslot[char] - if replacement == true then - if lookups then - local looks = glyphs[tfmdata.characters[char].description.index].lookups - if looks then - local lookups = otfdata.luatex.internals[lookups[1]].lookups - local unicodes = otfdata.luatex.unicodes - for l=1,#lookups do - local lv = looks[lookups[l]] - if lv then - replacement = unicodes[lv[1][2]] or char - cacheslot[char] = replacement - break + local trace = fonts.otf.trace_replacements + local c, r = trace and { }, trace and { } + local lookup, index, current = 1, f, start + while current ~= nil do + if current.id == glyph then -- test for more ? + local char = current.char + local cacheslot = sequence[index] + local replacement = cacheslot[char] + if replacement == true then + if lookups then + local looks = glyphs[tfmdata.characters[char].description.index].lookups -- SLOW, USE OTFDATA + if looks then + local glyphlookups = otfdata.luatex.internals[lookups[lookup]].lookups + local unicodes = otfdata.luatex.unicodes + for gl=1,#glyphlookups do + local lv = looks[glyphlookups[gl]] + if lv then + replacement = unicodes[lv[1][2]] or char + cacheslot[char] = replacement + break + end + end + else + replacement, cacheslot[char] = char, char end + else + replacement, cacheslot[char] = char, char end + end + if trace then + c[#c+1], r[#r+1] = char, replacement + end + current.char = replacement + if current == stop then + break else - replacement, cacheslot[char] = char, char + current, lookup, index = current.next, lookup + 1, index + 1 end + elseif current == stop then + break else - replacement, cacheslot[char] = char, char + current = current.next end end - if fonts.otf.trace_replacements then - report("otf chain",format("%s: replacing character %s by single %s",kind,char,replacement)) + if trace then + report("otf chain",format("%s: single replacement %s by %s",kind,table.hexed(c),table.hexed(r))) end - start.char = replacement return start end @@ -3375,7 +3459,7 @@ do end end if fonts.otf.trace_replacements then - report("otf chain",format("%s: replacing character %s by multiple",kind,char)) + report("otf chain",format("%s: replacing character 0x%04X by multiple 0x%04X",kind,char,table.hexed(replacement))) end start.char = replacement[1] if #replacement > 1 then @@ -3426,7 +3510,7 @@ do end end if fonts.otf.trace_replacements then - report("otf chain",format("%s: replacing character %s by alternate",kind,char)) + report("otf chain",format("%s: replacing character 0x%04X by alternate",kind,char)) end start.char = replacement[1] return start @@ -3451,7 +3535,7 @@ do if id == disc then s = s.next discfound = true - elseif characters[s.char].description.class == 'mark' then + elseif characters[s.char].description.class == 'mark' then -- marks s = s.next else local lg = ligatures[1][s.char] @@ -3469,7 +3553,11 @@ do end if ligatures[2] then if trace then - report("otf chain",format("%s: replacing character %s by ligature",kind,start.char)) + if start == stop then + report("otf chain",format("%s: replacing character 0x%04X by ligature 0x%04X",kind,start.char,ligatures[2])) + else + report("otf chain",format("%s: replacing character 0x%04X upto 0x%04X by ligature 0x%04X",kind,start.char,stop.char,ligatures[2])) + end end return toligature(start,stop,ligatures[2],flags[1],discfound) end @@ -3480,187 +3568,195 @@ do return stop end - function chainprocs.gpos_mark2base(start,stop,kind,lookupname,sequence,f,l,lookups) - local component = start.next - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - local char = start.char - local anchortag = sequence[f][char] -- sequence[1][char] + -- weird, mkmk can have a mark2base, in idris font + + function chainprocs.gpos_mark2base(start,stop,kind,lookupname,sequence,f,l,lookups,flags) + -- dynamic resolver + local markchar = start.char + if marks[markchar] then + local anchortag = sequence[f][markchar] if anchortag == true then + local ok = false local classes = otfdata.anchor_classes + local lookups = otfdata.luatex.internals[lookups[1]].lookups for k=1,#classes do local v = classes[k] - if v.lookup == lookupname and v.type == kind then + if v.lookup == lookups[1] then -- let's gamble for uniqueness: and v.type == kind then anchortag = v.name - -- sequence[1][char] = anchortag - sequence[f][char] = anchortag + sequence[f][markchar] = anchortag + ok = true break end end + if not ok and fonts.otf.trace_anchors then + report("otf chain",format("%s: no matching mark2base anchor class for 0x%04X, lookup %s",kind,markchar,lookups[1])) + end end if anchortag ~= true then - local glyph = glyphs[characters[char].description.index] - if glyph.anchors and glyph.anchors[anchortag] then - local trace = fonts.otf.trace_anchors - local last, done = start, false - local baseanchors = glyph.anchors['basechar'][anchortag] - local factor = tfmdata.factor - while true do - local nextchar = component.char - local charnext = characters[nextchar] - local markanchors = glyphs[charnext.description.index].anchors['mark'][anchortag] - if markanchors then - for anchor,data in pairs(markanchors) do - local ba = baseanchors[anchor] - if ba then - local dx = scale(ba[1]-data[1], factor) - local dy = scale(ba[2]-data[2], factor) - component.xoffset = start.xoffset - dx - component.yoffset = start.yoffset + dy - if trace then - report("otf chain",format("%s: anchoring mark %s to basechar %s => (%s,%s) => (%s,%s)",kind,component.char,start.char,dx,dy,component.xoffset,component.yoffset)) + local component = start.prev + while component and component.id == glyph and component.subtype<256 and component.font == currentfont do + local basechar = component.char + if marks[basechar] then + component = component.prev + else + local bglyph = glyphs[characters[basechar].description.index] -- startchar + local baseanchors = bglyph.anchors['basechar'] + if baseanchors then + local ba = baseanchors[anchortag] + if ba then + local mglyph = glyphs[characters[markchar].description.index] + local markanchors = mglyph.anchors['mark'] + if markanchors then + local ma = markanchors[anchortag] + if ma then + local factor = tfmdata.factor + local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor) + start.xoffset, start.yoffset = component.xoffset - dx, component.yoffset + dy + if fonts.otf.trace_anchors then + report("otf chain",format("%s: anchoring mark 0x%04X to basechar 0x%04X => (%s,%s) => (%s,%s)", + kind,markchar,basechar,dx,dy,start.xoffset,start.yoffset)) + end + return start, true end - done = true - break end end end - last = component - component = component.next - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - -- ok - else - break - end + break end - return last, done end end end return start, false end - function chainprocs.gpos_mark2ligature(start,stop,kind,lookupname,sequence,f,l,lookups) - local component = start.next - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - local char = start.char - local anchortag = sequence[f][char] -- [1][char] + function chainprocs.gpos_mark2ligature(start,stop,kind,lookupname,sequence,f,l,lookups,flags) + -- dynamic resolver + local markchar = start.char + if marks[markchar] then + local anchortag = sequence[f][markchar] if anchortag == true then local classes = otfdata.anchor_classes + local lookups = otfdata.luatex.internals[lookups[1]].lookups + local ok = false for k=1,#classes do local v = classes[k] - if v.lookup == lookupname and v.type == kind then + if v.lookup == lookups[1] then -- and v.type == kind then anchortag = v.name - -- sequence[1][char] = anchortag - sequence[f][char] = anchortag + sequence[f][markchar] = anchortag + ok = true break end end + if not ok and fonts.otf.trace_anchors then + report("otf chain",format("%s: no matching mark2ligature anchor class for 0x%04X, lookup %s",kind,markchar,lookups[1])) + end end if anchortag ~= true then - local glyph = glyphs[characters[char].description.index] - if glyph.anchors and glyph.anchors[anchortag] then - local trace = fonts.otf.trace_anchors - local done = false - local last = start - local baseanchors = glyph.anchors['baselig'][anchortag] - local factor = tfmdata.factor - while true do - local nextchar = component.char - local charnext = characters[nextchar] - local markanchors = glyphs[charnext.description.index].anchors['mark'][anchortag] - if markanchors then - for anchor,data in pairs(markanchors) do - local ba = baseanchors[anchor] + local component = start.prev + while component and component.id == glyph and component.subtype<256 and component.font == currentfont do + local basechar = component.char + if marks[basechar] then + component = component.prev + else + local bglyph = glyphs[characters[basechar].description.index] -- startchar + local baseanchors = bglyph.anchors['baselig'] + if baseanchors then + local ba = baseanchors[anchortag] + if ba then + local n = has_attribute(start,marknumber) + ba = ba[n] -- ok ? if ba then - local n = has_attribute(component,marknumber) - local ban = ba[n] - if ban then - local dx = scale(ban[1]-data[1], factor) - local dy = scale(ban[2]-data[2], factor) - component.xoffset = start.xoffset - dx - component.yoffset = start.yoffset + dy - if trace then - report("otf chain",format("%s: anchoring mark %s to baselig %s => (%s,%s) => (%s,%s)",kind,component.char,start.char,dx,dy,component.xoffset,component.yoffset)) + local mglyph = glyphs[characters[markchar].description.index] + local markanchors = mglyph.anchors['mark'] + if markanchors then + local ma = markanchors[anchortag] + if ma then + local factor = tfmdata.factor + local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor) + start.xoffset, start.yoffset = component.xoffset - dx, component.yoffset + dy + if fonts.otf.trace_anchors then + report("otf chain",format("%s: anchoring mark 0x%04X to baseligature 0x%04X => (%s,%s) => (%s,%s)", + kind,basechar,markchar,dx,dy,start.xoffset,start.yoffset)) + end + return start, true end - done = true - break end end end end - last = component - component = component.next - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - -- ok - else - break - end + break end - return last, done end end end return start, false end + -- to be checked + function chainprocs.gpos_mark2mark(start,stop,kind,lookupname,sequence,f,l,lookups) local component = start.next if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - local char = start.char - local anchortag = sequence[f][char] -- [1][char] + local markchar = start.char + local anchortag = sequence[f][markchar] -- [1][char] if anchortag == true then local classes = otfdata.anchor_classes + local ok = false for k=1,#classes do local v = classes[k] - if v.lookup == lookupname and v.type == kind then + if v.lookup == lookupname then -- and v.type == kind then anchortag = v.name - -- sequence[1][char] = anchortag - sequence[f][char] = anchortag + sequence[f][markchar] = anchortag + ok = true break end end + if not ok and fonts.otf.trace_anchors then + report("otf chain",format("%s: no matching mark2mark anchor class for 0x%04X, lookup %s",kind,markchar,lookups[1])) + end end - local baseattr = has_attribute(start,marknumber) - local markattr = has_attribute(component,marknumber) - if baseattr == markattr and anchortag ~= true then - local glyph = glyphs[characters[char].description.index] - if glyph.anchors and glyph.anchors[anchortag] then - local trace = fonts.otf.trace_anchors - local last, done = false - local baseanchors = glyph.anchors['basemark'][anchortag] - local factor = tfmdata.factor - while true do - local nextchar = component.char - local charnext = characters[nextchar] - local markanchors = glyphs[charnext.description.index].anchors['mark'][anchortag] - if markanchors then - for anchor,data in pairs(markanchors) do - local ba = baseanchors[anchor] - if ba then - local dx = scale(ba[1]-data[1], factor) - local dy = scale(ba[2]-data[2], factor) - component.xoffset = start.xoffset - dx - component.yoffset = start.yoffset + dy - if trace then - report("otf chain",format("%s: anchoring mark %s to basemark %s => (%s,%s) => (%s,%s)",kind,component.char,start.char,dx,dy,component.xoffset,component.yoffset)) + if anchortag ~= true then + -- the following may have been be spoiled while idrising the other ones + local markattr = has_attribute(start, marknumber) or 1 -- i need to check this ! 1 is new ! + local baseattr = has_attribute(component,marknumber) or 1 -- i need to check this ! 1 is new ! + if baseattr == markattr then + local glyph = glyphs[characters[markchar].description.index] + if glyph.anchors and glyph.anchors[anchortag] then + local trace = fonts.otf.trace_anchors + local done = false + local baseanchors = glyph.anchors['basemark'][anchortag] + while true do + local basechar = component.char + local charnext = characters[basechar] + local markanchors = glyphs[charnext.description.index].anchors['mark'][anchortag] + if markanchors then + for anchor,data in pairs(markanchors) do + local ba = baseanchors[anchor] + if ba then + local factor = tfmdata.factor + local dx, dy = scale(ba[1]-ma[1],factor), scale(ba[2]-ma[2],factor) + start.xoffset, start.yoffset = component.xoffset - dx, component.yoffset + dy + if fonts.otf.trace_anchors then + report("otf chain",format("%s: anchoring mark 0x%04X to basemark 0x%04X => (%s,%s) => (%s,%s)", + kind,markchar,basechar,dx,dy,component.xoffset,component.yoffset)) + end + done = true + break end - done = true - break end end - end - last = component - component = component.next - if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then - markattr = has_attribute(component,marknumber) - if baseattr ~= markattr then + component = component.next + if component and component.id == glyph and component.subtype<256 and component.font == currentfont and marks[component.char] then + markattr = has_attribute(component,marknumber) + if baseattr ~= markattr then + break + end + else break end - else - break end + return start, done end - return last, done end end end @@ -3685,73 +3781,150 @@ do return stop end + local zwnj = 0x200C + local zwj = 0x200D + + -- what pointer to return, spec says stop + function fonts.otf.features.process.contextchain(start,kind,lookupname,contextdata) - local done = false - local contexts = contextdata.lookups - local flags = contextdata.flags - local skipmark, skipligature, skipbase = unpack(flags) + local contexts, flags, done = contextdata.lookups, contextdata.flags, false + local skipmark, skipligature, skipbase = unpack(flags) -- unpack slower than assignment for k=1,#contexts do - local match, next, first, last = true, start, start, start + local match, next, last = true, start, start local rule, lookuptype, sequence, f, l, lookups = unpack(contexts[k]) -- unpack is slow - if #sequence == 1 then + local s = #sequence + if s == 1 then match = next.id == glyph and next.subtype<256 and next.font == currentfont and sequence[1][next.char] else -- todo: better space check (maybe check for glue) ---~ print("\nSTART ", k, start) - local n, s = 1, #sequence - while n <= s do - if next then - local id = next.id - if id == glyph and next.subtype<256 and next.font == currentfont then -- normal char - local char = next.char + local n = f + while n <= l do + if last then + local id = last.id + if id == glyph and last.subtype<256 and last.font == currentfont then + local char = last.char local class = characters[char].description.class if class == skipmark or class == skipligature or class == skipbase then ---~ print("S",n,char,utf.char(char)) - -- skip + -- skip 'm + last = last.next elseif sequence[n][char] then ---~ print("Y",n,char,utf.char(char)) - if n == f then - first = next - end - if n == l then - last = next + if n < l then + last = last.next end n = n + 1 else ---~ print("N",n,char,utf.char(char)) match = false break end - elseif id == disc then ---~ print("D",n) - -- skip - elseif not sequence[n][32] then -- brrr ---~ print("S",n) + elseif id == disc then -- what to do with kerns? + last = last.next + else match = false break end - next = next.next - elseif sequence[n][32] then - n = n + 1 else ---~ print("S",n) match = false break end end ---~ print((match and "MATCH") or "NO MATCH") + if match and f > 1 then + local prev = start.prev + if prev then + if f == 2 then + match = prev.id == glyph and prev.subtype<256 and prev.font == currentfont and sequence[1][prev.char] + else + local n = f-1 + while n >= 1 do + if prev then + local id = prev.id + if id == glyph and prev.subtype<256 and prev.font == currentfont then -- normal char + local char = prev.char + local class = characters[char].description.class + if class == skipmark or class == skipligature or class == skipbase then + -- skip 'm + elseif sequence[n][char] then + n = n -1 + else + match = false break + end + elseif id == disc then + -- skip 'm + elseif sequence[n][32] then + n = n -1 + else + match = false break + end + prev = prev.prev + elseif sequence[n][32] then + n = n -1 + else + match = false break + end + end + end + elseif f == 2 then + match = sequence[1][32] + else + for n=f-1,1 do + if not sequence[n][32] then + match = false break + end + end + end + end + if match and s > l then + local next = last.next + if next then + if s-l == 1 then + match = next.id == glyph and next.subtype<256 and next.font == currentfont and sequence[s][next.char] + else + local n = l+ 1 + while n <= s do + if next then + local id = next.id + if id == glyph and next.subtype<256 and next.font == currentfont then -- normal char + local char = next.char + local class = characters[char].description.class + if class == skipmark or class == skipligature or class == skipbase then + -- skip 'm + elseif sequence[n][char] then + n = n + 1 + else + match = false break + end + elseif id == disc then + -- skip 'm + elseif sequence[n][32] then -- brrr + n = n + 1 + else + match = false break + end + next = next.next + elseif sequence[n][32] then + n = n + 1 + else + match = false break + end + end + end + elseif s-l == 1 then + match = sequence[s][32] + else + for n=l+1,s do + if not sequence[n][32] then + match = false break + end + end + end + end end if match then local trace = fonts.otf.trace_contexts if trace then - local char = first.char - report("otf chain",format("%s: rule %s of %s matches, replacing starts at char %s (%s) lookuptype %s",kind,rule,lookupname,char,utf.char(char),lookuptype)) + local char = start.char + report("otf chain",format("%s: rule %s of %s matches at char 0x%04X (%s) for (%s,%s,%s) chars, lookuptype %s",kind,rule,lookupname,char,utf.char(char),f-1,l-f+1,s-l,lookuptype)) end if lookups then local cp = chainprocs[lookuptype] if cp then - if start == first then - start = cp(first,last,kind,lookupname,sequence,f,l,lookups,flags) - else - first = cp(first,last,kind,lookupname,sequence,f,l,lookups,flags) - end + start = cp(start,last,kind,lookupname,sequence,f,l,lookups,flags) else report("otf chain",format("%s: lookuptype %s not supported yet for %s",kind,lookuptype,lookupname)) end @@ -3765,6 +3938,20 @@ do return start, done end +--~ if true then +--~ if n < f then +--~ texio.write_nl(string.format("%s before %s %04x %s %s %s",lookupname,n,char,class,skipmark or "?",tostring(sequence[n][char]))) +--~ elseif n > l then +--~ texio.write_nl(string.format("%s after %s %04x %s %s %s",lookupname,n,char,class,skipmark or "?",tostring(sequence[n][char]))) +--~ else +--~ texio.write_nl(string.format("%s current %s %04x %s %s %s",lookupname,n,char,class,skipmark or "?",tostring(sequence[n][char]))) +--~ end +--~ end + +--~ elseif char == zwnj and sequence[n][32] then -- brrr + + -- this needs to be fixed ! ! ! ! ! ! ! ! + function fonts.otf.features.process.reversecontextchain(start,kind,lookupname,contextdata) -- PROBABLY WRONG, WE NEED TO WALK BACK OVER THE LIST local done = false @@ -3814,7 +4001,7 @@ do local trace = fonts.otf.trace_contexts if trace then local char = first.char - report("otf reverse chain",format("%s: rule %s of %s matches, replacing starts at char %s (%s) lookuptype %s",kind,rule,lookupname,char,utf.char(char),lookuptype)) + report("otf reverse chain",format("%s: rule %s of %s matches, replacing starts at char 0x%04X (%s) lookuptype %s",kind,rule,lookupname,char,utf.char(char),lookuptype)) end if lookups then local cp = chainprocs[lookuptype] @@ -4078,9 +4265,6 @@ fonts.initializers.node.otf.equaldigits = fonts.initializers.common.equaldigits fonts.initializers.base.otf.lineheight = fonts.initializers.common.lineheight fonts.initializers.node.otf.lineheight = fonts.initializers.common.lineheight -fonts.initializers.base.otf.complement = fonts.initializers.common.complement -fonts.initializers.node.otf.complement = fonts.initializers.common.complement - fonts.initializers.base.otf.compose = fonts.initializers.common.compose fonts.initializers.node.otf.compose = fonts.initializers.common.compose @@ -4206,12 +4390,13 @@ do fonts.analyzers.methods.latn = fonts.analyzers.aux.setstate - -- arab / todo: 0640 tadwil - -- this info eventually will go into char-def + local zwnj = 0x200C + local zwj = 0x200D + local isol = { - [0x0621] = true, + [0x0621] = true, } local isol_fina = { @@ -4224,6 +4409,7 @@ do local isol_fina_medi_init = { [0x0626] = true, [0x0628] = true, [0x0629] = true, [0x062A] = true, [0x062B] = true, [0x062C] = true, [0x062D] = true, [0x062E] = true, [0x0633] = true, [0x0634] = true, [0x0635] = true, [0x0636] = true, [0x0637] = true, [0x0638] = true, [0x0639] = true, [0x063A] = true, + [0x0640] = true, -- tadwil [0x0641] = true, [0x0642] = true, [0x0643] = true, [0x0644] = true, [0x0645] = true, [0x0646] = true, [0x0647] = true, [0x0649] = true, [0x064A] = true, [0x067E] = true, [0x0686] = true, @@ -4294,10 +4480,15 @@ do if current.id == glyph and current.subtype<256 and current.font == font then done = true local char = current.char - local chardata = characters[char] - if not chardata then + local chardata = characters[char] -- some day we will make a characters.marks hash + if not chardata then -- this is also more efficient since it's shared -- troubles - elseif chardata.description.class == "mark" then -- marks are now in components + -- elseif char == zwj then + -- -- can probably be ignored, we could turn it into a kern or penalty + -- elseif char == zwnj then + -- -- acts like a space, we could turn it into a kern or penalty + -- finish() + elseif chardata.description.class == "mark" then set_attribute(current,state,5) -- mark if trace then fcs(current,"font:mark") end elseif isol[char] then @@ -4493,9 +4684,9 @@ do fonts.analyzers.methods.stretch_hang = true fonts.analyzers.methods.hang_data = { - inter_char_stretch_factor = 2.00, -- we started with 0.5, then 1.0 - inter_char_half_factor = 0.50, -- normally there is no reason to change this - inter_char_half_schrink_factor = 0.25, -- normally there is no reason to change this + inter_char_stretch_factor = 2.00, -- we started with 0.5, then 1.0 + inter_char_half_factor = 0.50, -- normally there is no reason to change this + inter_char_half_shrink_factor = 0.25, -- normally there is no reason to change this } local hang_data = fonts.analyzers.methods.hang_data @@ -4514,7 +4705,7 @@ do return insert_before(head,current,nodes.penalty(10000)) end - function fonts.analyzers.methods.hang(head,font,attr) + function fonts.analyzers.methods.hani(head,font,attr) -- maybe make a special version with no trace local characters = fontdata[font].characters local current, done, stretch, prevclass = head, false, 0, 0 @@ -4523,9 +4714,10 @@ do end -- penalty before break local interspecialskip = - stretch * hang_data.inter_char_half_factor - local interspecialshrink = stretch * hang_data.inter_char_half_schrink_factor + local interspecialshrink = stretch * hang_data.inter_char_half_shrink_factor local internormalstretch = stretch * hang_data.inter_char_stretch_factor local trace = fonts.color.trace +-- todo: check for first and last while current do if current.id == glyph and current.subtype<256 then if current.font == font then @@ -4534,7 +4726,9 @@ do -- don't ask -) elseif opening_punctuation_fw[char] or opening_parenthesis_fw[char] then if trace then fcs(current,"font:init") end +if head ~= current then head, _ = insert_before(head,current,nodes.glue(interspecialskip,0,interspecialshrink)) +end head, current = insert_after(head,current,nodes.penalty(10000)) head, current = insert_after(head,current,nodes.glue(0,internormalstretch,0)) prevclass, done = 1, true @@ -4592,7 +4786,7 @@ do return head, done end - fonts.analyzers.methods.hani = fonts.analyzers.methods.hang + fonts.analyzers.methods.hang = fonts.analyzers.methods.hani end diff --git a/tex/context/base/font-run.tex b/tex/context/base/font-run.tex index c3fde7791..2703600f5 100644 --- a/tex/context/base/font-run.tex +++ b/tex/context/base/font-run.tex @@ -182,14 +182,15 @@ \vskip2pt % the \noexpand before \blank is needed for non etex \edef\ascii{name: {\noexpand\black\fontname\font}} + \def\do##1##2{\ifx##1\undefined\else\ifx##1\empty\else##2\fi\fi}% \doifelse\v!unknown{#2} {\edef\theshowfontspecs {name: {\noexpand\black\fontname\font}}} {\edef\theshowfontspecs {name: {\noexpand\black\fontname\font}\noexpand\quad - encoding: {\noexpand\black\currentencoding}\noexpand\quad - mapping: {\noexpand\black\currentmapping }\noexpand\quad - handling: {\noexpand\black\fonthandling}}}% + \do\currentencoding{encoding: {\noexpand\black\currentencoding\noexpand\quad}}% + \do\currentmapping {mapping: {\noexpand\black\currentmapping \noexpand\quad}}% + \do\fonthandling {handling: {\noexpand\black\fonthandling }}}}% \tf % also sets em \hbox to 40em{\blue\hfill\tinyfont\setstrut\strut\theshowfontspecs} \egroup diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua index 7190cdc6f..460330525 100644 --- a/tex/context/base/font-syn.lua +++ b/tex/context/base/font-syn.lua @@ -145,10 +145,10 @@ function fonts.names.identify() local function traverse(what, method) for n, suffix in pairs(fonts.names.filters.list) do nofread, nofok = 0, 0 - local t = os.clock() -- use elapser + local t = os.gettimeofday() -- use elapser logs.report("fontnames", string.format("identifying %s font files with suffix %s",what,suffix)) method(suffix) - logs.report("fontnames", string.format("%s %s files identified, %s hash entries added, runtime %s seconds", nofread, what,nofok, os.clock()-t)) + logs.report("fontnames", string.format("%s %s files identified, %s hash entries added, runtime %s seconds", nofread, what,nofok, os.gettimeofday()-t)) end end traverse("tree", function(suffix) diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua index d8a575021..88a85652e 100644 --- a/tex/context/base/font-tfm.lua +++ b/tex/context/base/font-tfm.lua @@ -181,6 +181,7 @@ excessive memory usage in CJK fonts, we no longer pass the boundingbox.)

--ldx]]-- function fonts.tfm.do_scale(tfmtable, scaledpoints) + local trace = fonts.trace if scaledpoints < 0 then scaledpoints = (- scaledpoints/1000) * tfmtable.designsize -- already in sp end @@ -190,9 +191,17 @@ function fonts.tfm.do_scale(tfmtable, scaledpoints) for k,v in pairs(tfmtable) do t[k] = (type(v) == "table" and { }) or v end - local tc = t.characters - local trace = fonts.trace -- local zerobox = { 0, 0, 0, 0 } + local tp = t.parameters + for k,v in pairs(tfmtable.parameters) do + if k == 1 then + tp[k] = v + else + tp[k] = v*delta + end + end + local protrusionfactor = 1000/tp[6] -- emwidth + local tc = t.characters for k,v in pairs(tfmtable.characters) do local description = v.description or v -- shared data local chr = { @@ -214,6 +223,18 @@ function fonts.tfm.do_scale(tfmtable, scaledpoints) -- else -- -- chr.boundingbox = zerobox -- most afm en otf files have bboxes so .. -- end + local ve = v.expansion_factor + if ve then + chr.expansion_factor = ve*1000 -- expansionfactor + end + local vl = v.left_protruding + if vl then + chr.left_protruding = protrusionfactor*chr.width*vl + end + local vr = v.right_protruding + if vr then + chr.right_protruding = protrusionfactor*chr.width*vr + end local vi = description.italic if vi then chr.italic = vi*delta @@ -253,14 +274,6 @@ function fonts.tfm.do_scale(tfmtable, scaledpoints) end tc[k] = chr end - local tp = t.parameters - for k,v in pairs(tfmtable.parameters) do - if k == 1 then - tp[k] = v - else - tp[k] = v*delta - end - end -- t.encodingbytes, t.filename, t.fullname, t.name: elsewhere t.size = scaledpoints if t.fonts then @@ -392,88 +405,6 @@ function fonts.initializers.common.lineheight(tfmdata,value) end end - ---[[ldx-- -

The following feature is kind of experimental and deals with fallback characters.

---ldx]]-- - -fonts.initializers.complements = fonts.initializers.complements or { } -fonts.initializers.complements.data = fonts.initializers.complements.data or { } - -function fonts.initializers.complements.load(pattern) - local data = fonts.initializers.complements.data[pattern] - if not data then - data = { } - for k,v in pairs(characters.data) do - local vd = v.description - if vd and vd:find(pattern) then - local vs = v.specials - if vs and vs[1] == "compat" then - data[#data+1] = k - end - end - end - fonts.initializers.complements.data[pattern] = data - end - return data -end - -function fonts.initializers.common.complement(tfmdata,value) -- todo: value = latin:compat,.... - if value then - local chr, index, data, get_virtual_id = tfmdata.characters, nil, characters.data, fonts.tfm.get_virtual_id - local selection = fonts.initializers.complements.load("LATIN") -- will be value - -- for _, k in ipairs(selection) do - for i=1,#selection do - local k = selection[i] - if not chr[k] then - local dk = data[k] - local vs, name = dk.specials, dk.adobename - index = index or get_virtual_id(tfmdata) - local ok, t, w, h, d, krn, pre = true, {}, 0, 0, 0, nil, nil - for i=2,#vs do - local vsi = vs[i] - local c = chr[vsi] - if c then - local k = krn and krn[vsi] - if k then - t[#t+1] = { 'right', k } - w = w + k - end - t[#t+1] = { 'slot', index, vsi } - w = w + c.width - h = h + c.height - d = d + c.depth - krn = c.kerns - else - ok = false - break - end - end - if ok then - chr[k] = { - unicode = k, - name = name, - commands = t, - width = w, - height = h, - depth = d, - kerns = krn - } - local c = vs[2] - for k,v in pairs(chr) do -- slow - local krn = v.kerns - if krn then - krn[k] = krn[c] - end - end - end - end - end - end -end - -table.insert(fonts.triggers,"complement") - --[[ldx--

It does not make sense any more to support messed up encoding vectors so we stick to those that implement oldstyle and small caps. After all, diff --git a/tex/context/base/hand-ini.mkii b/tex/context/base/hand-ini.mkii new file mode 100644 index 000000000..03f9e05e2 --- /dev/null +++ b/tex/context/base/hand-ini.mkii @@ -0,0 +1,698 @@ +%D \module +%D [ file=hand-ini, % moved from enco-ini / pro +%D version=2000.12.27, % 1998.12.03, +%D title=\CONTEXT\ Handling Macros, +%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. + +%D {\em This module is experimental and implements font +%D specific features, like hanging punctuation.} + +\unprotect + +\startmessages dutch library: handlings + title: handling + 1: font afhandeling -- + 2: font afhandeling -- wordt geladen + 3: onbekende font afhandeling -- +\stopmessages + +\startmessages english library: handlings + title: handling + 1: font handling -- + 2: font handling -- is loaded + 3: unknown font handling -- +\stopmessages + +\startmessages german library: handlings % to do + title: handling + 1: font handling -- + 2: font handling -- is loaded + 3: unknown font handling -- +\stopmessages + +\startmessages czech library: handlings % to do + title: handling + 1: font handling -- + 2: font handling -- is loaded + 3: unknown font handling -- +\stopmessages + +\startmessages italian library: handlings % to do + title: handling + 1: font handling -- + 2: font handling -- is loaded + 3: unknown font handling -- +\stopmessages + +\startmessages norwegian library: handlings % to do + title: handling + 1: font handling -- + 2: font handling -- is loaded + 3: unknown font handling -- +\stopmessages + +\startmessages romanian library: handlings % to do + title: handling + 1: font handling -- + 2: font handling -- is loaded + 3: unknown font handling -- +\stopmessages + +\startmessages french library: handlings + title: manipulation + 1: manipulation -- de police + 2: la manipulation -- de police est chargée + 3: manipulation -- inconnue de police +\stopmessages + +\newif\iftracefonthandling % \tracefonthandlingtrue + +\newif\ifskiphandlingdef \skiphandlingdeffalse + +\newtoks\everyenablefonthandling + +% much in common with hz/protruding defs +% todo: fix others + +\let\normalchar\char % also done in enco-ini + +\def\dosetsomehandling#1#2#3 #4 % no define since directly set + {\ifskiphandlingdef \else + \doifnumberelse{\string#2} + {#1{#2#3}{#4}} + {\doifelsenothing{#3} + {#1{`#2}{#4}} + {\let\char\empty + \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}}\donothing + \let\char\normalchar}}% + \fi} + +\def\dosetpairhandling#1#2#3 #4 #5 % no define since directly set + {\ifskiphandlingdef \else + \doifnumberelse{\string#2} + {#1{#2#3}{#4}{#5}} + {\doifelsenothing{#3} + {#1{`#2}{#4}{#5}} + {\let\char\empty + \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}{#5}}\donothing + \let\char\normalchar}}% + \fi} + +% \def\dosettriplethandling#1#2#3 #4 #5 #6 % no define since directly set +% {\ifskiphandlingdef \else +% \doifnumberelse{\string#2} +% {#1{#2#3}{#4}{#5}{#6}} +% {\doifelsenothing{#3} +% {#1{`#2}{#4}{#5}{#6}} +% {\let\char\empty +% \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}{#5}{#6}}\donothing +% \let\char\normalchar}}% +% \fi} + +\def\dosetquartethandling#1#2#3 #4 #5 #6 #7 % no define since directly set + {\ifskiphandlingdef \else + \doifnumberelse{\string#2} + {#1{#2#3}{#4}{#5}{#6}{#7}} + {\doifelsenothing{#3} + {#1{`#2}{#4}{#5}{#6}{#7}} + {\let\char\empty + \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}{#5}{#6}{#7}}\donothing + \let\char\normalchar}}% + \fi} + + +% \def\doinhsomehandling#1#2 #3 % +% {\ifskiphandlingdef \else +% \let\char\empty +% \doifnumberelse{\csname#2\endcsname}{#1{\csname#2\endcsname}{`#3}}\donothing +% \let\char\normalchar +% \fi} + +\def\doinhsomehandling#1#2#3 #4 % to be checked + {\ifskiphandlingdef \else + \if#3\relax\relax + #1{`#2}{`#4}% + \else + \let\char\empty + \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{`#4}}\donothing + \let\char\normalchar + \fi + \fi} + +% adjustspacing + +\newdimen\adjustdimen \let\handledfont\font + +\ifx\undefined\pdfadjustspacing % we don't use pdftex + + \let\enableadjusting \relax + \let\disableadjusting \relax + \let\setadjusting \gobbletwoarguments + + \def\defineadjustfactor #1 #2 {} + \def\inheritadjustfactor #1 #2 {} + + \let\setfontadjusting \gobbleoneargument + +\else + + \def\enableadjusting {\pdfadjustspacing\plustwo} + \def\disableadjusting {\pdfadjustspacing\zerocount} + + \appendtoks \disableadjusting \to \everyforgetall % Here or not here? + + \def\dododefineadjustfactor#1#2% + {\adjustdimen#2pt\multiply\adjustdimen\plusthousand\divide\adjustdimen\maxcard\relax + \efcode\handledfont#1\adjustdimen} + + \beginETEX + + \def\dododefineadjustfactor#1#2% +% {\efcode\handledfont#1\dimexpr#2pt*\plusthousand/\maxcard\relax} + {\efcode\handledfont#1\dimexpr#2\onepoint*\plusthousand/\maxcard\relax} + + \endETEX + + \def\dodoinheritadjustfactor#1#2% + {\efcode\handledfont#1\efcode\handledfont#2\relax} + + \def\defineadjustfactor#1 #2 % + {\setfonttoks + \let\inherithandling\inheritadjustfactor + \appendtoks\dosetsomehandling\dododefineadjustfactor#1 #2 \to\fonttoks} + + \def\inheritadjustfactor#1 #2 % + {\setfonttoks + \appendtoks\doinhsomehandling\dodoinheritadjustfactor#1 #2 \to\fonttoks} + + \ifnum\pdftexversion<120 + \let\@@pdfexpandbonus\plusthousand + \else + \def\@@pdfexpandbonus{autoexpand}% + \fi + + \def\setfontadjusting#1% + {\doifvalue{\@fha@\@fha@#1\c!type}\v!hz{\dosetfontadjusting{#1}}} + + \def\dosetfontadjusting#1% + {\iftracefonthandling\showfontadjusting{#1}\fi + \pdffontexpand\handledfont + \csname\@fha@\@fha@#1\c!max \endcsname\space + \csname\@fha@\@fha@#1\c!min \endcsname\space + \csname\@fha@\@fha@#1\c!step\endcsname\space + \@@pdfexpandbonus\relax} + + \def\showfontadjusting#1% + {\writestatus\m!handlings{[adjust]\space#1\space + \csname\@fha@\@fha@#1\c!max \endcsname/% + \csname\@fha@\@fha@#1\c!min \endcsname/% + \csname\@fha@\@fha@#1\c!step\endcsname\space + \fontname\handledfont}} +\fi + +\ifx\setfontadjusting\gobbleoneargument \else + \appendtoks + \setfontadjusting\askedfonthandling + \to \everyenablefonthandling +\fi + +% protruding + +\newif\ifembasedprotruding \embasedprotrudingfalse + +\newdimen\lproddimen \newdimen\rproddimen \let\handledfont\font + +\ifx\undefined\pdfprotrudechars % we don't use pdftex + + \let\enableprotruding \relax + \let\disableprotruding \relax + \let\setprotrudingfactor \gobbleoneargument + + \def\defineprotrudefactor #1 #2 #3 {} + \def\inheritprotrudefactor #1 #2 {} + +\else + + \def\enableprotruding {\pdfprotrudechars\plustwo} + \def\disableprotruding{\pdfprotrudechars\zerocount} + + \appendtoks \disableprotruding \to \everyforgetall % Here or not here? + + \lproddimen1000\onepoint \divide\lproddimen\maxcard + \rproddimen1000\onepoint \divide\rproddimen\maxcard + + \def\setprotrudingfactor#1% + {\doifvalue{\@fha@\@fha@#1\c!type}\v!hanging{\dosetprotrudingfactor{#1}}} + + \beginTEX + + \def\dosetprotrudingfactor#1% no \onepoint instead of pt + {\lproddimen\csname\@fha@\@fha@#1\c!left\endcsname\s!pt + \multiply\lproddimen\plusthousand\divide\lproddimen\maxcard\relax + \rproddimen\csname\@fha@\@fha@#1\c!right\endcsname\s!pt + \multiply\rproddimen\plusthousand\divide\rproddimen\maxcard\relax + \iftracefonthandling\showprotrudingfactor{#1}\fi} + + \endTEX + + \beginETEX \dimexpr + + \def\dosetprotrudingfactor#1% no \onepoint instead of pt + {\lproddimen\dimexpr\csname\@fha@\@fha@#1\c!left \endcsname\onepoint*\plusthousand/\maxcard\relax + \rproddimen\dimexpr\csname\@fha@\@fha@#1\c!right\endcsname\onepoint*\plusthousand/\maxcard\relax + \iftracefonthandling\showprotrudingfactor{#1}\fi} + + \endETEX + + \def\showprotrudingfactor#1% + {\writestatus\m!handlings{[protrude]\space#1\space + \csname\@fha@\@fha@#1\c!left \endcsname\space + \csname\@fha@\@fha@#1\c!right\endcsname\space + \fontname\handledfont}} + + \beginETEX \fontcharwd + + % division before multiplication, else overflow with "sa>5" + + \newdimen\protrudethreshold \protrudethreshold=36pt + + % keep this + + % \def\redodefineprotrudefactor#1% + % {\ifdim\emwidth>\protrudethreshold + % \divide\scratchdimen\emwidth + % \multiply\scratchdimen\fontcharwd\handledfont#1\relax + % \else + % \multiply\scratchdimen\fontcharwd\handledfont#1\relax + % \divide\scratchdimen\emwidth + % \fi} + + % \def\dododefineprotrudefactor#1#2#3% + % {\scratchdimen#2\lproddimen + % \ifembasedprotruding \else + % \redodefineprotrudefactor{#1}% + % \fi + % \lpcode\handledfont#1\scratchdimen + % \scratchdimen#3\rproddimen + % \ifembasedprotruding \else + % \redodefineprotrudefactor{#1}% + % \fi + % \rpcode\handledfont#1\scratchdimen} + + \def\dododefineprotrudefactor#1#2#3% + {\lpcode\handledfont#1\dimexpr#2\lproddimen + \ifembasedprotruding \else + \ifdim\emwidth>\protrudethreshold + /\emwidth*\fontcharwd\handledfont#1% + \else + *\fontcharwd\handledfont#1/\emwidth + \fi + \fi + \relax + \rpcode\handledfont#1\dimexpr#3\rproddimen + \ifembasedprotruding \else + \ifdim\emwidth>\protrudethreshold + /\emwidth*\fontcharwd\handledfont#1% + \else + *\fontcharwd\handledfont#1/\emwidth + \fi + \fi + \relax} + + \endETEX + + \beginTEX + + \ifx\undefined\charbox \newbox\charbox \fi + + \def\protrudethreshold{36\onepoint} + + \def\redodefineprotrudefactor + {\ifdim\emwidth>\protrudethreshold + \divide\scratchdimen\emwidth + \multiply\scratchdimen\wd\charbox + \else + \multiply\scratchdimen\wd\charbox + \divide\scratchdimen\emwidth + \fi} + + \def\dododefineprotrudefactor#1#2#3% + {\setbox\charbox{\handledfont\char#1}% ! yet untested ! + \scratchdimen#2\lproddimen + \ifembasedprotruding \else + \redodefineprotrudefactor + \fi + \lpcode\handledfont#1\scratchdimen + \scratchdimen#3\rproddimen + \ifembasedprotruding \else + \redodefineprotrudefactor + \fi + \rpcode\handledfont#1\scratchdimen} + + \endTEX + + \def\dodoinheritprotrudefactor#1#2% + {\lpcode\handledfont#1\lpcode\handledfont#2\relax + \rpcode\handledfont#1\rpcode\handledfont#2\relax} + + \def\defineprotrudefactor#1 #2 #3 % + {\setfonttoks + \let\inherithandling\inheritprotrudefactor + \appendtoks\dosetpairhandling\dododefineprotrudefactor#1 #2 #3 \to\fonttoks} + + \def\inheritprotrudefactor#1 #2 % + {\setfonttoks + \appendtoks\doinhsomehandling\dodoinheritprotrudefactor#1 #2 \to\fonttoks} + +\fi + +\ifx\setprotrudingfactor\gobbleoneargument \else + \appendtoks + \setprotrudingfactor\askedfonthandling + \to \everyenablefonthandling +\fi + +% Basic support for a new pdftex feature: space factors +% +% \knbccode -- kern before char code +% \knbscode -- kern before space code +% \stbscode -- stretch before space code +% \shbscode -- shrink before space code +% +% Setting \knsbcode\font`\.=200 means that if a period sits before +% a interword space (glue), then the interword glue will be increased +% by an amount of 1em*200/1000, i.e. the value is given in thousandths +% of an em. (HTT) + +\newdimen\spfacdimen + +\ifx\undefined\pdfadjustinterwordglue % we don't use pdftex + + \let\enablespacehandling \relax + \let\disablespacehandling \relax + \let\enablekernhandling \relax + \let\disablekernhandling \relax + + \let\setspacehandling \gobbleoneargument + + \def\definespacefactor #1 #2 #3 #4 #5 {} + \def\inheritspacefactor #1 #2 {} + +\else + + \def\enablespacehandling {\pdfadjustinterwordglue\plusone } + \def\disablespacehandling{\pdfadjustinterwordglue\minusone} + \def\enablekernhandling {\pdfprependkern \plusone } + \def\disablekernhandling {\pdfprependkern \minusone} + + \appendtoks \disablespacehandling \to \everyforgetall % Here or not here? + + \def\dosetspacehandling#1% + {\spfacdimen\csname\@fha@\@fha@#1\c!factor\endcsname\s!pt + \multiply\spfacdimen\plusthousand\divide\spfacdimen\maxcard\relax} + + \def\setspacehandling#1% + {\doifvalue{\@fha@\@fha@#1\c!type}\v!spacing{\dosetspacehandling{#1}}} + + \def\dododefinespacefactor#1#2#3#4#5% + {\sfcode#1\plusthousand + \knbccode\handledfont#1\dimexpr#2\spfacdimen\relax + \knbscode\handledfont#1\dimexpr#3\spfacdimen\relax + \stbscode\handledfont#1\dimexpr#4\spfacdimen\relax + \shbscode\handledfont#1\dimexpr#5\spfacdimen\relax} + + \def\dodoinheritspacefactor#1#2% + {\sfcode#1\plusthousand + \knbccode\handledfont#1\knbccode\handledfont#2\relax + \knbscode\handledfont#1\knbscode\handledfont#2\relax + \stbscode\handledfont#1\stbscode\handledfont#2\relax + \shbscode\handledfont#1\shbscode\handledfont#2\relax} + + \def\definespacefactor#1 #2 #3 #4 #5 % + {\setfonttoks + \let\inherithandling\inheritspacefactor + \appendtoks\dosetquartethandling\dododefinespacefactor#1 #2 #3 #4 #5 \to\fonttoks} + + \def\inheritspacefactor#1 #2 % + {\setfonttoks + \appendtoks\doinhsomehandling\dodoinheritspacefactor#1 #2 \to\fonttoks} + +\fi + +\ifx\setspacehandling\gobbleoneargument \else + \appendtoks + \setspacehandling\askedfonthandling + \to \everyenablefonthandling +\fi + +% font attributes + +\let\notagcode\minusone + +\ifx\tagcode\undefined + + \def\settagcode #1 #2 {} + +\else + + \def\dodosettagcode#1#2% + {\tagcode\handledfont#1 #2\relax} + + \def\settagcode#1 #2 % + {\setfonttoks + \appendtoks\dosetsomehandling\dodosettagcode#1 #2 \to\fonttoks} + +\fi + +% hook into font mechanism + +\let\fonthandling\empty + +\beginTEX + + \def\startfonthandling[#1]% + {\def\fonthandling{#1}% + \expandafter\ifx\csname\@fha@\fonthandling\endcsname\relax + \expandafter\newtoks\csname\@fha@\fonthandling\endcsname + \fi + \setfonttoks} + +\endTEX + +\beginETEX + + \def\startfonthandling[#1]% + {\def\fonthandling{#1}% + \ifcsname\@fha@\fonthandling\endcsname\else + \expandafter\newtoks\csname\@fha@\fonthandling\endcsname + \fi + \setfonttoks} + +\endETEX + +\def\stopfonthandling + {\let\fonthandling\empty} + +\def\setfonttoks + {\@EA\let\@EA\fonttoks\csname\@fha@\fonthandling\endcsname} + +\def\definefonthandling + {\dotripleempty\dodefinefonthandling} + +\def\dodefinefonthandling[#1][#2][#3]% + {\ifthirdargument + \setvalue{\@fha@\@fha@#1}{#2}% + \getparameters + [\@fha@\@fha@#1] + [\c!type=\v!hanging,% + \c!left=1,\c!right=1,% + \c!min=20,\c!max=20,\c!step=5,% + \c!factor=1,% + #3]% + \else + \setvalue{\@fha@\@fha@\@fha@#1}{#2}% + \fi} + +\def\setupfonthandling + {\dodoubleempty\dosetupfonthandling} + +\def\dosetupfonthandling[#1][#2]% + {\getparameters[\@fha@\@fha@#1][#2]} + +\def\enablehandling + {\dodoubleempty\doenablehandling} + +\def\doenablehandling[#1][#2]% handling / symbolic fontname + {\fastenablehandling{#1}{#2}} % for the moment the same as: + +\beginTEX + +\def\fastenablehandling#1#2% + {\edef\askedfonthandling{#1}% + \edef\filoffonthandling{#2}% + \@EA\ifx\csname\@fha@\@fha@\@fha@\askedfonthandling\endcsname\relax + \@EA\ifx\csname\@fha@\@fha@\askedfonthandling\endcsname\relax + \@EAEAEA\nofastenablehandling + \else + \@EAEAEA\dofastenablehandling + \fi + \else + \@EA\redofastenablehandling + \fi} + +\def\xfastenablehandling#1% + {\edef\askedfonthandling{#1}% + \@EA\ifx\csname\@fha@\@fha@\askedfonthandling\endcsname + \@EA\nofastenablehandling + \else + \@EA\dofastenablehandling + \fi} + +\endTEX + +\beginETEX \ifcsname + +\def\fastenablehandling#1#2% also gets #2 passed + {\edef\askedfonthandling{#1}% + \edef\filoffonthandling{#2}% + \ifcsname\@fha@\@fha@\@fha@\askedfonthandling\endcsname + \@EA\redofastenablehandling + \else\ifcsname\@fha@\@fha@\askedfonthandling\endcsname + \@EAEAEA\dofastenablehandling + \else + \@EAEAEA\nofastenablehandling + \fi\fi} + +\def\xfastenablehandling#1% + {\edef\askedfonthandling{#1}% + \ifcsname\@fha@\@fha@\askedfonthandling\endcsname + \@EA\dofastenablehandling + \else + \@EA\nofastenablehandling + \fi} + +\endETEX + +\def\redofastenablehandling + {\startdirectcharacters + \edef\fonthandling{\csname\@fha@\@fha@\@fha@\askedfonthandling\endcsname}% + \rawprocesscommacommand[\fonthandling]\xfastenablehandling + \stopdirectcharacters} + +\def\dofastenablehandling + {\startdirectcharacters + \the\everyenablefonthandling + \edef\fonthandling{\csname\@fha@\@fha@\askedfonthandling\endcsname}% + \checkfonthandling\filoffonthandling + \rawprocesscommacommand[\fonthandling]\dodoenablehandling + \registerfonthandling\filoffonthandling + \stopdirectcharacters} + +\def\nofastenablehandling + {\the\everyenablefonthandling + \let\fonthandling\askedfonthandling + \dodoenablehandling\fonthandling} + +\beginTEX + +\def\dodoenablehandling#1% + {\@EA\ifx\csname\@fha@#1\endcsname\relax\else + \the\csname\@fha@#1\endcsname + \fi} + +\endTEX + +\beginETEX \ifcsname + +\def\dodoenablehandling#1% + {\ifcsname\@fha@#1\endcsname + \the\csname\@fha@#1\endcsname + \fi} + +\endETEX + +%D We must not use \type {\purefontname} here (was a bug)! + +% not robust as long as tex reuses definitions internally +% +% \def\checkfonthandling#1% we need a fast compare +% {\doifelsevalue{#1\s!handling\c!file}{\fontname\font} +% \skiphandlingdeftrue\skiphandlingdeffalse} +% +% \def\registerfonthandling#1% +% {\@EA\xdef\csname#1\s!handling\c!file\endcsname{\fontname\font}} + +\def\checkfonthandling #1{\skiphandlingdeffalse} +\let\registerfonthandling \gobbleoneargument + +%D This one makes live easier (less definitions): + +\def\inherithandling #1 #2 % + {\inheritprotrudefactor #1 #2 % + \inheritadjustfactor #1 #2 } + +%D \macros +%D {usehandling} +%D +%D Handling definitions are collected in dedicated files and +%D loaded only once: +%D +%D % \showsetup{usehandling} + +\def\dousehandling#1% is the same as encoding + {\doifundefined{\c!file\f!handlingprefix#1}% + {\letvalueempty{\c!file\f!handlingprefix#1}% + \makeshortfilename[\truefilename{\f!handlingprefix#1}]% + \startreadingfile + \readsysfile\shortfilename + {\showmessage\m!handlings2{#1}} + {\showmessage\m!handlings3{#1}}% + \stopreadingfile}} + +\def\usehandling[#1]% + {\processcommalist[#1]\dousehandling} + +%D New: + +\def\overloadcharacter#1 #2 % + {\setfonttoks + \doifnumberelse{\string#2} + {\appendtoks\dooverloadcharacter{#1}{\char#2 }\to\fonttoks} + {\appendtoks\dooverloadcharacter{#1}{#2}\to\fonttoks}} + +\def\dooverloadcharacter#1% + {\setvalue{\characterencoding\string#1}} + +%D Let's now see if this macro works: + +% \setupfonthandling +% [\s!default] +% [\c!links=1,\c!rechts=1,\c!min=20,\c!max=20,\c!stap=5] + +% Beware of fonttoks: +% +% \startfonthandling[morespacing] +% \appendtoks +% \fontdimen2\handledfont=.50em +% \fontdimen3\handledfont=.25em +% \fontdimen4\handledfont=.25em +% \to \fonttoks +% \stopfonthandling +% +% \definefonthandling [morespacing] [morespacing] +% +% \definefontsynonym[xtexnansi-lmr7][texnansi-lmr7][handling=morespacing] +% \definefont[crap][texnansi-lmr7] +% +% \crap \the\fontdimen2\font, \the\fontdimen3\font, \the\fontdimen4\font + +\usehandling [def] + +\protect \endinput diff --git a/tex/context/base/hand-ini.mkiv b/tex/context/base/hand-ini.mkiv new file mode 100644 index 000000000..527c32da7 --- /dev/null +++ b/tex/context/base/hand-ini.mkiv @@ -0,0 +1,50 @@ +%D \module +%D [ file=hand-ini, +%D version=2008.02.12, +%D title=\CONTEXT\ Handling Macros, +%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. + +%D Handling is implemented differently in \MKIV. Maybe I'll cook up +%D some compatibility hack. + +% \definefontfeature[demo][default][mode=node,expansion=quality] +% \definefontfeature[demo][default][mode=node,protrusion=pure] + +\unprotect + +%D New stuff. + +\def\setupfontexpansion [#1][#2]{\ctxlua{commands.setupfontexpansion ("#1","#2")}} +\def\setupfontprotrusion[#1][#2]{\ctxlua{commands.setupfontprotrusion("#1","#2")}} + +%D Old stuff. + +\def\fonthandlingerror{\writestatus\m!fonts{font handling is replaced by features in mkiv}} + +\def\enableadjusting {\pdfadjustspacing\plustwo } \let\enableexpansion \enableadjusting +\def\disableadjusting {\pdfadjustspacing\zerocount} \let\disableexpansion\disableadjusting +\def\enableprotruding {\pdfprotrudechars\plustwo } +\def\disableprotruding{\pdfprotrudechars\zerocount} + +\appendtoks \disableadjusting \to \everyforgetall % Here or not here? +\appendtoks \disableprotruding \to \everyforgetall % Here or not here? + +\def\startfonthandling #1{\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen +\def\definefonthandling {\dotripleempty\dodefinefonthandling} +\def\setupfonthandling {\dodoubleempty\dosetupfonthandling } +\def\dodefinefonthandling[#1][#2][#3]{\fonthandlingerror} +\def\dosetupfonthandling [#1][#2]{\fonthandlingerror} +\def\usehandling [#1]{\fonthandlingerror} + +%D Just to be sure, maybe users use it: + +\let\fonthandling\empty + +\protect \endinput diff --git a/tex/context/base/hand-ini.tex b/tex/context/base/hand-ini.tex index adb1c1dd5..4d19b5284 100644 --- a/tex/context/base/hand-ini.tex +++ b/tex/context/base/hand-ini.tex @@ -13,690 +13,6 @@ \writestatus{loading}{Context Handling Macros (ini)} -% \pushmacro -> dedicated fast one +\loadmarkfile{hand-ini} -%D {\em This module is experimental and implements font -%D specific features, like hanging punctuation.} - -\unprotect - -\startmessages dutch library: handlings - title: handling - 1: font afhandeling -- - 2: font afhandeling -- wordt geladen - 3: onbekende font afhandeling -- -\stopmessages - -\startmessages english library: handlings - title: handling - 1: font handling -- - 2: font handling -- is loaded - 3: unknown font handling -- -\stopmessages - -\startmessages german library: handlings % to do - title: handling - 1: font handling -- - 2: font handling -- is loaded - 3: unknown font handling -- -\stopmessages - -\startmessages czech library: handlings % to do - title: handling - 1: font handling -- - 2: font handling -- is loaded - 3: unknown font handling -- -\stopmessages - -\startmessages italian library: handlings % to do - title: handling - 1: font handling -- - 2: font handling -- is loaded - 3: unknown font handling -- -\stopmessages - -\startmessages norwegian library: handlings % to do - title: handling - 1: font handling -- - 2: font handling -- is loaded - 3: unknown font handling -- -\stopmessages - -\startmessages romanian library: handlings % to do - title: handling - 1: font handling -- - 2: font handling -- is loaded - 3: unknown font handling -- -\stopmessages - -\startmessages french library: handlings - title: manipulation - 1: manipulation -- de police - 2: la manipulation -- de police est chargée - 3: manipulation -- inconnue de police -\stopmessages - -\newif\iftracefonthandling % \tracefonthandlingtrue - -\newif\ifskiphandlingdef \skiphandlingdeffalse - -\newtoks\everyenablefonthandling - -% much in common with hz/protruding defs -% todo: fix others - -\let\normalchar\char % also done in enco-ini - -\def\dosetsomehandling#1#2#3 #4 % no define since directly set - {\ifskiphandlingdef \else - \doifnumberelse{\string#2} - {#1{#2#3}{#4}} - {\doifelsenothing{#3} - {#1{`#2}{#4}} - {\let\char\empty - \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}}\donothing - \let\char\normalchar}}% - \fi} - -\def\dosetpairhandling#1#2#3 #4 #5 % no define since directly set - {\ifskiphandlingdef \else - \doifnumberelse{\string#2} - {#1{#2#3}{#4}{#5}} - {\doifelsenothing{#3} - {#1{`#2}{#4}{#5}} - {\let\char\empty - \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}{#5}}\donothing - \let\char\normalchar}}% - \fi} - -% \def\dosettriplethandling#1#2#3 #4 #5 #6 % no define since directly set -% {\ifskiphandlingdef \else -% \doifnumberelse{\string#2} -% {#1{#2#3}{#4}{#5}{#6}} -% {\doifelsenothing{#3} -% {#1{`#2}{#4}{#5}{#6}} -% {\let\char\empty -% \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}{#5}{#6}}\donothing -% \let\char\normalchar}}% -% \fi} - -\def\dosetquartethandling#1#2#3 #4 #5 #6 #7 % no define since directly set - {\ifskiphandlingdef \else - \doifnumberelse{\string#2} - {#1{#2#3}{#4}{#5}{#6}{#7}} - {\doifelsenothing{#3} - {#1{`#2}{#4}{#5}{#6}{#7}} - {\let\char\empty - \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{#4}{#5}{#6}{#7}}\donothing - \let\char\normalchar}}% - \fi} - - -% \def\doinhsomehandling#1#2 #3 % -% {\ifskiphandlingdef \else -% \let\char\empty -% \doifnumberelse{\csname#2\endcsname}{#1{\csname#2\endcsname}{`#3}}\donothing -% \let\char\normalchar -% \fi} - -\def\doinhsomehandling#1#2#3 #4 % to be checked - {\ifskiphandlingdef \else - \if#3\relax\relax - #1{`#2}{`#4}% - \else - \let\char\empty - \doifnumberelse{\csname#2#3\endcsname}{#1{\csname#2#3\endcsname}{`#4}}\donothing - \let\char\normalchar - \fi - \fi} - -% adjustspacing - -\newdimen\adjustdimen \let\handledfont\font - -\ifx\undefined\pdfadjustspacing % we don't use pdftex - - \let\enableadjusting \relax - \let\disableadjusting \relax - \let\setadjusting \gobbletwoarguments - - \def\defineadjustfactor #1 #2 {} - \def\inheritadjustfactor #1 #2 {} - - \let\setfontadjusting \gobbleoneargument - -\else - - \def\enableadjusting {\pdfadjustspacing\plustwo} - \def\disableadjusting {\pdfadjustspacing\zerocount} - - \appendtoks \disableadjusting \to \everyforgetall % Here or not here? - - \def\dododefineadjustfactor#1#2% - {\adjustdimen#2pt\multiply\adjustdimen\plusthousand\divide\adjustdimen\maxcard\relax - \efcode\handledfont#1\adjustdimen} - - \beginETEX - - \def\dododefineadjustfactor#1#2% -% {\efcode\handledfont#1\dimexpr#2pt*\plusthousand/\maxcard\relax} - {\efcode\handledfont#1\dimexpr#2\onepoint*\plusthousand/\maxcard\relax} - - \endETEX - - \def\dodoinheritadjustfactor#1#2% - {\efcode\handledfont#1\efcode\handledfont#2\relax} - - \def\defineadjustfactor#1 #2 % - {\setfonttoks - \let\inherithandling\inheritadjustfactor - \appendtoks\dosetsomehandling\dododefineadjustfactor#1 #2 \to\fonttoks} - - \def\inheritadjustfactor#1 #2 % - {\setfonttoks - \appendtoks\doinhsomehandling\dodoinheritadjustfactor#1 #2 \to\fonttoks} - - \ifnum\pdftexversion<120 - \let\@@pdfexpandbonus\plusthousand - \else - \def\@@pdfexpandbonus{autoexpand}% - \fi - - \def\setfontadjusting#1% - {\doifvalue{\@fha@\@fha@#1\c!type}\v!hz{\dosetfontadjusting{#1}}} - - \def\dosetfontadjusting#1% - {\iftracefonthandling\showfontadjusting{#1}\fi - \pdffontexpand\handledfont - \csname\@fha@\@fha@#1\c!max \endcsname\space - \csname\@fha@\@fha@#1\c!min \endcsname\space - \csname\@fha@\@fha@#1\c!step\endcsname\space - \@@pdfexpandbonus\relax} - - \def\showfontadjusting#1% - {\writestatus\m!handlings{[adjust]\space#1\space - \csname\@fha@\@fha@#1\c!max \endcsname/% - \csname\@fha@\@fha@#1\c!min \endcsname/% - \csname\@fha@\@fha@#1\c!step\endcsname\space - \fontname\handledfont}} -\fi - -\ifx\setfontadjusting\gobbleoneargument \else - \appendtoks - \setfontadjusting\askedfonthandling - \to \everyenablefonthandling -\fi - -% protruding - -\newif\ifembasedprotruding \embasedprotrudingfalse - -\newdimen\lproddimen \newdimen\rproddimen \let\handledfont\font - -\ifx\undefined\pdfprotrudechars % we don't use pdftex - - \let\enableprotruding \relax - \let\disableprotruding \relax - \let\setprotrudingfactor \gobbleoneargument - - \def\defineprotrudefactor #1 #2 #3 {} - \def\inheritprotrudefactor #1 #2 {} - -\else - - \def\enableprotruding {\pdfprotrudechars\plustwo} - \def\disableprotruding{\pdfprotrudechars\zerocount} - - \appendtoks \disableprotruding \to \everyforgetall % Here or not here? - - \lproddimen1000\onepoint \divide\lproddimen\maxcard - \rproddimen1000\onepoint \divide\rproddimen\maxcard - - \def\setprotrudingfactor#1% - {\doifvalue{\@fha@\@fha@#1\c!type}\v!hanging{\dosetprotrudingfactor{#1}}} - - \beginTEX - - \def\dosetprotrudingfactor#1% no \onepoint instead of pt - {\lproddimen\csname\@fha@\@fha@#1\c!left\endcsname\s!pt - \multiply\lproddimen\plusthousand\divide\lproddimen\maxcard\relax - \rproddimen\csname\@fha@\@fha@#1\c!right\endcsname\s!pt - \multiply\rproddimen\plusthousand\divide\rproddimen\maxcard\relax - \iftracefonthandling\showprotrudingfactor{#1}\fi} - - \endTEX - - \beginETEX \dimexpr - - \def\dosetprotrudingfactor#1% no \onepoint instead of pt - {\lproddimen\dimexpr\csname\@fha@\@fha@#1\c!left \endcsname\onepoint*\plusthousand/\maxcard\relax - \rproddimen\dimexpr\csname\@fha@\@fha@#1\c!right\endcsname\onepoint*\plusthousand/\maxcard\relax - \iftracefonthandling\showprotrudingfactor{#1}\fi} - - \endETEX - - \def\showprotrudingfactor#1% - {\writestatus\m!handlings{[protrude]\space#1\space - \csname\@fha@\@fha@#1\c!left \endcsname\space - \csname\@fha@\@fha@#1\c!right\endcsname\space - \fontname\handledfont}} - - \beginETEX \fontcharwd - - % division before multiplication, else overflow with "sa>5" - - \newdimen\protrudethreshold \protrudethreshold=36pt - - % keep this - - % \def\redodefineprotrudefactor#1% - % {\ifdim\emwidth>\protrudethreshold - % \divide\scratchdimen\emwidth - % \multiply\scratchdimen\fontcharwd\handledfont#1\relax - % \else - % \multiply\scratchdimen\fontcharwd\handledfont#1\relax - % \divide\scratchdimen\emwidth - % \fi} - - % \def\dododefineprotrudefactor#1#2#3% - % {\scratchdimen#2\lproddimen - % \ifembasedprotruding \else - % \redodefineprotrudefactor{#1}% - % \fi - % \lpcode\handledfont#1\scratchdimen - % \scratchdimen#3\rproddimen - % \ifembasedprotruding \else - % \redodefineprotrudefactor{#1}% - % \fi - % \rpcode\handledfont#1\scratchdimen} - - \def\dododefineprotrudefactor#1#2#3% - {\lpcode\handledfont#1\dimexpr#2\lproddimen - \ifembasedprotruding \else - \ifdim\emwidth>\protrudethreshold - /\emwidth*\fontcharwd\handledfont#1% - \else - *\fontcharwd\handledfont#1/\emwidth - \fi - \fi - \relax - \rpcode\handledfont#1\dimexpr#3\rproddimen - \ifembasedprotruding \else - \ifdim\emwidth>\protrudethreshold - /\emwidth*\fontcharwd\handledfont#1% - \else - *\fontcharwd\handledfont#1/\emwidth - \fi - \fi - \relax} - - \endETEX - - \beginTEX - - \ifx\undefined\charbox \newbox\charbox \fi - - \def\protrudethreshold{36\onepoint} - - \def\redodefineprotrudefactor - {\ifdim\emwidth>\protrudethreshold - \divide\scratchdimen\emwidth - \multiply\scratchdimen\wd\charbox - \else - \multiply\scratchdimen\wd\charbox - \divide\scratchdimen\emwidth - \fi} - - \def\dododefineprotrudefactor#1#2#3% - {\setbox\charbox{\handledfont\char#1}% ! yet untested ! - \scratchdimen#2\lproddimen - \ifembasedprotruding \else - \redodefineprotrudefactor - \fi - \lpcode\handledfont#1\scratchdimen - \scratchdimen#3\rproddimen - \ifembasedprotruding \else - \redodefineprotrudefactor - \fi - \rpcode\handledfont#1\scratchdimen} - - \endTEX - - \def\dodoinheritprotrudefactor#1#2% - {\lpcode\handledfont#1\lpcode\handledfont#2\relax - \rpcode\handledfont#1\rpcode\handledfont#2\relax} - - \def\defineprotrudefactor#1 #2 #3 % - {\setfonttoks - \let\inherithandling\inheritprotrudefactor - \appendtoks\dosetpairhandling\dododefineprotrudefactor#1 #2 #3 \to\fonttoks} - - \def\inheritprotrudefactor#1 #2 % - {\setfonttoks - \appendtoks\doinhsomehandling\dodoinheritprotrudefactor#1 #2 \to\fonttoks} - -\fi - -\ifx\setprotrudingfactor\gobbleoneargument \else - \appendtoks - \setprotrudingfactor\askedfonthandling - \to \everyenablefonthandling -\fi - -% Basic support for a new pdftex feature: space factors -% -% \knbccode -- kern before char code -% \knbscode -- kern before space code -% \stbscode -- stretch before space code -% \shbscode -- shrink before space code -% -% Setting \knsbcode\font`\.=200 means that if a period sits before -% a interword space (glue), then the interword glue will be increased -% by an amount of 1em*200/1000, i.e. the value is given in thousandths -% of an em. (HTT) - -\newdimen\spfacdimen - -\ifx\undefined\pdfadjustinterwordglue % we don't use pdftex - - \let\enablespacehandling \relax - \let\disablespacehandling \relax - \let\enablekernhandling \relax - \let\disablekernhandling \relax - - \let\setspacehandling \gobbleoneargument - - \def\definespacefactor #1 #2 #3 #4 #5 {} - \def\inheritspacefactor #1 #2 {} - -\else - - \def\enablespacehandling {\pdfadjustinterwordglue\plusone } - \def\disablespacehandling{\pdfadjustinterwordglue\minusone} - \def\enablekernhandling {\pdfprependkern \plusone } - \def\disablekernhandling {\pdfprependkern \minusone} - - \appendtoks \disablespacehandling \to \everyforgetall % Here or not here? - - \def\dosetspacehandling#1% - {\spfacdimen\csname\@fha@\@fha@#1\c!factor\endcsname\s!pt - \multiply\spfacdimen\plusthousand\divide\spfacdimen\maxcard\relax} - - \def\setspacehandling#1% - {\doifvalue{\@fha@\@fha@#1\c!type}\v!spacing{\dosetspacehandling{#1}}} - - \def\dododefinespacefactor#1#2#3#4#5% - {\sfcode#1\plusthousand - \knbccode\handledfont#1\dimexpr#2\spfacdimen\relax - \knbscode\handledfont#1\dimexpr#3\spfacdimen\relax - \stbscode\handledfont#1\dimexpr#4\spfacdimen\relax - \shbscode\handledfont#1\dimexpr#5\spfacdimen\relax} - - \def\dodoinheritspacefactor#1#2% - {\sfcode#1\plusthousand - \knbccode\handledfont#1\knbccode\handledfont#2\relax - \knbscode\handledfont#1\knbscode\handledfont#2\relax - \stbscode\handledfont#1\stbscode\handledfont#2\relax - \shbscode\handledfont#1\shbscode\handledfont#2\relax} - - \def\definespacefactor#1 #2 #3 #4 #5 % - {\setfonttoks - \let\inherithandling\inheritspacefactor - \appendtoks\dosetquartethandling\dododefinespacefactor#1 #2 #3 #4 #5 \to\fonttoks} - - \def\inheritspacefactor#1 #2 % - {\setfonttoks - \appendtoks\doinhsomehandling\dodoinheritspacefactor#1 #2 \to\fonttoks} - -\fi - -\ifx\setspacehandling\gobbleoneargument \else - \appendtoks - \setspacehandling\askedfonthandling - \to \everyenablefonthandling -\fi - -% font attributes - -\let\notagcode\minusone - -\ifx\tagcode\undefined - - \def\settagcode #1 #2 {} - -\else - - \def\dodosettagcode#1#2% - {\tagcode\handledfont#1 #2\relax} - - \def\settagcode#1 #2 % - {\setfonttoks - \appendtoks\dosetsomehandling\dodosettagcode#1 #2 \to\fonttoks} - -\fi - -% hook into font mechanism - -\let\fonthandling\empty - -\beginTEX - - \def\startfonthandling[#1]% - {\def\fonthandling{#1}% - \expandafter\ifx\csname\@fha@\fonthandling\endcsname\relax - \expandafter\newtoks\csname\@fha@\fonthandling\endcsname - \fi - \setfonttoks} - -\endTEX - -\beginETEX - - \def\startfonthandling[#1]% - {\def\fonthandling{#1}% - \ifcsname\@fha@\fonthandling\endcsname\else - \expandafter\newtoks\csname\@fha@\fonthandling\endcsname - \fi - \setfonttoks} - -\endETEX - -\def\stopfonthandling - {\let\fonthandling\empty} - -\def\setfonttoks - {\@EA\let\@EA\fonttoks\csname\@fha@\fonthandling\endcsname} - -\def\definefonthandling - {\dotripleempty\dodefinefonthandling} - -\def\dodefinefonthandling[#1][#2][#3]% - {\ifthirdargument - \setvalue{\@fha@\@fha@#1}{#2}% - \getparameters - [\@fha@\@fha@#1] - [\c!type=\v!hanging,% - \c!left=1,\c!right=1,% - \c!min=20,\c!max=20,\c!step=5,% - \c!factor=1,% - #3]% - \else - \setvalue{\@fha@\@fha@\@fha@#1}{#2}% - \fi} - -\def\setupfonthandling - {\dodoubleempty\dosetupfonthandling} - -\def\dosetupfonthandling[#1][#2]% - {\getparameters[\@fha@\@fha@#1][#2]} - -\def\enablehandling - {\dodoubleempty\doenablehandling} - -\def\doenablehandling[#1][#2]% handling / symbolic fontname - {\fastenablehandling{#1}{#2}} % for the moment the same as: - -\beginTEX - -\def\fastenablehandling#1#2% - {\edef\askedfonthandling{#1}% - \edef\filoffonthandling{#2}% - \@EA\ifx\csname\@fha@\@fha@\@fha@\askedfonthandling\endcsname\relax - \@EA\ifx\csname\@fha@\@fha@\askedfonthandling\endcsname\relax - \@EAEAEA\nofastenablehandling - \else - \@EAEAEA\dofastenablehandling - \fi - \else - \@EA\redofastenablehandling - \fi} - -\def\xfastenablehandling#1% - {\edef\askedfonthandling{#1}% - \@EA\ifx\csname\@fha@\@fha@\askedfonthandling\endcsname - \@EA\nofastenablehandling - \else - \@EA\dofastenablehandling - \fi} - -\endTEX - -\beginETEX \ifcsname - -\def\fastenablehandling#1#2% also gets #2 passed - {\edef\askedfonthandling{#1}% - \edef\filoffonthandling{#2}% - \ifcsname\@fha@\@fha@\@fha@\askedfonthandling\endcsname - \@EA\redofastenablehandling - \else\ifcsname\@fha@\@fha@\askedfonthandling\endcsname - \@EAEAEA\dofastenablehandling - \else - \@EAEAEA\nofastenablehandling - \fi\fi} - -\def\xfastenablehandling#1% - {\edef\askedfonthandling{#1}% - \ifcsname\@fha@\@fha@\askedfonthandling\endcsname - \@EA\dofastenablehandling - \else - \@EA\nofastenablehandling - \fi} - -\endETEX - -\def\redofastenablehandling - {\startdirectcharacters - \edef\fonthandling{\csname\@fha@\@fha@\@fha@\askedfonthandling\endcsname}% - \rawprocesscommacommand[\fonthandling]\xfastenablehandling - \stopdirectcharacters} - -\def\dofastenablehandling - {\startdirectcharacters - \the\everyenablefonthandling - \edef\fonthandling{\csname\@fha@\@fha@\askedfonthandling\endcsname}% - \checkfonthandling\filoffonthandling - \rawprocesscommacommand[\fonthandling]\dodoenablehandling - \registerfonthandling\filoffonthandling - \stopdirectcharacters} - -\def\nofastenablehandling - {\the\everyenablefonthandling - \let\fonthandling\askedfonthandling - \dodoenablehandling\fonthandling} - -\beginTEX - -\def\dodoenablehandling#1% - {\@EA\ifx\csname\@fha@#1\endcsname\relax\else - \the\csname\@fha@#1\endcsname - \fi} - -\endTEX - -\beginETEX \ifcsname - -\def\dodoenablehandling#1% - {\ifcsname\@fha@#1\endcsname - \the\csname\@fha@#1\endcsname - \fi} - -\endETEX - -%D We must not use \type {\purefontname} here (was a bug)! - -% not robust as long as tex reuses definitions internally -% -% \def\checkfonthandling#1% we need a fast compare -% {\doifelsevalue{#1\s!handling\c!file}{\fontname\font} -% \skiphandlingdeftrue\skiphandlingdeffalse} -% -% \def\registerfonthandling#1% -% {\@EA\xdef\csname#1\s!handling\c!file\endcsname{\fontname\font}} - -\def\checkfonthandling #1{\skiphandlingdeffalse} -\let\registerfonthandling \gobbleoneargument - -%D This one makes live easier (less definitions): - -\def\inherithandling #1 #2 % - {\inheritprotrudefactor #1 #2 % - \inheritadjustfactor #1 #2 } - -%D \macros -%D {usehandling} -%D -%D Handling definitions are collected in dedicated files and -%D loaded only once: -%D -%D % \showsetup{usehandling} - -\def\dousehandling#1% is the same as encoding - {\doifundefined{\c!file\f!handlingprefix#1}% - {\letvalueempty{\c!file\f!handlingprefix#1}% - \makeshortfilename[\truefilename{\f!handlingprefix#1}]% - \startreadingfile - \readsysfile\shortfilename - {\showmessage\m!handlings2{#1}} - {\showmessage\m!handlings3{#1}}% - \stopreadingfile}} - -\def\usehandling[#1]% - {\processcommalist[#1]\dousehandling} - -%D New: - -\def\overloadcharacter#1 #2 % - {\setfonttoks - \doifnumberelse{\string#2} - {\appendtoks\dooverloadcharacter{#1}{\char#2 }\to\fonttoks} - {\appendtoks\dooverloadcharacter{#1}{#2}\to\fonttoks}} - -\def\dooverloadcharacter#1% - {\setvalue{\characterencoding\string#1}} - -%D Let's now see if this macro works: - -% \setupfonthandling -% [\s!default] -% [\c!links=1,\c!rechts=1,\c!min=20,\c!max=20,\c!stap=5] - -% Beware of fonttoks: -% -% \startfonthandling[morespacing] -% \appendtoks -% \fontdimen2\handledfont=.50em -% \fontdimen3\handledfont=.25em -% \fontdimen4\handledfont=.25em -% \to \fonttoks -% \stopfonthandling -% -% \definefonthandling [morespacing] [morespacing] -% -% \definefontsynonym[xtexnansi-lmr7][texnansi-lmr7][handling=morespacing] -% \definefont[crap][texnansi-lmr7] -% -% \crap \the\fontdimen2\font, \the\fontdimen3\font, \the\fontdimen4\font - -\usehandling [def] - -\protect \endinput +\endinput diff --git a/tex/context/base/l-aux.lua b/tex/context/base/l-aux.lua index 03a5c2bbf..fdcc88e46 100644 --- a/tex/context/base/l-aux.lua +++ b/tex/context/base/l-aux.lua @@ -48,6 +48,10 @@ do return lpeg.match(pattern,str) end + function aux.add_settings_to_array(t,str) + return table.merge(t, lpeg.match(pattern,str)) + end + end function aux.hash_to_string(h,separator,yes,no,strict,omit) @@ -86,3 +90,14 @@ function aux.array_to_string(a,separator) return "" end end + +-- temporary here + +function aux.getparameters(self,class,parentclass,settings) + local sc = self[class] + if not sc then + sc = table.clone(self[parent]) + self[class] = sc + end + aux.add_settings_to_array(sc, settings) +end diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua index f4ad2225f..291c06707 100644 --- a/tex/context/base/l-file.lua +++ b/tex/context/base/l-file.lua @@ -9,11 +9,11 @@ if not versions then versions = { } end versions['l-file'] = 1.001 if not file then file = { } end function file.removesuffix(filename) - return filename:gsub("%.%a+$", "") + return filename:gsub("%.[%a%d]+$", "") end function file.addsuffix(filename, suffix) - if not filename:find("%.%a-$") then + if not filename:find("%.[%a%d]+$") then return filename .. "." .. suffix else return filename @@ -21,7 +21,11 @@ function file.addsuffix(filename, suffix) end function file.replacesuffix(filename, suffix) - return (filename:gsub("%.%a+$", "." .. suffix)) + if not filename:find("%.[%a%d]+$") then + return filename .. "." .. suffix + else + return (filename:gsub("%.[%a%d]+$","."..suffix)) + end end function file.dirname(name) @@ -40,12 +44,36 @@ function file.extname(name) return name:match("^.+%.([^/\\]-)$") or "" end +function file.stripsuffix(name) + return (name:gsub("%.[%a%d]+$","")) +end + +--~ function file.join(...) +--~ local t = { ... } +--~ for i=1,#t do +--~ t[i] = (t[i]:gsub("\\","/")):gsub("/+$","") +--~ end +--~ return table.concat(t,"/") +--~ end + +--~ print(file.join("x/","/y")) +--~ print(file.join("http://","/y")) +--~ print(file.join("http://a","/y")) +--~ print(file.join("http:///a","/y")) +--~ print(file.join("//nas-1","/y")) + function file.join(...) - local t = { ... } - for i=1,#t do - t[i] = (t[i]:gsub("\\","/")):gsub("/+$","") + local pth = table.concat({...},"/") + pth = pth:gsub("\\","/") + local a, b = pth:match("^(.*://)(.*)$") + if a and b then + return a .. b:gsub("//+","/") + end + a, b = pth:match("^(//)(.*)$") + if a and b then + return a .. b:gsub("//+","/") end - return table.concat(t,"/") + return (pth:gsub("//+","/")) end function file.is_writable(name) diff --git a/tex/context/base/l-io.lua b/tex/context/base/l-io.lua index 7d3fea163..a178c838f 100644 --- a/tex/context/base/l-io.lua +++ b/tex/context/base/l-io.lua @@ -67,38 +67,10 @@ function io.noflines(f) return n end ---~ t, f, n = os.clock(), io.open("testbed/sample-utf16-bigendian-big.txt",'rb'), 0 ---~ for a in io.characters(f) do n = n + 1 end ---~ print(string.format("characters: %s, time: %s", n, os.clock()-t)) - do local sb = string.byte ---~ local nextchar = { ---~ [ 4] = function(f) ---~ return f:read(1), f:read(1), f:read(1), f:read(1) ---~ end, ---~ [ 2] = function(f) ---~ return f:read(1), f:read(1) ---~ end, ---~ [ 1] = function(f) ---~ return f:read(1) ---~ end, ---~ [-2] = function(f) ---~ local a = f:read(1) ---~ local b = f:read(1) ---~ return b, a ---~ end, ---~ [-4] = function(f) ---~ local a = f:read(1) ---~ local b = f:read(1) ---~ local c = f:read(1) ---~ local d = f:read(1) ---~ return d, c, b, a ---~ end ---~ } - local nextchar = { [ 4] = function(f) return f:read(1,1,1,1) diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua index 9e589621b..56893aaf2 100644 --- a/tex/context/base/l-lpeg.lua +++ b/tex/context/base/l-lpeg.lua @@ -38,4 +38,3 @@ function lpeg.splitter(pattern, action) return (((1-lpeg.P(pattern))^1)/action+1)^0 end - diff --git a/tex/context/base/l-os.lua b/tex/context/base/l-os.lua index 26303ea95..7c6121719 100644 --- a/tex/context/base/l-os.lua +++ b/tex/context/base/l-os.lua @@ -13,6 +13,19 @@ end if not os.exec then os.exec = os.execute end if not os.spawn then os.spawn = os.execute end +--~ os.type : windows | unix (new, we already guessed os.platform) +--~ os.name : windows | msdos | linux | macosx | solaris | .. | generic (new) + +if not io.fileseparator then + if string.find(os.getenv("PATH"),";") then + io.fileseparator, io.pathseparator, os.platform = "\\", ";", os.type or "windows" + else + io.fileseparator, io.pathseparator, os.platform = "/" , ":", os.type or "unix" + end +end + +os.platform = os.platform or os.type or (io.pathseparator == ";" and "windows") or "unix" + function os.launch(str) if os.platform == "windows" then os.execute("start " .. str) -- os.spawn ? @@ -32,19 +45,15 @@ if not os.times then -- cstime = children system time function os.times() return { - utime = os.clock(), -- user - stime = 0, -- system - cutime = 0, -- children user - cstime = 0, -- children system + utime = os.gettimeofday(), -- user + stime = 0, -- system + cutime = 0, -- children user + cstime = 0, -- children system } end end -if os.gettimeofday then - os.clock = os.gettimeofday -else - os.gettimeofday = os.clock -end +os.gettimeofday = os.gettimeofday or os.clock do local startuptime = os.gettimeofday() diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua index b0344c002..b8059c0c9 100644 --- a/tex/context/base/l-string.lua +++ b/tex/context/base/l-string.lua @@ -332,3 +332,28 @@ function string:split_settings() -- no {} handling, see l-aux for lpeg variant return nil end end + +local patterns_escapes = { + ["-"] = "%-", + ["."] = "%.", + ["+"] = "%+", + ["*"] = "%*", + ["%"] = "%%", + ["("] = "%)", + [")"] = "%)", + ["["] = "%[", + ["]"] = "%]", +} + + +function string:pattesc() + return (self:gsub(".",patterns_escapes)) +end + +function string:tohash() + local t = { } + for s in self:gmatch("([^, ]+)") do -- lpeg + t[s] = true + end + return t +end diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua index 8a25e9eaf..44cecff69 100644 --- a/tex/context/base/l-table.lua +++ b/tex/context/base/l-table.lua @@ -79,7 +79,8 @@ end --~ return t --~ end -function table.merge(t, ...) +function table.merge(t, ...) -- first one is target + t = t or {} local lst = {...} for i=1,#lst do for k, v in pairs(lst[i]) do @@ -608,6 +609,14 @@ function table.tohash(t) return h end +function table.fromhash(t) + local h = { } + for k, v in pairs(t) do -- no ipairs here + if v then h[#h+1] = k end + end + return h +end + function table.contains(t, v) if t then for i=1, #t do @@ -639,3 +648,19 @@ end --~ return table.serialize(a) == table.serialize(b) --~ end +function table.clone(t,p) -- t is optional or nil or table + if not p then + t, p = { }, t or { } + elseif not t then + t = { } + end + setmetatable(t, { __index = function(_,key) return p[key] end }) + return t +end + + +function table.hexed(t,seperator) + local tt = { } + for i=1,#t do tt[i] = string.format("0x%04X",t[i]) end + return table.concat(tt,seperator or " ") +end diff --git a/tex/context/base/l-url.lua b/tex/context/base/l-url.lua index 2e0907eb7..906ce0c0c 100644 --- a/tex/context/base/l-url.lua +++ b/tex/context/base/l-url.lua @@ -29,7 +29,7 @@ do local scheme = lpeg.Cs((escaped+(1-colon-slash-qmark-hash))^0) * colon + lpeg.Cc("") local authority = slash * slash * lpeg.Cs((escaped+(1- slash-qmark-hash))^0) + lpeg.Cc("") - local path = lpeg.Cs((escaped+(1- qmark-hash))^0) + lpeg.Cc("") + local path = slash * lpeg.Cs((escaped+(1- qmark-hash))^0) + lpeg.Cc("") local query = qmark * lpeg.Cs((escaped+(1- hash))^0) + lpeg.Cc("") local fragment = hash * lpeg.Cs((escaped+(1- endofstring))^0) + lpeg.Cc("") @@ -42,29 +42,52 @@ do end function url.hashed(str) - str = url.split(str) - return { scheme = str[1], authority = str[2], path = str[3], query = str[4], fragment = str[5] } + local s = url.split(str) + return { + scheme = (s[1] ~= "" and s[1]) or "file", + authority = s[2], + path = s[3], + query = s[4], + fragment = s[5], + original=str + } end function url.filename(filename) local t = url.hashed(filename) - return (t.scheme == "file" and t.path:gsub("^/([a-zA-Z]:/)","%1")) or filename + return (t.scheme == "file" and t.path:gsub("^/([a-zA-Z])([:|])/)","%1:")) or filename +end + +function url.query(str) + if type(str) == "string" then + local t = { } + for k, v in str:gmatch("([^&=]*)=([^&=]*)") do + t[k] = v + end + return t + else + return str + end end --~ print(url.filename("file:///c:/oeps.txt")) --~ print(url.filename("c:/oeps.txt")) --~ print(url.filename("file:///oeps.txt")) +--~ print(url.filename("file:///etc/test.txt")) --~ print(url.filename("/oeps.txt")) -- from the spec on the web (sort of): --~ --~ function test(str) --~ print(table.serialize(url.hashed(str))) ---~ -- print(table.serialize(url.split(str))) --~ end ---~ --~ test("%56pass%20words") --~ test("file:///c:/oeps.txt") +--~ test("file:///c|/oeps.txt") +--~ test("file:///etc/oeps.txt") +--~ test("file://./etc/oeps.txt") +--~ test("file:////etc/oeps.txt") --~ test("ftp://ftp.is.co.za/rfc/rfc1808.txt") --~ test("http://www.ietf.org/rfc/rfc2396.txt") --~ test("ldap://[2001:db8::7]/c=GB?objectClass?one#what") @@ -75,3 +98,6 @@ end --~ test("urn:oasis:names:specification:docbook:dtd:xml:4.1.2") --~ test("/etc/passwords") --~ test("http://www.pragma-ade.com/spaced%20name") + +--~ test("zip:///oeps/oeps.zip#bla/bla.tex") +--~ test("zip:///oeps/oeps.zip?bla/bla.tex") diff --git a/tex/context/base/l-xml.lua b/tex/context/base/l-xml.lua index 69002e64e..2ece2d91a 100644 --- a/tex/context/base/l-xml.lua +++ b/tex/context/base/l-xml.lua @@ -39,6 +39,8 @@ xml.trace_lpath = false xml.trace_print = false xml.trace_remap = false +-- todo: some things per xml file, liek namespace remapping + --[[ldx--

First a hack to enable namespace resolving. A namespace is characterized by a . The following function associates a namespace prefix with a @@ -657,7 +659,7 @@ function xml.text(root) return (root and xml.tostring(root)) or "" end -function xml.content(root) +function xml.content(root) -- bugged return (root and root.dt and xml.tostring(root.dt)) or "" end @@ -988,14 +990,13 @@ do local t = {...} for i=1,#t do if s == t[i] then return true end end return false end - function xml.traverse(root,pattern,handle,reverse,index,parent,wildcard) + local function traverse(root,pattern,handle,reverse,index,parent,wildcard) if not root then -- error return false elseif pattern == false then -- root handle(root,root.dt,root.ri) return false elseif pattern == true then -- wildcard - local traverse = xml.traverse local rootdt = root.dt if rootdt then local start, stop, step = 1, #rootdt, 1 @@ -1026,7 +1027,7 @@ do elseif command == 11 then -- parent local ep = root.__p__ or parent if index < #pattern then - if not xml.traverse(ep,pattern,handle,reverse,index+1,root) then return false end + if not traverse(ep,pattern,handle,reverse,index+1,root) then return false end elseif handle(root,rootdt,k) then return false end @@ -1041,12 +1042,11 @@ do if command == 11 then -- parent local ep = root.__p__ or parent if index < #pattern then - if not xml.traverse(ep,pattern,handle,reverse,index+1,root) then return false end + if not traverse(ep,pattern,handle,reverse,index+1,root) then return false end elseif handle(root,rootdt,k) then return false end else - local traverse = xml.traverse local rootdt = root.dt local start, stop, step, n, dn = 1, #rootdt, 1, 0, 1 if command == 30 then @@ -1140,6 +1140,7 @@ do if index == #pattern then if handle(root,rootdt,root.ri or k) then return false end if wildcard and multiple then +--~ if wildcard or multiple then if not traverse(e,pattern,handle,reverse,index,root,true) then return false end end else @@ -1200,6 +1201,8 @@ do return true end + xml.traverse = traverse + end --[[ldx-- @@ -1270,7 +1273,7 @@ do traverse(root, lpath(pattern), function(r,d,k) rt,dt,dk = r,d,k return true end, 'reverse') return dt and dt[dk], rt, dt, dk end - function xml.filters.count(root, pattern,everything) + function xml.filters.count(root,pattern,everything) local n = 0 traverse(root, lpath(pattern), function(r,d,t) if everything or type(d[t]) == "table" then @@ -1340,13 +1343,15 @@ do local rt, dt, dk traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end) local ekat = (dt and dt[dk] and dt[dk].at) or (rt and rt.at) - return (ekat and ekat[arguments]) or "" + return (ekat and (ekat[arguments] or ekat[arguments:gsub("^([\"\'])(.*)%1$","%2")])) or "" end - function xml.filters.text(root,pattern,arguments) + function xml.filters.text(root,pattern,arguments) -- ?? why index local dtk, rt, dt, dk = xml.filters.index(root,pattern,arguments) if dtk then local dtkdt = dtk.dt - if #dtkdt == 1 and type(dtkdt[1]) == "string" then + if not dtkdt then + return "", rt, dt, dk + elseif #dtkdt == 1 and type(dtkdt[1]) == "string" then return dtkdt[1], rt, dt, dk else return xml.tostring(dtkdt), rt, dt, dk @@ -1411,7 +1416,7 @@ do

Which will print all the titles in the document. The iterator variant takes - 1.5 times the runtime of the function variant which si due to the overhead in + 1.5 times the runtime of the function variant which is due to the overhead in creating the wrapper. So, instead of:

@@ -1430,6 +1435,10 @@ do return coroutine.wrap(function() traverse(root, lpath(pattern), coroutine.yield, reverse) end) end + function xml.elements_only(root,pattern,reverse) + return coroutine.wrap(function() traverse(root, lpath(pattern), function(r,d,k) coroutine.yield(d[k]) end, reverse) end) + end + function xml.each_element(root, pattern, handle, reverse) local ok traverse(root, lpath(pattern), function(r,d,k) ok = true handle(r,d,k) end, reverse) @@ -1575,10 +1584,20 @@ do end end - function xml.include(xmldata,pattern,attribute,recursive,findfile) + local function load_data(name) -- == io.loaddata + local f, data = io.open(name), "" + if f then + data = f:read("*all",'b') -- 'b' ? + f:close() + end + return data + end + + function xml.include(xmldata,pattern,attribute,recursive,loaddata) -- parse="text" (default: xml), encoding="" (todo) - pattern = pattern or 'include' -- attribute = attribute or 'href' + pattern = pattern or 'include' + loaddata = loaddata or load_data local function include(r,d,k) local ek, name = d[k], nil if not attribute or attribute == "" then @@ -1593,29 +1612,21 @@ do end end end - if name then - name = (findfile and findfile(name)) or name - if name ~= "" then - local f = io.open(name) - if f then - if ek.at["parse"] == "text" then -- for the moment hard coded - d[k] = xml.escaped(f:read("*all")) - else - local xi = xml.load(f) - if recursive then - xml.include(xi,pattern,attribute,recursive,findfile) - end - xml.assign(d,k,xi) - end - f:close() - else - xml.empty(d,k) - end - else + local data = (name and name ~= "" and loaddata(name)) or "" + if data == "" then + xml.empty(d,k) + elseif ek.at["parse"] == "text" then -- for the moment hard coded + d[k] = xml.escaped(data) + else + local xi = xml.convert(data) + if not xi then xml.empty(d,k) + else + if recursive then + xml.include(xi,pattern,attribute,recursive,loaddata) + end + xml.assign(d,k,xi) end - else - xml.empty(d,k) end end xml.each_element(xmldata, pattern, include) diff --git a/tex/context/base/luat-crl.lua b/tex/context/base/luat-crl.lua index 973655999..c0690b8af 100644 --- a/tex/context/base/luat-crl.lua +++ b/tex/context/base/luat-crl.lua @@ -12,12 +12,13 @@ curl.cachepath = caches.setpath(texmf.instance,"curl") curl.cached = { } function curl.fetch(protocol, name) - local cachename = curl.cachepath .. "/" .. file.robustname(name) - cachename = cachename:gsub("[\\/]", io.fileseparator) + local cachename = curl.cachepath .. "/" .. name:gsub("[^%a%d%.]+","-") +-- cachename = cachename:gsub("[\\/]", io.fileseparator) + cachename = cachename:gsub("[\\]", "/") if not curl.cached[name] then if not io.exists(cachename) then curl.cached[name] = cachename - local command = "curl --silent --create-dirs --output " .. cachename .. " " .. protocol .. "://" .. name + local command = "curl --silent --create-dirs --output " .. cachename .. " " .. name -- no protocol .. "://" os.spawn(command) end if io.exists(cachename) then diff --git a/tex/context/base/luat-deb.lua b/tex/context/base/luat-deb.lua index fc671d6be..a32d923bd 100644 --- a/tex/context/base/luat-deb.lua +++ b/tex/context/base/luat-deb.lua @@ -21,63 +21,63 @@ lmx.variables['color-background-two'] = lmx.variables['color-background-blue' lmx.variables['title-default'] = 'ConTeXt Status Information' lmx.variables['title'] = lmx.variables['title-default'] -if not trace then trace = { } end -if not trace.list then trace.list = { } end -if not trace.strings then trace.strings = { } end +if not tracers then tracers = { } end +if not tracers.list then tracers.list = { } end +if not tracers.strings then tracers.strings = { } end -trace.strings.undefined = "undefined" +tracers.strings.undefined = "undefined" -function trace.split(csname) +function tracers.split(csname) return csname:match("^(.+):(.+)$") end -function trace.type(csname) - tag, name = trace.split(csname) +function tracers.type(csname) + tag, name = tracers.split(csname) if tag then return tag else return nil end end -function trace.name(csname) - tag, name = trace.split(csname) +function tracers.name(csname) + tag, name = tracers.split(csname) if tag then return name else return csname end end -function trace.cs(csname) - tag, name = trace.split(csname) - if trace.types[tag] then - return trace.types[tag](name) +function tracers.cs(csname) + tag, name = tracers.split(csname) + if tracers.types[tag] then + return tracers.types[tag](name) else - return trace.primitive(csname) + return tracers.primitive(csname) end end -function trace.dimen(name) - return (tex.dimen[name] and number.topoints(tex.dimen[name])) or trace.strings.undefined +function tracers.dimen(name) + return (tex.dimen[name] and number.topoints(tex.dimen[name])) or tracers.strings.undefined end -function trace.count(name) - return tex.count[name] or trace.strings.undefined +function tracers.count(name) + return tex.count[name] or tracers.strings.undefined end -function trace.toks(name) - return (tex.toks[name] and string.limit(tex.toks[name],40)) or trace.strings.undefined +function tracers.toks(name) + return (tex.toks[name] and string.limit(tex.toks[name],40)) or tracers.strings.undefined end -function trace.primitive(name) - return tex[name] or trace.strings.undefined +function tracers.primitive(name) + return tex[name] or tracers.strings.undefined end -trace.types = { - ['d'] = trace.dimen, - ['c'] = trace.count, - ['t'] = trace.toks, - ['p'] = trace.primitive +tracers.types = { + ['d'] = tracers.dimen, + ['c'] = tracers.count, + ['t'] = tracers.toks, + ['p'] = tracers.primitive } -function trace.knownlist(name) - return trace.list[name] and #trace.list[name] > 0 +function tracers.knownlist(name) + return tracers.list[name] and #tracers.list[name] > 0 end -function trace.showdebuginfo() +function tracers.showdebuginfo() lmx.set('title', 'ConTeXt Debug Information') lmx.set('color-background-one', lmx.get('color-background-green')) lmx.set('color-background-two', lmx.get('color-background-blue')) @@ -85,7 +85,7 @@ function trace.showdebuginfo() lmx.restore() end -function trace.showerror() +function tracers.showerror() lmx.set('title', 'ConTeXt Error Information') lmx.set('errormessage', status.lasterrorstring) lmx.set('linenumber', status.linenumber) @@ -132,23 +132,23 @@ function trace.showerror() lmx.restore() end -function trace.overloaderror() +function tracers.overloaderror() --~ callback.register('show_error_hook', function(identifier, filename, linenumber) ---~ trace.showerror(identifier, filename, linenumber) +--~ tracers.showerror(identifier, filename, linenumber) --~ end ) - callback.register('show_error_hook', trace.showerror) + callback.register('show_error_hook', tracers.showerror) end -trace.list['scratch'] = { +tracers.list['scratch'] = { 0, 2, 4, 6, 8 } -trace.list['internals'] = { +tracers.list['internals'] = { 'p:hsize', 'p:parindent', 'p:leftskip','p:rightskip', 'p:vsize', 'p:parskip', 'p:baselineskip', 'p:lineskip', 'p:topskip' } -trace.list['context'] = { +tracers.list['context'] = { 'd:lineheight', 'c:realpageno', 'c:pageno', 'c:subpageno' } diff --git a/tex/context/base/luat-deb.tex b/tex/context/base/luat-deb.tex index d76cb212e..55686ac11 100644 --- a/tex/context/base/luat-deb.tex +++ b/tex/context/base/luat-deb.tex @@ -22,8 +22,8 @@ } \stopruntimeluacode -\def\showdebuginfo{\ctxlua{trace.showdebuginfo()}} -\def\overloaderror{\ctxlua{trace.overloaderror()}} +\def\showdebuginfo{\ctxlua{tracers.showdebuginfo()}} +\def\overloaderror{\ctxlua{tracers.overloaderror()}} \def\breakpoint{\showdebuginfo\wait} diff --git a/tex/context/base/luat-env.lua b/tex/context/base/luat-env.lua index c75edc5f3..73df7e3f1 100644 --- a/tex/context/base/luat-env.lua +++ b/tex/context/base/luat-env.lua @@ -4,88 +4,53 @@ -- copyright: PRAGMA ADE / ConTeXt Development Team -- license : see context related readme files ---~ do ---~ local normal_require = require ---~ local find_lua_file = find_lua_file or kpse.find_file -- you can predefine one - ---~ function require(modname,luctoo) ---~ local file, longfile ---~ if luctoo then ---~ file = modname .. '.luc'; ---~ longfile = find_lua_file(file) ---~ end ---~ if not longfile then ---~ file = modname .. '.lua'; ---~ longfile = find_lua_file(file) ---~ end ---~ if longfile then ---~ local dir = longfile:match("^(.+[/\\]).-$") ---~ local pth = package.path:gsub("\\","/") ---~ dir = dir:gsub("\\","/") ---~ if pth:find(dir) then ---~ package.path = pth -- nicely sanitized ---~ else ---~ package.path = pth .. ';' .. dir .. '?.lua' -- dir has trailing / ---~ end ---~ normal_require(modname) ---~ end ---~ end ---~ end - -- here we don't assume any extra libraries +-- A former version provides functionality for non embeded core +-- scripts i.e. runtime library loading. Given the amount of +-- Lua code we use now, this no longer makes sense. Much of this +-- evolved before bytecode arrays were available. + if not versions then versions = { } end versions['luat-env'] = 1.001 -- environment if not environment then environment = { } end -environment.useluc = false -- for testing ---~ environment.silent = true -- for testing +--~ environment.useluc = true -- still testing, so we don't use luc yet if environment.silent == nil then environment.silent = false end if environment.useluc == nil then environment.useluc = true end -- kpse is overloaded by this time -if environment.formatname == nil then environment.formatname = tex.formatname end -if environment.formatpath == nil then environment.formatpath = kpse.find_file(tex.formatname,"fmt") or "." end -if environment.jobname == nil then environment.jobname = tex.jobname end -if environment.progname == nil then environment.progname = os.getenv("progname") or "luatex" end -if environment.engine == nil then environment.engine = os.getenv("engine") or "context" end -if environment.enginepath == nil then environment.enginepath = os.getenv("SELFAUTOLOC") or "." end -if environment.initex == nil then environment.initex = tex.formatname == "" end - -environment.formatpath = string.gsub(environment.formatpath:gsub("\\","/"),"/([^/]-)$","") -environment.enginepath = string.gsub(environment.enginepath:gsub("\\","/"),"/([^/]-)$","") +--~ if environment.formatname == nil then if tex then environment.formatname = tex.formatname end end +--~ if environment.formatpath == nil then if kpse then environment.formatpath = kpse.find_file(tex.formatname,"fmt") or "." end end +--~ if environment.jobname == nil then if tex then environment.jobname = tex.jobname end end +--~ if environment.progname == nil then environment.progname = os.getenv("progname") or "luatex" end +--~ if environment.engine == nil then environment.engine = os.getenv("engine") or "context" end +--~ if environment.enginepath == nil then environment.enginepath = os.getenv("SELFAUTOLOC") or "." end +--~ if environment.initex == nil then if tex then environment.initex = tex.formatname == "" end end -if environment.formatname == "" then environment.formatpath = "cont-en" end -if environment.formatpath == "" then environment.formatpath = '.' end -if environment.enginepath == "" then environment.enginepath = '.' end -if environment.version == nil then environment.version = "unknown" end +if not environment.formatname or environment.formatname == "" then if tex then environment.formatname = tex.formatname end end +if not environment.jobname or environment.jobname == "" then if tex then environment.jobname = tex.jobname end end -function environment.get(name) - return os.getenv(name) or "" -end +if not environment.progname or environment.progname == "" then environment.progname = "luatex" end +if not environment.engine or environment.engine == "" then environment.engine = "context" end +if not environment.formatname or environment.formatname == "" then environment.formatname = "cont-en" end +if not environment.formatpath or environment.formatpath == "" then environment.formatpath = '.' end +if not environment.enginepath or environment.enginepath == "" then environment.enginepath = '.' end +if not environment.version or environment.version == "" then environment.version = "unknown" end -function environment.cleanname(filename) - if filename and filename ~= "" then - return filename:gsub( "\\", "/") - else -- leave nil and empty untouched - return filename - end -end +environment.formatpath = string.gsub(environment.formatpath:gsub("\\","/"),"/([^/]-)$","") +environment.enginepath = string.gsub(environment.enginepath:gsub("\\","/"),"/([^/]-)$","") function environment.texfile(filename) - return environment.cleanname(input.find_file(texmf.instance,filename,'tex')) -end - -function environment.ctxfile(filename) - return environment.cleanname(input.find_file(texmf.instance,filename,'tex')) + return input.find_file(texmf.instance,filename,'tex') end function environment.luafile(filename) - return environment.cleanname(input.find_file(texmf.instance,filename,'tex') or input.find_file(texmf.instance,filename,'texmfscripts')) + return input.find_file(texmf.instance,filename,'tex') or input.find_file(texmf.instance,filename,'texmfscripts') end function environment.showmessage(...) -- todo, cleaner @@ -110,12 +75,18 @@ function environment.setlucpath() end end +environment.setlucpath() + +function environment.loadedluacode(fullname) + return loadfile(fullname) +end + function environment.luafilechunk(filename) local filename = filename:gsub("%.%a+$", "") .. ".lua" local fullname = environment.luafile(filename) if fullname and fullname ~= "" then environment.showmessage("loading file", fullname) - return loadfile(fullname) + return environment.loadedluacode(fullname) else environment.showmessage("unknown file", filename) return nil @@ -124,19 +95,11 @@ end -- the next ones can use the previous ones -function environment.loadluafile(filename,register) +function environment.loadluafile(filename) filename = filename:gsub("%.%a+$", "") .. ".lua" local fullname = environment.luafile(filename) if fullname and fullname ~= "" then environment.showmessage("loading", fullname) - if register then - if not environment.regfil then - environment.regfil = io.open('luafiles.tmp', 'w') -- we can consider 'a' - end - if environment.regfil then - environment.regfil:write(fullname .."\n") - end - end dofile(fullname) else environment.showmessage("unknown file", filename) @@ -147,7 +110,7 @@ function environment.loadlucfile(filename,version) local filename = filename:gsub("%.%a+$", "") local fullname = nil if environment.initex or not environment.useluc then - environment.loadluafile(filename,environment.initex) + environment.loadluafile(filename) else if environment.lucpath and environment.lucpath ~= "" then fullname = environment.lucpath .. "/" .. filename .. ".luc" @@ -177,17 +140,79 @@ function environment.loadlucfile(filename,version) end end -function environment.loadedctxfile(filename) - local fullname = environment.ctxfile(filename) - local i = io.open(fullname) - if i then - local data = i:read('*all') - i:close() - return data +-- -- -- the next function was posted by Peter Cawley on the lua list -- -- -- +-- -- -- -- -- -- +-- -- -- stripping makes the compressed format file about 1MB smaller -- -- -- +-- -- -- -- -- -- +-- -- -- using this trick is at your own risk -- -- -- + +local function strip_code(dump) + local version, format, endian, int, size, ins, num = dump:byte(5, 11) + local subint + if endian == 1 then + subint = function(dump, i, l) + local val = 0 + for n = l, 1, -1 do + val = val * 256 + dump:byte(i + n - 1) + end + return val, i + l + end + else + subint = function(dump, i, l) + local val = 0 + for n = 1, l, 1 do + val = val * 256 + dump:byte(i + n - 1) + end + return val, i + l + end + end + local strip_function + strip_function = function(dump) + local count, offset = subint(dump, 1, size) + local stripped, dirty = string.rep("\0", size), offset + count + offset = offset + count + int * 2 + 4 + offset = offset + int + subint(dump, offset, int) * ins + count, offset = subint(dump, offset, int) + for n = 1, count do + local t + t, offset = subint(dump, offset, 1) + if t == 1 then + offset = offset + 1 + elseif t == 4 then + offset = offset + size + subint(dump, offset, size) + elseif t == 3 then + offset = offset + num + end + end + count, offset = subint(dump, offset, int) + stripped = stripped .. dump:sub(dirty, offset - 1) + for n = 1, count do + local proto, off = strip_function(dump:sub(offset, -1)) + stripped, offset = stripped .. proto, offset + off - 1 + end + offset = offset + subint(dump, offset, int) * int + int + count, offset = subint(dump, offset, int) + for n = 1, count do + offset = offset + subint(dump, offset, size) + size + int * 2 + end + count, offset = subint(dump, offset, int) + for n = 1, count do + offset = offset + subint(dump, offset, size) + size + end + stripped = stripped .. string.rep("\0", int * 3) + return stripped, offset + end + return dump:sub(1,12) .. strip_function(dump:sub(13,-1)) +end + +environment.stripcode = false -- true + +function environment.loadedluacode(fullname) + if environment.stripcode then + return loadstring(strip_code(string.dump(loadstring(io.loaddata(fullname))))) else - environment.showmessage("missing",filename) - return "" + return loadfile(fullname) end end -environment.setlucpath() +-- -- end of stripping code -- -- diff --git a/tex/context/base/luat-env.tex b/tex/context/base/luat-env.tex index ec2b942eb..8fdfff295 100644 --- a/tex/context/base/luat-env.tex +++ b/tex/context/base/luat-env.tex @@ -11,6 +11,18 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +%D Originally we compiled the lua files externally and loaded +%D then at runtime, but when the amount grew, we realized that +%D we needed away to store them in the format, which is what +%D bytecode arrays do. And so the following is obsolete: +%D +%D \starttyping +%D \chardef\ctxluaembeddingmode \plusone +%D +%D 0 = external compilation and loading +%D 1 = runtime compilation and embedding +%D \stoptyping + % \writestatus{loading}{Lua Support Macros (environment)} % print (lua.id) @@ -79,18 +91,14 @@ %D Next we load the initialization code. \startruntimectxluacode - if not environment then environment = { } end + environment = environment or { } environment.jobname = "\jobname" % tex.jobname environment.formatname = "\contextformat" % tex.formatname environment.initex = \ifproductionrun false \else true \fi % tex.formatname == "" environment.version = "\contextversion" - dofile(input.find_file(texmf.instance,"luat-env.lua","tex")) +-- dofile(input.find_file(texmf.instance,"luat-env.lua","tex")) \stopruntimectxluacode -% 0 = external compilation and loading -% 1 = runtime compilation and embedding - -\chardef\ctxluaembeddingmode \plusone \chardef\ctxluaexecutionmode \zerocount % private % we start at 500, below this, we store predefined data (dumps) @@ -140,7 +148,8 @@ \stopruntimectxluacode}% \ctxlua { lua.bytedata[\the\luabytecodecounter] = { "#1", "#2" } - lua.bytecode[\the\luabytecodecounter] = environment.luafilechunk("#1")}} + lua.bytecode[\the\luabytecodecounter] = environment.luafilechunk("#1") + }} \def\ctxluafileload#1#2% load a (either not compiled) chunk at runtime {\doifelsenothing{#2} @@ -148,21 +157,14 @@ {\ctxlua{environment.loadlucfile("#1",#2)}}} \def\registerctxluafile#1#2% name version - {\ifcase\ctxluaembeddingmode - \ifproductionrun \else - \global\everyloadluacode\expandafter{\the\everyloadluacode\ctxluafileload{#1}{#2}}% - \fi - \ifcase\ctxluaexecutionmode\or\ctxluafileload{#1}{#2}\fi - \else - \ifproductionrun \else - \ctxluabyteload{#1}{#2}% - \fi - \global\everyloadluacode\expandafter\expandafter\expandafter{\expandafter\the\expandafter\everyloadluacode - \expandafter\ctxluabytecode\expandafter{\the\luabytecodecounter}}% - \ifcase\ctxluaexecutionmode\or\ctxluabytecode{\the\luabytecodecounter}\fi - \fi} - -\ifcase\ctxluaembeddingmode \else \registerctxluafile{luat-env}{1.001} \fi + {\ifproductionrun \else + \ctxluabyteload{#1}{#2}% + \fi + \global\everyloadluacode\expandafter\expandafter\expandafter{\expandafter\the\expandafter\everyloadluacode + \expandafter\ctxluabytecode\expandafter{\the\luabytecodecounter}}% + \ifcase\ctxluaexecutionmode\or\ctxluabytecode{\the\luabytecodecounter}\fi} + +\registerctxluafile{luat-env}{1.001} \chardef\ctxluaexecutionmode \plusone diff --git a/tex/context/base/luat-ini.lua b/tex/context/base/luat-ini.lua index e7757d51b..092593541 100644 --- a/tex/context/base/luat-ini.lua +++ b/tex/context/base/luat-ini.lua @@ -14,7 +14,7 @@ cluttered by macro package code.

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

Please create a namespace within these tables before using them!

diff --git a/tex/context/base/luat-inp.lua b/tex/context/base/luat-inp.lua index 618696cb6..9f04ad82c 100644 --- a/tex/context/base/luat-inp.lua +++ b/tex/context/base/luat-inp.lua @@ -82,17 +82,22 @@ input.formats ['lua'] = 'LUAINPUTS' -- new input.suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } -- here we catch a few new thingies (todo: add these paths to context.tmf) +-- +-- FONTFEATURES = .;$TEXMF/fonts/fea// +-- FONTCIDMAPS = .;$TEXMF/fonts/cid// -function input.checkconfigdata(instance) +function input.checkconfigdata(instance) -- not yet ok, no time for debugging now 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 + local p = instance.environment[proname] + local v = instance.environment[varname] + if not ((p and p ~= "") or (v and v ~= "")) then + instance.variables[varname] = default -- or environment? end end fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") - fix("FONTFEATURES", ".;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") - fix("FONTCIDMAPS" , ".;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") + fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS") end -- backward compatible ones @@ -193,6 +198,11 @@ function input.reset() end +function input.reset_hashes(instance) + instance.lists = { } + instance.found = { } +end + function input.bare_variable(str) -- return string.gsub(string.gsub(string.gsub(str,"%s+$",""),'^"(.+)"$',"%1"),"^'(.+)'$","%1") return (str:gsub("\s*([\"\']?)(.+)%1\s*", "%2")) @@ -258,7 +268,7 @@ input.settrace(tonumber(os.getenv("MTX.INPUT.TRACE") or os.getenv("MTX_INPUT_TRA -- loading the database files. do - local clock = os.clock + local clock = os.gettimeofday or os.clock function input.starttiming(instance) if instance then @@ -532,6 +542,7 @@ function input.aux.extend_texmf_var(instance,specification) -- crap instance.variables['TEXMF'] = "{" .. instance.variables['TEXMF'] .. "}" end input.expand_variables(instance) + input.reset_hashes(instance) end -- locators @@ -547,28 +558,6 @@ function input.locatedatabase(instance,specification) return input.methodhandler('locators', instance, specification) end ---~ poor mans solution, from before we had lfs.isdir ---~ ---~ function input.locators.tex(instance,specification) ---~ if specification and specification ~= '' then ---~ local files = { ---~ file.join(specification,'files'..input.lucsuffix), ---~ file.join(specification,'files'..input.luasuffix), ---~ file.join(specification,input.lsrname) ---~ } ---~ for _, filename in pairs(files) do ---~ local f = io.open(filename) ---~ if f then ---~ input.logger('! tex locator', specification..' found') ---~ input.aux.append_hash(instance,'file',specification,filename) ---~ f:close() ---~ return ---~ end ---~ end ---~ input.logger('? tex locator', specification..' not found') ---~ end ---~ end - function input.locators.tex(instance,specification) if specification and specification ~= '' and lfs.isdir(specification) then input.logger('! tex locator', specification..' found') @@ -927,8 +916,6 @@ function input.expand_variables(instance) for k,v in pairs(instance.expansions) do instance.expansions[k] = v:gsub("\\", '/') end - -- ########## - --~ input.splitexpansions(instance) -- better not, fuzzy end function input.aux.expand_vars(instance,lst) -- simple vars @@ -1380,7 +1367,7 @@ input.is_readable.tex = input.is_readable.file -- name/name function input.aux.collect_files(instance,names) - local filelist = nil + local filelist = { } for _, fname in pairs(names) do if fname then if input.trace > 2 then @@ -1412,15 +1399,20 @@ function input.aux.collect_files(instance,names) if blobfile then if type(blobfile) == 'string' then if not dname or blobfile:find(dname) then - if not filelist then filelist = { } end - -- input.logger('= collected', blobpath.." | "..blobfile.." | "..bname) - filelist[#filelist+1] = file.join(blobpath,blobfile,bname) + filelist[#filelist+1] = { + hash.type, + file.join(blobpath,blobfile,bname), -- search + input.concatinators[hash.type](blobpath,blobfile,bname) -- result + } end else for _, vv in pairs(blobfile) do if not dname or vv:find(dname) then - if not filelist then filelist = { } end - filelist[#filelist+1] = file.join(blobpath,vv,bname) + filelist[#filelist+1] = { + hash.type, + file.join(blobpath,vv,bname), -- search + input.concatinators[hash.type](blobpath,vv,bname) -- result + } end end end @@ -1431,7 +1423,11 @@ function input.aux.collect_files(instance,names) end end end - return filelist + if #filelist > 0 then + return filelist + else + return nil + end end function input.suffix_of_format(str) @@ -1450,54 +1446,30 @@ function input.suffixes_of_format(str) end end ---~ function input.aux.qualified_path(filename) -- make platform dependent / not good yet ---~ return ---~ filename:find("^%.+/") or ---~ filename:find("^/") or ---~ filename:find("^%a+%:") or ---~ filename:find("^%a+##") ---~ end - ---~ function input.normalize_name(original) ---~ -- internally we use type##spec##subspec ; this hackery slightly slows down searching ---~ local str = original or "" ---~ str = str:gsub("::", "##") -- :: -> ## ---~ str = str:gsub("^(%a+)://" ,"%1##") -- zip:// -> zip## ---~ str = str:gsub("(.+)##(.+)##/(.+)","%1##%2##%3") -- ##/spec -> ##spec ---~ if (input.trace>1) and (original ~= str) then ---~ input.logger('= normalizer',original.." -> "..str) ---~ end ---~ return str ---~ end +do -do -- called about 700 times for an empty doc (font initializations etc) + -- called about 700 times for an empty doc (font initializations etc) -- i need to weed the font files for redundant calls local letter = lpeg.R("az","AZ") - local separator = lpeg.P("##") + local separator = lpeg.P("://") - local qualified = lpeg.P(".")^0 * lpeg.P("/") + letter*lpeg.P(":") + letter^1*separator - local normalized = lpeg.Cs( - (letter^1*(lpeg.P("://")/"##") * (1-lpeg.P(false))^1) + - (lpeg.P("::")/"##" + (1-separator)^1*separator*(1-separator)^1*separator*(lpeg.P("/")/"") + 1)^0 - ) + local qualified = lpeg.P(".")^0 * lpeg.P("/") + letter*lpeg.P(":") + letter^1*separator + local rootbased = lpeg.P("/") + letter*lpeg.P(":") - -- ./name ../name /name c: zip## (todo: use url internally and get rid of ##) + -- ./name ../name /name c: :// function input.aux.qualified_path(filename) return qualified:match(filename) end + function input.aux.rootbased_path(filename) + return rootbased:match(filename) + end - -- zip:// -> zip## ; :: -> ## ; aa##bb##/cc -> aa##bb##cc function input.normalize_name(original) - local str = normalized:match(original or "") - if input.trace > 1 and original ~= str then - input.logger('= normalizer',original.." -> "..str) - end - return str + return original end -end --- split the next one up, better for jit +end function input.aux.register_in_trees(instance,name) if not name:find("^%.") then @@ -1505,11 +1477,13 @@ function input.aux.register_in_trees(instance,name) end end +-- split the next one up, better for jit + function input.aux.find_file(instance,filename) -- todo : plugin (scanners, checkers etc) local result = { } local stamp = nil - filename = input.normalize_name(filename) - filename = file.collapse_path(filename:gsub("\\","/")) + filename = input.normalize_name(filename) -- elsewhere + filename = file.collapse_path(filename:gsub("\\","/")) -- elsewhere -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -1581,7 +1555,7 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec local typespec = input.variable_of_format(filetype) local pathlist = input.expanded_path_list(instance,typespec) if not pathlist or #pathlist == 0 then - -- no pathlist, access check only + -- no pathlist, access check only / todo == wildcard if input.trace > 2 then input.logger('? filename',filename) input.logger('? filetype',filetype or '?') @@ -1596,8 +1570,9 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec end -- this is actually 'other text files' or 'any' or 'whatever' local filelist = input.aux.collect_files(instance,wantedfiles) - filename = filelist and filelist[1] - if filename then + local lf = filelist and filelist[1] + if fl then + filename = fl[3] result[#result+1] = filename done = true end @@ -1607,8 +1582,8 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec local doscan, recurse if input.trace > 2 then input.logger('? filename',filename) - if pathlist then input.logger('? path list',table.concat(pathlist," | ")) end - if filelist then input.logger('? file list',table.concat(filelist," | ")) end + -- if pathlist then input.logger('? path list',table.concat(pathlist," | ")) end + -- if filelist then input.logger('? file list',table.concat(filelist," | ")) end end -- a bit messy ... esp the doscan setting here for _, path in pairs(pathlist) do @@ -1621,16 +1596,18 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec -- compare list entries with permitted pattern pathname = pathname:gsub("([%-%.])","%%%1") -- this also influences pathname = pathname:gsub("/+$", '/.*') -- later usage of pathname - pathname = pathname:gsub("//", '/.-/') + pathname = pathname:gsub("//", '/.-/') -- not ok for /// but harmless local expr = "^" .. pathname -- input.debug('?',expr) - for _, f in pairs(filelist) do + for _, fl in ipairs(filelist) do + local f = fl[2] if f:find(expr) then -- input.debug('T',' '..f) if input.trace > 2 then input.logger('= found in hash',f) end - result[#result+1] = f + --- todo, test for readable + result[#result+1] = fl[3] input.aux.register_in_trees(instance,f) -- for tracing used files done = true if not instance.allresults then break end @@ -1640,7 +1617,7 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec end end if not done and doscan then - -- check if on disk / unchecked / does not work at all + -- check if on disk / unchecked / does not work at all / also zips if input.method_is_file(pathname) then -- ? local pname = pathname:gsub("%.%*$",'') if not pname:find("%*") then @@ -1717,10 +1694,7 @@ end if not input.concatinators then input.concatinators = { } end -function input.concatinators.tex(tag,path,name) - return tag .. '/' .. path .. '/' .. name -end - +input.concatinators.tex = file.join input.concatinators.file = input.concatinators.tex function input.find_files(instance,filename,filetype,mustexist) @@ -1922,15 +1896,6 @@ function input.aux.register_file(files, name, path) end end --- zip:: zip## zip:// --- zip::pathtozipfile::pathinzipfile (also: pathtozipfile/pathinzipfile) --- file::name --- tex::name --- kpse::name --- kpse::format::name --- parent::n::name --- parent::name (default 2) - if not input.finders then input.finders = { } end if not input.openers then input.openers = { } end if not input.loaders then input.loaders = { } end @@ -1940,30 +1905,37 @@ input.openers.notfound = { nil } input.loaders.notfound = { false, nil, 0 } function input.splitmethod(filename) - local method, specification = filename:match("^(.-)##(.+)$") - if method and specification then - return method, specification + if not filename then + return { } -- safeguard + elseif type(filename) == "table" then + return filename -- already split + elseif not filename:find("://") then + return { scheme="file", path = filename, original=filename } -- quick hack else - return 'tex', filename + return url.hashed(filename) end end function input.method_is_file(filename) - local method, specification = input.splitmethod(filename) - return method == 'tex' or method == 'file' + return input.splitmethod(filename).scheme == 'file' +end + +function table.sequenced(t,sep) -- temp here + local s = { } + for k, v in pairs(t) do + s[#s+1] = k .. "=" .. v + end + return table.concat(s, sep or " | ") end function input.methodhandler(what, instance, filename, filetype) -- ... - local method, specification = input.splitmethod(filename) - if method and specification then -- redundant - if input[what][method] then - input.logger('= handler',filename.." -> "..what.." | "..method.." | "..specification) - return input[what][method](instance,specification,filetype) - else - return nil - end + local specification = (type(filename) == "string" and input.splitmethod(filename)) or filename -- no or { }, let it bomb + local scheme = specification.scheme + if input[what][scheme] then + input.logger('= handler',specification.original .." -> " .. what .. " -> " .. table.sequenced(specification)) + return input[what][scheme](instance,filename,filetype) -- todo: specification else - return input[what].tex(instance,filename,filetype) + return input[what].tex(instance,filename,filetype) -- todo: specification end end @@ -1997,6 +1969,8 @@ function input.texdatablob(instance, filename, filetype) return data or "" end +input.loadtexfile = input.texdatablob + function input.openfile(filename) -- brrr texmf.instance here / todo ! ! ! ! ! local fullname = input.findtexfile(texmf.instance, filename) if fullname and (fullname ~= "") then diff --git a/tex/context/base/luat-lib.lua b/tex/context/base/luat-lib.lua index b4e1ad0ad..0b18f3eeb 100644 --- a/tex/context/base/luat-lib.lua +++ b/tex/context/base/luat-lib.lua @@ -21,19 +21,13 @@ os.setlocale(nil,nil) -- useless feature and even dangerous in luatex if not io.fileseparator then if string.find(os.getenv("PATH"),";") then - io.fileseparator, io.pathseparator, os.platform = "\\", ";", "windows" + io.fileseparator, io.pathseparator, os.platform = "\\", ";", os.type or "windows" else - io.fileseparator, io.pathseparator, os.platform = "/" , ":", "unix" + io.fileseparator, io.pathseparator, os.platform = "/" , ":", os.type or "unix" end end -if not os.platform then - if io.pathseparator == ";" then - os.platform = "windows" - else - os.platform = "unix" - end -end +os.platform = os.platform or os.type or (io.pathseparator == ";" and "windows") or "unix" -- arg normalization -- diff --git a/tex/context/base/luat-lmx.lua b/tex/context/base/luat-lmx.lua index 65434668a..626482e6a 100644 --- a/tex/context/base/luat-lmx.lua +++ b/tex/context/base/luat-lmx.lua @@ -6,7 +6,7 @@ if not versions then versions = { } end versions['luat-mlx'] = 1.001 --- we can now use l-xml +-- we can now use l-xml, and we can also use lpeg lmx = { } @@ -94,9 +94,9 @@ lmx.lmxfile = function(filename) return filename end lmx.htmfile = function(filename) return filename end if environment.platform == "windows" then - lmx.popupfile = function(filename) os.spawn("start " .. filename) end + lmx.popupfile = function(filename) os.execute("start " .. filename) end else - lmx.popupfile = function(filename) os.spawn(filename) end + lmx.popupfile = function(filename) os.execute(filename) end end function lmx.show(name) diff --git a/tex/context/base/luat-sta.lua b/tex/context/base/luat-sta.lua new file mode 100644 index 000000000..15581222c --- /dev/null +++ b/tex/context/base/luat-sta.lua @@ -0,0 +1,183 @@ +if not modules then modules = { } end modules ['luat-sta'] = { + version = 1.001, + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +states = states or { } +states.data = states.data or { } +states.hash = states.hash or { } +states.tag = states.tag or "" +states.filename = states.filename or "" + +function states.save(filename,tag) + tag = tag or states.tag + filename = file.addsuffix(filename or states.filename,'lus') + io.savedata(filename, + "-- generator : luat-sta.lua\n" .. + "-- state tag : " .. tag .. "\n\n" .. + table.serialize(states.data[tag or states.tag] or {},true) + ) +end + +function states.load(filename,tag) + states.filename = filename + states.tag = tag or "whatever" + states.filename = file.addsuffix(states.filename,'lus') + states.data[states.tag], states.hash[states.tag] = (io.exists(filename) and dofile(filename)) or { }, { } +end + +function states.set_by_tag(tag,key,value,default,persistent) + local d, h = states.data[tag], states.hash[tag] + if d then + local dkey, hkey = key, key + local pre, post = key:match("(.+)%.([^%.]+)$") + if pre and post then + for k in pre:gmatch("[^%.]+") do + local dk = d[k] + if not dk then + dk = { } + d[k] = dk + end + d = dk + end + dkey, hkey = post, key + end + if type(value) == nil then + value = value or default + elseif persistent then + value = value or d[dkey] or default + else + value = value or default + end + d[dkey], h[hkey] = value, value + end +end + +function states.get_by_tag(tag,key,default) + local h = states.hash[tag] + if h and h[key] then + return h[key] + else + local d = states.data[tag] + if d then + for k in key:gmatch("[^%.]+") do + local dk = d[k] + if dk then + d = dk + else + return default + end + end + return d or default + end + end +end + +function states.set(key,value,default,persistent) + states.set_by_tag(states.tag,key,value,default,persistent) +end + +function states.get(key,default) + return states.get_by_tag(states.tag,key,default) +end + +--~ states.data.update = { +--~ ["version"] = { +--~ ["major"] = 0, +--~ ["minor"] = 1, +--~ }, +--~ ["rsync"] = { +--~ ["server"] = "contextgarden.net", +--~ ["module"] = "minimals", +--~ ["repository"] = "current", +--~ ["flags"] = "-rpztlv --stats", +--~ }, +--~ ["tasks"] = { +--~ ["update"] = true, +--~ ["make"] = true, +--~ ["delete"] = false, +--~ }, +--~ ["platform"] = { +--~ ["host"] = true, +--~ ["other"] = { +--~ ["mswin"] = false, +--~ ["linux"] = false, +--~ ["linux-64"] = false, +--~ ["osx-intel"] = false, +--~ ["osx-ppc"] = false, +--~ ["sun"] = false, +--~ }, +--~ }, +--~ ["context"] = { +--~ ["available"] = {"current", "beta", "alpha", "experimental"}, +--~ ["selected"] = "current", +--~ }, +--~ ["formats"] = { +--~ ["cont-en"] = true, +--~ ["cont-nl"] = true, +--~ ["cont-de"] = false, +--~ ["cont-cz"] = false, +--~ ["cont-fr"] = false, +--~ ["cont-ro"] = false, +--~ }, +--~ ["engine"] = { +--~ ["pdftex"] = { +--~ ["install"] = true, +--~ ["formats"] = { +--~ ["pdftex"] = true, +--~ }, +--~ }, +--~ ["luatex"] = { +--~ ["install"] = true, +--~ ["formats"] = { +--~ }, +--~ }, +--~ ["xetex"] = { +--~ ["install"] = true, +--~ ["formats"] = { +--~ ["xetex"] = false, +--~ }, +--~ }, +--~ ["metapost"] = { +--~ ["install"] = true, +--~ ["formats"] = { +--~ ["mpost"] = true, +--~ ["metafun"] = true, +--~ }, +--~ }, +--~ }, +--~ ["fonts"] = { +--~ }, +--~ ["doc"] = { +--~ }, +--~ ["modules"] = { +--~ ["f-urwgaramond"] = false, +--~ ["f-urwgothic"] = false, +--~ ["t-bnf"] = false, +--~ ["t-chromato"] = false, +--~ ["t-cmscbf"] = false, +--~ ["t-cmttbf"] = false, +--~ ["t-construction-plan"] = false, +--~ ["t-degrade"] = false, +--~ ["t-french"] = false, +--~ ["t-lettrine"] = false, +--~ ["t-lilypond"] = false, +--~ ["t-mathsets"] = false, +--~ ["t-tikz"] = false, +--~ ["t-typearea"] = false, +--~ ["t-vim"] = false, +--~ }, +--~ } + + +--~ states.save("teststate", "update") +--~ states.load("teststate", "update") + +--~ print(states.get_by_tag("update","rsync.server","unknown")) +--~ states.set_by_tag("update","rsync.server","oeps") +--~ print(states.get_by_tag("update","rsync.server","unknown")) +--~ states.save("teststate", "update") +--~ states.load("teststate", "update") +--~ print(states.get_by_tag("update","rsync.server","unknown")) diff --git a/tex/context/base/luat-tex.lua b/tex/context/base/luat-tex.lua index 0fb262698..74bf45938 100644 --- a/tex/context/base/luat-tex.lua +++ b/tex/context/base/luat-tex.lua @@ -187,6 +187,8 @@ if texconfig and not texlua then do texio.write_nl(s .. b .. "\n") end + -- this will become: ctx.install_statistics(fnc() return ..,.. end) etc + function ctx.show_statistics() local function ws(...) ctx.writestatus("mkiv lua stats",string.format(...)) @@ -222,6 +224,12 @@ if texconfig and not texlua then do if languages then ws("language load time - %s seconds (n=%s)", input.loadtime(languages), languages.hyphenation.n()) end + if figures then + ws("graphics processing time - %s seconds (n=%s) (including tex)", input.loadtime(figures), figures.n or "?") + end + if metapost then + ws("metapost processing time - %s seconds (+ loading: %s seconds)", input.loadtime(metapost), input.loadtime(mplib)) + end if status.luastate_bytes then ws("current memory usage - %s bytes", status.luastate_bytes) end @@ -422,7 +430,7 @@ if texconfig and not texlua then 'hash_extra', 'max_strings', 'pool_free', 'pool_size', 'string_vacancies', 'obj_tab_size', 'pdf_mem_size', 'dest_names_size', 'nest_size', 'param_size', 'save_size', 'stack_size', - 'trie_size', 'hyph_size', + 'trie_size', 'hyph_size', 'max_in_open', 'ocp_stack_size', 'ocp_list_size', 'ocp_buf_size' } @@ -449,6 +457,7 @@ if texconfig and not texlua then end texconfig.max_print_line = 100000 + texconfig.max_in_open = 127 end @@ -475,111 +484,3 @@ function cs.testcase(b) tex.sprint(tex.texcatcodes, "\\secondoftwoarguments") end end - --- This is not the most ideal place, but it will do. Maybe we need to move --- attributes to node-att.lua. - -if node then - - nodes = nodes or { } - - do - - -- just for testing - - local reserved = { } - - function nodes.register(n) - reserved[#reserved+1] = n - end - - function nodes.cleanup_reserved(nofboxes) -- todo - local nr, free = #reserved, node.free - for i=1,nr do - free(reserved[i]) - end - local nl, tb, flush = 0, tex.box, node.flush_list - if nofboxes then - for i=1,nofboxes do - local l = tb[i] - if l then - -- flush(l) - tb[i] = nil - nl = nl + 1 - end - end - end - reserved = { } - return nr, nl, nofboxes - end - - end - - do - - local pdfliteral = node.new("whatsit",8) pdfliteral.next, pdfliteral.prev = nil, nil pdfliteral.mode = 1 - local disc = node.new("disc") disc.next, disc.prev = nil, nil - local kern = node.new("kern",1) kern.next, kern.prev = nil, nil - local penalty = node.new("penalty") penalty.next, penalty.prev = nil, nil - local glue = node.new("glue") glue.next, glue.prev = nil, nil - local glue_spec = node.new("glue_spec") glue_spec.next, glue_spec.prev = nil, nil - - nodes.register(pdfliteral) - nodes.register(disc) - nodes.register(kern) - nodes.register(penalty) - nodes.register(glue) - nodes.register(glue_spec) - - local copy = node.copy - - function nodes.penalty(p) - local n = copy(penalty) - n.penalty = p - return n - end - function nodes.kern(k) - local n = copy(kern) - n.kern = k - return n - end - function nodes.glue(width,stretch,shrink) - local n = copy(glue) - local s = copy(glue_spec) - s.width, s.stretch, s.shrink = width, stretch, shrink - n.spec = s - return n - end - function nodes.glue_spec(width,stretch,shrink) - local s = copy(glue_spec) - s.width, s.stretch, s.shrink = width, stretch, shrink - return s - end - - function nodes.disc() - return copy(disc) - end - - function nodes.pdfliteral(str) - local t = copy(pdfliteral) - t.data = str - return t - end - - end - -end - -if tex then - - function tex.node_mem_status() - -- todo: lpeg - local s = status.node_mem_usage - local t = { } - for n, tag in s:gmatch("(%d+) ([a-z_]+)") do - t[tag] = n - end - return t - end - -end diff --git a/tex/context/base/luat-tmp.lua b/tex/context/base/luat-tmp.lua index 438378b41..916d82491 100644 --- a/tex/context/base/luat-tmp.lua +++ b/tex/context/base/luat-tmp.lua @@ -360,7 +360,7 @@ function input.aux.load_data(instance,pathname,dataname,filename) end end --- we will make a better format, maybe something xml or just text +-- we will make a better format, maybe something xml or just text or lua input.automounted = input.automounted or { } diff --git a/tex/context/base/luat-tre.lua b/tex/context/base/luat-tre.lua new file mode 100644 index 000000000..e749a5b33 --- /dev/null +++ b/tex/context/base/luat-tre.lua @@ -0,0 +1,45 @@ +-- filename : luat-tre.lua +-- comment : companion to luat-lib.tex +-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL +-- copyright: PRAGMA ADE / ConTeXt Development Team +-- license : see context related readme files + +if not versions then versions = { } end versions['luat-tre'] = 1.001 + +-- \input tree://oeps1/**/oeps.tex + +do + + local done, found = { }, { } + + function input.finders.tree(instance,specification,filetype) + local fnd = found[specification] + if not fnd then + local spec = input.splitmethod(specification).path or "" + if spec ~= "" then + local path, name = file.dirname(spec), file.basename(spec) + if path == "" then path = "." end + local hash = done[path] + if not hash then + local pattern = path .. "/*" -- we will use the proper splitter + hash = dir.glob(pattern) + done[path] = hash + end + local pattern = "/" .. name:gsub("([%.%-%+])", "%%%1") .. "$" + for k, v in pairs(hash) do + if v:find(pattern) then + found[specification] = v + return v + end + end + end + fnd = unpack(input.finders.notfound) + found[specification] = fnd + end + return fnd + end + + input.openers.tree = input.openers.generic + input.loaders.tree = input.loaders.generic + +end diff --git a/tex/context/base/luat-zip.lua b/tex/context/base/luat-zip.lua index c5a63aeed..91279cfe0 100644 --- a/tex/context/base/luat-zip.lua +++ b/tex/context/base/luat-zip.lua @@ -19,80 +19,117 @@ if not zip.supported then function zip.openarchive (...) return nil end -- needed ? function zip.closenarchive (...) end -- needed ? - function input.registerzipfile (...) end -- needed ? function input.usezipfile (...) end -- needed ? else - function input.locators.zip(instance,specification) - local name, spec = specification:match("^(.-)##(.-)$") - local f = io.open(name or specification) - if f then -- todo: reuse code - input.logger('! zip locator', specification..' found') - if name and spec then - input.aux.append_hash(instance,'zip',"zip##"..specification,name) - input.aux.extend_texmf_var(instance, "zip##"..specification) + -- zip:///oeps.zip?name=bla/bla.tex + -- zip:///oeps.zip?tree=tex/texmf-local + + local function validzip(str) + if not str:find("^zip://") then + return "zip:///" .. str + else + return str + end + end + + zip.archives = { } + zip.registeredfiles = { } + + function zip.openarchive(instance,name) + if not name or name == "" then + return nil + else + local arch = zip.archives[name] + if arch then + return arch else - input.aux.append_hash(instance,'zip',"zip##"..specification.."##",specification) - input.aux.extend_texmf_var(instance, "zip##"..specification.."##") + local full = input.find_file(instance,name) or "" + local arch = (full ~= "" and zip.open(full)) or false + zip.archives[name] = arch + return arch end - f:close() + end + end + + function zip.closearchive(instance,name) + if not name or name == "" and zip.archives[name] then + zip.close(zip.archives[name]) + zip.archives[name] = nil + end + end + + -- zip:///texmf.zip?tree=/tex/texmf + -- zip:///texmf.zip?tree=/tex/texmf-local + -- zip:///texmf-mine.zip?tree=/tex/texmf-projects + + function input.locators.zip(instance,specification) -- where is this used? startup zips (untested) + specification = input.splitmethod(specification) + local zipfile = specification.path + local zfile = zip.openarchive(instance,name) -- tricky, could be in to be initialized tree + if zfile then + input.logger('! zip locator', specification.original ..' found') else - input.logger('? zip locator', specification..' not found') + input.logger('? zip locator', specification.original ..' not found') end end function input.hashers.zip(instance,tag,name) input.report("loading zip file",name,"as",tag) - input.registerzipfile(instance,name,tag) + input.usezipfile(instance,tag .."?tree=" .. name) end function input.concatinators.zip(tag,path,name) - return tag .. path .. '/' .. name + if not path or path == "" then + return tag .. '?name=' .. name + else + return tag .. '?name=' .. path .. "/" .. name + end end function input.is_readable.zip(name) return true end - function input.finders.zip(instance,filename,filetype) - local archive, dataname = filename:match("^(.+)##/*(.+)$") - if archive and dataname then - local zfile = zip.openarchive(archive) - if not zfile then - archive = input.find_file(instance,archive,filetype) - zfile = zip.openarchive(archive) - end - if zfile then - input.logger('! zip finder',archive) - local dfile = zfile:open(dataname) - if dfile then - dfile = zfile:close() - input.logger('+ zip finder',filename) - return 'zip##' .. filename + function input.finders.zip(instance,specification,filetype) + specification = input.splitmethod(specification) + if specification.path then + local q = url.query(specification.query) + if q.name then + local zfile = zip.openarchive(instance,specification.path) + if zfile then + input.logger('! zip finder',specification.path) + local dfile = zfile:open(q.name) + if dfile then + dfile = zfile:close() + input.logger('+ zip finder',q.name) + return specification.original + end + else + input.logger('? zip finder',specification.path) end - else - input.logger('? zip finder',archive) end end input.logger('- zip finder',filename) return unpack(input.finders.notfound) end - function input.openers.zip(instance,filename) - if filename and filename ~= "" then - local archive, dataname = filename:match("^(.-)##/*(.+)$") - if archive and dataname then - local zfile= zip.openarchive(archive) + function input.openers.zip(instance,specification) + local zipspecification = input.splitmethod(specification) + if zipspecification.path then + local q = url.query(zipspecification.query) + if q.name then + local zfile = zip.openarchive(instance,zipspecification.path) if zfile then - input.logger('+ zip starter',archive) - local dfile = zfile:open(dataname) + input.logger('+ zip starter',zipspecification.path) + local dfile = zfile:open(q.name) if dfile then - input.show_open(filename) - return input.openers.text_opener(filename,dfile,'zip') + input.show_open(specification) + return input.openers.text_opener(specification,dfile,'zip') end else - input.logger('- zip starter',archive) + input.logger('- zip starter',zipspecification.path) end end end @@ -100,15 +137,15 @@ else return unpack(input.openers.notfound) end - function input.loaders.zip(instance, filename) -- we could use input.openers.zip - if filename and filename ~= "" then - input.logger('= zip loader',filename) - local archive, dataname = filename:match("^(.+)##/*(.+)$") - if archive and dataname then - local zfile = zip.openarchive(archive) + function input.loaders.zip(instance,specification) + specification = input.splitmethod(specification) + if specification.path then + local q = url.query(specification.query) + if q.name then + local zfile = zip.openarchive(instance,specification.path) if zfile then - input.logger('= zip starter',archive) - local dfile = zfile:open(dataname) + input.logger('+ zip starter',specification.path) + local dfile = zfile:open(q.name) if dfile then input.show_load(filename) input.logger('+ zip loader',filename) @@ -117,105 +154,67 @@ else return true, s, #s end else - input.logger('- zip starter',archive) + input.logger('- zip starter',specification.path) end end end input.logger('- zip loader',filename) - return unpack(input.loaders.notfound) - end - - zip.archives = { } - zip.registeredfiles = { } - - function zip.openarchive(name) - if name and name ~= "" and not zip.archives[name] then - zip.archives[name] = zip.open(name) - end - return zip.archives[name] - end - - function zip.closearchive(name) - if zip.archives[name] then - zip.close(archives[name]) - zip.archives[name] = nil - end - end - - -- aparte register maken voor user (register tex / zip), runtime tree register - -- todo: alleen url syntax toestaan - -- user function: also handle zip::name::path - - function input.usezipfile(instance,zipname) -- todo zip:// - zipname = input.normalize_name(zipname) - if not zipname:find("^zip##") then - zipname = "zip##"..zipname - end - input.logger('! zip user','file '..zipname) - if not zipname:find("^zip##(.+)##(.-)$") then - zipname = zipname .. "##" -- dummy spec - end - local tag = zipname - local name = zipname:match("zip##(.+)##.-") - input.aux.prepend_hash(instance,'zip',tag,name) - input.aux.extend_texmf_var(instance, tag) - input.registerzipfile(instance,name,tag) + return unpack(input.openers.notfound) end - function input.registerzipfile(instance,zipname,tag) - if not zip.registeredfiles[zipname] then - input.starttiming(instance) - local z = zip.open(zipname) - if not z then - zipname = input.find_file(instance,zipname) - z = zip.open(zipname) - end + -- zip:///somefile.zip + -- zip:///somefile.zip?tree=texmf-local -> mount + + function input.usezipfile(instance,zipname) + zipname = validzip(zipname) + input.logger('! zip use','file '..zipname) + local specification = input.splitmethod(zipname) + local zipfile = specification.path + if zipfile and not zip.registeredfiles[zipname] then + local tree = url.query(specification.query).tree or "" + input.logger('! zip register','file '..zipname) + local z = zip.openarchive(instance,zipfile) if z then input.logger("= zipfile","registering "..zipname) + input.starttiming(instance) + input.aux.prepend_hash(instance,'zip',zipname,zipfile) + input.aux.extend_texmf_var(instance,zipname) -- resets hashes too zip.registeredfiles[zipname] = z - input.aux.register_zip_file(instance,zipname,tag) + instance.files[zipname] = input.aux.register_zip_file(z,tree or "") + input.stoptiming(instance) else input.logger("? zipfile","unknown "..zipname) end - input.stoptiming(instance) + else + input.logger('! zip register','no file '..zipname) end end - function input.aux.register_zip_file(instance,zipname,tagname) - if zip.registeredfiles[zipname] then - if not tagname:find("^zip##") then - tagname = "zip##" .. tagname - end - local path, name, n = nil, nil, 0 - if not instance.files[tagname] then - instance.files[tagname] = { } - end - local files, filter = instance.files[tagname], "" - local subtree = tagname:match("^zip##.+##(.+)$") - if subtree then - filter = "^"..subtree.."/(.+)/(.-)$" - else - filter = "^(.+)/(.-)$" - end - input.logger('= zip filter',filter) - -- we can consider putting a files.luc in the file - local register = input.aux.register_file - for i, _ in zip.registeredfiles[zipname]:files() do - path, name = i.filename:match(filter) - if path then - if name and name ~= '' then - register(files, name, path) - n = n + 1 - else - -- directory - end - else - register(files, i.filename, '') + function input.aux.register_zip_file(z,tree) + local files, filter = { }, "" + if tree == "" then + filter = "^(.+)/(.-)$" + else + filter = "^"..tree.."/(.+)/(.-)$" + end + input.logger('= zip filter',filter) + local register, n = input.aux.register_file, 0 + for i in z:files() do + local path, name = i.filename:match(filter) + if path then + if name and name ~= '' then + register(files, name, path) n = n + 1 + else + -- directory end + else + register(files, i.filename, '') + n = n + 1 end - input.report(n, 'entries in', zipname) end + input.report('= zip entries',n) + return files end end diff --git a/tex/context/base/lxml-ini.lua b/tex/context/base/lxml-ini.lua index d21ee5e10..0c26e08e4 100644 --- a/tex/context/base/lxml-ini.lua +++ b/tex/context/base/lxml-ini.lua @@ -140,30 +140,29 @@ end xml.originalload = xml.load +--~ function xml.load(filename) +--~ input.starttiming(lxml) +--~ local x = xml.originalload(filename) +--~ input.stoptiming(lxml) +--~ return x +--~ end + function xml.load(filename) input.starttiming(lxml) - local x = xml.originalload(filename) + local xmldata = xml.convert((filename and input.loadtexfile(texmf.instance,filename)) or "") input.stoptiming(lxml) - return x -end - -function lxml.filename(filename) -- some day we will do this in input, first figure out / - return input.find_file(texmf.instance,url.filename(filename)) or "" + return xmldata end function lxml.load(id,filename) - if texmf then - local fullname = lxml.filename(filename) - if fullname ~= "" then - filename = fullname - end - end lxml.loaded[id] = xml.load(filename) return lxml.loaded[id], filename end function lxml.include(id,pattern,attribute,recurse) - xml.include(lxml.id(id),pattern,attribute,recurse,lxml.filename) + input.starttiming(lxml) + xml.include(lxml.id(id),pattern,attribute,recurse,function(name) return (name and input.loadtexfile(texmf.instance,name)) or "" end) + input.stoptiming(lxml) end function lxml.utfize(id) @@ -298,18 +297,34 @@ function lxml.setsetup(id,pattern,setup) end end else - if trace then - texio.write_nl(string.format("lpath pattern -> %s -> %s", pattern, setup)) - end - for rt, dt, dk in xml.elements(lxml.id(id),pattern) do - local dtdk = (dt and dt[dk]) or rt - dtdk.command = setup - if trace then + local a, b = setup:match("^(.+:)(%*)$") + if a and b then + for rt, dt, dk in xml.elements(lxml.id(id),pattern) do + local dtdk = (dt and dt[dk]) or rt local ns, tg = dtdk.rn or dtdk.ns, dtdk.tg - if ns == "" then - texio.write_nl(string.format("lpath matched -> %s -> %s", tg, setup)) - else - texio.write_nl(string.format("lpath matched -> %s:%s -> %s", ns, tg, setup)) + dtdk.command = a .. tg + if trace then + if ns == "" then + texio.write_nl(string.format("lpath matched -> %s -> %s", tg, dtdk.command)) + else + texio.write_nl(string.format("lpath matched -> %s:%s -> %s", ns, tg, dtdk.command)) + end + end + end + else + if trace then + texio.write_nl(string.format("lpath pattern -> %s -> %s", pattern, setup)) + end + for rt, dt, dk in xml.elements(lxml.id(id),pattern) do + local dtdk = (dt and dt[dk]) or rt + dtdk.command = setup + if trace then + local ns, tg = dtdk.rn or dtdk.ns, dtdk.tg + if ns == "" then + texio.write_nl(string.format("lpath matched -> %s -> %s", tg, setup)) + else + texio.write_nl(string.format("lpath matched -> %s:%s -> %s", ns, tg, setup)) + end end end end diff --git a/tex/context/base/lxml-ini.tex b/tex/context/base/lxml-ini.tex index 1d605f857..a1a6cd905 100644 --- a/tex/context/base/lxml-ini.tex +++ b/tex/context/base/lxml-ini.tex @@ -21,7 +21,7 @@ \def\xmlloadbuffer #1#2{\ctxlua{lxml.loadbuffer("#1","#2")}} \def\xmlutfize #1{\ctxlua{lxml.utfize("#1")}} \def\xmlfirst #1#2{\ctxlua{lxml.first("#1","#2")}} -\def\xmllast #1#2{\ctxlua{lxml.last("#1","#2")}} +\def\xmllast #1#2{\ctxlua{lxml.last("#1","#2")}} \def\xmlall #1#2{\ctxlua{lxml.all("#1","#2")}} \def\xmlfilter #1#2{\ctxlua{lxml.filter("#1","#2")}} \def\xmlcommand #1#2#3{\ctxlua{lxml.command("#1","#2","#3")}} @@ -51,9 +51,18 @@ \def\xmlremapname #1#2#3#4{\ctxlua{xml.remapname(lxml.id("#1"),"#2","#3","#4")}} % element \def\xmlremapnamespace#1#2#3{\ctxlua{xml.rename_space(lxml.id("#1"),"#2","#3")}} % document \def\xmldelete #1#2{\ctxlua{xml.delete(lxml.id("#1"),"#2")}} -\def\xmlinclude #1#2#3{\ctxlua{lxml.include("#1","#2","#3",true)}} +\def\xmlinclude #1#2#3{\ctxlua{lxml.include(lxml.id("#1"),"#2","#3",true)}} \def\xmldoifelse #1#2{\ctxlua{cs.testcase(xml.found(lxml.id("#1"),"#2",false))}} \def\xmldoifelsetext #1#2{\ctxlua{cs.testcase(xml.found(lxml.id("#1"),"#2",true ))}} +\def\xmlverbatim #1{\ctxlua{lxml.verbatim(lxml.id("#1"))}} + +\def\xmldoifelse #1#2{\ctxlua{commands.doifelse(xml.found(lxml.id("#1"),"#2",false))}} +\def\xmldoifelsetext #1#2{\ctxlua{commands.doifelse(xml.found(lxml.id("#1"),"#2",true ))}} +\def\xmldoif #1#2{\ctxlua{commands.doif (xml.found(lxml.id("#1"),"#2",false))}} +\def\xmldoiftext #1#2{\ctxlua{commands.doif (xml.found(lxml.id("#1"),"#2",true ))}} +\def\xmldoifnot #1#2{\ctxlua{commands.doifnot (xml.found(lxml.id("#1"),"#2",false))}} +\def\xmldoifnottext #1#2{\ctxlua{commands.doifnot (xml.found(lxml.id("#1"),"#2",true ))}} + % \startxmlsetups xml:include % \xmlinclude{main}{include}{filename|href} @@ -75,7 +84,7 @@ \let\xmlregistersetup\xmlappendsetup \def\xmlregisteredsetups - {\the\registeredxmlsetups} + {\the\registeredxmlsetups\registeredxmlsetups\emptytoks} \def\doxmlprocess#1#2#3#4% {\begingroup diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua index 0a038989e..cfe28a09f 100644 --- a/tex/context/base/math-ini.lua +++ b/tex/context/base/math-ini.lua @@ -92,8 +92,8 @@ end function mathematics.mathaccent(class,family,slot) return ("\\omathaccent\"%X%02X%04X"):format(class,family,slot) end -function mathematics.delimiter(class,family,slot) - return ("\\odelimiter\"%X%02X%04X"):format(class,family,slot) +function mathematics.delimiter(class,family,slot,largefamily,largeslot) + return ("\\odelimiter\"%X%02X%04X\"%02X%04X"):format(class,family,slot,largefamily,largeslot) end function mathematics.mathchardef(name,class,family,slot) -- we can avoid this one return ("\\omathchardef\\%s\"%X%02X%04X"):format(name,class,family,slot) @@ -149,6 +149,7 @@ function mathematics.define() end for k,v in pairs(characters.data) do local m = v.mathclass + -- i need to clean this up a bit if m then local c = v.mathname if c == false then @@ -162,13 +163,19 @@ function mathematics.define() mathematics.setmathcharacter(k,m,f,i,fe,ie) end else - if not c then - -- fallback - c = v.contextname - else - -- math specific command - end - if c then + if v.contextname then + local s = slots[k] + local c = v.contextname + if s then + local f, i, fe, ie = s[1], s[2], s[3], s[4] + if mathematics.trace then + trace(k,c,f,i,fe,ie) + end + -- todo: mathortext + -- mathematics.setmathsymbol(c,m,f,i,fe,ie,k) + mathematics.setmathcharacter(k,m,f,i,fe,ie) + end + elseif c then local s = slots[k] if s then local f, i, fe, ie = s[1], s[2], s[3], s[4] diff --git a/tex/context/base/meta-pdf.lua b/tex/context/base/meta-pdf.lua index 8e53c1883..64c886950 100644 --- a/tex/context/base/meta-pdf.lua +++ b/tex/context/base/meta-pdf.lua @@ -115,9 +115,9 @@ function mptopdf.steps.convert() mptopdf.data = mptopdf.data:gsub("%s*([^%a]-)%s*(%a+)", function(args,cmd) if cmd == "textext" then t = mptopdf.texts[tonumber(args)] - return "mp.textext(" .. "\"" .. t[2] .. "\"," .. t[3] .. ",\"" .. t[1] .. "\")\n" + return "mps.textext(" .. "\"" .. t[2] .. "\"," .. t[3] .. ",\"" .. t[1] .. "\")\n" else - return "mp." .. cmd .. "(" .. args:gsub(" +",",") .. ")\n" + return "mps." .. cmd .. "(" .. args:gsub(" +",",") .. ")\n" end end) end @@ -229,37 +229,37 @@ end -- mp interface -mp = { } +mps = mps or { } -function mp.creator(a, b, c) +function mps.creator(a, b, c) mptopdf.version = tonumber(b) end -function mp.creationdate(a) +function mps.creationdate(a) mptopdf.date= a end -function mp.newpath() +function mps.newpath() mptopdf.stack.path = { } end -function mp.boundingbox(llx, lly, urx, ury) +function mps.boundingbox(llx, lly, urx, ury) mptopdf.texcode("\\MPSboundingbox{" .. llx .. "}{" .. lly .. "}{" .. urx .. "}{" .. ury .. "}") end -function mp.moveto(x,y) +function mps.moveto(x,y) mptopdf.stack.path[#mptopdf.stack.path+1] = {x,y,"m"} end -function mp.curveto(ax, ay, bx, by, cx, cy) +function mps.curveto(ax, ay, bx, by, cx, cy) mptopdf.stack.path[#mptopdf.stack.path+1] = {ax,ay,bx,by,cx,cy,"c"} end -function mp.lineto(x,y) +function mps.lineto(x,y) mptopdf.stack.path[#mptopdf.stack.path+1] = {x,y,"l"} end -function mp.rlineto(x,y) +function mps.rlineto(x,y) local dx, dy = 0, 0 if #mptopdf.stack.path > 0 then dx, dy = mptopdf.stack.path[#mptopdf.stack.path][1], mptopdf.stack.path[#mptopdf.stack.path][2] @@ -267,72 +267,72 @@ function mp.rlineto(x,y) mptopdf.stack.path[#mptopdf.stack.path+1] = {dx,dy,"l"} end -function mp.translate(tx,ty) +function mps.translate(tx,ty) mptopdf.pdfcode("1 0 0 0 1 " .. tx .. " " .. ty .. " cm") end -function mp.scale(sx,sy) +function mps.scale(sx,sy) mptopdf.stack.concat = {sx,0,0,sy,0,0} end -function mp.concat(sx, rx, ry, sy, tx, ty) +function mps.concat(sx, rx, ry, sy, tx, ty) mptopdf.stack.concat = {sx,rx,ry,sy,tx,ty} end -function mp.setlinejoin(d) +function mps.setlinejoin(d) mptopdf.pdfcode(d .. " j") end -function mp.setlinecap(d) +function mps.setlinecap(d) mptopdf.pdfcode(d .. " J") end -function mp.setmiterlimit(d) +function mps.setmiterlimit(d) mptopdf.pdfcode(d .. " M") end -function mp.gsave() +function mps.gsave() mptopdf.pdfcode("q") end -function mp.grestore() +function mps.grestore() mptopdf.pdfcode("Q") end -function mp.setdash(...) +function mps.setdash(...) local n = select("#",...) mptopdf.pdfcode("[" .. table.concat({...}," ",1,n-1) .. "] " .. select(n,...) .. " d") end -function mp.resetdash() +function mps.resetdash() mptopdf.pdfcode("[ ] 0 d") end -function mp.setlinewidth(d) +function mps.setlinewidth(d) mptopdf.pdfcode(d .. " w") end -function mp.closepath() +function mps.closepath() mptopdf.stack.close = true end -function mp.fill() +function mps.fill() mptopdf.flushpath('f') end -function mp.stroke() +function mps.stroke() mptopdf.flushpath('S') end -function mp.both() +function mps.both() mptopdf.flushpath('B') end -function mp.clip() +function mps.clip() mptopdf.flushpath('W n') end -function mp.textext(font, scale, str) -- old parser +function mps.textext(font, scale, str) -- old parser local dx, dy = 0, 0 if #mptopdf.stack.path > 0 then dx, dy = mptopdf.stack.path[1][1], mptopdf.stack.path[1][2] @@ -342,7 +342,7 @@ function mp.textext(font, scale, str) -- old parser mptopdf.resetpath() end ---~ function mp.handletext(font,scale.str,dx,dy) +--~ function mps.handletext(font,scale.str,dx,dy) --~ local one, two = string.match(str, "^(%d+)::::(%d+)") --~ if one and two then --~ mptopdf.texcode("\\MPTOPDFtextext{"..font.."}{"..scale.."}{"..one.."}{"..two.."}{"..dx.."}{"..dy.."}") @@ -357,7 +357,7 @@ if false and ctx and ctx.aux and ctx.aux.definecolor then -- does not work due to Q-q mess-up - function mp.setrgbcolor(r,g,b) -- extra check + function mps.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.1 then -- g is extra check mptopdf.texcode("\\doresetattribute{transparency}\\MPSspecial{" .. g*10000 .. "}{" .. b*10000 .. "}") @@ -368,17 +368,17 @@ if false and ctx and ctx.aux and ctx.aux.definecolor then end end - function mp.setcmykcolor(c,m,y,k) + function mps.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) + function mps.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 + function mps.setrgbcolor(r,g,b) -- extra check r, g = tonumber(r), tonumber(g) -- needed when we use lpeg if r == 0.0123 and g < 0.1 then mptopdf.texcode("\\MPSspecial{" .. g*10000 .. "}{" .. b*10000 .. "}") @@ -389,68 +389,68 @@ else end end - function mp.setcmykcolor(c,m,y,k) + function mps.setcmykcolor(c,m,y,k) mptopdf.texcode("\\MPScmyk{" .. c .. "}{" .. m .. "}{" .. y .. "}{" .. k .. "}") end - function mp.setgray(s) + function mps.setgray(s) mptopdf.texcode("\\MPSgray{" .. s .. "}") end end -function mp.specials(version,signal,factor) -- 2.0 123 1000 +function mps.specials(version,signal,factor) -- 2.0 123 1000 end -function mp.special(...) -- 7 1 0.5 1 0 0 1 3 +function mps.special(...) -- 7 1 0.5 1 0 0 1 3 local n = select("#",...) mptopdf.texcode("\\MPSbegin\\MPSset{" .. table.concat({...},"}\\MPSset{",2,n) .. "}\\MPSend") end -function mp.begindata() +function mps.begindata() end -function mp.enddata() +function mps.enddata() end -function mp.showpage() +function mps.showpage() end -mp.n = mp.newpath -- n -mp.p = mp.closepath -- h -mp.l = mp.lineto -- l -mp.r = mp.rlineto -- r -mp.m = mp.moveto -- m -mp.c = mp.curveto -- c -mp.hlw = mp.setlinewidth -mp.vlw = mp.setlinewidth +mps.n = mps.newpath -- n +mps.p = mps.closepath -- h +mps.l = mps.lineto -- l +mps.r = mps.rlineto -- r +mps.m = mps.moveto -- m +mps.c = mps.curveto -- c +mps.hlw = mps.setlinewidth +mps.vlw = mps.setlinewidth -mp.C = mp.setcmykcolor -- k -mp.G = mp.setgray -- g -mp.R = mp.setrgbcolor -- rg +mps.C = mps.setcmykcolor -- k +mps.G = mps.setgray -- g +mps.R = mps.setrgbcolor -- rg -mp.lj = mp.setlinejoin -- j -mp.ml = mp.setmiterlimit -- M -mp.lc = mp.setlinecap -- J -mp.sd = mp.setdash -- d -mp.rd = mp.resetdash +mps.lj = mps.setlinejoin -- j +mps.ml = mps.setmiterlimit -- M +mps.lc = mps.setlinecap -- J +mps.sd = mps.setdash -- d +mps.rd = mps.resetdash -mp.S = mp.stroke -- S -mp.F = mp.fill -- f -mp.B = mp.both -- B -mp.W = mp.clip -- W +mps.S = mps.stroke -- S +mps.F = mps.fill -- f +mps.B = mps.both -- B +mps.W = mps.clip -- W -mp.q = mp.gsave -- q -mp.Q = mp.grestore -- Q +mps.q = mps.gsave -- q +mps.Q = mps.grestore -- Q -mp.s = mp.scale -- (not in pdf) -mp.t = mp.concat -- (not the same as pdf anyway) +mps.s = mps.scale -- (not in pdf) +mps.t = mps.concat -- (not the same as pdf anyway) -mp.P = mp.showpage +mps.P = mps.showpage -- experimental -function mp.attribute(id,value) +function mps.attribute(id,value) mptopdf.texcode("\\attribute " .. id .. "=" .. value .. " ") -- mptopdf.texcode("\\dompattribute{" .. id .. "}{" .. value .. "}") end @@ -473,8 +473,8 @@ do -- assumes \let\c\char ) * lpeg.Cc("}") local package = lpeg.Cs(spec + text^0) - function mp.fshow(str,font,scale) -- lpeg parser - mp.textext(font,scale,package:match(str)) + function mps.fshow(str,font,scale) -- lpeg parser + mps.textext(font,scale,package:match(str)) end end @@ -490,83 +490,83 @@ do local cnumber = lpeg.C(number) local cstring = lpeg.C(nonspace) - local specials = (lpeg.P("%%MetaPostSpecials:") * sp * (cstring * sp^0)^0 * eol) / mp.specials - local special = (lpeg.P("%%MetaPostSpecial:") * sp * (cstring * sp^0)^0 * eol) / mp.special - local boundingbox = (lpeg.P("%%BoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mp.boundingbox - local highresboundingbox = (lpeg.P("%%HiResBoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mp.boundingbox + local specials = (lpeg.P("%%MetaPostSpecials:") * sp * (cstring * sp^0)^0 * eol) / mps.specials + local special = (lpeg.P("%%MetaPostSpecial:") * sp * (cstring * sp^0)^0 * eol) / mps.special + local boundingbox = (lpeg.P("%%BoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mps.boundingbox + local highresboundingbox = (lpeg.P("%%HiResBoundingBox:") * sp * (cnumber * sp^0)^4 * eol) / mps.boundingbox local setup = lpeg.P("%%BeginSetup") * (1 - lpeg.P("%%EndSetup") )^1 local prolog = lpeg.P("%%BeginProlog") * (1 - lpeg.P("%%EndProlog"))^1 local comment = lpeg.P('%')^1 * (1 - eol)^1 - local curveto = ((cnumber * sp)^6 * lpeg.P("curveto") ) / mp.curveto - local lineto = ((cnumber * sp)^2 * lpeg.P("lineto") ) / mp.lineto - local rlineto = ((cnumber * sp)^2 * lpeg.P("rlineto") ) / mp.rlineto - local moveto = ((cnumber * sp)^2 * lpeg.P("moveto") ) / mp.moveto - local setrgbcolor = ((cnumber * sp)^3 * lpeg.P("setrgbcolor") ) / mp.setrgbcolor - local setcmykcolor = ((cnumber * sp)^4 * lpeg.P("setcmykcolor") ) / mp.setcmykcolor - local setgray = ((cnumber * sp)^1 * lpeg.P("setgray") ) / mp.setgray - local newpath = ( lpeg.P("newpath") ) / mp.newpath - local closepath = ( lpeg.P("closepath") ) / mp.closepath - local fill = ( lpeg.P("fill") ) / mp.fill - local stroke = ( lpeg.P("stroke") ) / mp.stroke - local clip = ( lpeg.P("clip") ) / mp.clip - local both = ( lpeg.P("gsave fill grestore")) / mp.both + local curveto = ((cnumber * sp)^6 * lpeg.P("curveto") ) / mps.curveto + local lineto = ((cnumber * sp)^2 * lpeg.P("lineto") ) / mps.lineto + local rlineto = ((cnumber * sp)^2 * lpeg.P("rlineto") ) / mps.rlineto + local moveto = ((cnumber * sp)^2 * lpeg.P("moveto") ) / mps.moveto + local setrgbcolor = ((cnumber * sp)^3 * lpeg.P("setrgbcolor") ) / mps.setrgbcolor + local setcmykcolor = ((cnumber * sp)^4 * lpeg.P("setcmykcolor") ) / mps.setcmykcolor + local setgray = ((cnumber * sp)^1 * lpeg.P("setgray") ) / mps.setgray + local newpath = ( lpeg.P("newpath") ) / mps.newpath + local closepath = ( lpeg.P("closepath") ) / mps.closepath + local fill = ( lpeg.P("fill") ) / mps.fill + local stroke = ( lpeg.P("stroke") ) / mps.stroke + local clip = ( lpeg.P("clip") ) / mps.clip + local both = ( lpeg.P("gsave fill grestore")) / mps.both local showpage = ( lpeg.P("showpage") ) - local setlinejoin = ((cnumber * sp)^1 * lpeg.P("setlinejoin") ) / mp.setlinejoin - local setlinecap = ((cnumber * sp)^1 * lpeg.P("setlinecap") ) / mp.setlinecap - local setmiterlimit = ((cnumber * sp)^1 * lpeg.P("setmiterlimit") ) / mp.setmiterlimit - local gsave = ( lpeg.P("gsave") ) / mp.gsave - local grestore = ( lpeg.P("grestore") ) / mp.grestore + local setlinejoin = ((cnumber * sp)^1 * lpeg.P("setlinejoin") ) / mps.setlinejoin + local setlinecap = ((cnumber * sp)^1 * lpeg.P("setlinecap") ) / mps.setlinecap + local setmiterlimit = ((cnumber * sp)^1 * lpeg.P("setmiterlimit") ) / mps.setmiterlimit + local gsave = ( lpeg.P("gsave") ) / mps.gsave + local grestore = ( lpeg.P("grestore") ) / mps.grestore - local setdash = (lpeg.P("[") * (cnumber * sp^0)^0 * lpeg.P("]") * sp * cnumber * sp * lpeg.P("setdash")) / mp.setdash - local concat = (lpeg.P("[") * (cnumber * sp^0)^6 * lpeg.P("]") * sp * lpeg.P("concat") ) / mp.concat - local scale = ( (cnumber * sp^0)^6 * sp * lpeg.P("concat") ) / mp.concat + local setdash = (lpeg.P("[") * (cnumber * sp^0)^0 * lpeg.P("]") * sp * cnumber * sp * lpeg.P("setdash")) / mps.setdash + local concat = (lpeg.P("[") * (cnumber * sp^0)^6 * lpeg.P("]") * sp * lpeg.P("concat") ) / mps.concat + local scale = ( (cnumber * sp^0)^6 * sp * lpeg.P("concat") ) / mps.concat - local fshow = (lpeg.P("(") * lpeg.C((1-lpeg.P(")"))^1) * lpeg.P(")") * space * cstring * space * cnumber * space * lpeg.P("fshow")) / mp.fshow + local fshow = (lpeg.P("(") * lpeg.C((1-lpeg.P(")"))^1) * lpeg.P(")") * space * cstring * space * cnumber * space * lpeg.P("fshow")) / mps.fshow local fshow = (lpeg.P("(") * lpeg.Cs( ( lpeg.P("\\(")/"\\050" + lpeg.P("\\)")/"\\051" + (1-lpeg.P(")")) )^1 ) - * lpeg.P(")") * space * cstring * space * cnumber * space * lpeg.P("fshow")) / mp.fshow + * lpeg.P(")") * space * cstring * space * cnumber * space * lpeg.P("fshow")) / mps.fshow - local setlinewidth_x = (lpeg.P("0") * sp * cnumber * sp * lpeg.P("dtransform truncate idtransform setlinewidth pop")) / mp.setlinewidth - local setlinewidth_y = (cnumber * sp * lpeg.P("0 dtransform exch truncate exch idtransform pop setlinewidth") ) / mp.setlinewidth + local setlinewidth_x = (lpeg.P("0") * sp * cnumber * sp * lpeg.P("dtransform truncate idtransform setlinewidth pop")) / mps.setlinewidth + local setlinewidth_y = (cnumber * sp * lpeg.P("0 dtransform exch truncate exch idtransform pop setlinewidth") ) / mps.setlinewidth - local c = ((cnumber * sp)^6 * lpeg.P("c") ) / mp.curveto -- ^6 very inefficient, ^1 ok too - local l = ((cnumber * sp)^2 * lpeg.P("l") ) / mp.lineto - local r = ((cnumber * sp)^2 * lpeg.P("r") ) / mp.rlineto - local m = ((cnumber * sp)^2 * lpeg.P("m") ) / mp.moveto - local vlw = ((cnumber * sp)^1 * lpeg.P("vlw")) / mp.setlinewidth - local hlw = ((cnumber * sp)^1 * lpeg.P("hlw")) / mp.setlinewidth + local c = ((cnumber * sp)^6 * lpeg.P("c") ) / mps.curveto -- ^6 very inefficient, ^1 ok too + local l = ((cnumber * sp)^2 * lpeg.P("l") ) / mps.lineto + local r = ((cnumber * sp)^2 * lpeg.P("r") ) / mps.rlineto + local m = ((cnumber * sp)^2 * lpeg.P("m") ) / mps.moveto + local vlw = ((cnumber * sp)^1 * lpeg.P("vlw")) / mps.setlinewidth + local hlw = ((cnumber * sp)^1 * lpeg.P("hlw")) / mps.setlinewidth - local R = ((cnumber * sp)^3 * lpeg.P("R") ) / mp.setrgbcolor - local C = ((cnumber * sp)^4 * lpeg.P("C") ) / mp.setcmykcolor - local G = ((cnumber * sp)^1 * lpeg.P("G") ) / mp.setgray + local R = ((cnumber * sp)^3 * lpeg.P("R") ) / mps.setrgbcolor + local C = ((cnumber * sp)^4 * lpeg.P("C") ) / mps.setcmykcolor + local G = ((cnumber * sp)^1 * lpeg.P("G") ) / mps.setgray - local lj = ((cnumber * sp)^1 * lpeg.P("lj") ) / mp.setlinejoin - local ml = ((cnumber * sp)^1 * lpeg.P("ml") ) / mp.setmiterlimit - local lc = ((cnumber * sp)^1 * lpeg.P("lc") ) / mp.setlinecap + local lj = ((cnumber * sp)^1 * lpeg.P("lj") ) / mps.setlinejoin + local ml = ((cnumber * sp)^1 * lpeg.P("ml") ) / mps.setmiterlimit + local lc = ((cnumber * sp)^1 * lpeg.P("lc") ) / mps.setlinecap - local n = lpeg.P("n") / mp.newpath - local p = lpeg.P("p") / mp.closepath - local S = lpeg.P("S") / mp.stroke - local F = lpeg.P("F") / mp.fill - local B = lpeg.P("B") / mp.both - local W = lpeg.P("W") / mp.clip - local P = lpeg.P("P") / mp.showpage + local n = lpeg.P("n") / mps.newpath + local p = lpeg.P("p") / mps.closepath + local S = lpeg.P("S") / mps.stroke + local F = lpeg.P("F") / mps.fill + local B = lpeg.P("B") / mps.both + local W = lpeg.P("W") / mps.clip + local P = lpeg.P("P") / mps.showpage - local q = lpeg.P("q") / mp.gsave - local Q = lpeg.P("Q") / mp.grestore + local q = lpeg.P("q") / mps.gsave + local Q = lpeg.P("Q") / mps.grestore - local sd = (lpeg.P("[") * (cnumber * sp^0)^0 * lpeg.P("]") * sp * cnumber * sp * lpeg.P("sd")) / mp.setdash - local rd = ( lpeg.P("rd")) / mp.resetdash + local sd = (lpeg.P("[") * (cnumber * sp^0)^0 * lpeg.P("]") * sp * cnumber * sp * lpeg.P("sd")) / mps.setdash + local rd = ( lpeg.P("rd")) / mps.resetdash - local s = ( (cnumber * sp^0)^2 * lpeg.P("s") ) / mp.scale - local t = (lpeg.P("[") * (cnumber * sp^0)^6 * lpeg.P("]") * sp * lpeg.P("t") ) / mp.concat + local s = ( (cnumber * sp^0)^2 * lpeg.P("s") ) / mps.scale + local t = (lpeg.P("[") * (cnumber * sp^0)^6 * lpeg.P("]") * sp * lpeg.P("t") ) / mps.concat -- experimental - local attribute = ((cnumber * sp)^2 * lpeg.P("attribute")) / mp.attribute - local A = ((cnumber * sp)^2 * lpeg.P("A")) / mp.attribute + local attribute = ((cnumber * sp)^2 * lpeg.P("attribute")) / mps.attribute + local A = ((cnumber * sp)^2 * lpeg.P("A")) / mps.attribute local preamble = ( prolog + setup + diff --git a/tex/context/base/mult-con.tex b/tex/context/base/mult-con.tex index 7a37869a9..c80911c79 100644 --- a/tex/context/base/mult-con.tex +++ b/tex/context/base/mult-con.tex @@ -1974,6 +1974,10 @@ itemalign: itemuitlijnen itemalign feldoffset offsetpole offsetcampo offsetcamp offsetchamp + action: actie action + aktion akce + azione actiune + action openaction: openactie openaction oeffenaktion otevriakci azioneapri actiunedeschidere @@ -3408,116 +3412,116 @@ nofit: nietpassend nofit %D \stopcompressdefinitions -%D All relevent commands of \CONTEXT\ are specified in a -%D structured way that enables the generation of reference -%D cards. This specification is setup in a language independant -%D way. The next category of variables is only used in this -%D context. - -%D \startcompressdefinitions - -\startsetupvariables dutch english - german czech - italian romanian - french - - enumeration: doornummering enumeration - nummerierung vycet - enumerazione enumerare - enumeration - description: doordefinitie description - beschreibung popis - descrizione descriere - description - indentation: doorsprong indentation - einzug odsazeni - rientro indentare - indentation - labeling: doorlabel labeling - beschriften oznacovani - etichettatura etichetare - etiquettage - combinedlist: samengesteldelijst combinedlist - kombiniereliste kombinovanyseznam - elencocombinato listacombinata - listeimbriquee - % beware: section clashes with sectionlevel - section: sectie section - abschnitt oddil - sezione sectiune - section - register: register register - register rejstrik - registro registru - registre - interaction: interactie interaction - interaktion interakce - interazione interactiune - interaction - synonym: synoniem synonym - synonym synonymum - sinonimo sinonim - synonyme - synonyms: synoniemen synonyms - synonyme synonyma - sinonimi sinonime - synonymes - sort: sorteer sort - sortiere trid - sort sortare - tri - sorts: sorteren sorts - sortieren tridit - sorts sortari - tris - name: naam name - name jmeno - nome nume - name - float: blok float - gleitobjekt plvouciobjekt - oggettomobile obiectmobil - flottant - floats: blokken floats - gleitobjekte plvouciobjekty - oggettimobili obiectemobile - flottants - paragraph: alinea paragraph - absatz odstavec - capoverso paragraf - paragraphe - framedtext: kadertekst framedtext - umrahmtertext oramovanytext - testoincorniciato textinconjurat - texteencadre - itemgroup: itemgroup itemgroup - itemgroup itemgroup - itemgroup itemgroup - itemgroup - typing: typen typing - tippen typing - typing typing - typing - buffer: buffer buffer - puffer buffer - buffer buffer - buffer - formula: formule formula - formel rovnice - formula formula - formule - subformula: subformule subformula - unterformel podrovnice - sottoformula subformula - sousformule - tabulate: tabulatie tabulate - tabulator tabelator - tabulato tabulate - tabule - -\stopsetupvariables - -%D \stopcompressdefinitions +% %D All relevent commands of \CONTEXT\ are specified in a +% %D structured way that enables the generation of reference +% %D cards. This specification is setup in a language independant +% %D way. The next category of variables is only used in this +% %D context. + +% %D \startcompressdefinitions +% +% \startsetupvariables dutch english +% german czech +% italian romanian +% french +% +% enumeration: doornummering enumeration +% nummerierung vycet +% enumerazione enumerare +% enumeration +% description: doordefinitie description +% beschreibung popis +% descrizione descriere +% description +% indentation: doorsprong indentation +% einzug odsazeni +% rientro indentare +% indentation +% labeling: doorlabel labeling +% beschriften oznacovani +% etichettatura etichetare +% etiquettage +% combinedlist: samengesteldelijst combinedlist +% kombiniereliste kombinovanyseznam +% elencocombinato listacombinata +% listeimbriquee +% % beware: section clashes with sectionlevel +% section: sectie section +% abschnitt oddil +% sezione sectiune +% section +% register: register register +% register rejstrik +% registro registru +% registre +% interaction: interactie interaction +% interaktion interakce +% interazione interactiune +% interaction +% synonym: synoniem synonym +% synonym synonymum +% sinonimo sinonim +% synonyme +% synonyms: synoniemen synonyms +% synonyme synonyma +% sinonimi sinonime +% synonymes +% sort: sorteer sort +% sortiere trid +% sort sortare +% tri +% sorts: sorteren sorts +% sortieren tridit +% sorts sortari +% tris +% name: naam name +% name jmeno +% nome nume +% name +% float: blok float +% gleitobjekt plvouciobjekt +% oggettomobile obiectmobil +% flottant +% floats: blokken floats +% gleitobjekte plvouciobjekty +% oggettimobili obiectemobile +% flottants +% paragraph: alinea paragraph +% absatz odstavec +% capoverso paragraf +% paragraphe +% framedtext: kadertekst framedtext +% umrahmtertext oramovanytext +% testoincorniciato textinconjurat +% texteencadre +% itemgroup: itemgroup itemgroup +% itemgroup itemgroup +% itemgroup itemgroup +% itemgroup +% typing: typen typing +% tippen typing +% typing typing +% typing +% buffer: buffer buffer +% puffer buffer +% buffer buffer +% buffer +% formula: formule formula +% formel rovnice +% formula formula +% formule +% subformula: subformule subformula +% unterformel podrovnice +% sottoformula subformula +% sousformule +% tabulate: tabulatie tabulate +% tabulator tabelator +% tabulato tabulate +% tabule +% +% \stopsetupvariables + +% %D \stopcompressdefinitions %D The number of elements used for composing user defined %D commands is rather small. We use a \type{-} for empty diff --git a/tex/context/base/mult-ini.lua b/tex/context/base/mult-ini.lua new file mode 100644 index 000000000..a92561b09 --- /dev/null +++ b/tex/context/base/mult-ini.lua @@ -0,0 +1,56 @@ +if not modules then modules = { } end modules ['mult-ini'] = { + version = 1.001, + comment = "companion to mult-ini.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +interfaces = interfaces or { } +interfaces.messages = interfaces.messages or { } +interfaces.constants = interfaces.constants or { } +interfaces.variables = interfaces.variables or { } + +input.storage.register(false,"interfaces/messages", interfaces.messages, "interfaces.messages" ) +input.storage.register(false,"interfaces/constants", interfaces.constants, "interfaces.constants") +input.storage.register(false,"interfaces/variables", interfaces.variables, "interfaces.variables") + +function interfaces.setmessage(category,str) + local m = interfaces.messages[category] or { } + for k, v in str:gmatch("(%S+) *: *(.-) *[\n\r]") do + m[k] = v:gsub("%-%-","%%s") + end + interfaces.messages[category] = m +end + +function interfaces.getmessage(category,tag) + local m = interfaces.messages[category] + return (m and m[tag]) or "unknown message" +end + +function interfaces.makemessage(category,tag,arguments) + local m = interfaces.messages[category] + m = (m and m[tag] ) or "unknown message" + if not m then + return m .. " " .. tag + elseif not arguments then + return m + elseif arguments:find(",") then + return string.format(m,unpack(arguments:split(","))) + else + return string.format(m,arguments) + end +end + +function interfaces.showmessage(category,tag,arguments) + local m = interfaces.messages[category] + ctx.writestatus((m and m.title) or "unknown title",interfaces.makemessage(category,tag,arguments)) +end + +function interfaces.setvariable(variable,given) + interfaces.variables[given] = variable +end + +function interfaces.setconstant(constant,given) + interfaces.constants[given] = constant +end diff --git a/tex/context/base/mult-ini.mkii b/tex/context/base/mult-ini.mkii new file mode 100644 index 000000000..fff800df1 --- /dev/null +++ b/tex/context/base/mult-ini.mkii @@ -0,0 +1,131 @@ +%D \module +%D [ file=mult-ini, +%D version=1996.06.01, +%D title=\CONTEXT\ Multilingual Macros, +%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. + +\unprotect + +%D This is the oldest variant. Here we filter messages from a big string. + +\def\findinterfacemessage#1#2% + {\let#2\empty + \def\dofindinterfacemessage##1 #1: ##2\relax##3\end{\def#2{##2}}% + \edef\!!stringa{\getvalue{\??ms\currentmessagelibrary} #1: \relax}% + \expandafter\dofindinterfacemessage\!!stringa\end} + +\def\composemessagetext#1--#2--#3--#4--#5--#6--#7--#8--#9\\% + {\def\docomposemessagetext##1,##2,##3,##4,##5,##6,##7,##8,##9\\% + {\edef\currentmessagetext{#1##1#2##2#3##3#4##4#5##5#6##6#7##7#8##8}}% + \docomposemessagetext} + +\def\setmessagetext#1#2% + {\def\currentmessagelibrary{#1}% + \findinterfacemessage{#2}\currentmessagetext} + +\unexpanded\def\getmessage#1#2% + {\def\currentmessagelibrary{#1}% + \findinterfacemessage{#2}\currentmessagetext + \currentmessagetext} + +\unexpanded\def\makemessage#1#2#3% + {\def\currentmessagelibrary{#1}% + \findinterfacemessage{#2}\currentmessagetext + \@EA\composemessagetext\currentmessagetext----------------\\#3,,,,,,,,\\% + \currentmessagetext} + +\def\showmessage#1#2#3% + {\def\currentmessagelibrary{#1}% + \findinterfacemessage{#2}\currentmessagetext + \findinterfacemessage{title}\currentmessagetitle + \ifx\currentmessagetext\empty + \def\currentmessagetext{}% + \else + \@EA\composemessagetext\currentmessagetext----------------\\#3,,,,,,,,\\% + \fi + \@EA\writestatus\@EA{\currentmessagetitle}{\currentmessagetext}} + +\def\doaddinterfacemessage#1#2% + {\findinterfacemessage{#1}\currentmessagetext + \doifelsenothing\currentmessagetext + {\setxvalue{\??ms\currentmessagelibrary}% + {\getvalue{\??ms\currentmessagelibrary} #1: #2\relax}} + {\debuggerinfotrue % we consider this an important error + \debuggerinfo + {message} + {duplicate tag #1 + in library \currentmessagelibrary\space + of interface \currentresponses}}% + \futurelet\next\getinterfacemessage} + +\bgroup +\obeylines +\gdef\addinterfacemessage#1: #2 + {\doaddinterfacemessage{#1}{#2}}% +\egroup + +\def\getinterfacemessage + {\ifx\next\stopmessages + \egroup\expandafter\gobbleoneargument + \else + \expandafter\addinterfacemessage + \fi} + +\let\stopmessages\undefined % for dep checker + +\def\startmessages #1 library: #2 + {\definemessageconstant{#2}% handy for modules + \bgroup + \obeylines + \doifinsetelse{#1}{\currentresponses,all} + {\def\next + {\def\currentmessagelibrary{#2}% + \doifundefined{\??ms\currentmessagelibrary} + {\letgvalueempty{\??ms\currentmessagelibrary}}% + \futurelet\next\getinterfacemessage}} + {\long\def\next##1\stopmessages{\egroup}}% + \next} + +%D Here, the messages are stored in a way that saves hash +%D entries, i.e. they are packed in one macro per library. +%D This was important in the days when we used \TEX's with +%D hash tables of about 10.000. The next, less efficient way +%D of storing the message, makes \CONTEXT\ run upto 5\% +%D faster by storing each message in a macro. In July 2000, +%D this costs some 185 additional hash entries, and since +%D we run large \TEX's, let do it! + +\def\startmessages #1 library: #2 + {\definemessageconstant{#2}% handy for modules + \bgroup + \obeylines + \doifundefined{\m!prefix!#2}{\setgvalue{\m!prefix!#2}{#2}}% + \doifinsetelse{#1}{\currentresponses,all} + {\def\next + {\def\currentmessagelibrary{#2}% + \futurelet\next\getinterfacemessage}} + {\long\def\next##1\stopmessages{\egroup}}% + \next} + +\def\findinterfacemessage#1#2% + {\edef#2{\getvalue{\??ms\currentmessagelibrary#1}}} + +\def\doaddinterfacemessage#1#2% + {\doifdefined{\??ms\currentmessagelibrary#1} + {\debuggerinfotrue % we consider this an important error + \debuggerinfo + {message} + {duplicate tag #1 + in library \currentmessagelibrary\space + of interface \currentresponses}}% + \setxvalue{\??ms\currentmessagelibrary#1}{#2}% + \futurelet\next\getinterfacemessage} + +\protect \endinput diff --git a/tex/context/base/mult-ini.mkiv b/tex/context/base/mult-ini.mkiv new file mode 100644 index 000000000..e785624f5 --- /dev/null +++ b/tex/context/base/mult-ini.mkiv @@ -0,0 +1,41 @@ +%D \module +%D [ file=mult-ini, +%D version=2008.02.15, +%D title=\CONTEXT\ Multilingual Macros, +%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. + +\unprotect + +\registerctxluafile{mult-ini}{1.001} + +\def\startmessages #1 library: #2 % + {\bgroup + \doifundefined{\m!prefix!#2}{\setgvalue{\m!prefix!#2}{#2}}% + \catcode13=\active + \doifinsetelse{#1}{\currentresponses,all}\dostartmessages\nostartmessages{#2}} + +\def\dostartmessages#1#2\stopmessages + {\ctxlua{interfaces.setmessage("#1",[[#2]])}% + \egroup} + +\def\nostartmessages#1#2\stopmessages + {\egroup} + +\unexpanded\def\setmessagetext #1#2{\edef\currentmessagetext{\ctxlua{tex.sprint(tex.ctxcatcodes,interfaces.getmessage("#1","#2"))}}} +\unexpanded\def\getmessage #1#2{\ctxlua{tex.sprint(tex.ctxcatcodes,interfaces.getmessage("#1","#2"))}} +\unexpanded\def\makemessage #1#2#3{\ctxlua{tex.sprint(tex.ctxcatcodes,interfaces.makemessage("#1","#2","#3"))}} +\unexpanded\def\showmessage #1#2#3{\ctxlua{interfaces.showmessage("#1","#2","#3")}} + +%D This way we also have the keywords at the lua end: + +\def\dowithinterfaceconstant#1#2{\ctxlua{interfaces.setconstant("#1","#2")}} +\def\dowithinterfacevariable#1#2{\ctxlua{interfaces.setvariable("#1","#2")}} + +\protect \endinput diff --git a/tex/context/base/mult-ini.tex b/tex/context/base/mult-ini.tex index 68180d372..53a1014c5 100644 --- a/tex/context/base/mult-ini.tex +++ b/tex/context/base/mult-ini.tex @@ -77,8 +77,10 @@ \def\c!prefix!{c!} \def\e!prefix!{e!} \def\f!prefix!{f!} \def\k!prefix!{k!} \def\l!prefix!{l!} \def\m!prefix!{m!} \def\p!prefix!{p!} \def\r!prefix!{r!} \def\s!prefix!{s!} -\def\v!prefix!{v!} \def\x!prefix!{x!} \def\y!prefix!{y!} -\def\t!prefix!{t!} +\def\v!prefix!{v!} \def\t!prefix!{t!} + +% \def\x!prefix!{x!} % obsolete +% \def\y!prefix!{y!} % obsolete %D \macros %D [constants,variables,commands] @@ -381,121 +383,11 @@ %D are a bit more complicated than neccessary. The \NEWLINE\ %D token is used as message separator. %D -%D For internal purposes one can use \type {\dogetmessage}, +%D For internal purposes one can use \type {\setmessagetext}, %D which puts the message text asked for in \type %D {\currentmessagetext}. -\def\findinterfacemessage#1#2% - {\let#2\empty - \def\dofindinterfacemessage##1 #1: ##2\relax##3\end{\def#2{##2}}% - \edef\!!stringa{\getvalue{\??ms\currentmessagelibrary} #1: \relax}% - \expandafter\dofindinterfacemessage\!!stringa\end} - -\def\composemessagetext#1--#2--#3--#4--#5--#6--#7--#8--#9\\% - {\def\docomposemessagetext##1,##2,##3,##4,##5,##6,##7,##8,##9\\% - {\edef\currentmessagetext{#1##1#2##2#3##3#4##4#5##5#6##6#7##7#8##8}}% - \docomposemessagetext} - -\def\dogetmessage#1#2% - {\def\currentmessagelibrary{#1}% - \findinterfacemessage{#2}\currentmessagetext} - -\unexpanded\def\getmessage#1#2% - {\def\currentmessagelibrary{#1}% - \findinterfacemessage{#2}\currentmessagetext - \currentmessagetext} - -\unexpanded\def\makemessage#1#2#3% - {\def\currentmessagelibrary{#1}% - \findinterfacemessage{#2}\currentmessagetext - \@EA\composemessagetext\currentmessagetext----------------\\#3,,,,,,,,\\% - \currentmessagetext} - -\def\showmessage#1#2#3% - {\def\currentmessagelibrary{#1}% - \findinterfacemessage{#2}\currentmessagetext - \findinterfacemessage{title}\currentmessagetitle - \ifx\currentmessagetext\empty - \def\currentmessagetext{}% - \else - \@EA\composemessagetext\currentmessagetext----------------\\#3,,,,,,,,\\% - \fi - \@EA\writestatus\@EA{\currentmessagetitle}{\currentmessagetext}} - -\def\doaddinterfacemessage#1#2% - {\findinterfacemessage{#1}\currentmessagetext - \doifelsenothing\currentmessagetext - {\setxvalue{\??ms\currentmessagelibrary}% - {\getvalue{\??ms\currentmessagelibrary} #1: #2\relax}} - {\debuggerinfotrue % we consider this an important error - \debuggerinfo - {message} - {duplicate tag #1 - in library \currentmessagelibrary\space - of interface \currentresponses}}% - \futurelet\next\getinterfacemessage} - -\bgroup -\obeylines -\gdef\addinterfacemessage#1: #2 - {\doaddinterfacemessage{#1}{#2}}% -\egroup - -\def\getinterfacemessage - {\ifx\next\stopmessages - \egroup\expandafter\gobbleoneargument - \else - \expandafter\addinterfacemessage - \fi} - -\let\stopmessages\undefined % for dep checker - -\def\startmessages #1 library: #2 - {\definemessageconstant{#2}% handy for modules - \bgroup - \obeylines - \doifinsetelse{#1}{\currentresponses,all} - {\def\next - {\def\currentmessagelibrary{#2}% - \doifundefined{\??ms\currentmessagelibrary} - {\letgvalueempty{\??ms\currentmessagelibrary}}% - \futurelet\next\getinterfacemessage}} - {\long\def\next##1\stopmessages{\egroup}}% - \next} - -%D Here, the messages are stored in a way that saves hash -%D entries, i.e. they are packed in one macro per library. -%D This was important in the days when we used \TEX's with -%D hash tables of about 10.000. The next, less efficient way -%D of storing the message, makes \CONTEXT\ run upto 5\% -%D faster by storing each message in a macro. In July 2000, -%D this costs some 185 additional hash entries, and since -%D we run large \TEX's, let do it! - -\def\startmessages #1 library: #2 - {\definemessageconstant{#2}% handy for modules - \bgroup - \obeylines - \doifinsetelse{#1}{\currentresponses,all} - {\def\next - {\def\currentmessagelibrary{#2}% - \futurelet\next\getinterfacemessage}} - {\long\def\next##1\stopmessages{\egroup}}% - \next} - -\def\findinterfacemessage#1#2% - {\edef#2{\getvalue{\??ms\currentmessagelibrary#1}}} - -\def\doaddinterfacemessage#1#2% - {\doifdefined{\??ms\currentmessagelibrary#1} - {\debuggerinfotrue % we consider this an important error - \debuggerinfo - {message} - {duplicate tag #1 - in library \currentmessagelibrary\space - of interface \currentresponses}}% - \setxvalue{\??ms\currentmessagelibrary#1}{#2}% - \futurelet\next\getinterfacemessage} +\loadmarkfile{mult-ini} %D \macros %D {ifshowwarnings, ifshowmessages} @@ -512,6 +404,8 @@ %D Turning off messages also turns off warnings, which is %D quote logical because they are less important. +% not yet mkiv + \newif\ifshowwarnings \showwarningstrue \newif\ifshowmessages \showmessagestrue @@ -1280,20 +1174,35 @@ \def\c!internal!n {-} \let\c!internal! \c!internal!y +% \def\setinterfaceconstant#1#2% +% {\setvalue{\c!prefix!#1}{\c!internal!#1}% +% \doifelse{#2}\nointerfaceobject % ? +% {\debuggerinfo{constant}{#1 defined as #1 by default}% +% }% \setvalue{\k!prefix!#1}{#1}} % was #2 -> #1 +% {\debuggerinfo{constant}{#1 defined as #2}% +% \ifinterfacetranslation +% \setvalue{\x!prefix!#1}{#2}% +% \fi +% \checksetvalue{\k!prefix!#2}{#1}% +% \setvalue{\k!prefix!#2}{#1}}} + +% temporary mkiv hack + +\ifx\dowithinterfaceconstant\undefined \let\dowithinterfaceconstant\gobbletwoarguments \fi +\ifx\dowithinterfacevariable\undefined \let\dowithinterfacevariable\gobbletwoarguments \fi + \def\setinterfaceconstant#1#2% - {\setvalue{\c!prefix!#1}{\c!internal!#1}% + {\dowithinterfaceconstant{#1}{#2}% + \setvalue{\c!prefix!#1}{\c!internal!#1}% \doifelse{#2}\nointerfaceobject % ? - {\debuggerinfo{constant}{#1 defined as #1 by default}% - }% \setvalue{\k!prefix!#1}{#1}} % was #2 -> #1 + {\debuggerinfo{constant}{#1 defined as #1 by default}}% {\debuggerinfo{constant}{#1 defined as #2}% - \ifinterfacetranslation - \setvalue{\x!prefix!#1}{#2}% - \fi \checksetvalue{\k!prefix!#2}{#1}% \setvalue{\k!prefix!#2}{#1}}} \def\setinterfacevariable#1#2% - {\doifelse{#2}\nointerfaceobject + {\dowithinterfacevariable{#1}{#2}% + \doifelse{#2}\nointerfaceobject {\debuggerinfo{variable}{#1 defined as #1 by default}% \checksetvalue{\v!prefix!#1}{#1}% \setvalue{\v!prefix!#1}{#1}} @@ -1330,40 +1239,43 @@ %D in these situations we could use the c||version, but for %D documentation purposes the x||alternative comes in handy. -\def\defineinterfaceconstant#1#2% - {\setvalue{\c!prefix!#1}{#2}% - \ifinterfacetranslation - \setvalue{\x!prefix!#1}{#2}% - \fi} - -%D \macros -%D {startinterfacesetupconstant} -%D -%D The next command, \type{\startinterfacesetupconstant}, which -%D behavior also depends on the boolean, is used for constants -%D that are only needed in these quick reference macro's. The -%D following, more efficient approach does not work here, -%D because it sometimes generates spaces. -%D -%D \starttyping -%D \def\setinterfacesetupconstant -%D {\ifinterfacetranslation -%D \expandafter\setinterfaceconstant -%D \fi} -%D \stoptyping -%D -%D We therefore use the more redundant but robust method: - -\def\setinterfacesetupvariable#1#2% - {\ifinterfacetranslation - \doifelse{#2}\nointerfaceobject - {\setvalue{\y!prefix!#1}{#1}} - {\setvalue{\y!prefix!#1}{#2}}% - \fi} - -\def\startsetupvariables{\startinterfaceobjects\setinterfacesetupvariable\stopsetupvariables} +% \def\defineinterfaceconstant#1#2% +% {\setvalue{\c!prefix!#1}{#2}% +% \ifinterfacetranslation +% \setvalue{\x!prefix!#1}{#2}% +% \fi} -\let\stopsetupvariables\relax +\def\defineinterfaceconstant#1#2% + {\setvalue{\c!prefix!#1}{#2}} + +% %D \macros +% %D {startinterfacesetupconstant} +% %D +% %D The next command, \type{\startinterfacesetupconstant}, which +% %D behavior also depends on the boolean, is used for constants +% %D that are only needed in these quick reference macro's. The +% %D following, more efficient approach does not work here, +% %D because it sometimes generates spaces. +% %D +% %D \starttyping +% %D \def\setinterfacesetupconstant +% %D {\ifinterfacetranslation +% %D \expandafter\setinterfaceconstant +% %D \fi} +% %D \stoptyping +% %D +% %D We therefore use the more redundant but robust method: + +% \def\setinterfacesetupvariable#1#2% +% {\ifinterfacetranslation +% \doifelse{#2}\nointerfaceobject +% {\setvalue{\y!prefix!#1}{#1}} +% {\setvalue{\y!prefix!#1}{#2}}% +% \fi} +% +% \def\startsetupvariables{\startinterfaceobjects\setinterfacesetupvariable\stopsetupvariables} +% +% \let\stopsetupvariables\relax %D \macros %D {startelements} @@ -1432,83 +1344,68 @@ %D %D \stopcommands %D \stoptyping -%D -%D Here we also have to take care of the optional translation -%D needed for reference cards. -% \ifx\doifdefinedascommandelse\undefined -% \let\doifdefinedascommandelse\thirdofthreearguments -% \else -% % this one will be defined in the encoding modules -% \fi +% %D Here we also have to take care of the optional translation +% %D needed for reference cards. + +% \def\setinterfacecommand#1#2% +% {\doifelse{#2}\nointerfaceobject +% {\debuggerinfo{command}{no link to #1}% +% \setinterfacesetupvariable{#1}{#1}} +% {\doifelse{#1}{#2} +% {\debuggerinfo{command}{#1 remains #1}} +% {\doifdefinedelse{#2} +% {\debuggerinfo{command}{core command #2 redefined as #1}}% +% {\debuggerinfo{command}{#2 defined as #1}}% +% %\@EAEAEA\def\@EA\csname\@EA#2\@EA\endcsname\@EA{\csname#1\endcsname}}% +% \@EA\def\csname#2\@EA\endcsname\@EA{\csname#1\endcsname}}% ugly but faster +% \setinterfacesetupvariable{#1}{#2}}} \def\setinterfacecommand#1#2% {\doifelse{#2}\nointerfaceobject - {\debuggerinfo{command}{no link to #1}% - \setinterfacesetupvariable{#1}{#1}} + {\debuggerinfo{command}{no link to #1}} {\doifelse{#1}{#2} {\debuggerinfo{command}{#1 remains #1}} {\doifdefinedelse{#2} {\debuggerinfo{command}{core command #2 redefined as #1}}% {\debuggerinfo{command}{#2 defined as #1}}% - %\@EAEAEA\def\@EA\csname\@EA#2\@EA\endcsname\@EA{\csname#1\endcsname}}% - \@EA\def\csname#2\@EA\endcsname\@EA{\csname#1\endcsname}}% ugly but faster - \setinterfacesetupvariable{#1}{#2}}} + \@EA\def\csname#2\@EA\endcsname\@EA{\csname#1\endcsname}}}} \def\startcommands{\startinterfaceobjects\setinterfacecommand\stopcommands} \let\stopcommands\relax -%D \macros -%D {getinterfaceconstant, getinterfacevariable} -%D -%D Generating the interface translation macro's that are used -%D in the reference lists, is enabled by setting the boolean: -%D -%D \starttyping -%D \interfacetranslationtrue -%D \stoptyping -%D -%D Keep in mind that enabling interfacetranslation costs a -%D bit of hash space. +% %D \macros +% %D {getinterfaceconstant, getinterfacevariable} +% %D +% %D Generating the interface translation macro's that are used +% %D in the reference lists, is enabled by setting the boolean: +% %D +% %D \starttyping +% %D \interfacetranslationtrue +% %D \stoptyping +% %D +% %D Keep in mind that enabling interfacetranslation costs a +% %D bit of hash space. +% +% %D Interface translation is obsolete now that we use an \XML\ +% %D definition base. -\newif\ifinterfacetranslation +% \newif\ifinterfacetranslation -% for a long time: -% % \def\getinterfaceconstant#1% % {\ifinterfacetranslation -% \doifdefinedelse{\x!prefix!#1} -% {\getvalue{\x!prefix!#1}} -% {#1}% +% \executeifdefined{\x!prefix!#1}{#1}% % \else % #1% % \fi} -% + % \def\getinterfacevariable#1% % {\ifinterfacetranslation -% \doifdefinedelse{\y!prefix!#1} -% {\getvalue{\y!prefix!#1}} -% {#1}% +% \executeifdefined{\y!prefix!#1}{#1}% % \else % #1% % \fi} -% -% more compact - -\def\getinterfaceconstant#1% - {\ifinterfacetranslation - \executeifdefined{\x!prefix!#1}{#1}% - \else - #1% - \fi} - -\def\getinterfacevariable#1% - {\ifinterfacetranslation - \executeifdefined{\y!prefix!#1}{#1}% - \else - #1% - \fi} %D When a reference list is generated, one does not need to %D generate a new format. Just reloading the relevant diff --git a/tex/context/base/mult-sys.tex b/tex/context/base/mult-sys.tex index 69381aab3..62d6931d6 100644 --- a/tex/context/base/mult-sys.tex +++ b/tex/context/base/mult-sys.tex @@ -90,6 +90,7 @@ %D As the name of their define command states, the next set of %D constants is used in the message macro's. +\definemessageconstant {check} \definemessageconstant {colors} \definemessageconstant {columns} \definemessageconstant {encodings} @@ -777,7 +778,7 @@ %D And only after this selection is done, we can define %D messages, otherwise the default language is in use. -\ifinterfacetranslation \else +% \ifinterfacetranslation \else % interfacetranslation is obsolete \startmessages dutch library: check title: controle @@ -837,7 +838,7 @@ 3: -- -- remplace une macro, utilisez des MAJUSCULES ! \stopmessages -\fi +% \fi %D Ok, here are some more, because we've got ouselves some %D extensions to \CONTEXT. diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua index 3ca07c16c..195c604d2 100644 --- a/tex/context/base/node-ini.lua +++ b/tex/context/base/node-ini.lua @@ -136,42 +136,43 @@ do nodes.before = node.insert_before -- broken nodes.after = node.insert_after -function nodes.before(h,c,n) - if c then - if c == h then - n.next = h - n.prev = nil - h.prev = n - else - local cp = c.prev - n.next = c - n.prev = cp - if cp then - cp.next = n + function nodes.before(h,c,n) + if c then + if c == h then + n.next = h + n.prev = nil + h.prev = n + else + local cp = c.prev + n.next = c + n.prev = cp + if cp then + cp.next = n + end + c.prev = n + return h, n end - c.prev = n - return h, n end + return n, n end - return n, n -end -function nodes.after(h,c,n) - if c then - local cn = c.next - if cn then - n.next = cn - cn.prev = n - else - n.next = nil - end - c.next = n - n.prev = c - if c ~= h then - return h, n + + function nodes.after(h,c,n) + if c then + local cn = c.next + if cn then + n.next = cn + cn.prev = n + else + n.next = nil + end + c.next = n + n.prev = c + if c ~= h then + return h, n + end end + return n, n end - return n, n -end function nodes.show_list(head, message) if message then @@ -906,3 +907,133 @@ end --~ end --~ end +-- for the moment we put this here: + +do + + nodes.tracers = { } + nodes.tracers.characters = { } + + local glyph, disc = node.id('glyph'), node.id('disc') + + local fontdata = fonts.tfm.id + + local function collect(head,list,tag,n) + n = n or 0 + local ok, fn = false, nil + while head do + local id = head.id + if id == glyph then + local f = head.font + if f ~= fn then + ok, fn = false, f + end + local c = head.char + local d = fontdata[f].characters[c] + local i = (d and d.description.index) or -1 + if not ok then + ok = true + n = n + 1 + list[n] = list[n] or { } + list[n][tag] = { } + end + local l = list[n][tag] + l[#l+1] = { c, f, i } + elseif id == disc then + -- skip + else + ok = false + end + head = head.next + end + end + + function nodes.tracers.characters.equal(ta, tb) + if #ta ~= #tb then + return false + else + for i=1,#ta do + local a, b = ta[i], tb[i] + if a[1] ~= b[1] or a[2] ~= b[2] or a[3] ~= b[3] then + return false + end + end + end + return true + end + function nodes.tracers.characters.string(t) + local tt = { } + for i=1,#t do + tt[i] = utf.char(t[i][1]) + end + return table.concat(tt,"") + end + function nodes.tracers.characters.unicodes(t,decimal) + local tt = { } + for i=1,#t do + if decimal then + tt[i] = t[i][1] + else + tt[i] = string.format("%04X",t[i][1]) + end + end + return table.concat(tt," ") + end + function nodes.tracers.characters.indices(t,decimal) + local tt = { } + for i=1,#t do + if decimal then + tt[i] = t[i][3] + else + tt[i] = string.format("%04X",t[i][3]) + end + end + return table.concat(tt," ") + end + function nodes.tracers.characters.fonts(t) + local f = t[1] and t[1][2] + return (f and file.basename(fontdata[f].filename or "unknown")) or "unknown" + end + + function nodes.tracers.characters.start() + local npc = nodes.process_characters + local list = { } + function nodes.process_characters(head) + local n = #list + collect(head,list,'before',n) + local h, d = npc(head) + collect(head,list,'after',n) + if #list > n then + list[#list+1] = { } + end + return h, d + end + function nodes.tracers.characters.stop() + tracers.list['characters'] = list + lmx.set('title', 'ConTeXt Character Processing Information') + lmx.set('color-background-one', lmx.get('color-background-yellow')) + lmx.set('color-background-two', lmx.get('color-background-purple')) + lmx.show('context-characters.lmx') + lmx.restore() + nodes.process_characters = npc + end + end + + local stack = { } + + function nodes.tracers.start(tag) + stack[#stack+1] = tag + local tracer = nodes.tracers[tag] + if tracer and tracer.start then + tracer.start() + end + end + function nodes.tracers.stop() + local tracer = stack[#stack] + if tracer and tracer.stop then + tracer.stop() + end + stack[#stack] = nil + end + +end diff --git a/tex/context/base/node-ini.tex b/tex/context/base/node-ini.tex index 6b6700e5d..845a62b31 100644 --- a/tex/context/base/node-ini.tex +++ b/tex/context/base/node-ini.tex @@ -43,4 +43,14 @@ \def\visualizenextnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,false,true)}}} \def\visualizeflatnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,true,true)}}} +\def\starttracingnodes[#1]{\ctxlua{nodes.tracers.characters.start("#1")}} +\def\stoptracingnodes {\ctxlua{nodes.tracers.characters.stop()}} + +% \starttext +% \starttracingnodes[characters] +% \input tufte \par +% \input tufte \par +% \stoptracingnodes +% \stoptext + \endinput diff --git a/tex/context/base/page-flt.tex b/tex/context/base/page-flt.tex index 73410380a..0e61a6baa 100644 --- a/tex/context/base/page-flt.tex +++ b/tex/context/base/page-flt.tex @@ -863,6 +863,7 @@ \def\dofloatinfomessage#1#2#3% {\bgroup \showmessage\m!floatblocks{#2}{#3}% + \setmessagetext\m!floatblocks{#2}% \@EA\floatinfo\@EA#1\@EA{\currentmessagetext}% \egroup} @@ -1298,9 +1299,11 @@ % indirect macro can be more efficient \setgvalue{@fl@r@#1}% {\tracefloatnumber{#1}% +\ifconditional\retainfloatnumber\else \dowritetolist{#1}{\getvalue{@fl@n@#1}}{#3}{#1}% \gdefconvertedargument\flasciititle{#3}% \asciititle is global \doifsomething{#2}{\rawreference\s!flt{#2}{{\getvalue{@fl@n@#1}}{\flasciititle}}}% +\fi \letgvalue{@fl@r@#1}\relax}% nils \setgvalue{@fl@t@#1}% {\preparefullnumber{\??kj#1}{\getvalue{@fl@n@#1}}\preparednumber @@ -2073,6 +2076,10 @@ \xdef\naturalfloatwidth {\the\wd#1}% \xdef\naturalfloatdepth {\the\dp#1}} +\def\doifelsemainfloatbody#1#2% + {\ifinsidesplitfloat\ifconditional\splitfloatfirstdone#2\else#1\fi\else#1\fi} + + \long\def\docompletefloat#1#2#3#4#5#6#7% #7 = box number {%\flushsidefloats % moved \presetfloatvariables{#1}{#4}{#2}{#6}% @@ -2090,8 +2097,8 @@ \ifnofloatcaption \global\setbox\floatbox\vbox {\unvbox\floatbox - \vss % gets rid of the depth (unless tabulate) - \rawpagereference\s!flt{#2}}% + \doifelsemainfloatbody{\rawpagereference\s!flt{#2}}\donothing + \vss}% gets rid of the depth (unless tabulate) \egroup \dofloat{#4}{}{#6}% \else @@ -2099,16 +2106,19 @@ \ifnofloatnumber \global\setbox\floatbox\vbox {\unvbox\floatbox % no \vss, keep the depth - \rawreference\s!flt{#2}{{}{\asciititle}}}% + \doifelsemainfloatbody{\rawreference\s!flt{#2}{{}{\asciititle}}}\donothing}% \egroup \dofloat{#4}{}{#6}% \else \preparefloatnumber{#1}% \global\setbox\floatbox\vbox {\unvbox\floatbox % no \vss, keep the depth - \tracefloatnumber{#1}% - \rawreference\s!flt{#2}{{\composedsectionnumber}{\asciititle}}% - \dowritetolist{#3}{\composedsectionnumber}{#6}{#3}}% + \doifelsemainfloatbody + {\tracefloatnumber{#1}% + \rawreference\s!flt{#2}{{\composedsectionnumber}{\asciititle}}% + \dowritetolist{#3}{\composedsectionnumber}{#6}{#3}} + \donothing + }% \egroup \preparefullnumber{\??kj#1}\composedsectionnumber\preparednumber \dofloat{#4}{\labeltexts{#5}{\preparednumber}}{#6}% @@ -2289,14 +2299,16 @@ \unvbox\collectedpagefloats \fi} -\def\flushrestfloats - {\doif\@@bkcache\v!no\doflushsavedfloats} +% \def\flushrestfloats +% {\doif\@@bkcache\v!no\doflushfloats} + +% \let\flushrestfloats\relax \def\dopostponeblock {\bgroup % new may 2004 \setsystemmode\v!postponing % new may 2004 \the\everytopofpage - \flushrestfloats +% \flushrestfloats \flushpagefloats \donefalse \ifinpostponing \else @@ -2340,7 +2352,8 @@ {\realfolio}{\nofpostponedpageblocks}\to\postponedpageblocks \egroup \showmessage\m!layouts3\nofpostponedpageblocks - \dostartbuffer[rbuf-\nofpostponedpageblocks][\e!start\v!postponing][\e!stop\v!postponing]} + \dostartbuffer[rbuf-\nofpostponedpageblocks]% + [\e!start\v!postponing][\e!stop\v!postponing]} \def\dodostartpostponing {\doglobal\increment\nofpostponedblocks diff --git a/tex/context/base/page-ini.tex b/tex/context/base/page-ini.tex index 03d90198a..41cac8dcc 100644 --- a/tex/context/base/page-ini.tex +++ b/tex/context/base/page-ini.tex @@ -1136,7 +1136,7 @@ \hsize\paperwidth \hfill\hbox{\placetestinfo\hskip.5cm}\vss \settexthoffset\hskip\texthoffset % brrrr - %\tlap{\placeversioninfo}\vskip.5cm}} + %\tlap{\placeversioninfo}\vskip.5cm \vbox to 1cm{\vss\placeversioninfo\vss}}} \def\dotestinfo#1#2#3% diff --git a/tex/context/base/page-num.tex b/tex/context/base/page-num.tex index d9f3bcdc0..374cf89ef 100644 --- a/tex/context/base/page-num.tex +++ b/tex/context/base/page-num.tex @@ -94,7 +94,7 @@ \def\savenofsubpages {\ifsubpaging \showmessage\m!layouts6{\newnofsubpages,\the\subpageno}% - \savetwopassdata{\s!subpage}{\newnofsubpages}{\the\subpageno}% + \immediatesavetwopassdata{\s!subpage}{\newnofsubpages}{\the\subpageno}% \fi} \def\setsubpagenumbers diff --git a/tex/context/base/page-one.tex b/tex/context/base/page-one.tex index b0c109a1c..fd4f55387 100644 --- a/tex/context/base/page-one.tex +++ b/tex/context/base/page-one.tex @@ -361,6 +361,9 @@ \ifflushingfloats \else \OTRONEdosettopinserts \OTRONEdosetbotinserts + \ifsomefloatwaiting + \doif\@@bkcache\v!no\doflushfloats + \fi \fi} % \def\OTRONEdotopinsertions diff --git a/tex/context/base/prop-ini.tex b/tex/context/base/prop-ini.tex index b7aef6e18..084842fdd 100644 --- a/tex/context/base/prop-ini.tex +++ b/tex/context/base/prop-ini.tex @@ -29,10 +29,6 @@ % more efficient: \def\currentproperty {\csname\??py:c:\number\propertylevel\endcsname} % string - -% \def\previouspropertylevel{\numexpr(\csname\??py:p:\currentpropertytype\endcsname+1)} -% \letvalue{\??py:p:0}\empty - \def\currentpropertytype {\csname\??py\currentproperty\c!type\endcsname} \def\docheckproperty % watch the s instead of e @@ -74,19 +70,9 @@ \global\advance\previouspropertylevel\minusone \global\advance\propertylevel\minusone} -% \def\propertyparameter #1{\csname\??py\currentproperty#1\endcsname} -% \def\checkedpropertyparameter#1{\executeifdefined{\??py\currentproperty#1}} - \def\defineproperty {\dotripleempty\dodefineproperty} -% \def\dodefineproperty[#1][#2][#3]% global ! ! ! -% {\ifundefined{\??py#1\c!globaal}% -% ... actions ... -% \fi} -% -% since we may perform tests each time before a call, we prefer the faster: - \def\defineproperty {\dotripleempty\dodefineproperty} diff --git a/tex/context/base/prop-mis.tex b/tex/context/base/prop-mis.tex index ed287d044..d78e0c584 100644 --- a/tex/context/base/prop-mis.tex +++ b/tex/context/base/prop-mis.tex @@ -35,14 +35,16 @@ \setupproperty [\s!effect] - [\c!rulethickness=.25pt, - \c!stretch=1] - -\defineproperty [\v!inner] [\s!effect] -\defineproperty [\v!outer] [\s!effect] -\defineproperty [\v!both] [\s!effect] -\defineproperty [\v!normal] [\s!effect] -\defineproperty [\v!hidden] [\s!effect] + [\c!rulethickness=\zeropoint, + \c!stretch=0] + +\defineproperty [\v!inner] [\s!effect] [\c!rulethickness=.25pt] +\defineproperty [\v!outer] [\s!effect] [\c!rulethickness=.25pt] +\defineproperty [\v!both] [\s!effect] [\c!rulethickness=.25pt] +\defineproperty [\v!normal] [\s!effect] +\defineproperty [\v!hidden] [\s!effect] + +\defineproperty [\v!stretch] [\s!effect] [\c!stretch=1] %D Plugin: diff --git a/tex/context/base/s-abr-01.tex b/tex/context/base/s-abr-01.tex index 101d9bcdb..6d984ca31 100644 --- a/tex/context/base/s-abr-01.tex +++ b/tex/context/base/s-abr-01.tex @@ -123,6 +123,7 @@ \logo [KPATHSEA] {kpathsea} \logo [KPSE] {kpse} \logo [KPSEWHICH] {kpsewhich} +\logo [MKTEXLSR] {mktexlsr} \logo [LAMSTEX] {\LamSTeX} \logo [LATEX] {\LaTeX} \logo [LATEXTE] {\LaTeX2e} diff --git a/tex/context/base/s-pre-64.tex b/tex/context/base/s-pre-64.tex index b1204f169..bdc17e18c 100644 --- a/tex/context/base/s-pre-64.tex +++ b/tex/context/base/s-pre-64.tex @@ -131,7 +131,7 @@ \def\StartItem {\blank[line] \begingroup - \EveryPar {\AdaptShape}} + \EveryPar {\AdaptShape}} % beware: \ABBREV aan gegin gaat fout \def\StopItem {\endgraf @@ -161,6 +161,8 @@ {\setuplayer[base][state=repeat] \setlayer[base][preset=rightbottom]{\color[white]{\scale[height=9pt]{\strut#1}}}} +\let\titlefont\relax + \startmode[atpragma] \definefontfeature[default][method=node,script=latn,language=dflt,liga=yes,onum=yes,kern=yes] \definedfont[palatinosanscom-regular*default at 12pt] \setupinterlinespace[line=15pt] diff --git a/tex/context/base/spec-fdf.tex b/tex/context/base/spec-fdf.tex index 754ce4a0f..f55cff7a7 100644 --- a/tex/context/base/spec-fdf.tex +++ b/tex/context/base/spec-fdf.tex @@ -908,8 +908,8 @@ \@EA\processallactionsinset\@EA [#3] [\v!repeat=>\edef\pdf@@actions{\pdf@@actions /Mode /Repeat }]% -\collectdriverresource -% \flushatshipout % since it can be buried in a chained box + \collectdriverresource + %\flushatshipout % since it can be buried in a chained box {\doPDFannotation{0pt}{0pt} {/Subtype /Movie /Border [0 0 0] diff --git a/tex/context/base/syst-ext.tex b/tex/context/base/syst-ext.tex index c63452644..d270f1805 100644 --- a/tex/context/base/syst-ext.tex +++ b/tex/context/base/syst-ext.tex @@ -3826,19 +3826,45 @@ %D Therefore we smuggle a \type {\relax} in front of the %D argument, which we remove afterwards. +% \def\doprocessseparatedlist#1]#2[#3]#4% +% {\def\dodoprocessseparatedlist##1##2#3% +% {\if]##1% +% \let\dodoprocessseparatedlist\relax +% \else\if]##2% +% \let\dodoprocessseparatedlist\relax +% \else\ifx\blankspace##2% +% #4{##1}% +% \else +% #4{##1##2}% +% \fi\fi\fi +% \dodoprocessseparatedlist}% +% \@EA\dodoprocessseparatedlist\gobbleoneargument#1#3]#3} + +% testcase Vit Zyka: +% +% \def\Do#1{(#1)} +% 1\processseparatedlist[{aap noot}] [ ]\Do \par +% 2\processseparatedlist[{aap} {noot}][ ]\Do \par +% 3\processseparatedlist[aap {noot}] [ ]\Do \par +% 4\processseparatedlist[aap noot] [ ]\Do \par +% 5\processseparatedlist[aap;noot;a noot;noot a; noot a noot][;]\Do \par +% 6\processseparatedlist[][;]\Do \par +% 7\processseparatedlist[;][;]\Do \par + \def\doprocessseparatedlist#1]#2[#3]#4% - {\def\dodoprocessseparatedlist##1##2#3% - {\if]##1% - \let\dodoprocessseparatedlist\relax - \else\if]##2% - \let\dodoprocessseparatedlist\relax - \else\ifx\blankspace##2% - #4{##1}% - \else - #4{##1##2}% - \fi\fi\fi - \dodoprocessseparatedlist}% - \@EA\dodoprocessseparatedlist\gobbleoneargument#1#3]#3} + {\def\dodoprocessseparatedlist##1##2#3% + {\def\!!stringa{##2}% suggested by VZ + \if]##1% + \let\dodoprocessseparatedlist\relax + \else\ifx\blankspace\!!stringa + #4{##1}% + \else\if]##2% + \let\dodoprocessseparatedlist\relax + \else + #4{##1##2}% + \fi\fi\fi + \dodoprocessseparatedlist}% + \@EA\dodoprocessseparatedlist\gobbleoneargument#1#3]#3} \def\processseparatedlist[% {\doprocessseparatedlist\relax} diff --git a/tex/context/base/syst-new.tex b/tex/context/base/syst-new.tex index ad5a84178..5d98977ec 100644 --- a/tex/context/base/syst-new.tex +++ b/tex/context/base/syst-new.tex @@ -550,9 +550,9 @@ %D new stuff : \def\partialexpanded#1% - {\let\notexpanded\noexpand + {\let\@@notexpanded\noexpand \long\xdef\@@expanded{\noexpand#1}% - \let\notexpanded\empty + \let\@@notexpanded\empty \@@expanded} % for Simon ; watch how we make them fully expandable (i.e. diff --git a/tex/context/base/syst-xtx.tex b/tex/context/base/syst-xtx.tex index ad8efa0a6..a10173117 100644 --- a/tex/context/base/syst-xtx.tex +++ b/tex/context/base/syst-xtx.tex @@ -25,6 +25,10 @@ \setcclcucx 201C 201C 201C \setcclcucx 201D 201D 201D +% patch needed for greek + +% \setcclcucx 1FFD 1FFD 1FFD + \ifx\XeTeXuseglyphmetrics\undefined \else \XeTeXuseglyphmetrics=1 \fi diff --git a/tex/context/base/toks-ini.tex b/tex/context/base/toks-ini.tex index 48c3d920d..90311eb13 100644 --- a/tex/context/base/toks-ini.tex +++ b/tex/context/base/toks-ini.tex @@ -45,11 +45,13 @@ % % \stoptext -\def\dograbuntil#1#2% - {\long\def\next##1#1{#2##1}\next} - -\def\grabuntil#1% - {\expandafter\dograbuntil\expandafter{\csname#1\endcsname}} +% incompatible with mkii ! ! ! ! so we need other names here +% +% \def\dograbuntil#1#2% +% {\long\def\next##1#1{#2##1}\next} +% +% \def\grabuntil#1% +% {\expandafter\dograbuntil\expandafter{\csname#1\endcsname}} \def\dostartremapper#1% {\ctxlua{collectors.install("#1", "\e!stop#1")}} diff --git a/tex/context/base/type-gyr.tex b/tex/context/base/type-gyr.tex index 3fa266f8e..01d5c8202 100644 --- a/tex/context/base/type-gyr.tex +++ b/tex/context/base/type-gyr.tex @@ -132,6 +132,7 @@ \definefontsynonym [Palatino-BoldSlanted] [Palatino-BoldItalic] \loadmapfile[qpl-\typescriptthree.map] + \unloadmapfile[\typescriptthree-urw-palatino.map] \stoptypescript % TeXGyreTermes @@ -152,6 +153,7 @@ \definefontsynonym [Times-BoldSlanted] [Times-BoldItalic] \loadmapfile[qtm-\typescriptthree.map] + \unloadmapfile[\typescriptthree-urw-times.map] \stoptypescript % TeXGyreHeros @@ -161,7 +163,7 @@ % qtmb TeXGyreHeros-Bold % qtmbi TeXGyreHeros-BoldItalic -\starttypescript [serif] [heros,helvetica] [ec,texnansi,cs,el,qx,rm,t5,t2a,t2b,t2c,l7x] +\starttypescript [sans] [heros,helvetica] [ec,texnansi,cs,el,qx,rm,t5,t2a,t2b,t2c,l7x] \definefontsynonym [Helvetica] [\typescriptthree-qhvr] [encoding=\typescriptthree] \definefontsynonym [Helvetica-Oblique] [\typescriptthree-qhvri] [encoding=\typescriptthree] \definefontsynonym [Helvetica-Bold] [\typescriptthree-qhvb] [encoding=\typescriptthree] @@ -169,6 +171,25 @@ \definefontsynonym [Helvetica-Caps] [\typescriptthree-qhvr-sc] [encoding=\typescriptthree] \loadmapfile[qhv-\typescriptthree.map] + \unloadmapfile[\typescriptthree-urw-helvetica.map] +\stoptypescript + +% TeXGyreCursor +% +% qcrr TeXGyreCursor-Regular +% qcrri TeXGyreCursor-Italic +% qcrb TeXGyreCursor-Bold +% qcrbi TeXGyreCursor-BoldItalic + +\starttypescript [mono] [cursor,courier] [ec,texnansi,cs,el,qx,rm,t5,t2a,t2b,t2c,l7x] + \definefontsynonym [Courier] [\typescriptthree-qcrr] [encoding=\typescriptthree] + \definefontsynonym [Courier-Bold] [\typescriptthree-qcrri] [encoding=\typescriptthree] + \definefontsynonym [Courier-Oblique] [\typescriptthree-qcrb] [encoding=\typescriptthree] + \definefontsynonym [Courier-BoldOblique] [\typescriptthree-qcrbi] [encoding=\typescriptthree] + \fakecontrolspace + + \loadmapfile[qcr-\typescriptthree.map] + \unloadmapfile[\typescriptthree-urw-courier.map] \stoptypescript % TeXGyreBonum @@ -189,6 +210,7 @@ \definefontsynonym [Bookman-DemiBoldSlanted] [Bookman-DemiBoldItalic] \loadmapfile[qbk-\typescriptthree.map] + \unloadmapfile[\typescriptthree-urw-bookman.map] \stoptypescript % TeXGyreScola @@ -209,6 +231,7 @@ \definefontsynonym [Schoolbook-BoldSlanted] [Schoolbook-BoldItalic] \loadmapfile[qcs-\typescriptthree.map] + \unloadmapfile[\typescriptthree-urw-ncntrsbk.map] \stoptypescript % TeXGyreAdventor diff --git a/tex/context/base/type-ini.tex b/tex/context/base/type-ini.tex index a009c37e1..d01b9c73b 100644 --- a/tex/context/base/type-ini.tex +++ b/tex/context/base/type-ini.tex @@ -386,11 +386,9 @@ \setxvalue{\splitoffname \c!state}{3}% \doglobal\removefromcommalist\splitoffname\allfontmapsfiles} -\def\preloadmapfile[#1]% - {\expanded{\processcommalist[#1]}\dopreloadmapfile} - -\def\loadmapfile[#1]% - {\expanded{\processcommalist[#1]}\loadthemapfile} +\def\preloadmapfile[#1]{\expanded{\processcommalist[#1]}\dopreloadmapfile} +\def\loadmapfile [#1]{\expanded{\processcommalist[#1]}\loadthemapfile} +\def\unloadmapfile [#1]{\expanded{\processcommalist[#1]}\unloadthemapfile} % too soon, no driver known, \ifproductionrun \loadallfontmapfiles \fi @@ -416,6 +414,10 @@ \fi \fi +\def\unloadthemapfile#1% + {\splitfiletype{#1}% + \doglobal\removefromcommalist\splitoffname\allfontmapsfiles} + \let\usedmapfile\gobbletwoarguments \let\usedmapline\gobbletwoarguments diff --git a/tex/context/base/type-one.tex b/tex/context/base/type-one.tex index bc0d45027..ae9a9275b 100644 --- a/tex/context/base/type-one.tex +++ b/tex/context/base/type-one.tex @@ -1087,7 +1087,6 @@ % Bookman (URW) - \starttypescript [serif] [bookman] [qx] \definefontsynonym [qx-ubkl8a] [qbkr] [encoding=qx] \definefontsynonym [qx-ubkli8a] [qbkri] [encoding=qx] diff --git a/tex/context/base/type-otf.tex b/tex/context/base/type-otf.tex index cd3fdfa35..2b0a3dbdc 100644 --- a/tex/context/base/type-otf.tex +++ b/tex/context/base/type-otf.tex @@ -637,7 +637,7 @@ \definefontsynonym [Iwona-CapsMedium] [file:IwonaMedium-Regular] [features=smallcaps] \definefontsynonym [Iwona-CapsMedium-Italic] [file:IwonaMedium-Italic] [features=smallcaps] \definefontsynonym [Iwona-CapsHeavy] [file:IwonaHeavy-Regular] [features=smallcaps] - \definefontsynonym [Iwona-CapsHeavy-Italic] [file:IwonaHeavy-Italic] [features=smallcaps] + \definefontsynonym [Iwona-CapsHeavy-Italic] [file:IwonaHeavy-Italic] [features=smallcaps] \definefontsynonym [Iwona-CondRegular] [file:IwonaCond-Regular] [features=default] \definefontsynonym [Iwona-CondItalic] [file:IwonaCond-Italic] [features=default] diff --git a/tex/context/base/x-cals.mkiv b/tex/context/base/x-cals.mkiv index d2281f4d7..5d4a9b573 100644 --- a/tex/context/base/x-cals.mkiv +++ b/tex/context/base/x-cals.mkiv @@ -66,6 +66,10 @@ do end local texsprint = tex.sprint + local xmlsprint = xml.sprint + + --local function texsprint(a,b) print(b) end + --local function xmlsprint(a) print(a) end function lxml.cals.table(root,namespace) @@ -123,7 +127,8 @@ do else texsprint(tex.ctxcatcodes,"\\bTD") end - texsprint(xml.content(dk)) + -- xmlsprint(xml.content(dk)) + xmlsprint(dk) texsprint(tex.ctxcatcodes,"\\eTD") col = col + (s or 1) end @@ -135,6 +140,7 @@ do for r, d, k in xml.elements(lxml.id(root),tgroupspec) do local tgroup = d[k] +-- print(tgroupspec,"!!!!!!!!!!!!!!!!!", r, d, k) lxml.directives.before(root,"cdx") -- "cals:table" texsprint(tex.ctxcatcodes, "\\bgroup") lxml.directives.setup(root,"cdx") -- "cals:table" diff --git a/tex/context/base/x-fig-00.tex b/tex/context/base/x-fig-00.tex index 0559a4056..d293dc39f 100644 --- a/tex/context/base/x-fig-00.tex +++ b/tex/context/base/x-fig-00.tex @@ -76,6 +76,50 @@ %D The special keyword \type {reset} can be used to reset %D this list. +%D We park some mkiv code here. Eventually we will hook this into mkiv +%D searching differently (just a standard feature, no need for loading +%D modules because we need less code). Actually, what we do here is more +%D like res-*: we load the xml file once. + +% \startluacode +% +% document.figurebases = { } +% document.figurebases.data = { } +% document.figurebases.found = { } +% +% function document.figurebases.find(basename,askedlabel) +% document.figurebases.found = { } +% local base = document.figurebases.data[basename] +% local page = 0 +% if not base then +% base = xml.load(basename) +% document.figurebases.data[basename] = base +% end +% for e, d, k in xml.elements(base,"figurelibrary/figure/label") do +% page = page + 1 +% if xml.content(d[k]) == askedlabel then +% document.figurebases.found = { +% name = xml.filters.text(e,"file"), +% page = page, +% } +% return true +% end +% end +% return false +% end +% +% function commands.findfigurefilenameinbase(basename,askedlabel) +% if document.figurebases.find(basename,askedlabel) then +% commands.xdef("figurefilename",document.figurebases.found.name or "") +% commands.xdef("figurefilepage",document.figurebases.found.page or "") +% end +% end +% +% \stopluacode +% +% \def\findfigurefilenameinbase#1#2% +% {\ctxlua{commands.findfigurefilenameinbase("#1","\askedlabel")}} + \startcommands dutch english german czech italian romanian @@ -116,6 +160,9 @@ \xdef\figurefilename{\XMLpop{file}}\endinput}% \egroup} +\def\findfigurefilenameinbase#1#2% sets \figurefilename and \figurefilepage + {\processXMLfilegrouped{#1}} + \def\getfigurefilename#1#2% {\startnointerference \traceXMLelementsfalse @@ -137,8 +184,11 @@ {\ifx\figurefilename\empty \bgroup \xdef\figurefilebasepath{#1}% - \assignfullfilename{#1}\figurefilebase\to\filename - \expanded{\processXMLfilegrouped{\filename.xml}}% + \assignfullfilename{#1}{\figurefilebase}\to\filename + \doiffileelse{\filename.xml} + {\doshowfigurestate{base file : \filename}% + \expanded{\findfigurefilenameinbase{\filename.xml}{\askedlabel}}} + \donothing \ifx\figurefilename\empty\else % \globallet\figurefilebase\figurefilebase \globallet\figurefilebase\filename % hm, bad omen that this is needed @@ -152,69 +202,33 @@ \globalletempty\figurefilebasepath \globalletempty\figurefilepage} -\ifx\doanalyzefiguredimensionsfromfile\undefined - - % will become obsolete once the new core-fig is used - - \let\normalcalculateexternalfigure\calculateexternalfigure - - \def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% - {\resetfigurefilebase - \ifx\figurebaselist\empty - \normalcalculateexternalfigure[#1][#2][#3][#4][#5][#6]% - \else - \def\docommand##1% - {\doshowfigurestate{base : check #3 in ##1}% - \getfigurefilename{##1}{#3}% - \ifx\figurefilename\empty\else\quitcommalist\fi}% - \processcommacommand[\figurebaselist]\docommand - \ifx\figurefilename\empty - \stripspaces\from#3\to\figurefilename % to be sure - \normalcalculateexternalfigure[#1][#2][\figurefilename][#4][#5][#6]% - \else - \doiffileelse{\figurefilebase.pdf} - {\let\figurepathlist\figurefilebasepath - \normalcalculateexternalfigure - [#1][#2][\figurefilebase.pdf]% - [\c!page=\figurefilepage,#4][#5][#6]} - {\@EA\stripspaces\@EA\from\figurefilename\to\figurefilename - \normalcalculateexternalfigure[#1][#2][\figurefilename][#4][#5][#6]}% - \fi - \fi} - -\else - - % todo: use different internal names, \figurebasepage and such - - \def\doanalyzefiguredimensionsfromfile - {\ifcase\figurestatus \ifx\figurebaselist\empty \else - \resetfigurefilebase - \doshowfigurestate{base list : \figurebaselist}% - \processcommacommand[\figurebaselist]\dodoanalyzefiguredimensionsfromfile - \ifx\figurefilename\empty - \doshowfigurestate{base warning : no matching name found}% - \else - \doiffileelse{\figurefilebase.pdf} - {\doshowfigurestate{base file : \figurefilebase.pdf}% - \doshowfigurestate{base page : \figurefilepage}% - \let\figurepathlist\figurefilebasepath - \analyzefigurefilename{\figurefilebase.pdf}\wantedfigurelabel - \let\wantedfigurepage\figurefilepage} - {\doshowfigurestate{base missing : \figurefilebase.pdf}} - \fi - \ifcase\figurestatus - \analyzefigurefilename\expandedfigurename\wantedfigurelabel - \fi - \fi \fi} - - \def\dodoanalyzefiguredimensionsfromfile#1% - {\doshowfigurestate{base check : \wantedfigurename\space in #1}% - \getfigurefilename{#1}\wantedfigurename - \ifx\figurefilename\empty\else - \quitcommalist - \fi} - -\fi +\def\doanalyzefiguredimensionsfromfile + {\ifcase\figurestatus \ifx\figurebaselist\empty \else + \resetfigurefilebase + \doshowfigurestate{base list : \figurebaselist}% + \processcommacommand[\figurebaselist]\dodoanalyzefiguredimensionsfromfile + \ifx\figurefilename\empty + \doshowfigurestate{base warning : no matching name found}% + \else + \doiffileelse{\figurefilebase.pdf} + {\doshowfigurestate{base file : \figurefilebase.pdf}% + \doshowfigurestate{base page : \figurefilepage}% + \let\figurepathlist\figurefilebasepath + \analyzefigurefilename{\figurefilebase.pdf}\wantedfigurelabel + \let\wantedfigurepage\figurefilepage} + {\doshowfigurestate{base missing : \figurefilebase.pdf}} + \fi + \ifcase\figurestatus + \analyzefigurefilename\expandedfigurename\wantedfigurelabel + \fi + \fi \fi} + +\def\dodoanalyzefiguredimensionsfromfile#1% + {\doshowfigurestate{base check : \wantedfigurename\space in #1}% + \getfigurefilename{#1}\wantedfigurename + \ifx\figurefilename\empty\else + \quitcommalist + \fi} \def\usefigurebase[#1]% {\doifelse{#1}\v!reset diff --git a/tex/context/base/x-mmp.mkiv b/tex/context/base/x-mmp.mkiv index 57061fda5..a0fed4bd6 100644 --- a/tex/context/base/x-mmp.mkiv +++ b/tex/context/base/x-mmp.mkiv @@ -82,7 +82,7 @@ -- for i=1,#id.dt do local e = id.dt[i] if type(e) == table then ... for r, d, k in xml.elements(id,"/*") do local e = d[k] - local tag = xml.tag(e) + local tag = e.tg if tag == "mprescripts" then tex.sprint(tex.ctxcatcodes,"{}") done = true @@ -93,7 +93,7 @@ local done, toggle = false, false for r, d, k in xml.elements(id,"/*") do local e = d[k] - local tag = xml.tag(e) + local tag = e.tg if tag == "mprescripts" then break elseif done then diff --git a/tex/context/base/x-res-04.tex b/tex/context/base/x-res-04.tex index 4d4d4dc7b..b5032f550 100644 --- a/tex/context/base/x-res-04.tex +++ b/tex/context/base/x-res-04.tex @@ -207,10 +207,10 @@ \globalletempty\figurefileoriginal \globalletempty\figurefilefile \xdef\figurefilebasepath{#1}% - \assignfullfilename{#1}{\figurefilebase.xml}\to\filename - \doiffileelse\filename + \assignfullfilename{#1}{\figurefilebase}\to\filename + \doiffileelse{\filename.xml} {\doshowfigurestate{base file : \filename}% - \processXMLfilegrouped\filename} + \expanded{\processXMLfilegrouped{\filename.xml}}} \donothing \ifx\figurefilename\empty \else % \global\let\figurefilebase\figurefilebase @@ -236,69 +236,33 @@ \ifx\doshowfigurestate\undefined \let\doshowfigurestate\gobbleoneargument \fi -\ifx\doanalyzefiguredimensionsfromfile\undefined - - % will become obsolete once the new core-fig is used - - \let\normalcalculateexternalfigure\calculateexternalfigure - - \def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% - {\resetfigurefilebase - \ifx\figurebaselist\empty - \normalcalculateexternalfigure[#1][#2][#3][#4][#5][#6]% - \else - \def\docommand##1% - {\doshowfigurestate{base : check #3 in ##1}% - \getfigurefilename{##1}{#3}% - \ifx\figurefilename\empty\else\quitcommalist\fi}% - \processcommacommand[\figurebaselist]\docommand - \ifx\figurefilename\empty - \stripspaces\from#3\to\figurefilename % to be sure - \normalcalculateexternalfigure[#1][#2][\figurefilename][#4][#5][#6]% - \else - \doiffileelse{\figurefilebase.pdf} - {\let\figurepathlist\figurefilebasepath - \normalcalculateexternalfigure - [#1][#2][\figurefilebase.pdf]% - [\c!page=\figurefilepage,#4][#5][#6]} - {\@EA\stripspaces\@EA\from\figurefilename\to\figurefilename - \normalcalculateexternalfigure[#1][#2][\figurefilename][#4][#5][#6]}% - \fi - \fi} - -\else - - % todo: use different internal names, \figurebasepage and such - - \def\doanalyzefiguredimensionsfromfile - {\ifcase\figurestatus \ifx\figurebaselist\empty \else - \resetfigurefilebase - \doshowfigurestate{base list : \figurebaselist}% - \processcommacommand[\figurebaselist]\dodoanalyzefiguredimensionsfromfile - \ifx\figurefilename\empty - \doshowfigurestate{base warning : no matching name found}% - \else - \doiffileelse{\figurefilebase.pdf} - {\doshowfigurestate{base file : \figurefilebase.pdf}% - \doshowfigurestate{base page : \figurefilepage}% - \let\figurepathlist\figurefilebasepath - \analyzefigurefilename{\figurefilebase.pdf}\wantedfigurelabel - \let\wantedfigurepage\figurefilepage} - {\doshowfigurestate{base missing : \figurefilebase.pdf}} - \fi - \ifcase\figurestatus - \analyzefigurefilename\expandedfigurename\wantedfigurelabel - \fi - \fi \fi} - - \def\dodoanalyzefiguredimensionsfromfile#1% - {\doshowfigurestate{base check : \wantedfigurename\space in #1}% - \getfigurefilename{#1}\wantedfigurename - \ifx\figurefilename\empty\else - \quitcommalist - \fi} - -\fi +\def\doanalyzefiguredimensionsfromfile + {\ifcase\figurestatus \ifx\figurebaselist\empty \else + \resetfigurefilebase + \doshowfigurestate{base list : \figurebaselist}% + \processcommacommand[\figurebaselist]\dodoanalyzefiguredimensionsfromfile + \ifx\figurefilename\empty + \doshowfigurestate{base warning : no matching name found}% + \else + \doiffileelse{\figurefilebase.pdf} + {\doshowfigurestate{base file : \figurefilebase.pdf}% + \doshowfigurestate{base page : \figurefilepage}% + \let\figurepathlist\figurefilebasepath + \analyzefigurefilename{\figurefilebase.pdf}\wantedfigurelabel + \let\wantedfigurepage\figurefilepage} + {\doshowfigurestate{base missing : \figurefilebase.pdf}} + \fi + \ifcase\figurestatus + \analyzefigurefilename\expandedfigurename\wantedfigurelabel + \fi + \fi \fi} + +\def\dodoanalyzefiguredimensionsfromfile#1% + {\doshowfigurestate{base check : \wantedfigurename\space in #1}% + \getfigurefilename{#1}\wantedfigurename + \ifx\figurefilename\empty\else + \quitcommalist + \fi} % management diff --git a/tex/context/base/x-set-11.tex b/tex/context/base/x-set-11.tex index e74665761..19ce18a75 100644 --- a/tex/context/base/x-set-11.tex +++ b/tex/context/base/x-set-11.tex @@ -310,11 +310,11 @@ \stopmessages \def\c!setup!internal!#1% - {{\dogetmessage{setup}{#1}% + {{\setmessagetext{setup}{#1}% \expanded{\setupintfont{\currentmessagetext}}}} \def\c!setup!text!#1% - {{\dogetmessage{setup}{#1}% + {{\setmessagetext{setup}{#1}% \setupvarfont{\currentmessagetext}}} \def\c!setup!command!#1% diff --git a/tex/context/interface/keys-cz.xml b/tex/context/interface/keys-cz.xml index 73e54d41b..43ff43c8e 100644 --- a/tex/context/interface/keys-cz.xml +++ b/tex/context/interface/keys-cz.xml @@ -1,6 +1,6 @@ - + @@ -489,6 +489,7 @@ + diff --git a/tex/context/interface/keys-de.xml b/tex/context/interface/keys-de.xml index 05c52afd5..01610a5bd 100644 --- a/tex/context/interface/keys-de.xml +++ b/tex/context/interface/keys-de.xml @@ -1,6 +1,6 @@ - + @@ -489,6 +489,7 @@ + diff --git a/tex/context/interface/keys-en.xml b/tex/context/interface/keys-en.xml index d17639592..9d8356d8a 100644 --- a/tex/context/interface/keys-en.xml +++ b/tex/context/interface/keys-en.xml @@ -1,6 +1,6 @@ - + @@ -489,6 +489,7 @@ + diff --git a/tex/context/interface/keys-fr.xml b/tex/context/interface/keys-fr.xml index 66aefca53..12a7773ca 100644 --- a/tex/context/interface/keys-fr.xml +++ b/tex/context/interface/keys-fr.xml @@ -1,6 +1,6 @@ - + @@ -489,6 +489,7 @@ + diff --git a/tex/context/interface/keys-it.xml b/tex/context/interface/keys-it.xml index 0273a0f65..7366a4988 100644 --- a/tex/context/interface/keys-it.xml +++ b/tex/context/interface/keys-it.xml @@ -1,6 +1,6 @@ - + @@ -489,6 +489,7 @@ + diff --git a/tex/context/interface/keys-nl.xml b/tex/context/interface/keys-nl.xml index 08d0f48d0..f46ea2c3a 100644 --- a/tex/context/interface/keys-nl.xml +++ b/tex/context/interface/keys-nl.xml @@ -1,6 +1,6 @@ - + @@ -489,6 +489,7 @@ + diff --git a/tex/context/interface/keys-ro.xml b/tex/context/interface/keys-ro.xml index a4b84829e..e887f86f3 100644 --- a/tex/context/interface/keys-ro.xml +++ b/tex/context/interface/keys-ro.xml @@ -1,6 +1,6 @@ - + @@ -489,6 +489,7 @@ + diff --git a/tex/context/patterns/lang-agr.pat b/tex/context/patterns/lang-agr.pat index d92d2e17d..122bcda21 100644 --- a/tex/context/patterns/lang-agr.pat +++ b/tex/context/patterns/lang-agr.pat @@ -34,10 +34,11 @@ ο1 υ1 ω1 -α2Ϊ1 -η2Ϊ1 -ω2Ϊ1 +ᾳ1 +ῃ1 +ῳ1 α2ι +α2ί α2ί α2ὶ α2ῖ @@ -49,27 +50,31 @@ α2ἵ α2ἳ α2ἷ +ά3ι ά3ι ᾶ3ι ἀ3ι ἁ3ι α2υ +α2ύ α2ύ α2ὺ α2ῦ α2ὐ α2ὔ -α2psiliὺ +α2ὒ α2ὖ α2ὑ α2ὕ α2ὓ α2ὗ +ά3υ ά3υ ᾶ3υ ἀ3υ ἁ3υ ε2ι +ε2ί ε2ί ε2ὶ ε2ῖ @@ -81,41 +86,47 @@ ε2ἵ ε2ἳ ε2ἷ +έ3ι έ3ι ἐ3ι ἑ3ι ε2υ +ε2ύ ε2ύ ε2ὺ ε2ῦ ε2ὐ ε2ὔ -ε2psiliὺ +ε2ὒ ε2ὖ ε2ὑ ε2ὕ ε2ὓ ε2ὗ +έ3υ έ3υ ἑ3υ ἐ3υ η2υ +η2ύ η2ύ η2ὺ η2ῦ η2ὐ η2ὔ -η2psiliὺ +η2ὒ η2ὖ η2ὑ η2ὕ η2ὓ η2ὗ +ή3υ ή3υ ῆ3υ ἠ3υ ἡ3υ ο2ι +ο2ί ο2ί ο2ὶ ο2ῖ @@ -127,25 +138,29 @@ ο2ἵ ο2ἳ ο2ἷ +ό3ι ό3ι ὀ3ι ὁ3ι ο2υ +ο2ύ ο2ύ ο2ὺ ο2ῦ ο2ὐ ο2ὔ -ο2psiliὺ +ο2ὒ ο2ὖ ο2ὑ ο2ὕ ο2ὓ ο2ὗ +ό3υ ό3υ ὀ3υ ὁ3υ υ2ι +υ2ί υ2ί υ2ὶ υ2ῖ @@ -157,14 +172,17 @@ υ2ἵ υ2ἳ υ2ἷ +ύ3ι ύ3ι ῦ3ι ὐ3ι ὑ3ι ου3ι +όυ4ι όυ4ι ὀυ4ι ὁυ4ι +ο3υί ο3υί ο3υῖ 4β. @@ -185,24 +203,6 @@ 4φ. 4χ. 4ψ. -4oxiaoxia -4βoxiaoxia -4γoxiaoxia -4δoxiaoxia -4ζoxiaoxia -4θoxiaoxia -4κoxiaoxia -4λoxiaoxia -4μoxiaoxia -4νoxiaoxia -4ξoxiaoxia -4πoxiaoxia -4ρoxiaoxia -4σoxiaoxia -4τoxiaoxia -4φoxiaoxia -4χoxiaoxia -4ψoxiaoxia .β4 .γ4 .δ4 @@ -231,7 +231,7 @@ 2ν1ν 2π1π 2ρ1ρ -psili2ρ1dasia2ρ +2ῤ1ῥ 2σ1σ 2τ1τ 2φ1φ @@ -459,296 +459,386 @@ psili2ρ1dasia2ρ 2ψ1τ 2ψ1φ 2ψ1χ -4βδoxiaoxia -4βλoxiaoxia -4βμoxiaoxia -4βνoxiaoxia -4βρoxiaoxia -4γδoxiaoxia -4γλoxiaoxia -4γμoxiaoxia -4γνoxiaoxia -4γρoxiaoxia -4δμoxiaoxia -4δνoxiaoxia -4δρoxiaoxia -4ζβoxiaoxia -4θλoxiaoxia -4λμoxiaoxia -4θνoxiaoxia -4θρoxiaoxia -4κλoxiaoxia -4κμoxiaoxia -4κνoxiaoxia -4κρoxiaoxia -4κτoxiaoxia -4μνoxiaoxia -4πλoxiaoxia -4πμoxiaoxia -4πνoxiaoxia -4πρoxiaoxia -4πτoxiaoxia -4σβoxiaoxia -4σγoxiaoxia -4σδoxiaoxia -4σθoxiaoxia -4σκoxiaoxia -4σμoxiaoxia -4σπoxiaoxia -4στoxiaoxia -4σφoxiaoxia -4σχoxiaoxia -4φθoxiaoxia -4φλoxiaoxia -4φμoxiaoxia -4φνoxiaoxia -4φρoxiaoxia -4χθoxiaoxia -4χλoxiaoxia -4χμoxiaoxia -4χνoxiaoxia -4χρoxiaoxia +ἀγω2ν1άρ ἀγω2ν1άρ ἀγω2ν1αρ +ἀδιέ2ξ1 ἀδιέ2ξ1 ἀδιε2ξ1 +ἀδυ2σ1ώ ἀδυ2σ1ώ ἀδυ2σ1ω +ἁλό2σ1 ἁλό2σ1 ἁλο2σ1 +ἀμπαλί2ν1 ἀμπαλί2ν1 ἀμπαλι2ν1 +ἀμφί2σ1β ἀμφί2σ1β ἀμφι2σ1β +ἀμφί2σ1ω ἀμφί2σ1ω +ἀμφι2σ1ώ ἀμφι2σ1ώ +ἀ2ν1αγής. ἀ2ν1αγής. ἀ2ν1αγὴς. +ἀ2ν1αγήσ. ἀ2ν1αγήσ. ἀ2ν1αγὴσ. ἀ2ν1αγο ἀ2ν1αγεῖ. ἀ2ν1αγῆ. +ἀ2ν1αγές. ἀ2ν1αγές. ἀ2ν1αγὲς. +ἀ2ν1αγέσ. ἀ2ν1αγέσ. ἀ2ν1αγὲσ. ἀ2ν1αγεῖς. ἀ2ν1αγεῖσ. ἀ2ν1αγῶν. +ἀ2ν1αγέσι ἀ2ν1αγέσι ἀ2ν1αγῆ +ἀ2ν1άγκυ ἀ2ν1άγκυ +ἀ2ν1αγκύ ἀ2ν1αγκύ ἄ2ν1αγν +ἀ2ν1άγν ἀ2ν1άγν ἀ2ν1αγν +ἀ3ν2αγνά ἀ3ν2αγνά ἀ3ν2αγνω +ἀ3ν2άγνω ἀ3ν2άγνω +ἀ3ν2αγνώ ἀ3ν2αγνώ +ἀ2ν1αγρί ἀ2ν1αγρί ἀ2ν1αγρῖ ἀ2ν1αγρι +ἀ2ν1άγωγ ἀ2ν1άγωγ +ἀ2ν1αγώγ ἀ2ν1αγώγ +ἀ3ν2αγώγι ἀ3ν2αγώγι +ἀ3ν2αγωγί ἀ3ν2αγωγί +ἀ4ν3αγωγία ἀ4ν3αγωγία +ἀ2ν1άδελ ἀ2ν1άδελ +ἀ2ν1αδέλ ἀ2ν1αδέλ +ἀ2ν1άελπ ἀ2ν1άελπ +ἀ2ν1αέλπ ἀ2ν1αέλπ ἄ2ν1αθλ +ἀ2ν1άθλ ἀ2ν1άθλ +ἀ2ν1αίδ ἀ2ν1αίδ ἀ2ν1αιδ ἄ2ν1αιμ +ἀ2ν1αίμ ἀ2ν1αίμ ἀ2ν1αιμ +ἀ2ν1αίσθ ἀ2ν1αίσθ ἀ2ν1αισθ ἀ2ν1αισι +ἀ2ν1αισί ἀ2ν1αισί +ἀ2ν1αίσχ ἀ2ν1αίσχ ἀ2ν1αισχ +ἀ2ν1αίτ ἀ2ν1αίτ ἀ2ν1αιτ +ἀ2ν1άκαν ἀ2ν1άκαν +ἀ2ν1ακάν ἀ2ν1ακάν +ἀ2ν1ακόλο ἀ2ν1ακόλο ἀ2ν1ακολο ἀ2ν1αλγ ἀ2ν1αλδ ἀ3ν2αλδα +ἀ3ν2αλδήσκ ἀ3ν2αλδήσκ +ἀ2ν1άλειπ ἀ2ν1άλειπ +ἀ2ν1αλείπ ἀ2ν1αλείπ ἀ2ν1αλειφ +ἀ2ν1άλειφ ἀ2ν1άλειφ +ἀ2ν1αλείφ ἀ2ν1αλείφ +ἀ2ν1αλήθ ἀ2ν1αλήθ ἀ2ν1αληθ +ἀ2ν1άλθ ἀ2ν1άλθ ἀ2ν1αλθ +ἀ2ν1άλιπ ἀ2ν1άλιπ +ἀ2ν1αλίπ ἀ2ν1αλίπ +ἀ2ν1άλιστ ἀ2ν1άλιστ +ἀ2ν1αλίστ ἀ2ν1αλίστ ἀ2ν1αλκ ἄ2ν1αλκ +ἀ2ν1άλκ ἀ2ν1άλκ +ἀ2ν1άλλ ἀ2ν1άλλ ἀ2ν1αλλ +ἀ3ν2άλλο ἀ3ν2άλλο +ἀ3ν2άλλε ἀ3ν2άλλε ἄ2ν1αλμ +ἀ2ν1άλμ ἀ2ν1άλμ ἀ2ν1αλμ ἄ2ν1αλο +ἀ2ν1άλου ἀ2ν1άλου +ἀ2ν1άλῳ. ἀ2ν1άλῳ. ἄ2ν1αλε. +ἀ2ν1άλοι ἀ2ν1άλοι +ἀ2ν1άλων. ἀ2ν1άλων. ἄ2ν1αλτ +ἀ2ν1άλτ ἀ2ν1άλτ +ἀ2ν1αμάξ ἀ2ν1αμάξ ἀ2ν1αμαξ +ἀ2ν1αμάρτ ἀ2ν1αμάρτ ἀ2ν1αμαρτ +ἀ2ν1αμέλγ ἀ2ν1αμέλγ ἀ2ν1αμελγ ἀ2ν1αμπ +ἀ2ν1άμπ ἀ2ν1άμπ ἀ2ν1αμφ ἀναμφι2σ1 +ἀ2ν1ανάγκ ἀ2ν1ανάγκ ἀ2ν1αναγκ ἄ2ν1ανδ +ἀ2ν1άνδ ἀ2ν1άνδ ἀ2ν1ανθ +ἀ3ν2ανθέ ἀ3ν2ανθέ +ἀ4ν3ανθές. ἀ4ν3ανθές. ἀ4ν3ανθὲς. +ἀ4ν3ανθέσ. ἀ4ν3ανθέσ. ἀ4ν3ανθὲσ. +ἀ4ν3ανθέσι ἀ4ν3ανθέσι +ἀ2ν1άνιο ἀ2ν1άνιο +ἀ2ν1ανίο ἀ2ν1ανίο +ἀ2ν1ανίω ἀ2ν1ανίω ἀ2ν1ανταγ ἀ2ν1ανταπ +ἀ2ν1αντί ἀ2ν1αντί ἀ2ν1αντι ἀνα2ξ1αγ +ἀνά2ξ1αν ἀνά2ξ1αν +ἀνα2ξ1άν ἀνα2ξ1άν ἀνα2ξ1αν +ἀνά2ξ1αρ ἀνά2ξ1αρ +ἀνα2ξ1άρ ἀνα2ξ1άρ +ἀνά2ξ1ιπ ἀνά2ξ1ιπ +ἀνα2ξ1ίπ ἀνα2ξ1ίπ +ἀ2ν1αξιόλ ἀ2ν1αξιόλ ἀ2ν1αξιολ +ἀ2ν1αξιόπ ἀ2ν1αξιόπ ἀ2ν1αξιοπ +ἀ2ν1άξιο ἀ2ν1άξιο +ἀ2ν1αξίο ἀ2ν1αξίο +ἀ2ν1αξίω ἀ2ν1αξίω +ἀ2ν1αξία ἀ2ν1αξία ἀ2ν1αξῖα +ἀ2ν1απάλλα ἀ2ν1απάλλα +ἀ2ν1απαλλά ἀ2ν1απαλλά +ἀ2ν1απάρτ ἀ2ν1απάρτ ἀ2ν1απαρτ +ἀ2ν1απαύδ ἀ2ν1απαύδ ἀ2ν1απαυδ +ἀ2ν1απόβ ἀ2ν1απόβ ἀ2ν1αποβ +ἀ2ν1απόγ ἀ2ν1απόγ ἀ2ν1απογ +ἀ2ν1αποδή ἀ2ν1αποδή ἀ2ν1αποδη +ἀ2ν1απόδο ἀ2ν1απόδο +ἀ2ν1αποδό ἀ2ν1αποδό +ἀ2ν1απόδρ ἀ2ν1απόδρ ἀ2ν1αποδρ +ἀ2ν1απόλαυ ἀ2ν1απόλαυ +ἀ2ν1απολαύ ἀ2ν1απολαύ +ἀ2ν1απολό ἀ2ν1απολό ἀ2ν1απολο +ἀ2ν1απόλυ ἀ2ν1απόλυ +ἀ2ν1απολύ ἀ2ν1απολύ +ἀ2ν1απόν ἀ2ν1απόν ἀ2ν1απον +ἀ2ν1απόπ ἀ2ν1απόπ ἀ2ν1αποπ +ἀ2ν1απόσ ἀ2ν1απόσ ἀ2ν1αποσ +ἀ2ν1απότε ἀ2ν1απότε ἀ2ν1αποτε +ἀ2ν1απότμ ἀ2ν1απότμ ἀ2ν1αποτμ +ἀ2ν1απότρ ἀ2ν1απότρ ἀ2ν1αποτρ +ἀ2ν1αρά ἀ2ν1αρά ἀ2ν1αρα +ἀ2ν1άρ ἀ2ν1άρ ἀ2ν1αρ ἄ2ν1αρ +ἀ3ν2αρίτ ἀ3ν2αρίτ ἀ3ν2αρῖτ ἀ3ν2αριτ ἀ3ν2αρπ +ἀ3ν2άρρ ἀ3ν2άρρ ἀ3ν2αρρ ἀ4ν3αρραγ ἀ3ν2αρτ +ἀ3ν2αρύτ ἀ3ν2αρύτ +ἀ2ν1άσκη ἀ2ν1άσκη +ἀ2ν1ασκή ἀ2ν1ασκή ἄ2ν1ασπι +ἀ2ν1ασπί ἀ2ν1ασπί +ἀ2ν1άσσατ ἀ2ν1άσσατ +ἀ2ν1ασσάτ ἀ2ν1ασσάτ +ἀ2ν1άστει ἀ2ν1άστει +ἀ2ν1αστεί ἀ2ν1αστεί +ἀ3ν2αστείβ ἀ3ν2αστείβ +ἀ3ν2άστειρ ἀ3ν2άστειρ +ἀ3ν2αστείρ ἀ3ν2αστείρ +ἀ3ν2άστειχ ἀ3ν2άστειχ +ἀ3ν2αστείχ ἀ3ν2αστείχ ἀ2ν1ατεὶ. +ἀ2ν1ατεί. ἀ2ν1ατεί. ἀ2ν1ατὶ. +ἀ2ν1ατί. ἀ2ν1ατί. ἄ2ν1ατος. ἄ2ν1ατοσ. +ἀ2ν1άτου. ἀ2ν1άτου. +ἀ2ν1άτω ἀ2ν1άτω ἄ2ν1ατον. ἄ2ν1ατε ἄ2ν1ατοι. +ἀ2ν1άτοις. ἀ2ν1άτοις. +ἀ2ν1άτοισ. ἀ2ν1άτοισ. +ἀ2ν1άττ ἀ2ν1άττ ἀ2ν1αττ +ἀ2ν1αύγ ἀ2ν1αύγ ἀ2ν1αυγ +ἀ2ν1αύδ ἀ2ν1αύδ ἀ2ν1αυδ +ἀ3ν2αυδί ἀ3ν2αυδί ἀ3ν2αυδι ἄ2ν1αυδ ἄ2ν1αυλ +ἀ2ν1αύλ ἀ2ν1αύλ +ἀ2ν1αύξ ἀ2ν1αύξ ἀ2ν1αυξ +ἀ2ν1αύχ ἀ2ν1αύχ ἀ2ν1αυχ +ἀ2ν1αφαίρ ἀ2ν1αφαίρ ἀ2ν1αφαιρ +ἀ2ν1αφή ἀ2ν1αφή ἀ2ν1αφὴ ἀ2ν1αφοῦ @@ -756,378 +846,616 @@ psili2ρ1dasia2ρ ἀ2ν1αφεῖ ἀ2ν1αφοῖ ἀ2ν1εφῶν. +ἀ2ν1αφέ ἀ2ν1αφέ ἀ2ν1αφὲ ἀ3ν2αφῆν +ἀ2ν1αφρόδ ἀ2ν1αφρόδ ἀ2ν1αφροδ ἄ2ν1αφρ +ἀ2ν1άφρ ἀ2ν1άφρ +ἀ2ν1αχύρ ἀ2ν1αχύρ ἀ2ν1αχυρ +ἀνδρό2σ1α ἀνδρό2σ1α ἀνδρο2σ1α +ἀ2ν1έγγ ἀ2ν1έγγ ἀ2ν1εγγ +ἀ2ν1έγερτ ἀ2ν1έγερτ +ἀ2ν1εγέρτ ἀ2ν1εγέρτ ἀ2ν1εγκ +ἀ2ν1έγκ ἀ2ν1έγκ ἀ2ν1εγχ +ἀ2ν1εδά ἀ2ν1εδά ἀ2ν1εδα +ἀ2ν1έδεσ ἀ2ν1έδεσ +ἀ2ν1εδέσ ἀ2ν1εδέσ +ἀ2ν1έδρασ ἀ2ν1έδρασ +ἀ2ν1εδράσ ἀ2ν1εδράσ +ἀ2ν1εέρ ἀ2ν1εέρ ἀ2ν1εερ +ἀ2ν1εθέλ ἀ2ν1εθέλ ἀ2ν1εθελ +ἀ2ν1έθι ἀ2ν1έθι +ἀ2ν1εθί ἀ2ν1εθί +ἀ2ν1είδε ἀ2ν1είδε +ἀ2ν1ειδέ ἀ2ν1ειδέ +ἀ2ν1είδω ἀ2ν1είδω +ἀ2ν1ειδώ ἀ2ν1ειδώ +ἀ2ν1είκα ἀ2ν1είκα +ἀ2ν1εικά ἀ2ν1εικά +ἀ2ν1εικό ἀ2ν1εικό ἀ2ν1εικο +ἀ2ν1ειλεί ἀ2ν1ειλεί ἀ2ν1ειλει +ἀ2ν1είμα ἀ2ν1είμα +ἀ2ν1εί2σ1ακ ἀ2ν1εί2σ1ακ +ἀ2ν1ει2σ1άκ ἀ2ν1ει2σ1άκ +ἀ2ν1εί2σ1ο ἀ2ν1εί2σ1ο +ἀ2ν1ει2σ1ό ἀ2ν1ει2σ1ό ἀ2ν1ει2σ1φορ +ἀ2ν1εί2σ1φορ ἀ2ν1εί2σ1φορ +ἀ2ν1ει2σ1φόρ ἀ2ν1ει2σ1φόρ +ἀ2ν1έκ ἀ2ν1έκ ἀ2ν1εκ +ἀ3ν2έκα ἀ3ν2έκα +ἀ3ν2εκάς. ἀ3ν2εκάς. ἀ3ν2εκὰς. +ἀ3ν2εκάσ. ἀ3ν2εκάσ. ἀ3ν2εκὰσ. ἀ3ν2εκτ +ἀ4ν3έ2κ1τιτ ἀ4ν3έ2κ1τιτ +ἀ4ν3ε2κ1τίτ ἀ4ν3ε2κ1τίτ ἀνε2κ1λιπ +ἀνε2κ1λό ἀνε2κ1λό ἀνε2κ1λο +ἀ2ν1έλαι ἀ2ν1έλαι ἀ2ν1ελαι +ἀ2ν1ελάτ ἀ2ν1ελάτ ἀ2ν1ελατ +ἀ2ν1έλεγκ ἀ2ν1έλεγκ +ἀ2ν1ελέγκ ἀ2ν1ελέγκ ἀ2ν1ελεγξ +ἀ2ν1ελέη ἀ2ν1ελέη +ἀ2ν1ελεή ἀ2ν1ελεή +ἀ2ν1έλεο ἀ2ν1έλεο +ἀ2ν1ελέο ἀ2ν1ελέο +ἀ2ν1ελέω ἀ2ν1ελέω +ἀ2ν1έλεε ἀ2ν1έλεε +ἀ2ν1ελκή ἀ2ν1ελκή ἀ2ν1ελκὴ ἀ2ν1ελκο ἀ2ν1ελκῆ +ἀ2ν1ελκές. ἀ2ν1ελκές. ἀ2ν1ελκὲς. +ἀ2ν1ελκέσ. ἀ2ν1ελκέσ. ἀ2ν1ελκὲσ. ἀ2ν1ελκε ἀ2ν1ελκῶ +ἀ2ν1ελκέσ ἀ2ν1ελκέσ ἄ2ν1ελκτ +ἀ2ν1έλκτ ἀ2ν1έλκτ +ἀ2ν1έλκω ἀ2ν1έλκω +ἀ2ν1ελκώ ἀ2ν1ελκώ +ἀ2ν1έλλ ἀ2ν1έλλ +ἀ2ν1έλπι ἀ2ν1έλπι +ἀ2ν1ελπί ἀ2ν1ελπί +ἀ2ν1έλυτρ ἀ2ν1έλυτρ +ἀ2ν1ελύτρ ἀ2ν1ελύτρ +ἀ2ν1έμβ ἀ2ν1έμβ ἀ2ν1εμβ +ἀ2ν1έμετ ἀ2ν1έμετ +ἀ2ν1εμέτ ἀ2ν1εμέτ +ἀ2ν1έμπ ἀ2ν1έμπ ἀ2ν1εμπ +ἀ2ν1έμφ ἀ2ν1έμφ ἀ2ν1εμφ +ἀ2ν1έν ἀ2ν1έν ἀ2ν1εν +ἀ3ν2ένει ἀ3ν2ένει +ἀ3ν2ενή ἀ3ν2ενή +ἀ3ν2έντες. ἀ3ν2έντες. +ἀ3ν2έντεσ. ἀ3ν2έντεσ. ἀ2ν1ε2ξ1 +ἀ3ν2ε3ξ2ίκα ἀ3ν2ε3ξ2ίκα +ἀ3ν2ε3ξ2ικά ἀ3ν2ε3ξ2ικά +ἀ2ν1έορ ἀ2ν1έορ +ἀ2ν1εόρ ἀ2ν1εόρ ἀ2ν1επ ἀ3ν2επν ἀ3ν2επτ ἀ2ν1εραστ +ἀ2ν1έραστ ἀ2ν1έραστ +ἀ2ν1εράστ ἀ2ν1εράστ ἀ2ν1εργ ἄ2ν1εργ +ἀ2ν1έργ ἀ2ν1έργ +ἀ2ν1έρεικ ἀ2ν1έρεικ +ἀ2ν1ερείκ ἀ2ν1ερείκ +ἀ2ν1έρεισ ἀ2ν1έρεισ +ἀ2ν1ερείσ ἀ2ν1ερείσ +ἀ2ν1ερεύνητ ἀ2ν1ερεύνητ +ἀ2ν1ερευνήτ ἀ2ν1ερευνήτ +ἀ2ν1ερί ἀ2ν1ερί ἀ2ν1ερι +ἀ2ν1ερυθρίαστ ἀ2ν1ερυθρίαστ +ἀ2ν1ερυθριάστ ἀ2ν1ερυθριάστ +ἀ2ν1έστι ἀ2ν1έστι +ἀ2ν1εστί ἀ2ν1εστί +ἀ2ν1έται ἀ2ν1έται +ἀ2ν1εταί ἀ2ν1εταί +ἀ2ν1έτοι ἀ2ν1έτοι +ἀ2ν1ετοί ἀ2ν1ετοί ἀ2ν1ετυ +ἀ2ν1έτυ ἀ2ν1έτυ +ἀ2ν1ετύ ἀ2ν1ετύ +ἀ2ν1εύθ ἀ2ν1εύθ ἀ2ν1ευθ ἄ2ν1ευκ +ἀ2ν1εύκ ἀ2ν1εύκ ἀ2ν1ευλ +ἀ2ν1εύρετ ἀ2ν1εύρετ +ἀ2ν1ευρέτ ἀ2ν1ευρέτ +ἀ2ν1ευφήμητ ἀ2ν1ευφήμητ +ἀ2ν1ευφημήτ ἀ2ν1ευφημήτ +ἀ2ν1εύχ ἀ2ν1εύχ ἀ2ν1ευχ +ἀ2ν1εύξ ἀ2ν1εύξ ἀ2ν1ευξ ἀ2ν1ηυξ ἀ2ν1ηῦγ ἀ2ν1ηυγ ἀ2ν1ευκτ +ἀ2ν1έφ ἀ2ν1έφ ἀ2ν1εφ +ἀ3ν2εφάλ ἀ3ν2εφάλ +ἀ3ν2έφελ ἀ3ν2έφελ +ἀ3ν2εφέλ ἀ3ν2εφέλ +ἀ2ν1εχέ ἀ2ν1εχέ ἀ2ν1εχε +ἀ2ν1έψα ἀ2ν1έψα +ἀ2ν1εψά ἀ2ν1εψά ἀ2ν1ηγεμ +ἀ2ν1ήδ ἀ2ν1ήδ ἀ2ν1ηδ +ἀ2ν1ήκεσ ἀ2ν1ήκεσ +ἀ2ν1ηκέσ ἀ2ν1ηκέσ +ἀ2ν1ήκο ἀ2ν1ήκο +ἀ2ν1ηκό ἀ2ν1ηκό ἀ2ν1ηκο +ἀ2ν1ηλάκ ἀ2ν1ηλάκ ἀ2ν1ηλακ +ἀ2ν1ήλατος. ἀ2ν1ήλατος. +ἀ2ν1ήλατοσ. ἀ2ν1ήλατοσ. +ἀ2ν1ηλάτου ἀ2ν1ηλάτου +ἀ2ν1ηλάτω ἀ2ν1ηλάτω +ἀ2ν1ήλατον. ἀ2ν1ήλατον. +ἀ2ν1ήλατε. ἀ2ν1ήλατε. +ἀ2ν1ηλάτοι ἀ2ν1ηλάτοι +ἀ2ν1ήλατοι ἀ2ν1ήλατοι +ἀ2ν1ήλατα ἀ2ν1ήλατα ἀ2ν1ηλεγ +ἀ2ν1ηλεή ἀ2ν1ηλεή ἀ2ν1ηλεὴ ἀ2ν1ηλεο ἀ2ν1ηλεε ἀ2ν1ηλεῶ +ἀ2ν1ηλεέ ἀ2ν1ηλεέ ἀ2ν1ηλεὲ ἀ2ν1ηλεῆ +ἀ2ν1ηλέη ἀ2ν1ηλέη +ἀ2ν1ήλειπ ἀ2ν1ήλειπ +ἀ2ν1ηλείπ ἀ2ν1ηλείπ +ἀ2ν1ηλή ἀ2ν1ηλή ἀ2ν1ηλὴ ἀ2ν1ηλοῦ ἀ2ν1ηλεῖ ἀ2ν1ηλῆ +ἀ2ν1ηλέ ἀ2ν1ηλέ ἀ2ν1ηλὲ ἀ2ν1ηλοῖ ἀ2ν1ηλῶ +ἀ2ν1ήλικ ἀ2ν1ήλικ +ἀ2ν1ηλίκ ἀ2ν1ηλίκ +ἀ2ν1ήλιο ἀ2ν1ήλιο +ἀ2ν1ηλίο ἀ2ν1ηλίο +ἀ2ν1ηλίω ἀ2ν1ηλίω +ἀ2ν1ήλια ἀ2ν1ήλια +ἀ2ν1ήλιπ ἀ2ν1ήλιπ +ἀ2ν1ηλίπ ἀ2ν1ηλίπ ἀ2ν1ηλιφ +ἀ2ν1ήμ ἀ2ν1ήμ ἀ2ν1ημ +ἀ2ν1ήνυ ἀ2ν1ήνυ +ἀ2ν1ηνύ ἀ2ν1ηνύ +ἀ2ν1ήρει ἀ2ν1ήρει +ἀ2ν1ηρεί ἀ2ν1ηρεί +ἀ2ν1ηρέμ ἀ2ν1ηρέμ ἀ2ν1ηρεμ ἀ2ν1ηρεφ +ἀ2ν1ήρι ἀ2ν1ήρι +ἀ2ν1ηρί ἀ2ν1ηρί +ἀ2ν1ήροτ ἀ2ν1ήροτ +ἀ2ν1ηρότ ἀ2ν1ηρότ +ἀ2ν1ήσσ ἀ2ν1ήσσ ἀ2ν1ησσ +ἀ2ν1ήττ ἀ2ν1ήττ ἀ2ν1ηττ +ἀ2ν1ήφα ἀ2ν1ήφα ἀ2ν1ηφα +ἀ2ν1ίατ ἀ2ν1ίατ +ἀ2ν1ιάτ ἀ2ν1ιάτ +ἀ2ν1ίδιο ἀ2ν1ίδιο +ἀ2ν1ιδίο ἀ2ν1ιδίο +ἀ2ν1ιδίω ἀ2ν1ιδίω +ἀ2ν1ίδια ἀ2ν1ίδια ἀ2ν1ιδιτ ἄ2ν1ιδρος ἄ2ν1ιδροσ +ἀ2ν1ίδρου ἀ2ν1ίδρου +ἀ2ν1ίδρω ἀ2ν1ίδρω ἄ2ν1ιδρον ἄ2ν1ιδρε +ἀ2ν1ίδροι ἀ2ν1ίδροι ἄ2ν1ιδροι +ἀ2ν1ίδρυτ ἀ2ν1ίδρυτ +ἀ2ν1ιδρύτ ἀ2ν1ιδρύτ ἀ2ν1ιδρωτ +ἀ2ν1ιδρώτ ἀ2ν1ιδρώτ +ἀ2ν1ίερ ἀ2ν1ίερ +ἀ2ν1ιέρ ἀ2ν1ιέρ +ἀ2ν1ιεράτ ἀ2ν1ιεράτ +ἀ3ν2ιέρω ἀ3ν2ιέρω +ἀ2ν1ίκ ἀ2ν1ίκ ἀ2ν1ικ ἄ2ν1ικ +ἀ3ν2ίκη ἀ3ν2ίκη +ἀ3ν2ική ἀ3ν2ική +ἀ2ν1ίλ ἀ2ν1ίλ ἀ2ν1ιλ +ἀ2ν1ίμαστ ἀ2ν1ίμαστ +ἀ2ν1ιμάστ ἀ2ν1ιμάστ +ἀ2ν1ίου ἀ2ν1ίου +ἀ2ν1ιού ἀ2ν1ιού ἄ2ν1ιππ +ἀ2ν1ίππ ἀ2ν1ίππ ἀ2ν1ισ ἄ2ν1ισ +ἀ2ν1ίσ ἀ2ν1ίσ ἀ3ν2ισᾶτ +ἀ3ν2ισάτ ἀ3ν2ισάτ +ἀ3ν2ίστ ἀ3ν2ίστ ἀ3ν2ιστ ἀ4ν3ιστορη +ἀ4ν3ιστόρη ἀ4ν3ιστόρη +ἀ4ν3ιστορή ἀ4ν3ιστορή +ἀ3ν2ίσχ ἀ3ν2ίσχ +ἀ4ν3ίσχυ ἀ4ν3ίσχυ ἄ2ν1ιχ +ἀ2ν1ίχ ἀ2ν1ίχ +ἀ2ν1ιχνεύτ ἀ2ν1ιχνεύτ +ἀ2ν1ίψ ἀ2ν1ίψ ἀ2ν1ιψ +ἀ2ν1όδε ἀ2ν1όδε +ἀ2ν1οδέ ἀ2ν1οδέ ἄ2ν1οζ +ἀ2ν1όζ ἀ2ν1όζ ἀ2ν1οικε ἀ2ν1οικον ἄ2ν1οικ +ἀ2ν1οίκ ἀ2ν1οίκ +ἀ2ν1οικτί ἀ2ν1οικτί ἄ2ν1οικτ +ἀ2ν1οίκτ ἀ2ν1οίκτ +ἀ2ν1οίμωκ ἀ2ν1οίμωκ +ἀ2ν1οιμώκ ἀ2ν1οιμώκ ἀ2ν1οιμωκ ἀ2ν1οιν ἄ2ν1οιν +ἀ2ν1οίν ἀ2ν1οίν ἄ2ν1οιστρ +ἀ2ν1οίστρ ἀ2ν1οίστρ +ἀ2ν1όλ ἀ2ν1όλ ἀ2ν1ολ ἄ2ν1ολ ἀ3ν2ολκ ἀ3ν2ολο +ἀ2ν1ομβρί ἀ2ν1ομβρί ἀ2ν1ομβρῖ ἄ2ν1ομβρο +ἀ2ν1όμβρο ἀ2ν1όμβρο +ἀ2ν1όμβρω ἀ2ν1όμβρω ἄ2ν1ομβρα +ἀ2ν1ομήλ ἀ2ν1ομήλ ἀ2ν1ομηλ +ἀ2ν1ομίλ ἀ2ν1ομίλ ἀ2ν1ομιλ +ἀ2ν1όμιχ ἀ2ν1όμιχ ἀ2ν1ομιχ +ἀ2ν1όμο ἀ2ν1όμο +ἀ2ν1ομό ἀ2ν1ομό ἀ2ν1ομο ἀ3ν2ομοθ +ἀ3ν2όμου. ἀ3ν2όμου. +ἀ3ν2όμῳ. ἀ3ν2όμῳ. +ἀ3ν2όμω. ἀ3ν2όμω. +ἀ2ν2όμοιν. ἀ2ν2όμοιν. +ἀ3ν2όμων. ἀ3ν2όμων. +ἀ3ν2όμοις. ἀ3ν2όμοις. +ἀ3ν2όμοισ. ἀ3ν2όμοισ. +ἀ3ν2όμους. ἀ3ν2όμους. +ἀ3ν2όμουσ. ἀ3ν2όμουσ. +ἀ2ν1όν ἀ2ν1όν ἀ2ν1ον ἄ2ν1οπ +ἀ2ν1όπ ἀ2ν1όπ +ἀ2ν1όρ ἀ2ν1όρ ἀ2ν1ορ ἄ2ν1ορ +ἀ3ν2οργάζ ἀ3ν2οργάζ ἄ3ν2ορθ +ἀ3ν2όρθ ἀ3ν2όρθ +ἀ3ν2ορμά ἀ3ν2ορμά ἀ3ν2ορτ +ἀ3ν2ορύ ἀ3ν2ορύ +ἀ2ν1όσι ἀ2ν1όσι +ἀ2ν1οσί ἀ2ν1οσί ἀ2ν1οσι ἄ2ν1οσμ +ἀ2ν1όσμ ἀ2ν1όσμ +ἀ2ν1όσφρ ἀ2ν1όσφρ ἀ2ν1οσφρ +ἀ2ν1ούα ἀ2ν1ούα +ἀ2ν1ουά ἀ2ν1ουά +ἀ2ν1ούσι ἀ2ν1ούσι +ἀ2ν1ουσί ἀ2ν1ουσί +ἀ2ν1ούτ ἀ2ν1ούτ ἀ2ν1ουτ ἀ2ν1οφθ +ἀ2ν1όχευτ ἀ2ν1όχευτ +ἀ2ν1οχεύτ ἀ2ν1οχεύτ ἄ2ν1οχλ +ἀ2ν1όχλ ἀ2ν1όχλ ἀ2ν1οψ ἄ2ν1οψ +ἀ2ν1όψ ἀ2ν1όψ ἀντα2ν1ισ +ἀντα2ν1ίσ ἀντα2ν1ίσ ἀντει2σ1 ἀντε2κ1 @@ -1138,58 +1466,83 @@ psili2ρ1dasia2ρ ἀντιπαρε2ξ1 ἀντιπρο2σ1 ἀντιπροσ3κ2υ +ἀντισύ2ν1 ἀντισύ2ν1 ἀντισυ2ν1 +ἀ2ν1ύ ἀ2ν1ύ ἀ2ν1υ ἀ3ν2υμ +ἀ3ν2ύσ ἀ3ν2ύσ ἀ3ν2υσ +ἀ2ν1υπέ2ρ1 ἀ2ν1υπέ2ρ1 ἀ2ν1υπε2ρ1 ἄ2ν1ῳδ ἀ2ν1ῴδ +ἀ2ν1ώδυ ἀ2ν1ώδυ -ἀ2ν1ωδυoxia +ἀ2ν1ωδύ +ἀ2ν1ώι ἀ2ν1ώι +ἀ2ν1ωί ἀ2ν1ωί +ἀ2ν1ώλ ἀ2ν1ώλ ἀ2ν1ωλ +ἀ2ν1ώμ ἀ2ν1ώμ ἀ2ν1ωμ +ἀ2ν1ών ἀ2ν1ών ἀ2ν1ων ἀ2ν1ωρ ἄ2ν1ωρ +ἀ2ν1ώρ ἀ2ν1ώρ ἄ2ν1ωτο +ἀ2ν1ώτο ἀ2ν1ώτο +ἀ2ν1ωφέλ ἀ2ν1ωφέλ ἀ2ν1ωφελ +ἀ2ν1ώχυ ἀ2ν1ώχυ +ἀ2ν1ωχύ ἀ2ν1ωχύ ἀπα2ν1αι +ἀπά2ν1ου ἀπά2ν1ου +ἀπα2ν1ούρ ἀπα2ν1ούρ ἁπα2ξ1 ἀπε2κ1λ ἁπε2ρ1 ἀποσυ2ν1 +ἀπρό2σ1 ἀπρό2σ1 ἀπρο2σ1 +ἀπρό3σ2κε ἀπρό3σ2κε +ἀπρο3σ2κέ ἀπρο3σ2κέ +ἀπρό3σ2κο ἀπρό3σ2κο +ἀπρο3σ2κό ἀπρο3σ2κό ἀπρο3σ2τ ἁρπα2ξ1 ἀρρε2ν1ω ἀρχισυ2ν1 ἀστε2ρ1ω +ἀσύ2ν1 ἀσύ2ν1 ἀσυ2ν1 +ἀξύ2ν1 ἀξύ2ν1 ἀξυ2ν1 +αὐτέ2κ1μ αὐτέ2κ1μ αὐτε2κ1μ αὐτε2ξ1 @@ -1197,129 +1550,242 @@ psili2ρ1dasia2ρ .γερα2σ1φ .δα2σ1π .διαμφι2σ1β +.διέ2κ1ρο .διέ2κ1ρο +.διε2κ1ρό .διε2κ1ρό +.διέ2ξ1 .διέ2ξ1 .διε2ξ1 .δικα2σ1π +.διό2σ1κ .διό2σ1κ .διο2σ1κ +.διό2σ1π .διό2σ1π .διο2σ1π +.δί2σ1α .δί2σ1α +.δι2σ1ά .δι2σ1ά +.δί2σ1η .δί2σ1η +.δι2σ1ή .δι2σ1ή +.δί2σ1ε .δί2σ1ε .δι2σ1ε .δι2σ1θ +.δύ2σ1 .δύ2σ1 .δυ2σ1 +δύ3σ2ω. δύ3σ2ω. +δύ3σ2εις. δύ3σ2εις. +δύ3σ2εισ. δύ3σ2εισ. +δύ3σ2ει. δύ3σ2ει. +.δύ3σ2ετ .δύ3σ2ετ +δύ3σ2ομεν. δύ3σ2ομεν. +δύ3σ2ουσιν. δύ3σ2ουσιν. +δύ3σ2οιμι. δύ3σ2οιμι. +δύ3σ2οις. δύ3σ2οις. +δύ3σ2οισ. δύ3σ2οισ. +δύ3σ2οι. δύ3σ2οι. +δύ3σ2οιτον. δύ3σ2οιτον. +δυ3σ2οίτην. δυ3σ2οίτην. +δύ3σ2οιμεν. δύ3σ2οιμεν. +δύ3σ2οιτε. δύ3σ2οιτε. +δύ3σ2οιεν. δύ3σ2οιεν. +δύ3σ2ειν. δύ3σ2ειν. +δύ3σ2ων. δύ3σ2ων. +δύ3σ2ον δύ3σ2ον +δυ3σ2όν δυ3σ2όν +δύ3σ2ουσ δύ3σ2ουσ +δυ3σ2ούσ δυ3σ2ούσ +δύ3σ2ῃ δύ3σ2ῃ +δύ3σ2ητον. δύ3σ2ητον. +δύ3σ2ωμεν. δύ3σ2ωμεν. +δύ3σ2ωσι. δύ3σ2ωσι. +δύ3σ2αιμι. δύ3σ2αιμι. +δύ3σ2αις. δύ3σ2αις. +δύ3σ2ειας. δύ3σ2ειας. +δύ3σ2αισ. δύ3σ2αισ. +δύ3σ2ειασ. δύ3σ2ειασ. +δύ3σ2αι. δύ3σ2αι. +δύ3σ2ειε. δύ3σ2ειε. +δύ3σ2αιτον. δύ3σ2αιτον. +δυ3σ2αίτην. δυ3σ2αίτην. +δύ3σ2αιμεν. δύ3σ2αιμεν. +δύ3σ2αιτε. δύ3σ2αιτε. +δύ3σ2αιεν δύ3σ2αιεν +δύ3σ2ειαν. δύ3σ2ειαν. +δύ3σ2ον. δύ3σ2ον. +δυ3σ2άτω. δυ3σ2άτω. +δύ3σ2ατον. δύ3σ2ατον. +δυ3σ2άτων. δυ3σ2άτων. +δύ3σ2ατε. δύ3σ2ατε. +δυ3σ2άντων. δυ3σ2άντων. +δύ3σ2ας. δύ3σ2ας. +δύ3σ2αν. δύ3σ2αν. +δύ3σ2αντ δύ3σ2αντ +δυ3σ2άντ δυ3σ2άντ +δύ3σ2ασ δύ3σ2ασ +δυ3σ2άσ δυ3σ2άσ +δύ3σ2ομαι. δύ3σ2ομαι. +.δύ3σ2εσ .δύ3σ2εσ +δυ3σ2όμεθα. δυ3σ2όμεθα. +δύ3σ2ονται. δύ3σ2ονται. +δυ3σ2οίμην. δυ3σ2οίμην. +δύ3σ2οιο. δύ3σ2οιο. +δύ3σ2οιτο. δύ3σ2οιτο. +δύ3σ2οισθον. δύ3σ2οισθον. +δυ3σ2οίσθην. δυ3σ2οίσθην. +δυ3σ2οίμεθα. δυ3σ2οίμεθα. +δύ3σ2οισθε. δύ3σ2οισθε. +δύ3σ2οιντο. δύ3σ2οιντο. +δύ3σ2εσθαι. δύ3σ2εσθαι. +.δυ3σ2όμεν .δυ3σ2όμεν +.δυ3σ2ομέν .δυ3σ2ομέν +δύ3σ2ωμαι. δύ3σ2ωμαι. +δύ3σ2ηται. δύ3σ2ηται. +δυ3σ2ώμεθα δυ3σ2ώμεθα +δύ3σ2ησθε. δύ3σ2ησθε. +δυ3σ2αίμην. δυ3σ2αίμην. +δύ3σ2αιο. δύ3σ2αιο. +δύ3σ2αιτο. δύ3σ2αιτο. +δύ3σ2αισθον. δύ3σ2αισθον. +δυ3σ2αίσθην. δυ3σ2αίσθην. +δυ3σ2αίμεθα. δυ3σ2αίμεθα. +δύ3σ2αισθαι. δύ3σ2αισθαι. +δύ3σ2αιντο. δύ3σ2αιντο. +δυ3σ2άσθω. δυ3σ2άσθω. +δύ3σ2ασθον. δύ3σ2ασθον. +δυ3σ2άσθων. δυ3σ2άσθων. +δύ3σ2ασθε. δύ3σ2ασθε. +δύ3σ2ασθαι. δύ3σ2ασθαι. +δυ3σ2άμεν δυ3σ2άμεν +δυσ3σ2αμέν δυσ3σ2αμέν +δύ3σ2ατο. δύ3σ2ατο. +δύ3σ2ετο. δύ3σ2ετο. +δύ3σ2αντο. δύ3σ2αντο. +δύ3σ2εο. δύ3σ2εο. +.δυσεί2σ1β .δυσεί2σ1β .δυσει2σ1β +.δυσέ2κ1 .δυσέ2κ1 .δυσε2κ1 +.δυσέ2ξ1 .δυσέ2ξ1 .δυσε2ξ1 .δυ3σ2ιθ +δύ3σ2ις. δύ3σ2ις. +δύ3σ2ισ. δύ3σ2ισ. +δύ3σ2εω δύ3σ2εω +δύ3σ2ιν. δύ3σ2ιν. +δύ3σ2ι. δύ3σ2ι. +δυ3σ2έοιν. δυ3σ2έοιν. +δύ3σ2εσι. δύ3σ2εσι. +δύ3σ2εσιν. δύ3σ2εσιν. +.δύ3σ2κε .δύ3σ2κε +.δυ3σ2μή. .δυ3σ2μή. .δυ3σ2μὴ. .δυ3σ2μῆς. @@ -1329,20 +1795,27 @@ psili2ρ1dasia2ρ .δυ3σ2μᾶ .δυ3σ2μα .δυ3σ2μῶ +.δυσξύ2ν1 .δυσξύ2ν1 .δυσξυ2ν1 +.δύ3σ2ταν .δύ3σ2ταν +.δυ3σ2τάν .δυ3σ2τάν .δυ3σ2την +.δυ3σ2τήν .δυ3σ2τήν ἐδυ2σ1τ +εἰ2ν1όδ εἰ2ν1όδ εἰ2ν1οδ εἰ2σ1 εἴ2σ1 +εἰ3σ2ί. εἰ3σ2ί. εἰ3σ2ὶ. εἰ3σ2ι. +εἰ3σ2ίν. εἰ3σ2ίν. εἰ3σ2ὶν. εἰ3σ2ιν. @@ -1351,76 +1824,117 @@ psili2ρ1dasia2ρ εἴσει. εἴ3σ2εται. εἴ3σ2εσθον. +εἰ3σ2όμ εἰ3σ2όμ εἴ3σ2εσθε. εἴ3σ2ονται +εἰ3σ2οίμην εἰ3σ2οίμην εἴ3σ2οιο εἴ3σ2οιτο εἴ3σ2οισθον +εἰ3σ2οίσθην εἰ3σ2οίσθην +εἰ3σ2οίμεθα εἰ3σ2οίμεθα εἴ3σ2οισθε εἴ3σ2οιντο εἴ3σ2εσθαι +εἰ3σ2όμεν εἰ3σ2όμεν +εἰ3σ2ομέν εἰ3σ2ομέν +εἴ3σ2άμην. εἴ3σ2άμην. εἴ3σ2ω εἴ3σ2ατο εἴ3σ2ασθον +εἰ3σ2άσθην εἰ3σ2άσθην +εἰ3σ2άμεθα εἰ3σ2άμεθα εἴ3σ2ασθε εἴ3σ2αντο εἴ3σ2ωμαι εἴ3σ2ησθον +εἰ3σ2ώμεθα εἰ3σ2ώμεθα εἴ3σ2ησθε εἴ3σ2ωνται +εἰ3σ2αίμην εἰ3σ2αίμην εἴ3σ2αιο εἴ3σ2αιτο εἴ3σ2αισθον +εἴ3σ2αίσθην εἴ3σ2αίσθην +εἰ3σ2αίμεθα εἰ3σ2αίμεθα εἴ3σ2αισθε εἴ3σ2αιντο +εἰ3σ2άσθω εἰ3σ2άσθω +εἰ3σ2άσθων εἰ3σ2άσθων εἴ3σ2ασθαι +εἰ3σ2άμεν εἰ3σ2άμεν +εἰ3σ2αμέν εἰ3σ2αμέν ἐ2κ1λ +ἐ3κ2λήθη ἐ3κ2λήθη +ἐ3κ2λάζ ἐ3κ2λάζ +ἐ3κ2λάγ ἐ3κ2λάγ +ἐ3κ2λάο ἐ3κ2λάο +ἐ3κ2λάσ ἐ3κ2λάσ +ἐ3κ2λαί ἐ3κ2λαί +ἐ3κ2λαύ ἐ3κ2λαύ +ἐ3κ2λεί ἐ3κ2λεί +ἐ4κ3λείπ ἐ4κ3λείπ +ἐ4κ3λείψ ἐ4κ3λείψ ἐ3κ2λῄ +ἐ3κ2κλέπ ἐ3κ2κλέπ +ἐ3κ2κλέψ ἐ3κ2κλέψ +ἐ3κ2λάπ ἐ3κ2λάπ ἐ3κ2λαπ +ἐ4κ3λάπτ ἐ4κ3λάπτ ἐ4κ3λαπτ +ἐ3κ2λέφ ἐ3κ2λέφ ἐ3κ2λεφ +ἐ3κ2λήρ ἐ3κ2λήρ ἐ3κ2ληρ +ἐ3κ2λίν ἐ3κ2λίν ἐ3κ2λιν +ἐ3κ2λύ ἐ3κ2λύ +ἐ4κ3λύσεω ἐ4κ3λύσεω +ἐ4κ3λύσει ἐ4κ3λύσει +ἐ4κ3λύσεοι ἐ4κ3λύσεοι +ἐ4κ3λύσεσι ἐ4κ3λύσεσι +ἐ3κ2λόμ ἐ3κ2λόμ +ἐ3κ2κλώσ ἐ3κ2κλώσ ἔ2κ1λει ἔ3κ2λεισ @@ -1430,179 +1944,274 @@ psili2ρ1dasia2ρ ἐ2κ1ν ἔ2κ1ν ἔ3κ2ναι +ἐ3κ2ναί ἐ3κ2ναί ἔ3κ2νησ +ἐ3κ2νήσ ἐ3κ2νήσ ἐ3κ2νυ ἐ2κ1ρ ἔ2κ1ρ +ἐ3κ2ράδ ἐ3κ2ράδ ἐ3κ2ραδ ἔ3κ2ραζ +ἐ3κ2ράζ ἐ3κ2ράζ ἔ3κ2ραγ +ἐ3κ2ράγ ἐ3κ2ράγ +ἐ3κ2ράτ ἐ3κ2ράτ ἐ3κ2ρατ +ἐ3κ2ραύγ ἐ3κ2ραύγ ἐ3κ2ραυγ ἔ3κ2ραι +ἐ3κ2ραί ἐ3κ2ραί ἔ3κ2ραν +ἐ3κ2ράν ἐ3κ2ράν +ἐ3κ2ρήη ἐ3κ2ρήη +ἐ3κ2ράα ἐ3κ2ράα +ἐ3κ2ραά ἐ3κ2ραά +ἐ3κ2ράθ ἐ3κ2ράθ ἐ3κ2ραθ ἔ3κ2ρεκ +ἐ3κ2ρέκ ἐ3κ2ρέκ ἔ3κ2ρεξ +ἐ3κ2ρέξ ἐ3κ2ρέξ +ἐ3κ2ρέμ ἐ3κ2ρέμ ἐ3κ2ρεμ +ἐ3κ2ρήμ ἐ3κ2ρήμ ἐ3κ2ρημ ἔ3κ2ριν +ἐ3κ2ρίν ἐ3κ2ρίν +ἐ3κ2ρίθ ἐ3κ2ρίθ +ἐ3κ2ρότ ἐ3κ2ρότ ἐ3κ2ροτ ἔ3κ2ρου +ἐ3κ2ρού ἐ3κ2ρού ἔ3κ2ρυπ +ἐ3κ2ρύπ ἐ3κ2ρύπ ἔ3κ2ρυψ +ἐ3κ2ρύψ ἐ3κ2ρύψ +ἐ3κ2ρύβ ἐ3κ2ρύβ +ἐ3κ2ρύφ ἐ3κ2ρύφ ἐ3κ2ρυσ ἔ3κ2ρωζ +ἐ3κ2ρώζ ἐ3κ2ρώζ ἔ3κ2ρωξ +ἐ3κ2ρώξ ἐ3κ2ρώξ ἐ2κ1ταθ ἔ2κ1ταμε. +ἐ2κ1τάμν ἐ2κ1τάμν ἐ2κ1ταν ἐ2κ1ταρ +ἐ2κ1τάσ ἐ2κ1τάσ ἐ2κ1τε +ἐ2κ1τέ ἐ2κ1τέ +ἐ3κ2τείν ἐ3κ2τείν +ἐ2κ1τήκ ἐ2κ1τήκ ἐ2κ1τι ἔ2κ1τι +ἐ2κ1τί ἐ2κ1τί ἔ3κ2τιζ +ἐ3κ2τίζ ἐ3κ2τίζ ἔ3κ2τισα +ἐ3κ2τίσα ἐ3κ2τίσα +ἐ2κ1τό ἐ2κ1τό ἐ2κ1το ἔ2κ1το +ἐ3κ2τός. ἐ3κ2τός. ἐ3κ2τὸς. +ἐ3κ2τόσ. ἐ3κ2τόσ. ἐ3κ2τὸσ. ἐ2κ1τρ ἔ2κ1τυπο +ἐ2κ1τύπου. ἐ2κ1τύπου. +ἐ2κ1τύπῳ. ἐ2κ1τύπῳ. ἔ2κ1τυπε. +ἐ2κ1τύπω. ἐ2κ1τύπω. +ἐ2κτύποι. ἐ2κτύποι. +ἐ2κ1τύπων. ἐ2κ1τύπων. +ἐ2κ1τύποις. ἐ2κ1τύποις. +ἐ2κ1τύποισ. ἐ2κ1τύποισ. +ἐ2κ1τύπους. ἐ2κ1τύπους. +ἐ2κ1τύπουσ. ἐ2κ1τύπουσ. ἔ2κ1τυπα. ἐ2κ1τυ +ἑλλή2σ1π ἑλλή2σ1π ἑλλη2σ1π ἐ2ν1 ἔ2ν1 +ἐ3ν2άκις ἐ3ν2άκις ἐ3ν2ακισ +ἐ3ν2ακόσ ἐ3ν2ακόσ ἐ3ν2ακοσ ἔ3ν2αρα. +ἐ3ν2άρων. ἐ3ν2άρων. +ἐ3ν2άροις. ἐ3ν2άροις. +ἐ3ν2άροισ. ἐ3ν2άροισ. ἐ3ν2αρηφ ἐ4ν3αραρ +ἐ3ν2άρεε ἐ3ν2άρεε +ἐ3ν2αρέω ἐ3ν2αρέω +ἐ3ν2αρέα ἐ3ν2αρέα +ἐ3ν2αρεά ἐ3ν2αρεά +ἐ3ν2άριε ἐ3ν2άριε +ἐ3ν2αρίω ἐ3ν2αρίω +ἐ3ν2αρία ἐ3ν2αρία +ἐ3ν2αριά ἐ3ν2αριά ἔ3ν2ασσ +ἐ3ν2άσσ ἐ3ν2άσσ +ἐ3ν2άσθ ἐ3ν2άσθ ἐ3ν2ασθ ἔ3ν2ατ +ἐ3ν2άτ ἐ3ν2άτ ἐνδυ2σ1τ +ἐ3ν2έγκ ἐ3ν2έγκ ἐ3ν2εγκ ἔ3ν2εικ ἐ3ν2εῖκ ἐ3ν2εικ +ἐ3ν2είκ ἐ3ν2είκ ἔ3ν2ειμ +ἐ3ν2είμ ἐ3ν2είμ +ἐ3ν2εμέσσ ἐ3ν2εμέσσ +ἐ3ν2εμήθ ἐ3ν2εμήθ +ἐ3ν2ενή ἐ3ν2ενή +ἐ3ν2εό ἐ3ν2εό ἐ3ν2εὸ ἐ3ν2εο ἐ3ν2εῶ +ἐ3ν2εά ἐ3ν2εά ἐ3ν2εὰ ἐ3ν2εᾶ +ἐ3ν2έπει ἐ3ν2έπει ἔ3ν2ερθε ἔ3ν2ευσ +ἐ3ν2εύσ ἐ3ν2εύσ +ἐ3ν2έχθ ἐ3ν2έχθ ἐ3ν2εχθ ἔ3ν2ησ +ἐ3ν2ήσ ἐ3ν2ήσ +ἐ3ν2ηή ἐ3ν2ηή ἐ3ν2ηὴ ἔ3ν2ην. +ἐ3ν2ηεί ἐ3ν2ηεί ἐ3ν2ηο ἐ3ν2ηῶ +ἐ3νηέ ἐ3νηέ +ἐ3ν2ήνο ἐ3ν2ήνο +ἐ3ν2ί ἐ3ν2ί ἐ3ν2ι ἔ3ν2ι +ἐ4ν3ιαύ ἐ4ν3ιαύ +ἐ5ν4ιαύσ ἐ5ν4ιαύσ ἐ5ν4ιαυσ ἐ4ν3ιδρ +ἐ4ν3ίδρ ἐ4ν3ίδρ +ἐ4ν3ίζ ἐ4ν3ίζ +ἐ4ν3ίη ἐ4ν3ίη +ἐ4ν3ιέτον. ἐ4ν3ιέτον. +ἐ4ν3ίεμεν. ἐ4ν3ίεμεν. +ἐ4ν3ίω. ἐ4ν3ίω. ἐ4ν3ιππ +ἐ4ν3ίππ ἐ4ν3ίππ +ἐ4ν3ίπτ ἐ4ν3ίπτ +ἐ4ν3ίψ ἐ4ν3ίψ +ἐ4ν3ίσσ ἐ4ν3ίσσ +ἐ4ν3ίστ ἐ4ν3ίστ ἐ4ν3ιστ ἐ4ν3ισχ +ἐ4ν3ίσχ ἐ4ν3ίσχ ἔ3ν2ος. ἔ3ν2οσ. @@ -1617,94 +2226,138 @@ psili2ρ1dasia2ρ ἔ3ν2ῃ. ἔ3ν2η. ἔ3ν2οσι +ἐ3ν2όσε ἐ3ν2όσε +ἐ3ν2υάλ ἐ3ν2υάλ ἐ3ν2υαλ ἔ3ν2υξ ἐ3ν2υξ +ἐ3ν2ύξ ἐ3ν2ύξ +ἐ3ν2ύσ ἐ3ν2ύσ ἐ3ν2υσ +ἐ3ν2υώ ἐ3ν2υώ ἐ3ν2υὼ +ἐ3ν2υόο ἐ3ν2υόο ἐ3ν2υοῦς ἐ2ξ1 ἔ2ξ1 +ἐ3ξ2ήρ ἐ3ξ2ήρ ἐ3ξ2ηρ ἐ3ξ2υ2ν1 ἐ3ξ2υρ +ἐ3ξ2ύρ ἐ3ξ2ύρ ἔ3ξ2υσ ἔ3ξ2ω. +ἑ2ξ1ήρετμ ἑ2ξ1ήρετμ +ἑ2ξ1ηρέτμ ἑ2ξ1ηρέτμ +ἐπεί2σ1 ἐπεί2σ1 ἐπει2σ1 +ἐπεί3σ2ατον. ἐπεί3σ2ατον. +ἐπει3σ2άτην. ἐπει3σ2άτην. +ἐπεί3σ2αμεν. ἐπεί3σ2αμεν. +ἐπεί3σ2ατε ἐπεί3σ2ατε +ἐπει3σ2άμην. ἐπει3σ2άμην. +ἐπεί3σ2ω. ἐπεί3σ2ω. +ἐπεί3σ2ατο ἐπεί3σ2ατο +ἐπεί3σ2ασθον. ἐπεί3σ2ασθον. +ἐπει3σ2άμεθα. ἐπει3σ2άμεθα. +ἐπεί3σ2ασθε. ἐπεί3σ2ασθε. +ἐπεί3σ2αντο. ἐπεί3σ2αντο. +ἐπεί3σ2θ ἐπεί3σ2θ ἐπει3σ2θ +ἐπε2κ1τεί ἐπε2κ1τεί +ἐπέ2κ1τει ἐπέ2κ1τει ἐπε2κ1τρ +ἐπέ2κ1τρ ἐπέ2κ1τρ ἐπε2ξ1 ἐπε2σ1β +ἐπιπρό2σ1θ ἐπιπρό2σ1θ ἐπιπρο2σ1θ ἐπισυ2ν1 ἐ2σ1 +ἐ3σ2άω ἐ3σ2άω ἐ3σ2ημ ἐ3σ2θ +ἐ4σ3θέσ ἐ4σ3θέσ ἐ3σ2ιγ ἐ3σ2κ +ἐ4σ3κά ἐ4σ3κά ἐ4σ3κα ἐ3σ2μὲν. +ἐ3σ2μέν. ἐ3σ2μέν. ἐ3σ2τ +ἐ3σ2όμεθα ἐ3σ2όμεθα +ἐ3σ2οίμην ἐ3σ2οίμην +ἐ3σ2όμ ἐ3σ2όμ ἐ3σ2ομ ἐ3σ2οῦ -ἐ3σ2ουoxia +ἐ3σ2ού ἐ3σ2υ +ἐ3σ2ύ ἐ3σ2ύ +ἐσύ2ν1 ἐσύ2ν1 ἐσυ2ν1 ἐ3σ2χ +ἐ4σ3χέ ἐ4σ3χέ +ἐ3σ2ώ ἐ3σ2ώ ἐ3σ2ω ἔ2σ1οπ εὐε2ξ1 +εὐε3ξ2ί εὐε3ξ2ί εὐε3ξ2ι +εὐπρό2σ1 εὐπρό2σ1 εὐπρο2σ1 +εὐσύ2ν1 εὐσύ2ν1 εὐσυ2ν1 +εὐξύ2ν1 εὐξύ2ν1 εὐξυ2ν1 ἐω2σ1φ ἤ2ν1οψ. ἤ2ν1οπ +ἠ2ν1όπ ἠ2ν1όπ .θεμι2σ1κρ +.θεό2σ1δ .θεό2σ1δ .θεο2σ1δ .θεοι2σ1εχθρ @@ -1712,75 +2365,115 @@ psili2ρ1dasia2ρ .θυο2σ1κ .καθυπε2ρ1 .καλω2σ1ορ +.καλω2σ1όρ .καλω2σ1όρ +.κα2ν1είς. .κα2ν1είς. .κα2ν1εὶς. +.κα2ν1είσ. .κα2ν1είσ. .κα2ν1εὶσ. .κα2ν1εν +.κα2ν1έν .κα2ν1έν .καταδυ2σ1ωπ +.κατεδυ2σ1ώπ .κατεδυ2σ1ώπ .κατει2σ1 +.κατε2ν1αί .κατε2ν1αί +.κατε2ν1ή .κατε2ν1ή +.κατε2ξ1α2ν1ί .κατε2ξ1α2ν1ί +.κατε2ξ1α2ν1έσ .κατε2ξ1α2ν1έσ .κερα2σ1φ +.κρά2σ1π .κρά2σ1π .κρα2σ1π +.κυνό2σ1α .κυνό2σ1α +.κυνό2σ1β .κυνό2σ1β .κυνο2σ1β +.κυνό2σ1ο .κυνό2σ1ο .κυνο2σ1ο .κυνο2σ1φ +.μελα2ν1άγ .μελα2ν1άγ .μελα2ν1αγ +.μελα2ν1άε .μελα2ν1άε +.μελα2ν1αέ .μελα2ν1αέ .μελα2ν1αθ .μελα2ν1αιγ .μελα2ν1αυγ +.μελα2ν1είμ .μελα2ν1είμ .μελα2ν1εῖμ +.μελά2ν1ιππ .μελά2ν1ιππ +.μελα2ν1ίππ .μελα2ν1ίππ +.μελα2ν1όμμ .μελα2ν1όμμ .μελα2ν1ομμ +.μελά2ν1οσσ .μελά2ν1οσσ +.μελα2ν1όσσ .μελα2ν1όσσ +.μελά2ν1οστ .μελά2ν1οστ +.μελα2ν1όστ .μελα2ν1όστ +.μελά2ν1ουρ .μελά2ν1ουρ +.μελα2ν1ούρ .μελα2ν1ούρ .μελα2ν1ουρ +.μελά2ν1υ .μελά2ν1υ +.μελα2ν1ύ .μελα2ν1ύ .μετε2ξ1α +.μετε2ξ1έ .μετε2ξ1έ .μετε2ξ1ε .μογι2σ1 .μογο2σ1τ .μυ2σ1π .μυ2σ1επ +.νεώ2σ1οικ .νεώ2σ1οικ +.νεω2σ1οίκ .νεω2σ1οίκ .νου2ν1ε .ξυ2ν1αγ .ξυ2ν1ε +.ξυ2ν1έ .ξυ2ν1έ +.ξύ2ν1ε .ξύ2ν1ε +.ξυ3ν2εώ .ξυ3ν2εώ .ξυ3ν2εῶ .ξυ2ν1ῆκ +.ξύ2ν1ι .ξύ2ν1ι +.ξυ2ν1ί .ξυ2ν1ί +οἱο2ν1εί. οἱο2ν1εί. οἱο2ν1εὶ. +οἱό2σ1 οἱό2σ1 +οἰ2σ1πώτ οἰ2σ1πώτ οἰ2σ1πωτ +ὁλο2ν1έν. ὁλο2ν1έν. ὁλο2ν1ὲν. ὁπω2σ1 @@ -1796,40 +2489,57 @@ psili2ρ1dasia2ρ ὁ2σ1τι2σ1οῦν. ἡτι2σ1οῦν. ὁποιου2σ1τινα2σ1οῦν. +οὐδενό2σ1ω οὐδενό2σ1ω +οὐδενο2σ1ώ οὐδενο2σ1ώ .παλι2ν1 +.παλί2ν1 .παλί2ν1 .πα2ν1 +.πά2ν1 .πά2ν1 +.πα3ν2ός. .πα3ν2ός. .πα3ν2ὸς. +.πα3ν2όσ. .πα3ν2όσ. .πα3ν2ὸσ. +.πα3ν2ί. .πα3ν2ί. .πα3ν2ὶ. +.πάνα. .πάνα. .πα3ν2ῶν. .πα3ν2ικ +.πα3ν2ίσδ .πα3ν2ίσδ .πα3ν2ισδ .πα3ν2οῦ. .πα3ν2ῷ. +.πα3ν2ό. .πα3ν2ό. .πα3ν2ὸ. +.πα3ν2όν. .πα3ν2όν. .πα3ν2ὸν. +.πα3ν2έ. .πα3ν2έ. .πα3ν2ὲ. +.πα3ν2οί. .πα3ν2οί. .πα3ν2οὶ. .πα3ν2οῖς. .πα3ν2οῖσ. +.πα3ν2ούς. .πα3ν2ούς. .πα3ν2οὺς. +.πα3ν2ούσ. .πα3ν2ούσ. .πα3ν2οὺσ. +.παρα2ν1ίσχ .παρα2ν1ίσχ +.παρεί2σ1 .παρεί2σ1 .παρει2σ1 .παρε2κ1λ @@ -1837,92 +2547,146 @@ psili2ρ1dasia2ρ .παρε2ν1εῖ .παρε2ν1ο .παρε2ξ1 +.παρέ2ξ1 .παρέ2ξ1 +παρέ3ξ2ω. παρέ3ξ2ω. +παρέ3ξ2εις. παρέ3ξ2εις. +παρέ3ξ2εισ. παρέ3ξ2εισ. +παρέ3ξ2ει. παρέ3ξ2ει. +παρέ3ξ2ετον. παρέ3ξ2ετον. +παρε3ξ2έτην. παρε3ξ2έτην. +παρέ3ξ2ομεν. παρέ3ξ2ομεν. +παρέ3ξ2ετε. παρέ3ξ2ετε. +παρέ3ξ2ουσι. παρέ3ξ2ουσι. +παρέ3ξ2ομαι παρέ3ξ2ομαι +παρέ3ξ2ῃ παρέ3ξ2ῃ +παρέ3ξ2εται. παρέ3ξ2εται. +παρέ3ξ2εσθον. παρέ3ξ2εσθον. +παρε3ξ2όμεθα. παρε3ξ2όμεθα. +παρέ3ξ2εσθε. παρέ3ξ2εσθε. +παρέ3ξ2ονται. παρέ3ξ2ονται. +.πλεο2ν1έ .πλεο2ν1έ .πλεο2ν1ε .προει2σ1 .προε2κ1 .προε2ν1 .προε2ξ1 +.προέ2ξ1 .προέ2ξ1 .προ2σ1 +.προ3σ2άβ .προ3σ2άβ .προ3σ2αβ .προσει2σ1 +.προ3σ2εί .προ3σ2εί +.προ3σ2έσει .προ3σ2έσει +.προ3σ2εσεί .προ3σ2εσεί .προσε2ν1 .προσε2ξ1 +.πρό3σ2θι .πρό3σ2θι +.προ3σ2θί .προ3σ2θί .προ4σ3θιγ +.πρό3σ2κοπ .πρό3σ2κοπ +.προ3σ2κόπ .προ3σ2κόπ .προ3σ2τασ +.προ3σ2τάτ .προ3σ2τάτ .προ3σ2τατ .προ3σ2ταυ +.προ3σ2τεί .προ3σ2τεί .προ3σ2τεν +.προ3σ2τέν .προ3σ2τέν .προ3σ2τερν +.πρό3σ2τερν .πρό3σ2τερν +.προ3σ2τέρν .προ3σ2τέρν +.προ3σ2τήσ .προ3σ2τήσ +.προ3σ2τόμ .προ3σ2τόμ .προ3σ2τομ +.πρό3σ2τῳ .πρό3σ2τῳ .προ3σ2τῴ .προ3σ2υγ .προ3σ2υμ .προ3σ2υ2ν1 +.πρό3σ2φαγμ .πρό3σ2φαγμ +.προ3σ2φάγμ .προ3σ2φάγμ +.προ3σ2φάζ .προ3σ2φάζ +.προ3σ2φάττ .προ3σ2φάττ +.πρό3σ2χημ .πρό3σ2χημ +.προ3σ2χήμ .προ3σ2χήμ +.πρό3σ2ω. .πρό3σ2ω. +.πρό3σ2ωθεν. .πρό3σ2ωθεν. +.προ3σ2ώτ .προ3σ2ώτ .προ3σ2ωτ .προϋπε2ξ1 +.πυ2ρ1άγ .πυ2ρ1άγ .πυ2ρ1αγ +.πυ2ρ1αίθ .πυ2ρ1αίθ .πυ2ρ1αιθ .πυ2ρ1ῆθ .πυ2ρ1ηθ +.πυ2ρ1ήθ .πυ2ρ1ήθ .πυ2ρ1ακ +.πύ2ρ1αυ .πύ2ρ1αυ +.πυ2ρ1αύ .πυ2ρ1αύ .πυ2ρ1αυ +.πυ2ρ1ήνεμ .πυ2ρ1ήνεμ +.πυ2ρ1ηνέμ .πυ2ρ1ηνέμ .πυ2ρ1ωπ +.σελα2σ1φό .σελα2σ1φό .σελα2σ1φο .συμπαρει2σ1 .συ2ν1 +.σύ2ν1 .σύ2ν1 +.συνδιέ2ξ1 .συνδιέ2ξ1 .συνδιε2ξ1 .συνδυ2σ1 @@ -1930,61 +2694,93 @@ psili2ρ1dasia2ρ .τεσσαρε2σ1κ .τρει2σ1κ .τρι2σ1 +.τρι3σ2μό .τρι3σ2μό .τρι3σ2μο .τρι3σ2μῶ .τρι3σ2π +.τρί3σ2τ .τρί3σ2τ .τρι3σ2τ +.τρι3σ2ώ .τρι3σ2ώ .τρι3σ2ω ὑο2σ1κ +ὑπεί2σ1 ὑπεί2σ1 ὑπει2σ1 +ὑπεί3σ2ας ὑπεί3σ2ας +ὑπεί3σ2ασ ὑπεί3σ2ασ +ὑπεί3σ2αν ὑπεί3σ2αν +ὑπει3σ2άν ὑπει3σ2άν +ὑπει3σ2άσ ὑπει3σ2άσ ὑπε2κ1λαμ +ὑπε2κ1λήψ ὑπε2κ1λήψ ὑπε2κ1τ ὑπε2ν1 ὑπε2ξ1 ὑπε2ρ1 +ὑπέ2ρ1 ὑπέ2ρ1 +ὑπέ3ρ2α. ὑπέ3ρ2α. +ὑπέ3ρ2ης. ὑπέ3ρ2ης. +ὑπέ3ρ2ησ. ὑπέ3ρ2ησ. +ὑπέ3ρ2ᾳ. ὑπέ3ρ2ᾳ. +ὑπέ3ρ2αν. ὑπέ3ρ2αν. +ὑπέ3ρ2αι. ὑπέ3ρ2αι. ὑπε3ρ2ῶν. +ὑπέ3ρ2αις. ὑπέ3ρ2αις. +ὑπέ3ρ2αισ. ὑπέ3ρ2αισ. +ὑπέ3ρ2ας. ὑπέ3ρ2ας. +ὑπέ3ρ2ασ. ὑπέ3ρ2ασ. ὑπε3ρ2εθ +ὑπε3ρ2έθ ὑπε3ρ2έθ +ὑπε3ρ2εί ὑπε3ρ2εί +ὑπέ3ρ2υθ ὑπέ3ρ2υθ +ὑπε3ρ2ύθ ὑπε3ρ2ύθ ὑπε3ρ2υθ ὑπερε2κ1τε +ὑπερε2κ1τί ὑπερε2κ1τί +ὑπε3ρ2έπτ ὑπε3ρ2έπτ ὑπε3ρ2επτ +ὑπε3ρ2έψ ὑπε3ρ2έψ ὑπε3ρ2εψ +ὑπε3ρ2έω ὑπε3ρ2έω ὑπε3ρ2ῶ +ὑπε3ρ2έε ὑπε3ρ2έε ὑπε3ρ2εῖς. ὑπε3ρ2εῖσ. ὑπε3ρ2εῖ. +ὑπε3ρ2έο ὑπε3ρ2έο ὑπε3ρ2οῦ ὑπε3ρ2εῖτ +ὑπε3ρ2ώ ὑπε3ρ2ώ ὑπε3ρ2ω ὕ2σ1τρ @@ -1992,55 +2788,91 @@ psili2ρ1dasia2ρ .φαε2σ1φ .φω2σ1φ .χαρι2σ1ανδρ +.χαρι2σ1άνδρ .χαρι2σ1άνδρ +.χει2ρ1άγ .χει2ρ1άγ .χει2ρ1αγ .χει2ρ1απ .χει2ρ1αψ .χει2ρ1ου .χει2ρ1ῶν +.χει2ρ1άν .χει2ρ1άν .χει2ρ1αν .χη2ν1ναλ +ὡ2σ1α2ν1εί. ὡ2σ1α2ν1εί. ὡ2σ1α2ν1εὶ. +ὡ2σ1αύτως. ὡ2σ1αύτως. +ὡ2σ1αύτωσ. ὡ2σ1αύτωσ. +ὡ2σ1εί. ὡ2σ1εί. ὡ2σ1εὶ. ὥ2σ1περ. +ὡ2σ1πε2ρ1εί. ὡ2σ1πε2ρ1εί. ὡ2σ1πε2ρ1εὶ. ὥ2σ1τε +ι2σ1χίλιοι. ι2σ1χίλιοι. +ι2σ1χιλίων. ι2σ1χιλίων. +ι2σ1χιλίοις. ι2σ1χιλίοις. +ι2σ1χιλίοισ. ι2σ1χιλίοισ. +ι2σ1χιλίους. ι2σ1χιλίους. +ι2σ1χιλίουσ. ι2σ1χιλίουσ. +ι2σ1χίλιαι. ι2σ1χίλιαι. +ι2σ1χιλίαις. ι2σ1χιλίαις. +ι2σ1χιλίαισ. ι2σ1χιλίαισ. +ι2σ1χιλίας. ι2σ1χιλίας. +ι2σ1χιλίασ. ι2σ1χιλίασ. +ι2σ1χίλια. ι2σ1χίλια. +ι2σ1μύριοι. ι2σ1μύριοι. +ι2σ1μυρίων. ι2σ1μυρίων. +ι2σ1μυρίοις. ι2σ1μυρίοις. +ι2σ1μυρίοισ. ι2σ1μυρίοισ. +ι2σ1μυρίους. ι2σ1μυρίους. +ι2σ1μυρίουσ. ι2σ1μυρίουσ. +ι2σ1μύριαι. ι2σ1μύριαι. +ι2σ1μυρίαις. ι2σ1μυρίαις. +ι2σ1μυρίαισ. ι2σ1μυρίαισ. +ι2σ1μυρίας. ι2σ1μυρίας. +ι2σ1μυρίασ. ι2σ1μυρίασ. +ι2σ1μύρια. ι2σ1μύρια. ι2σ1χιλιοστ ι2σ1μυριοστ +ι2σ1χιλιάκις. ι2σ1χιλιάκις. +ι2σ1χιλιάκισ. ι2σ1χιλιάκισ. +ι2σ1μυριάκις. ι2σ1μυριάκις. +ι2σ1μυριάκισ. ι2σ1μυριάκισ. } diff --git a/tex/context/sample/montgomery.tex b/tex/context/sample/montgomery.tex new file mode 100644 index 000000000..a38357ea4 --- /dev/null +++ b/tex/context/sample/montgomery.tex @@ -0,0 +1,13 @@ +Making oil requires a specific series of geological accidents over +inconceivable amounts of time. First, organic-rich sediment needs to +be burried faster than it can decay. Then the stuff needs to get pushed +miles down into the earth's crust to be cooked slowly. Burried too +deep or cooked too fast and the organic molecules burn off; +trapped too shallow or not for long enough and the muck never +turns into oil. Finally, an impermeable layer needs to seal the +oil in a porous layer of rock from which it can be recovered. Then +somebody has to find it and get it out of the ground. It takes +millions of years to produce a barrel of oil; we use millions of +barrels a day. There is no question that we will run out of oil --- +the only question is when. + diff --git a/tex/context/sample/sample.tex b/tex/context/sample/sample.tex index 3a433183e..f39c328ee 100644 --- a/tex/context/sample/sample.tex +++ b/tex/context/sample/sample.tex @@ -38,6 +38,8 @@ used in testing bibliographic references and citations. Simon \& Schuster, 2006, p.106 \NC \NR \NC weisman.tex \NC Alan Weisman \NC The World Without Us, \endgraf Thomas Dunne Books, 2007, p.160 \NC \NR +\NC montgomery.tex \NC David R Montgomery \NC Dirt, The Erosion of Civilizations, \endgraf + University of California Press, 2007, p.199 \NC \NR \stoptabulate % Tufte: This quote will always produce hyphenated text, apart from the content, @@ -52,9 +54,12 @@ used in testing bibliographic references and citations. % quite visible inter-character spacing in a text that can be typeset quite well by \TeX. % The Universe in a Nutshell: a beautiful designed book, (companion of A Short History -% of Time) +% of Time). % The World Without Us: A properly typeset, very readable book. Read it and you'll look at % the world around you differently (and a bit more freightened). +% Dirt, The Erosion of Civilizations: one of those books that you buy immediately after +% reading a few sentences. Also one of those books that every politician should read. + \stoptext diff --git a/tex/context/test/x-cals-test.xml b/tex/context/test/x-cals-test.xml index a41691acb..dc03668e3 100644 --- a/tex/context/test/x-cals-test.xml +++ b/tex/context/test/x-cals-test.xml @@ -395,4 +395,128 @@ + + + + + + + + + + + + + +

Grootheid

+
+ +

Eenheid

+
+ +

Symbool

+
+ +

Meetwaarden

+
+
+ + +

massa

+
+ + + +

125

+
+ +

195

+
+ +

280

+
+ +

380

+
+ +

500

+
+
+ + +

volume

+
+ + + +

16

+
+ +

25

+
+ +

36

+
+ +

49

+
+ +

64

+
+
+ + +

dichtheid

+
+ + + +

7,8

+
+ +

7,8

+
+ +

7,8

+
+ +

7,8

+
+ +

7,8

+
+
+
+
+
+ + diff --git a/tex/context/user/cont-sys.rme b/tex/context/user/cont-sys.rme index b90662cc3..335a7d984 100644 --- a/tex/context/user/cont-sys.rme +++ b/tex/context/user/cont-sys.rme @@ -121,6 +121,7 @@ % When you have your own fonts installed, you may want to predefine: % % \usetypescriptfile[type-buy] +% \usetypescriptfile [type-gyr] % Some styles default to Lucida Bright. You can overload % Lucida by Times cum suis. Watch out, the pos collection -- cgit v1.2.3