summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/typo-dir.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/typo-dir.lua')
-rw-r--r--tex/context/base/mkiv/typo-dir.lua207
1 files changed, 207 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/typo-dir.lua b/tex/context/base/mkiv/typo-dir.lua
new file mode 100644
index 000000000..482b7114d
--- /dev/null
+++ b/tex/context/base/mkiv/typo-dir.lua
@@ -0,0 +1,207 @@
+if not modules then modules = { } end modules ['typo-dir'] = {
+ version = 1.001,
+ comment = "companion to typo-dir.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- When we started with this, there were some issues in luatex so we needed to take care of
+-- intereferences. Some has been improved but we stil might end up with each node having a
+-- dir property. Now, the biggest problem is that there is an official bidi algorithm but
+-- some searching on the web shows that there are many confusing aspects and therefore
+-- proposals circulate about (sometimes imcompatible ?) improvements. In the end it all boils
+-- down to the lack of willingness to tag an input source. Of course tagging of each number
+-- and fenced strip is somewhat over the top, but now it has to be captured in logic. Texies
+-- normally have no problem with tagging but we need to handle any input. So, what we have
+-- done here (over the years) is starting from what we expect to see happen, especially with
+-- respect to punctation, numbers and fences. Eventually alternative algorithms will be provides
+-- so that users can choose (the reason why suggestion sfor improvements circulate on the web
+-- is that it is non trivial to predict the expected behaviour so one hopes that the ditor
+-- and the rest of the machinery match somehow. Anyway, the fun of tex is that it has no hard
+-- coded behavior. And ... we also want to have more debugging and extras and ... so we want
+-- a flexible approach. In the end we will have:
+--
+-- = full tagging (mechanism turned off)
+-- = half tagging (the current implementation)
+-- = unicode version x interpretation (several depending on the evolution)
+
+local next, type = next, type
+local format, insert, sub, find, match = string.format, table.insert, string.sub, string.find, string.match
+local utfchar = utf.char
+local formatters = string.formatters
+
+local nodes, node = nodes, node
+
+local trace_textdirections = false trackers.register("typesetters.directions.text", function(v) trace_textdirections = v end)
+local trace_mathdirections = false trackers.register("typesetters.directions.math", function(v) trace_mathdirections = v end)
+local trace_directions = false trackers.register("typesetters.directions", function(v) trace_textdirections = v trace_mathdirections = v end)
+
+local report_textdirections = logs.reporter("typesetting","text directions")
+local report_mathdirections = logs.reporter("typesetting","math directions")
+
+local hasbit = number.hasbit
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local tasks = nodes.tasks
+local tracers = nodes.tracers
+local setcolor = tracers.colors.set
+local resetcolor = tracers.colors.reset
+
+local implement = interfaces.implement
+
+local directions = typesetters.directions or { }
+typesetters.directions = directions
+
+local a_directions = attributes.private('directions')
+
+local variables = interfaces.variables
+local v_global = variables["global"]
+local v_local = variables["local"]
+local v_on = variables.on
+local v_yes = variables.yes
+
+local m_enabled = 2^6 -- 64
+local m_global = 2^7
+local m_fences = 2^8
+
+local handlers = { }
+local methods = { }
+local lastmethod = 0
+
+local function installhandler(name,handler)
+ local method = methods[name]
+ if not method then
+ lastmethod = lastmethod + 1
+ method = lastmethod
+ methods[name] = method
+ end
+ handlers[method] = handler
+ return method
+end
+
+directions.handlers = handlers
+directions.installhandler = installhandler
+
+local function tomode(specification)
+ local scope = specification.scope
+ local mode
+ if scope == v_global or scope == v_on then
+ mode = m_enabled + m_global
+ elseif scope == v_local then
+ mode = m_enabled
+ else
+ return 0
+ end
+ local method = methods[specification.method]
+ if method then
+ mode = mode + method
+ else
+ return 0
+ end
+ if specification.fences == v_yes then
+ mode = mode + m_fences
+ end
+ return mode
+end
+
+local function getglobal(a)
+ return a and a > 0 and hasbit(a,m_global)
+end
+
+local function getfences(a)
+ return a and a > 0 and hasbit(a,m_fences)
+end
+
+local function getmethod(a)
+ return a and a > 0 and a % m_enabled or 0
+end
+
+directions.tomode = tomode
+directions.getglobal = getglobal
+directions.getfences = getfences
+directions.getmethod = getmethod
+directions.installhandler = installhandler
+
+-- beware: in dha we have character properties and in dua|b we have direction properties
+
+function directions.setcolor(current,direction,reversed,mirror)
+ if mirror then
+ setcolor(current,"bidi:mirrored")
+ elseif direction == "l" then
+ setcolor(current,reversed and "bidi:left:reversed" or "bidi:left:original")
+ elseif direction == "r" then
+ setcolor(current,reversed and "bidi:right:reversed" or "bidi:right:original")
+ else
+ resetcolor(current)
+ end
+end
+
+implement {
+ name = "getbidimode",
+ actions = { tomode, context },
+ arguments = {
+ {
+ { "scope" },
+ { "method" },
+ { "fences" },
+ }
+ }
+}
+
+local enabled = false
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+function directions.handler(head) -- ,_,_,_,direction) -- nodes not nuts | 5th arg is direction
+ if not head.next then
+ return head, false
+ end
+ local attr = head[a_directions]
+ if not attr or attr == 0 then
+ return head, false
+ end
+ local method = getmethod(attr)
+ local handler = handlers[method]
+ if not handler then
+ return head, false
+ end
+ starttiming(directions)
+ local head, done = handler(head)
+ stoptiming(directions)
+ return head, done
+end
+
+statistics.register("text directions", function()
+ if enabled then
+ return statistics.elapsedseconds(directions)
+ end
+end)
+
+-- function directions.enable()
+-- tasks.enableaction("processors","directions.handler")
+-- end
+
+function directions.set(n) -- todo: names and numbers
+ if not enabled then
+ if trace_textdirections then
+ report_textdirections("enabling directions handler")
+ end
+ tasks.enableaction("processors","typesetters.directions.handler")
+ enabled = true
+ end
+ if not n or n == 0 then
+ n = unsetvalue
+ -- maybe tracing
+ end
+ texsetattribute(a_directions,n)
+end
+
+implement {
+ name = "setdirection",
+ arguments = "integer",
+ actions = directions.set
+}