1 ------------------------------------------------------------------------
2 -- MAIN PROCESS STEP 3: insert \xkanjiskip (prefix: none)
3 ------------------------------------------------------------------------
5 local node_type = node.type
6 local node_new = node.new
7 local node_prev = node.prev
8 local node_next = node.next
9 local has_attr = node.has_attribute
10 local node_insert_before = node.insert_before
11 local node_insert_after = node.insert_after
12 local node_hpack = node.hpack
14 local id_penalty = node.id('penalty')
15 local id_glyph = node.id('glyph')
16 local id_glue = node.id('glue')
17 local id_glue_spec = node.id('glue_spec')
18 local id_kern = node.id('kern')
19 local id_hlist = node.id('hlist')
20 local id_ins = node.id('ins')
21 local id_mark = node.id('mark')
22 local id_adjust = node.id('adjust')
23 local id_math = node.id('math')
24 local id_whatsit = node.id('whatsit')
26 local attr_icflag = luatexbase.attributes['luatexja@icflag']
27 local attr_curjfnt = luatexbase.attributes['luatexja@curjfnt']
34 local insert_skip = no_skip
36 -- (glyph_node nr) ... (node nq) <GLUE> ,,, (node np)
40 local after_wchar = 2 -- nr is a Japanese glyph_node
41 local insert_skip = no_skip
43 local cstb_get_inhibit_xsp_table = ltj.int_get_inhibit_xsp_table
45 local function is_japanese_glyph_node(p)
46 return p and (p.id==id_glyph)
47 and (p.font==has_attr(p,attr_curjfnt))
50 -- the following 2 functions are the lowest part.
51 -- cx: the Kanji code of np
52 local function insert_ascii_kanji_xkskip(head,q,cx)
53 if cstb_get_inhibit_xsp_table(cx)<=1 then return end
54 local g = node_new(id_glue)
55 g.subtype = 0; g.spec = node.copy(xkanji_skip)
56 node_insert_after(head, q, g)
59 local function insert_kanji_ascii_xkskip(head,q,p)
62 while p.components and p.subtype
63 and math.floor(p.subtype/2)%2==1 do
64 p = p.components; c = p.char
66 if cstb_get_inhibit_xsp_table(c)%2 == 1 then
67 if cstb_get_inhibit_xsp_table(nrc)%2 == 0 then g = false end
72 g.subtype = 0; g.spec = node.copy(xkanji_skip)
73 node_insert_after(head, q, g)
78 local function set_insert_skip_after_achar(p)
80 while p.components and p.subtype
81 and math.floor(p.subtype/2)%2 == 1 do
82 p=node.tail(p.components); c = p.char
84 if cstb_get_inhibit_xsp_table(c)>=2 then
85 insert_skip = after_schar
91 -- When p is a glyph_node ...
92 local function insks_around_char(head)
93 if is_japanese_glyph_node(np) then
94 if insert_skip==after_wchar then
95 local g = node_new(id_glue)
96 g.subtype=0; g.spec=node.copy(kanji_skip)
97 node_insert_before(head, np, g)
98 elseif insert_skip==after_schar then
99 insert_ascii_kanji_xkskip(head, nq, np.char)
101 insert_skip=after_wchar; nrc = np.char
103 if insert_skip==after_wchar then
104 insert_kanji_ascii_xkskip(head, nq, np)
106 set_insert_skip_after_achar(np)
111 -- Return first and last glyph nodes in a hbox
112 local first_char = nil
113 local last_char = nil
114 local find_first_char = nil
115 local function check_box(box_ptr)
116 local p = box_ptr; local found_visible_node = false
118 if p.id==id_glyph then
120 if find_first_char then
121 first_char = p; find_first_char = false
123 last_char = p; found_visible_node = true; p=node_next(p)
124 if not p then return found_visible_node end
127 if p.id==id_hlist then
128 found_visible_node = true
130 if check_box(p.head) then found_visible_node = true end
131 else if find_first_char then
132 find_first_char = false
137 elseif p.id==id_ins or p.id==id_mark
138 or p.id==id_adjust or p.id==id_whatsit
139 or p.id==id_penalty then
142 found_visible_node = true
143 if find_first_char then
144 find_first_char = false
151 return found_visible_node
154 -- When np is a hlist_node ...
155 local function insks_around_hbox(head)
157 find_first_char = true; first_char = nil; last_char = nil
158 if check_box(np.head) then
160 if is_japanese_glyph_node(first_char) then
161 nrc = first_char.char
162 if insert_skip==after_schar then
163 insert_ascii_kanji_xkskip(head, nq, first_char.char)
164 elseif insert_skip==after_wchar then
165 local g = node_new(id_glue)
166 g.subtype = 0; g.spec = node.copy(kanji_skip)
167 node_insert_before(head, np, g)
169 insert_skip = after_wchar
170 elseif first_char then
171 if insert_skip==after_wchar then
172 insert_kanji_ascii_xkskip(head, nq, first_char)
174 set_insert_skip_after_achar(first_char)
177 if is_japanese_glyph_node(last_char) then
178 if is_japanese_glyph_node(node_next(np)) then
179 local g = node_new(id_glue)
180 g.subtype = 0; g.spec = node.copy(kanji_skip)
181 node_insert_after(head, np, g)
183 insert_skip = after_wchar; nrc = last_char.char
184 elseif last_char then
185 set_insert_skip_after_achar(last_char)
186 else insert_skip = no_skip
188 else insert_skip = no_skip
190 else insert_skip = no_skip
195 -- When np is a penalty ...
196 local function insks_around_penalty(head)
200 -- When np is a kern ...
202 local function insks_around_kern(head)
203 if np.subtype==1 then -- \kern or \/
204 local i = has_attr(np, attr_icflag)
205 if not i then -- \kern
206 insert_skip = no_skip
210 elseif np.subtype==2 then
211 -- (np = kern from \accent) .. (accent char) .. (kern from \accent) .. (glyph)
212 np = node_next(node_next(np))
216 -- When np is a math_node ...
217 local function insks_around_math(head)
218 local g = { char = -1 }
219 if (np.subtype==0) and (insert_skip==after_wchar) then
220 insert_kanji_ascii_xkskip(head, nq, g)
221 insert_skip = no_skip
223 nq = np; set_insert_skip_after_achar(g)
227 function ltj.int_insert_kanji_skip(head)
228 if ltj.auto_spacing then
229 kanji_skip=tex.skip['kanjiskip']
231 kanji_skip=node_new(id_glue_spec)
232 kanji_skip.width=0; kanji_skip.stretch=0; kanji_skip.shrink=0
234 if ltj.auto_xspacing then
235 xkanji_skip=tex.skip['xkanjiskip']
237 xkanji_skip=node_new(id_glue_spec)
238 xkanji_skip.width=0; xkanji_skip.stretch=0; xkanji_skip.shrink=0
240 np = head; nq = nil; insert_skip = no_skip
242 if np.id==id_glyph then
244 insks_around_char(head); np=node_next(np)
245 until (not np) or np.id~=id_glyph
247 if np.id==id_hlist then
248 insks_around_hbox(head)
249 elseif np.id==id_penalty then
250 insks_around_penalty(head)
251 elseif np.id==id_kern then
252 insks_around_kern(head)
253 elseif np.id==id_math then
254 insks_around_math(head)
255 elseif np.id==id_ins or np.id==id_mark
256 or np.id==id_adjust or np.id==id_whatsit then
260 -- rule, disc, glue, margin_kern
261 insert_skip = no_skip