diff options
Diffstat (limited to 'Master/texmf-dist/tex/lualatex/simurgh/simurgh-unibidi.lua')
-rw-r--r-- | Master/texmf-dist/tex/lualatex/simurgh/simurgh-unibidi.lua | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/lualatex/simurgh/simurgh-unibidi.lua b/Master/texmf-dist/tex/lualatex/simurgh/simurgh-unibidi.lua new file mode 100644 index 00000000000..4b62c06561b --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/simurgh/simurgh-unibidi.lua @@ -0,0 +1,319 @@ +local err, warn, info = luatexbase.provides_module { + name = "simurgh-unibidi", + version = 0.01, + comment = "unicode bidi", + author = "Vafa Khalighi", + copyright = "Vafa Khalighi", + license = "see simurgh package documentation", + derived = "derived from import-typo-dir by Philipp Gesang" +} + +info "unicode bidi" + + + + + + +require "lualibs" -- we need the extended set + +local texsprint = tex.sprint +local stringformat = string.format +local tableconcat = table.concat +local copynode = node.copy + +----------------------------------------------------------------------- +--- prepare +----------------------------------------------------------------------- + +--- 1) wrap Luatexbase attribute handler in a Context style interface + +attributes = attributes or { } +local texsetattribute = tex.setattribute + + +local hidden = { + state = luatexbase.new_attribute ("typo-dir:state", true), + directions = luatexbase.new_attribute ("typo-dir:directions", true), + mathbidi = luatexbase.new_attribute ("typo-dir:mathbidi", true), +} + +local a_directions = hidden.directions + +attributes.private = attributes.private or function (attr_name) + local res = hidden [attr_name] + if not res then + res = luatexbase.new_attribute (attr_name) + end + return res +end + +local unsetvalue = luatexbase.get_unset_value () +attributes.unsetvalue = unsetvalue + +--- 2) simulate the multilingual interface; safe to purge afterwards +--- since Context uses local copies + +interfaces = interfaces or { } +interfaces.variables = interfaces.variables or { } +interfaces.variables.global = "global" +interfaces.variables["local"] = "local" +interfaces.variables.default = "default" +interfaces.variables.on = "on" +interfaces.variables.yes = "yes" + +--- 3) node tasks; we don’t have real node processors so we will need +--- to set up a makeshift interface + +nodes.tasks = nodes.tasks or { } +nodes.tasks.enableaction = function () end + +--- 4) commands namespace + +commands = commands or { } -- already present due to luaotfload-extrablibs + +--- 5) typesetters namespace +--- + +-- require "typo-krn" + +typesetters = typesetters or { } + +--- 6) the Context namespace; cannot be cleaned up without breaking +--- things; srsly there needs to be a non-Context equivalent for +--- this + +context = context or { } + +setmetatable (context, { + + --- this is quite primitive and considerably less functional than + --- the real deal as defined in cldf-ini.lua, but we already get + --- quite far with this reduced version + + __index = function (t, k) + + if k == "sprint" then + return function (...) texsprint (...) end + + elseif type (k) == "string" then + local command = [[\]] .. k + return function (...) + local res = { command } + for i = 1, select ("#", ...) do + --- just simple grouped arguments + res [#res + 1] = "{" + res [#res + 1] = select (i, ...) + res [#res + 1] = "}" + end + texsprint (tableconcat (res)) + end + + else + return context + end + end, + + __call = function (t, fmt, first, ...) + + if t == nil or fmt == nil then + return + end + + local tf = type (fmt) + + if tf == "string" then + if first then + texsprint (-1, stringformat (fmt, first, ...)) + else + texsprint (-1, fmt) + end + elseif tf == "function" then + texsprint (-1, fmt (first, ...)) + elseif first then --- and so on, + texsprint (-1, tostring (fmt), first, ...) + else + texsprint (-1, tostring (fmt)) + end + end, +}) + +--- 7) catcodes namespace + +catcodes = catcodes or { } +catcodes.numbers = catcodes.numbers or { } +catcodes.numbers.ctxcatcodes = -1 + +--- 8) whatsit prototype; expected to be present in the nodepool + +local n_textdir = node.new (node.id "whatsit", nodes.whatsitcodes.dir) +nodes.pool = nodes.pool or { } + +nodes.pool.textdir = function (dir) + local n = copynode (n_textdir) + n.dir = dir + return n +end + +--- 9) node identifiers + +nodes.nodecodes = table.mirrored (nodes.nodecodes) --> convenience + +---------------------------------------------------------------------- +--- import +----------------------------------------------------------------------- + +if not characters.directions then + require "simurgh-char-def" --> characters.data (unicode) + require "simurgh-char-ini" --> characters.* +end +--- the next three used to share “typo-dir.lua” before it was split +require "simurgh-unibidi-ini" --> typesetters.directions +require "simurgh-unibidi-core" --> typesetters.directions +require "simurgh-unibidi-math" --> typesetters.directions + +----------------------------------------------------------------------- +--- wrappers +----------------------------------------------------------------------- + +--- we use the *packagedata* namespace which should become canonical +--- anyways; also we keep a copy of typesetters.directions in a +--- subtable + +packagedata = packagedata or { } +local directions = typesetters.directions +local typo_dir = { directions = directions } +packagedata.typo_dir = typo_dir +local directionprocessor = directions.process +local mathdirectionprocessor = directions.processmath +local processorid = "typesetters.directions" + +--- emulate node tasks capability; we override the original definitions +--- of set() and setmath() with surrogates that work with Luatexbase +--- callback handlers + +directions.set = nil +directions.setmath = nil + + +--- we need to track which callbacks the node processor is hooked +--- into since we lack the combined version Context has + +local registered_as = { } --- procname -> callbacks + + +--- (node_t -> node_t) -> string -> string list -> bool + +local add_processor = function (processor, name, ...) + + for i=1, select ("#", ...) do + local callback = select (i, ...) + --- *IMPORTANT* the processor must be inserted at the top, + --- i.e. with a priority higher than any other callback! + luatexbase.add_to_callback (callback, processor, name, 1) + end + + registered_as [name] = { ... } + return true + +end + + +--- string -> bool + +local remove_processor = function (name) + + local callbacks = registered_as [name] + + if callbacks then + for i=1, #callbacks do + luatexbase.remove_from_callback (callbacks [i], name) + end + return true + end + + return false +end + +--- we use the same callbacks as a node processor in Context +--- unit -> bool + +local enabledirectionprocessor = function (math) + + local processor + + if math == true then + processor = function (hd) + --- different signature from the normal one + return mathdirectionprocessor (hd) + end + else + processor = function (hd) + return directionprocessor ("directions", a_directions, hd) + end + end + + return add_processor (processor, + processorid, + "pre_linebreak_filter", + "hpack_filter") +end + +typo_dir.enable = enabledirectionprocessor + + +--- unit -> bool +local disabledirectionprocessor = function ( ) + return remove_processor (processorid) +end + +typo_dir.disable = disabledirectionprocessor + + +local active = false --- activation state of direction processor + +typo_dir.set = function (n) + + if not n or n == 0 then + n = unsetvalue + end + + if not active then + info ("Installing simurgh direction handler (%d).", n) + enabledirectionprocessor () + active = true + end + + texsetattribute (a_directions, n) +end + + +local active = false --- activation state of math direction processor + +typo_dir.setmath = function (n) + + if not active and n and n > 0 then + info ("Installing simurgh math direction handler (%d).", n) + enabledirectionprocessor (true) + active = true + end +end + +typo_dir.getbidimode = directions.getbidimode + +typo_dir.getbidimode = function (specification) + context (directions.tomode (specification)) +end + +----------------------------------------------------------------------- +--- clean +----------------------------------------------------------------------- + +attributes.private = nil +attributes = nil +interfaces.variables = nil +interfaces = nil +nodes.tasks = nil + +collectgarbage "collect" + |