1if not modules then modules = { } end modules ['typo-dir'] = {
2 version = 1.001,
3 comment = "companion to typo-dir.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29local next, type = next, type
30local format, insert, sub, find, match = string.format, table.insert, string.sub, string.find, string.match
31
32local nodes, node = nodes, node
33
34local trace_textdirections = false trackers.register("typesetters.directions.text", function(v) trace_textdirections = v end)
35local trace_mathdirections = false trackers.register("typesetters.directions.math", function(v) trace_mathdirections = v end)
36local trace_directions = false trackers.register("typesetters.directions", function(v) trace_textdirections = v trace_mathdirections = v end)
37
38local one_too = false directives.register("typesetters.directions.onetoo", function(v) one_too = v end)
39
40local report_textdirections = logs.reporter("typesetting","text directions")
41
42
43local texsetattribute = tex.setattribute
44local unsetvalue = attributes.unsetvalue
45
46local nuts = nodes.nuts
47local getnext = nuts.getnext
48local getattr = nuts.getattr
49
50local enableaction = nodes.tasks.enableaction
51local tracers = nodes.tracers
52local setcolor = tracers.colors.set
53local resetcolor = tracers.colors.reset
54
55local implement = interfaces.implement
56
57local directions = typesetters.directions or { }
58typesetters.directions = directions
59
60local a_directions = attributes.private('directions')
61
62local variables = interfaces.variables
63local v_global = variables["global"]
64local v_local = variables["local"]
65local v_on = variables.on
66local v_yes = variables.yes
67
68local m_enabled = 0x00000040
69local m_global = 0x00000080
70local m_fences = 0x00000100
71
72local handlers = { }
73local methods = { }
74local lastmethod = 0
75
76local function installhandler(name,handler)
77 local method = methods[name]
78 if not method then
79 lastmethod = lastmethod + 1
80 method = lastmethod
81 methods[name] = method
82 end
83 handlers[method] = handler
84 return method
85end
86
87directions.handlers = handlers
88directions.installhandler = installhandler
89
90local function tomode(specification)
91 local scope = specification.scope
92 local mode
93 if scope == v_global or scope == v_on then
94 mode = m_enabled + m_global
95 elseif scope == v_local then
96 mode = m_enabled
97 else
98 return 0
99 end
100 local method = methods[specification.method]
101 if method then
102 mode = mode + method
103 else
104 return 0
105 end
106 if specification.fences == v_yes then
107 mode = mode + m_fences
108 end
109 return mode
110end
111
112local function getglobal(a)
113 return a and a > 0 and (a & m_global) ~= 0
114end
115
116local function getfences(a)
117 return a and a > 0 and (a & m_fences) ~= 0
118end
119
120local function getmethod(a)
121 return a and a > 0 and a % m_enabled or 0
122end
123
124directions.tomode = tomode
125directions.getglobal = getglobal
126directions.getfences = getfences
127directions.getmethod = getmethod
128directions.installhandler = installhandler
129
130
131
132function directions.setcolor(current,direction,reversed,mirror)
133 if mirror then
134 setcolor(current,"bidi:mirrored")
135 elseif direction == "l" then
136 setcolor(current,reversed and "bidi:left:reversed" or "bidi:left:original")
137 elseif direction == "r" then
138 setcolor(current,reversed and "bidi:right:reversed" or "bidi:right:original")
139 else
140 resetcolor(current)
141 end
142end
143
144implement {
145 name = "getbidimode",
146 actions = { tomode, context },
147 arguments = {
148 {
149 { "scope" },
150 { "method" },
151 { "fences" },
152 }
153 }
154}
155
156local enabled = false
157
158local starttiming = statistics.starttiming
159local stoptiming = statistics.stoptiming
160
161
162
163
164
165
166
167function directions.handler(head,where,direction)
168 local only_one = not getnext(head)
169 if only_one and not one_too then
170 return head
171 end
172 local attr = getattr(head,a_directions)
173 if not attr or attr == 0 then
174 return head
175 end
176 local method = getmethod(attr)
177 local handler = handlers[method]
178 if not handler then
179 return head
180 end
181 starttiming(directions)
182 head = handler(head,direction,only_one,where)
183 stoptiming(directions)
184 return head
185end
186
187statistics.register("text directions", function()
188 if enabled then
189 return statistics.elapsedseconds(directions)
190 end
191end)
192
193function directions.set(n)
194 if not enabled then
195 if trace_textdirections then
196 report_textdirections("enabling directions handler")
197 end
198 enableaction("processors","typesetters.directions.handler")
199 enabled = true
200 end
201 if not n or n == 0 then
202 n = unsetvalue
203
204 end
205 texsetattribute(a_directions,n)
206end
207
208implement {
209 name = "setdirection",
210 arguments = "integer",
211 actions = directions.set
212}
213 |