summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/lualatex/simurgh/simurgh-unibidi.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/lualatex/simurgh/simurgh-unibidi.lua')
-rw-r--r--Master/texmf-dist/tex/lualatex/simurgh/simurgh-unibidi.lua319
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"
+