1if not modules then modules = { } end modules ['math-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
20local nodes, node = nodes, node
21
22local trace_directions = false trackers.register("typesetters.directions.math", function(v) trace_directions = v end)
23
24local report_directions = logs.reporter("typesetting","math directions")
25
26local nuts = nodes.nuts
27local tonut = nuts.tonut
28local tonode = nuts.tonode
29
30local getnext = nuts.getnext
31local getchar = nuts.getchar
32local getid = nuts.getid
33local getlist = nuts.getlist
34local getattr = nuts.getattr
35
36local setchar = nuts.setchar
37local setlist = nuts.setlist
38
39local insertnodebefore = nuts.insertbefore
40local insertnodeafter = nuts.insertafter
41
42local nodecodes = nodes.nodecodes
43local enableaction = nodes.tasks.enableaction
44
45local glyph_code = nodecodes.glyph
46local hlist_code = nodecodes.hlist
47local vlist_code = nodecodes.vlist
48
49local nodepool = nuts.pool
50
51local new_direction = nodepool.direction
52
53local lefttoright_code = nodes.dirvalues.lefttoright
54
55local chardirections = characters.directions
56local charmirrors = characters.mirrors
57local charclasses = characters.textclasses
58
59local directions = typesetters.directions or { }
60
61local a_mathbidi = attributes.private('mathbidi')
62
63local function processmath(head)
64 local current = head
65 local start = nil
66 local stop = nil
67 local function capsulate()
68 head = insertnodebefore(head,start,new_direction(lefttoright_code))
69 insertnodeafter(head,stop,new_direction(lefttoright_code,true))
70 if trace_directions then
71 report_directions("reversed: %s",nodes.listtoutf(start,false,false,stop))
72 end
73 start = false
74 stop = nil
75 end
76 while current do
77 local id = getid(current)
78 if id == glyph_code then
79 local char = getchar(current)
80 local cdir = chardirections[char]
81 if cdir == "en" or cdir == "an" then
82 if not start then
83 start = current
84 end
85 stop = current
86 else
87 if not start then
88
89 elseif start == stop then
90 start = nil
91 else
92 capsulate()
93 end
94 if cdir == "on" then
95 local mirror = charmirrors[char]
96 if mirror then
97 local class = charclasses[char]
98 if class == "open" or class == "close" then
99 setchar(current,mirror)
100 if trace_directions then
101 report_directions("mirrored: %C to %C",char,mirror)
102 end
103 end
104 end
105 end
106 end
107 elseif not start then
108
109 if id == hlist_code or id == vlist_code then
110 local list = processmath(getlist(current))
111 setlist(current,list)
112 end
113 elseif start == stop then
114 start = nil
115 else
116 capsulate(head,start,stop)
117
118
119 if id == hlist_code or id == vlist_code then
120 local list = processmath(getlist(current))
121 setlist(current,list)
122 end
123 end
124 current = getnext(current)
125 end
126 if not start then
127
128 elseif start == stop then
129
130 else
131 capsulate()
132 end
133 return head
134end
135
136local enabled = false
137
138function directions.processmath(head)
139 if enabled then
140 local a = getattr(head,a_mathbidi)
141 if a and a > 0 then
142 return processmath(head)
143 end
144 end
145 return head
146end
147
148function directions.setmath(n)
149 if not enabled and n and n > 0 then
150 if trace_directions then
151 report_directions("enabling directions handler")
152 end
153 enableaction("math","typesetters.directions.processmath")
154 enabled = true
155 end
156end
157
158interfaces.implement {
159 name = "setmathdirection",
160 actions = directions.setmath,
161 arguments = "integer"
162}
163 |