1if not modules then modules = { } end modules ['s-languages-hyphenation'] = {
2 version = 1.001,
3 comment = "companion to s-languages-hyphenation.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
9moduledata.languages = moduledata.languages or { }
10moduledata.languages.hyphenation = moduledata.languages.hyphenation or { }
11
12local a_colormodel = attributes.private('colormodel')
13
14local tex = tex
15local context = context
16
17local nodecodes = nodes.nodecodes
18local nuts = nodes.nuts
19local nodepool = nuts.pool
20
21local disc_code = nodecodes.disc
22local glyph_code = nodecodes.glyph
23
24local emwidths = fonts.hashes.emwidths
25local exheights = fonts.hashes.exheights
26
27local newkern = nodepool.kern
28local newrule = nodepool.rule
29local newglue = nodepool.glue
30
31local insertnodeafter = nuts.insertafter
32
33local nextglyph = nuts.traversers.glyph
34
35local tonut = nodes.tonut
36local tonode = nodes.tonode
37local getid = nuts.getid
38local getnext = nuts.getnext
39local getdisc = nuts.getdisc
40local getattr = nuts.getattr
41local getfont = nuts.getfont
42local getfield = nuts.getfield
43local getlanguage = nuts.getlanguage
44local setlanguage = nuts.setlanguage
45local setlink = nuts.setlink
46local setdisc = nuts.setdisc
47local setfield = nuts.setfield
48local free_node = nuts.free
49
50local tracers = nodes.tracers
51local colortracers = tracers and tracers.colors
52local setnodecolor = colortracers.set
53
54
55
56local states = table.setmetatableindex(function(t,k)
57 return {
58 lefthyphenmin = tex.lefthyphenmin,
59 righthyphenmin = tex.righthyphenmin,
60 hyphenationmin = tex.hyphenationmin,
61 prehyphenchar = tex.prehyphenchar,
62 posthyphenchar = tex.posthyphenchar,
63 }
64end)
65
66local currentlanguage = language.current or function() return tex.language end
67
68interfaces.implement {
69 name = "storelanguagestate",
70 actions = function()
71 states[currentlanguage()] = {
72 lefthyphenmin = tex.lefthyphenmin,
73 righthyphenmin = tex.righthyphenmin,
74 hyphenationmin = tex.hyphenationmin,
75 prehyphenchar = tex.prehyphenchar,
76 posthyphenchar = tex.posthyphenchar,
77 }
78 end
79}
80
81function moduledata.languages.getstate(l)
82 return states[l]
83end
84
85
86
87local function identify(head,marked)
88 local current = tonut(head)
89 local prev = nil
90 while current do
91 local id = getid(current)
92 local next = getnext(current)
93 if id == disc_code then
94 if prev and next then
95 marked[#marked+1] = prev
96 local pre, post, replace, pre_tail, post_tail, replace_tail = getdisc(current,true)
97 if replace then
98 setlink(prev,replace)
99 setlink(replace_tail,next)
100 setdisc(pre,post,nil)
101 prev = tail
102 else
103 setlink(prev,next)
104 end
105 free_node(current)
106 end
107 elseif id == glyph_code then
108 prev = current
109 else
110 prev = nil
111 end
112 current = next
113 end
114end
115
116local function mark(head,marked,w,h,d,how)
117 head = tonut(head)
118 for i=1,#marked do
119 local current = marked[i]
120 local font = getfont(current)
121 local em = emwidths[font]
122 local ex = exheights[font]
123 local width = w*em
124 local rule = newrule(width,h*ex,d*ex)
125 head, current = insertnodeafter(head,current,newkern(-width/2))
126 head, current = insertnodeafter(head,current,rule)
127 head, current = insertnodeafter(head,current,newkern(-width/2))
128 head, current = insertnodeafter(head,current,newglue(0))
129 setnodecolor(rule,how)
130 end
131end
132
133local langs = { }
134local tags = { }
135local noflanguages = 0
136local colorbytag = false
137
138function moduledata.languages.hyphenation.showhyphens(head)
139 if noflanguages > 0 then
140 local marked = { }
141 local cached = { }
142
143 for n in nextglyph, tonut(head) do
144 cached[n] = {
145 getlanguage(n),
146 getfield(n,"left"),
147 getfield(n,"right")
148 }
149 end
150 for i=1,noflanguages do
151 local m = { }
152 local l = langs[i]
153 local s = states[l]
154 marked[i] = m
155 local lmin = s.lefthyphenmin
156 local rmin = s.righthyphenmin
157 for n in next, cached do
158 setlanguage(n,l)
159 setfield(n,"left",lmin)
160 setfield(n,"right",rmin)
161 end
162 languages.hyphenators.methods.original(head)
163 identify(head,m)
164 end
165 for i=noflanguages,1,-1 do
166 local l = noflanguages - i + 1
167 mark(head,marked[i],1/16,l/2,l/4,"hyphenation:"..(colorbytag and tags[i] or i))
168 end
169 for n, d in next, cached do
170 setlanguage(n,d[1])
171 setfield(n,"left",d[2])
172 setfield(n,"right",d[3])
173 end
174 return head, true
175 else
176 return head, false
177 end
178end
179
180function moduledata.languages.hyphenation.startcomparepatterns(list)
181 if list and list ~= "" then
182 tags = utilities.parsers.settings_to_array(list)
183 end
184 noflanguages = #tags
185 context.begingroup()
186 for i=1,noflanguages do
187 langs[i] = tags[i] and languages.getnumber(tags[i])
188 context.language{tags[i]}
189 end
190 context.endgroup()
191 nodes.tasks.enableaction("processors","moduledata.languages.hyphenation.showhyphens")
192end
193
194function moduledata.languages.hyphenation.stopcomparepatterns()
195 noflanguages = 0
196 nodes.tasks.disableaction("processors","moduledata.languages.hyphenation.showhyphens")
197end
198
199function moduledata.languages.hyphenation.showcomparelegend(list)
200 if list and list ~= "" then
201 tags = utilities.parsers.settings_to_array(list)
202 end
203 for i=1,#tags do
204 if i > 1 then
205 context.enspace()
206 end
207 context.color( { "hyphenation:"..(colorbytag and tags[i] or i) }, tags[i])
208 end
209end
210
211nodes.tasks.appendaction("processors","before","moduledata.languages.hyphenation.showhyphens")
212nodes.tasks.disableaction("processors","moduledata.languages.hyphenation.showhyphens")
213 |