typo-dir.lua /size: 7396 b    last modification: 2020-07-01 14:35
1
if
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
-- When we started with this, there were some issues in luatex so we needed to take care of
10
-- intereferences. Some has been improved but we stil might end up with each node having a
11
-- dir property. Now, the biggest problem is that there is an official bidi algorithm but
12
-- some searching on the web shows that there are many confusing aspects and therefore
13
-- proposals circulate about (sometimes imcompatible ?) improvements. In the end it all boils
14
-- down to the lack of willingness to tag an input source. Of course tagging of each number
15
-- and fenced strip is somewhat over the top, but now it has to be captured in logic. Texies
16
-- normally have no problem with tagging but we need to handle any input. So, what we have
17
-- done here (over the years) is starting from what we expect to see happen, especially with
18
-- respect to punctation, numbers and fences. Eventually alternative algorithms will be provides
19
-- so that users can choose (the reason why suggestion sfor improvements circulate on the web
20
-- is that it is non trivial to predict the expected behaviour so one hopes that the ditor
21
-- and the rest of the machinery match somehow. Anyway, the fun of tex is that it has no hard
22
-- coded behavior. And ... we also want to have more debugging and extras and ... so we want
23
-- a flexible approach. In the end we will have:
24
--
25
-- = full tagging (mechanism turned off)
26
-- = half tagging (the current implementation)
27
-- = unicode version x interpretation (several depending on the evolution)
28 29
local
next
,
type
=
next
,
type
30
local
format
,
insert
,
sub
,
find
,
match
=
string
.
format
,
table
.
insert
,
string
.
sub
,
string
.
find
,
string
.
match
31 32
local
nodes
,
node
=
nodes
,
node
33 34
local
trace_textdirections
=
false
trackers
.
register
(
"
typesetters.directions.text
"
,
function
(
v
)
trace_textdirections
=
v
end
)
35
local
trace_mathdirections
=
false
trackers
.
register
(
"
typesetters.directions.math
"
,
function
(
v
)
trace_mathdirections
=
v
end
)
36
local
trace_directions
=
false
trackers
.
register
(
"
typesetters.directions
"
,
function
(
v
)
trace_textdirections
=
v
trace_mathdirections
=
v
end
)
37 38
local
one_too
=
false
directives
.
register
(
"
typesetters.directions.onetoo
"
,
function
(
v
)
one_too
=
v
end
)
39 40
local
report_textdirections
=
logs
.
reporter
(
"
typesetting
"
,
"
text directions
"
)
41
----- report_mathdirections = logs.reporter("typesetting","math directions")
42 43
local
band
=
bit32
.
band
44 45
local
texsetattribute
=
tex
.
setattribute
46
local
unsetvalue
=
attributes
.
unsetvalue
47 48
local
nuts
=
nodes
.
nuts
49
local
getnext
=
nuts
.
getnext
50
local
getattr
=
nuts
.
getattr
51 52
local
enableaction
=
nodes
.
tasks
.
enableaction
53
local
tracers
=
nodes
.
tracers
54
local
setcolor
=
tracers
.
colors
.
set
55
local
resetcolor
=
tracers
.
colors
.
reset
56 57
local
implement
=
interfaces
.
implement
58 59
local
directions
=
typesetters
.
directions
or
{
}
60
typesetters
.
directions
=
directions
61 62
local
a_directions
=
attributes
.
private
(
'
directions
'
)
63 64
local
variables
=
interfaces
.
variables
65
local
v_global
=
variables
[
"
global
"
]
66
local
v_local
=
variables
[
"
local
"
]
67
local
v_on
=
variables
.
on
68
local
v_yes
=
variables
.
yes
69 70
local
m_enabled
=
0x00000040
-- 2^6 64
71
local
m_global
=
0x00000080
-- 2^7
72
local
m_fences
=
0x00000100
-- 2^8
73 74
local
handlers
=
{
}
75
local
methods
=
{
}
76
local
lastmethod
=
0
77 78
local
function
installhandler
(
name
,
handler
)
79
local
method
=
methods
[
name
]
80
if
not
method
then
81
lastmethod
=
lastmethod
+
1
82
method
=
lastmethod
83
methods
[
name
]
=
method
84
end
85
handlers
[
method
]
=
handler
86
return
method
87
end
88 89
directions
.
handlers
=
handlers
90
directions
.
installhandler
=
installhandler
91 92
local
function
tomode
(
specification
)
93
local
scope
=
specification
.
scope
94
local
mode
95
if
scope
=
=
v_global
or
scope
=
=
v_on
then
96
mode
=
m_enabled
+
m_global
97
elseif
scope
=
=
v_local
then
98
mode
=
m_enabled
99
else
100
return
0
101
end
102
local
method
=
methods
[
specification
.
method
]
103
if
method
then
104
mode
=
mode
+
method
105
else
106
return
0
107
end
108
if
specification
.
fences
=
=
v_yes
then
109
mode
=
mode
+
m_fences
110
end
111
return
mode
112
end
113 114
local
function
getglobal
(
a
)
115
return
a
and
a
>
0
and
band
(
a
,
m_global
)
~
=
0
116
end
117 118
local
function
getfences
(
a
)
119
return
a
and
a
>
0
and
band
(
a
,
m_fences
)
~
=
0
120
end
121 122
local
function
getmethod
(
a
)
123
return
a
and
a
>
0
and
a
%
m_enabled
or
0
124
end
125 126
directions
.
tomode
=
tomode
127
directions
.
getglobal
=
getglobal
128
directions
.
getfences
=
getfences
129
directions
.
getmethod
=
getmethod
130
directions
.
installhandler
=
installhandler
131 132
-- beware: in dha we have character properties and in dua|b we have direction properties
133 134
function
directions
.
setcolor
(
current
,
direction
,
reversed
,
mirror
)
135
if
mirror
then
136
setcolor
(
current
,
"
bidi:mirrored
"
)
137
elseif
direction
=
=
"
l
"
then
138
setcolor
(
current
,
reversed
and
"
bidi:left:reversed
"
or
"
bidi:left:original
"
)
139
elseif
direction
=
=
"
r
"
then
140
setcolor
(
current
,
reversed
and
"
bidi:right:reversed
"
or
"
bidi:right:original
"
)
141
else
142
resetcolor
(
current
)
143
end
144
end
145 146
implement
{
147
name
=
"
getbidimode
"
,
148
actions
=
{
tomode
,
context
}
,
149
arguments
=
{
150
{
151
{
"
scope
"
}
,
152
{
"
method
"
}
,
153
{
"
fences
"
}
,
154
}
155
}
156
}
157 158
local
enabled
=
false
159 160
local
starttiming
=
statistics
.
starttiming
161
local
stoptiming
=
statistics
.
stoptiming
162 163
-- If we have hbox{!} then the hbox determines the direction but we can consider
164
-- a fast analysis, not that it matters much because there's nothing to swap in
165
-- the list unless one glyphs becomes multiple (can that really happen?).
166
--
167
-- \enabledirectives[typesetters.directions.onetoo]
168 169
function
directions
.
handler
(
head
,
where
,
_
,
_
,
direction
)
170
local
only_one
=
not
getnext
(
head
)
171
if
only_one
and
not
one_too
then
172
return
head
173
end
174
local
attr
=
getattr
(
head
,
a_directions
)
175
if
not
attr
or
attr
=
=
0
then
176
return
head
177
end
178
local
method
=
getmethod
(
attr
)
179
local
handler
=
handlers
[
method
]
180
if
not
handler
then
181
return
head
182
end
183
starttiming
(
directions
)
184
head
=
handler
(
head
,
direction
,
only_one
,
where
)
185
stoptiming
(
directions
)
186
return
head
187
end
188 189
statistics
.
register
(
"
text directions
"
,
function
(
)
190
if
enabled
then
191
return
statistics
.
elapsedseconds
(
directions
)
192
end
193
end
)
194 195
function
directions
.
set
(
n
)
-- todo: names and numbers
196
if
not
enabled
then
197
if
trace_textdirections
then
198
report_textdirections
(
"
enabling directions handler
"
)
199
end
200
enableaction
(
"
processors
"
,
"
typesetters.directions.handler
"
)
201
enabled
=
true
202
end
203
if
not
n
or
n
=
=
0
then
204
n
=
unsetvalue
205
-- maybe tracing
206
end
207
texsetattribute
(
a_directions
,
n
)
208
end
209 210
implement
{
211
name
=
"
setdirection
"
,
212
arguments
=
"
integer
"
,
213
actions
=
directions
.
set
214
}
215