改行した箇所には自動的に空白が入るようになっている.
だが,日本語ではそのような振る舞いは不自然であり,p\TeX でも
「和文文字で行が終わった場合,改行文字は無視する」という
-使ç\94¨になっている.
+ä»\95æ§\98になっている.
そこで,入力が和文文字で終わった場合,コメント文字を挿入することにより
-この問題を解決する方法をとっている.
+この問題を解決する方法をとっている.{\small
この部分のコードは前田氏のjafontspecパッケージの部分から拝借したが,挿入する文字を|%|から
-(通常使用されることはないと思われる)|U+FFFFF|へと変更している.
+(通常使用されることはないと思われる)|U+FFFFF|へと変更している.}
+
+しかし,現行Lua\TeX の仕様により,完全にp\TeX と同じというわけには
+いかず,次のような動作になっている:
+\itemitem 入力行の末尾が,正規表現で
+\begintt
+[:jchar:][\{\}]^*$
+\endtt
+となっている場合,即ち,{\bf catcodeが11 or 12の和文文字の後に,
+グループ境界文字(catcodeが1 or 2の文字.通常は\hskip\ltjgetparameter{xkanjiskip}|{|%
+\hskip\ltjgetparameter{xkanjiskip}や\hskip\ltjgetparameter{xkanjiskip}|}|%
+\hskip\ltjgetparameter{xkanjiskip})が任意個続いて
+行が終わっていた}場合,この行の入力にコメント文字を追加.
+\itemitem 上の「和文文字」「グループ境界文字」の判定は,処理対象の入力行の前行末尾の時点の
+設定値をもとに行う.そのため,行の途中でcatcodeの変更を行った場合などで,p\TeX と異なる挙動
+を示す場合がある.
\item {\bf 和文フォントへの置換: |hyphenate| callback}
%% Load Lua modules.
\RequireLuaModule{luatexja.base}
\RequireLuaModule{luatexja.tangle}
+\RequireLuaModule{luatexja.charrange}
\RequireLuaModule{luatexja.stack}
+\RequireLuaModule{luatexja.inputbuf}
%%------------------ Tiny helpers
\unless\ifx\ltj@@cctb@org@def\newluatexcatcodetable
% Failure: luatexbase-cctb is not of expected version!
-\bebo
+%%% \bebo <- the meaning of this control sequence?
\ltj@@cctb@failure=3 %
\fi
local lang_ja = lang_ja_token[2]
--
-local rgjc_get_range_setting = ltj.int_get_range_setting
-local rgjc_char_to_range = ltj.int_char_to_range
-local rgjc_is_ucs_in_japanese_char = ltj.int_is_ucs_in_japanese_char
local ljfm_find_char_class = ltj.int_find_char_class
function math.two_add(a,b) return a+b end
function math.two_average(a,b) return (a+b)/2 end
-------------------------------------------------------------------------
--- CODE FOR STACK TABLE FOR CHARACTER PROPERTIES (prefix: cstb)
-------------------------------------------------------------------------
-
---- table: charprop_stack_table [stack_level][chr_code].{pre|post|xsp}
-local charprop_stack_table={}; charprop_stack_table[0]={}
-
-local function cstb_get_stack_level()
- local i = tex.getcount('ltj@@stack')
- local j = tex.currentgrouplevel
- if j > tex.getcount('ltj@@group@level') then
- i = i+1 -- new stack level
- tex.setcount('ltj@@group@level', j)
- for k,v in pairs(charprop_stack_table) do -- clear the stack above i
- if k>=i then charprop_stack_table[k]=nil end
- end
- charprop_stack_table[i] = table.fastcopy(charprop_stack_table[i-1])
- tex.setcount('ltj@@stack', i)
- local g = node_new(id_whatsit, sid_user)
- g.user_id=30112; g.type=100; g.value=j; node.write(g)
- end
- return i
-end
-
--- EXT
-function ltj.ext_set_stack_table(g,m,c,p,lb,ub)
- local i = cstb_get_stack_level()
- if p<lb or p>ub then
- ltj.error('Invalid code (' .. p .. '), should in the range '
- .. tostring(lb) .. '..' .. tostring(ub) .. '.',
- {"I'm going to use 0 instead of that illegal code value."})
- p=0
- elseif c<-1 or c>0x10FFFF then
- ltj.error('Invalid character code (' .. c
- .. '), should in the range -1.."10FFFF.',{})
- return
- elseif not charprop_stack_table[i][c] then
- charprop_stack_table[i][c] = {}
- end
- charprop_stack_table[i][c][m] = p
- if g=='global' then
- for j,v in pairs(charprop_stack_table) do
- if not charprop_stack_table[j][c] then charprop_stack_table[j][c] = {} end
- charprop_stack_table[j][c][m] = p
- end
- end
-end
-
--- EXT: store \ltj@tempskipa
-function ltj.ext_set_stack_skip(g,c)
- local i = cstb_get_stack_level()
- local sp = tex.getskip('ltj@tempskipa')
- if not charprop_stack_table[i][c] then
- charprop_stack_table[i][c] = {}
- end
- charprop_stack_table[i][c].width = sp.width
- charprop_stack_table[i][c].stretch = sp.stretch
- charprop_stack_table[i][c].shrink = sp.shrink
- charprop_stack_table[i][c].stretch_order = sp.stretch_order
- charprop_stack_table[i][c].shrink_order = sp.shrink_order
- if g=='global' then
- for j,v in pairs(charprop_stack_table) do
- if not charprop_stack_table[j][c] then charprop_stack_table[j][c] = {} end
- charprop_stack_table[j][c].width = sp.width
- charprop_stack_table[j][c].stretch = sp.stretch
- charprop_stack_table[j][c].shrink = sp.shrink
- charprop_stack_table[j][c].stretch_order = sp.stretch_order
- charprop_stack_table[j][c].shrink_order = sp.shrink_order
- end
- end
-end
-
--- mode: nil iff it is called in callbacks
-local function cstb_get_skip_table(m, idx)
- local i = charprop_stack_table[idx][m]
- return i or { width = 0, stretch = 0, shrink = 0,
- stretch_order = 0, shrink_order = 0 }
-end
-ltj.int_get_skip_table = cstb_get_skip_table
-
-local function cstb_get_penalty_table(m,c,d, idx)
- local i = charprop_stack_table[idx][c]
- if i then i=i[m] end
- return i or d
-end
-ltj.int_get_penalty_table = cstb_get_penalty_table
------------------------------------------------------------------------
-- CODE FOR GETTING/SETTING PARAMETERS
elseif k == 'yjabaselineshift' then
tex.write(print_scaled(tex.getattribute('ltj@ykblshift'))..'pt')
elseif k == 'kanjiskip' then
- tex.write(print_spec(cstb_get_skip_table('kanjiskip', tex.getcount('ltj@@stack'))))
+ tex.write(print_spec(luatexja.stack.get_skip_table('kanjiskip', tex.getcount('ltj@@stack'))))
elseif k == 'xkanjiskip' then
- tex.write(print_spec(cstb_get_skip_table('xkanjiskip', tex.getcount('ltj@@stack'))))
+ tex.write(print_spec(luatexja.stack.get_skip_table('xkanjiskip', tex.getcount('ltj@@stack'))))
elseif k == 'jcharwidowpenalty' then
- tex.write(cstb_get_penalty_table('jwp', 0, 0, tex.getcount('ltj@@stack')))
+ tex.write(luatexja.stack.get_penalty_table('jwp', 0, 0, tex.getcount('ltj@@stack')))
elseif k == 'autospacing' then
tex.write(tex.getattribute('ltj@autospc'))
elseif k == 'autoxspacing' then
function ltj.ext_get_parameter_binary(k,c)
if k == 'jacharrange' then
if c<0 or c>216 then c=0 end
- tex.write(rgjc_get_range_setting(c))
+ tex.write(luatexja.charrange.get_range_setting(c))
else
if c<0 or c>0x10FFFF then
ltj.error('Invalid character code (' .. c
c=0
end
if k == 'prebreakpenalty' then
- tex.write(cstb_get_penalty_table('pre', c, 0, tex.getcount('ltj@@stack')))
+ tex.write(luatexja.stack.get_penalty_table('pre', c, 0, tex.getcount('ltj@@stack')))
elseif k == 'postbreakpenalty' then
- tex.write(cstb_get_penalty_table('post', c, 0, tex.getcount('ltj@@stack')))
+ tex.write(luatexja.stack.get_penalty_table('post', c, 0, tex.getcount('ltj@@stack')))
elseif k == 'kcatcode' then
- tex.write(cstb_get_penalty_table('kcat', c, 0, tex.getcount('ltj@@stack')))
+ tex.write(luatexja.stack.get_penalty_table('kcat', c, 0, tex.getcount('ltj@@stack')))
elseif k == 'chartorange' then
- tex.write(rgjc_char_to_range(c))
+ tex.write(luatexja.charrange.char_to_range(c))
elseif k == 'jaxspmode' or k == 'alxspmode' then
- tex.write(cstb_get_inhibit_xsp_table(c))
+ tex.write(luatexja.stack.get_penalty_table('xsp', c, 3, tex.getcount('ltj@@stack')))
end
end
end
ltj.box_stack_level = 0
-- This is used in Step 2 (JFM glue/kern) and Step 3 (\[x]kanjiskip).
---- the following function is modified from jafontspec.lua (by K. Maeda).
---- Instead of "%", we use U+FFFFF for suppressing spaces.
-local function main1_process_input_buffer(buffer)
- local c = utf.byte(buffer, utf.len(buffer))
- local p = node_new(id_glyph)
- p.char = c
- if utf.len(buffer) > 0
- and rgjc_is_ucs_in_japanese_char(p) then
- buffer = buffer .. string.char(0xF3,0xBF,0xBF,0xBF) -- U+FFFFF
- end
- return buffer
-end
-
-
local function main1_suppress_hyphenate_ja(head)
for p in node.traverse_id(id_glyph, head) do
- if rgjc_is_ucs_in_japanese_char(p) then
+ if luatexja.charrange.is_ucs_in_japanese_char(p) then
local v = has_attr(p, attr_curjfnt)
if v then
p.font = v
end
-- CALLBACKS
-luatexbase.add_to_callback('process_input_buffer',
- function (buffer)
- return main1_process_input_buffer(buffer)
- end,'ltj.process_input_buffer')
luatexbase.add_to_callback('hpack_filter',
function (head)
return main1_set_box_stack_level(head, true)
\def\ltj@temp{#2}%
\ifx\ltj@temp\empty\ltj@tempcntb="10FFFF \else\ltj@tempcntb=#2 \fi%"
\fi
- \directlua{ltj.ext_add_char_range(\the\ltj@tempcnta,\the\ltj@tempcntb,
+ \directlua{luatexja.charrange.add_char_range(\the\ltj@tempcnta,\the\ltj@tempcntb,
\the\ltj@tempcntc)}%
}
\expandafter\ltj@@set@stack#1:{post}{-10000}{10000}}
\def\ltj@@set@stack#1,#2:#3#4#5{%
\ltj@tempcnta=#1\relax \ltj@tempcntb=#2\relax
- \directlua{ltj.ext_set_stack_table(ltj.isglobal, \asluastring{#3},
+ \directlua{luatexja.stack.set_stack_table(ltj.isglobal, \asluastring{#3},
\the\ltj@tempcnta,tex.getcount('ltj@tempcntb'),#4,#5)}}
% yalbaselineshift = <dimen>
\def\ltj@tempa{postonly}\ifx\ltj@temp\ltj@tempa\def\ltj@temp{1}\fi
\def\ltj@tempa{allow}\ifx\ltj@temp\ltj@tempa\def\ltj@temp{3}\fi
\ltj@tempcnta=#1\relax\ltj@tempcntb=\ltj@temp\relax
- \directlua{ltj.ext_set_stack_table(ltj.isglobal, 'xsp', \the\ltj@tempcnta,
+ \directlua{luatexja.stack.set_stack_table(ltj.isglobal, 'xsp', \the\ltj@tempcnta,
\the\ltj@tempcntb,0,3)}}
% alxspmode = {<char_code>, <mode>}
\def\ltj@tempa{postonly}\ifx\ltj@temp\ltj@tempa\def\ltj@temp{2}\fi
\def\ltj@tempa{allow}\ifx\ltj@temp\ltj@tempa\def\ltj@temp{3}\fi
\ltj@tempcnta=#1\relax\ltj@tempcntb=\ltj@temp\relax
- \directlua{ltj.ext_set_stack_table(ltj.isglobal, 'xsp', \the\ltj@tempcnta,
+ \directlua{luatexja.stack.set_stack_table(ltj.isglobal, 'xsp', \the\ltj@tempcnta,
\the\ltj@tempcntb,0,3)}}
% autospacing = <bool> (default: true)
\define@key[ltj]{japaram}{kanjiskip}{% % SKIP
\ltj@tempskipa=#1\relax
- \directlua{ltj.ext_set_stack_skip(ltj.isglobal, 'kanjiskip')}}
+ \directlua{luatexja.stack.set_stack_skip(ltj.isglobal, 'kanjiskip')}}
\define@key[ltj]{japaram}{xkanjiskip}{% % SKIP
\ltj@tempskipa=#1\relax
- \directlua{ltj.ext_set_stack_skip(ltj.isglobal, 'xkanjiskip')}}
+ \directlua{luatexja.stack.set_stack_skip(ltj.isglobal, 'xkanjiskip')}}
\define@key[ltj]{japaram}{jcharwidowpenalty}{% %COUNT
\ltj@tempcnta=#1
- \directlua{ltj.ext_set_stack_table(ltj.isglobal, 'jwp', 0,
+ \directlua{luatexja.stack.set_stack_table(ltj.isglobal, 'jwp', 0,
\the\ltj@tempcnta, -10000, 10000)}}
% differentjfm = { large | small | average | both }
\def\ltj@@scrange#1,{%
\edef\ltj@temp{#1}%
\ifx\ltj@temp\empty\let\next=\relax\else\let\next=\ltj@@scrange
- \ltj@tempcnta=#1 \directlua{ltj.ext_toggle_char_range(%
+ \ltj@tempcnta=#1 \directlua{luatexja.charrange.toggle_char_range(%
ltj.is_global,\the\ltj@tempcnta)}%
\fi\next
}
-- attr_icflag: 1: kern from \/, 2: 'lineend' kern from JFM
--
-local cstb_get_penalty_table = ltj.int_get_penalty_table
local ljfm_find_char_class = ltj.int_find_char_class
-- arithmetic with penalty.
set_attr(g, attr_icflag, FROM_JFM)
head = node_insert_before(head, p, g)
end
- q_post = cstb_get_penalty_table('post', p.char, 0, ltj.box_stack_level); chain = true
+ q_post = luatexja.stack.get_penalty_table('post', p.char, 0, ltj.box_stack_level); chain = true
elseif p.id==id_glyph then
- q_post = cstb_get_penalty_table('post', p.char, 0, ltj.box_stack_level)
+ q_post = luatexja.stack.get_penalty_table('post', p.char, 0, ltj.box_stack_level)
end
qs = ps; q = p; p = node_next(p)
end
local h = ltj.metrics[qs[2]].char_type[has_attr(q, attr_jchar_class)]
if h.kern and h.kern[x] then w = round(qs[1]*h.kern[x]) end
end
- q_post = add_penalty(q_post, cstb_get_penalty_table('pre', p.char, 0, ltj.box_stack_level))
+ q_post = add_penalty(q_post, luatexja.stack.get_penalty_table('pre', p.char, 0, ltj.box_stack_level))
real_insert(g, w, q_post, false)
elseif q.id==id_glyph then -- (q,p): AL-JA
local g = nil
ljfm_find_char_class('jcharbdd',ps[2]),
has_attr(p,attr_jchar_class))
end
- q_post = add_penalty(q_post, cstb_get_penalty_table('pre', p.char, 0, ltj.box_stack_level))
+ q_post = add_penalty(q_post, luatexja.stack.get_penalty_table('pre', p.char, 0, ltj.box_stack_level))
real_insert(g, 0, q_post, true)
elseif q.id==id_kern then -- (q,p): kern-JA
local g = nil
end
real_insert(g, 0, q_post, true)
end
- q, qs, q_post = p, ps, cstb_get_penalty_table('post', p.char, 0, ltj.box_stack_level)
- if cstb_get_penalty_table('kcat', p.char, 0, ltj.box_stack_level)%2~=1 then
+ q, qs, q_post = p, ps, luatexja.stack.get_penalty_table('post', p.char, 0, ltj.box_stack_level)
+ if luatexja.stack.get_penalty_table('kcat', p.char, 0, ltj.box_stack_level)%2~=1 then
widow_node = p
end
p = node_next(p); chain = true
local h = ltj.metrics[qs[2]].char_type[has_attr(q,attr_jchar_class)]
if h.kern and h.kern[x] then w = round(qs[1]*h.kern[x]) end
end
- q_post = add_penalty(q_post, cstb_get_penalty_table('pre', p.char, 0, ltj.box_stack_level))
+ q_post = add_penalty(q_post, luatexja.stack.get_penalty_table('pre', p.char, 0, ltj.box_stack_level))
real_insert(g, w, q_post, true)
elseif p.id==id_kern then -- (q,p): JA-kern
real_insert_kern(g)
if not widow_node then return end
local a = node_prev(widow_node)
local i = has_attr(a, attr_icflag) or 0
- local wp = cstb_get_penalty_table('jwp', 0, 0, ltj.box_stack_level)
+ local wp = luatexja.stack.get_penalty_table('jwp', 0, 0, ltj.box_stack_level)
if i==4 then
a.penalty=add_penalty(a.penalty, wp)
elseif i>=2 then
local node_new = node.new
local has_attr = node.has_attribute
-local floor = math.floor
local round = tex.round
local attr_icflag = luatexbase.attributes['ltj@icflag']
tex.sprint(ltj.is_global .. '\\protected\\expandafter\\def\\csname '
.. cstemp .. '\\endcsname'
.. '{\\csname ltj@curjfnt\\endcsname=' .. fn
- .. ' \\zw=' .. tex.round(f.size*ltj.metrics[j].zw) .. 'sp'
- .. '\\zh=' .. tex.round(f.size*ltj.metrics[j].zh) .. 'sp\\relax}')
+ .. ' \\zw=' .. round(f.size*ltj.metrics[j].zw) .. 'sp'
+ .. '\\zh=' .. round(f.size*ltj.metrics[j].zh) .. 'sp\\relax}')
end
-- extract jfm_file_name and jfm_var
end
------------------------------------------------------------------------
--- MANAGING THE RANGE OF JAPANESE CHARACTERS (prefix: rgjc)
-------------------------------------------------------------------------
--- jcr_table_main[chr_code] = index
--- index : internal 0, 1, 2, ..., 216 0: 'other'
--- external 1 2 216, (out of range): 'other'
-
--- initialize
-local jcr_table_main = {}
-local jcr_cjk = 0; local jcr_noncjk = 1; local ucs_out = 0x110000
-
-for i=0x80 ,0xFF do jcr_table_main[i]=1 end
-for i=0x100,ucs_out-1 do jcr_table_main[i]=0 end
-
--- EXT: add characters to a range
-function ltj.ext_add_char_range(b,e,ind) -- ind: external range number
- if ind<0 or ind>216 then
- ltj.error('Invalid range number (' .. ind ..
- '), should be in the range 1..216.',
- {}); return
- end
- for i=math.max(0x80,b),math.min(ucs_out-1,e) do
- jcr_table_main[i]=ind
- end
-end
-
-local function rgjc_char_to_range(c) -- return the (external) range number
- if c<0x80 or c>=ucs_out then return -1
- else
- local i = jcr_table_main[c] or 0
- if i==0 then return 217 else return i end
- end
-end
-
-local function rgjc_get_range_setting(i) -- i: internal range number
- return floor(tex.getattribute(
- luatexbase.attributes['ltj@kcat'..floor(i/31)])
- /math.pow(2, i%31))%2
-end
-ltj.int_get_range_setting = rgjc_get_range_setting
-ltj.int_char_to_range = rgjc_char_to_range
-
--- glyph_node p は和文文字か?
-local function rgjc_is_ucs_in_japanese_char(p)
- local c = p.char
- if c<0x80 then return false
- else
- local i=jcr_table_main[c]
- return (floor(
- has_attr(p, luatexbase.attributes['ltj@kcat'..floor(i/31)])
- /math.pow(2, i%31))%2 ~= jcr_noncjk)
- end
-end
-ltj.int_is_ucs_in_japanese_char = rgjc_is_ucs_in_japanese_char
-
--- EXT
-function ltj.ext_toggle_char_range(g, i) -- i: external range number
- if i==0 then return
- else
- local kc
- if i>0 then kc=0 else kc=1; i=-i end
- if i>216 then i=0 end
- local attr = luatexbase.attributes['ltj@kcat'..floor(i/31)]
- local a = tex.getattribute(attr)
- local k = math.pow(2, i%31)
- tex.setattribute(g,attr,(floor(a/k/2)*2+kc)*k+a%k)
- end
-end
-
-------------------------------------------------------------------------
-- MISC
------------------------------------------------------------------------
local f = p.font
local g = node_new(id_kern)
g.subtype = 1; node.set_attribute(g, attr_icflag, ITALIC)
- if rgjc_is_ucs_in_japanese_char(p) then
+ if luatexja.charrange.is_ucs_in_japanese_char(p) then
f = has_attr(p, attr_curjfnt)
local j = ltj.font_metric_table[f]
local c = ljfm_find_char_class(p.char, j.jfm)
local insert_skip = no_skip
local head
-local cstb_get_penalty_table = ltj.int_get_penalty_table
-local cstb_get_skip_table = ltj.int_get_skip_table
-
local function is_japanese_glyph_node(p)
return p and (p.id==id_glyph)
and (p.font==has_attr(p,attr_curjfnt))
local function skip_table_to_spec(n)
local g = node_new(id_glue_spec)
- local st = cstb_get_skip_table(n, ltj.box_stack_level)
+ local st = luatexja.stack.get_skip_table(n, ltj.box_stack_level)
g.width = st.width; g.stretch = st.stretch; g.shrink = st.shrink
g.stretch_order = st.stretch_order; g.shrink_order = st.shrink_order
return g
set_attr(g,attr_icflag,XKANJI_SKIP)
node_insert_after(head, q, g)
head = node.remove(head, h)
+ node.free(h)
else
add_glue_spec(h.spec, g.spec)
+ node.free(g.spec); node.free(g)
end
else
set_attr(g,attr_icflag,XKANJI_SKIP)
end
local function insert_ascii_kanji_xkskip(q, p)
- if cstb_get_penalty_table('xsp', p.char, 3, ltj.box_stack_level)<=1 then return end
+ if luatexja.stack.get_penalty_table('xsp', p.char, 3, ltj.box_stack_level)<=1 then return end
insert_xkanjiskip_node(q, p.font, p)
end
and math.floor(p.subtype/2)%2==1 do
p = p.components; c = p.char
end
- if cstb_get_penalty_table('xsp', c, 3, ltj.box_stack_level)%2 == 1 then
- if cstb_get_penalty_table('xsp', nrc, 3, ltj.box_stack_level)%2 == 0 then g = false end
+ if luatexja.stack.get_penalty_table('xsp', c, 3, ltj.box_stack_level)%2 == 1 then
+ if luatexja.stack.get_penalty_table('xsp', nrc, 3, ltj.box_stack_level)%2 == 0 then g = false end
else g = false
end
if g then insert_xkanjiskip_node(q, nrf, p) end
and math.floor(p.subtype/2)%2 == 1 do
p=node.tail(p.components); c = p.char
end
- if cstb_get_penalty_table('xsp', c, 3, ltj.box_stack_level)>=2 then
+ if luatexja.stack.get_penalty_table('xsp', c, 3, ltj.box_stack_level)>=2 then
insert_skip = after_schar
else
insert_skip = no_skip
if h.id==id_kern then
g.spec.width = g.spec.width + h.kern
head = node.remove(head, h)
+ node.free(h)
set_attr(g,attr_icflag,KANJI_SKIP)
ope(head, p, g)
else
add_glue_spec(h.spec, g.spec)
+ node.free(g.spec); node.free(g)
end
else
set_attr(g,attr_icflag,KANJI_SKIP)
--- /dev/null
+--
+-- luatexja/charrange.lua
+--
+luatexbase.provides_module({
+ name = 'luatexja.charrange',
+ date = '2011/04/01',
+ version = '0.1',
+ description = 'Handling the range of Japanese characters',
+})
+module('luatexja.charrange', package.seeall)
+local err, warn, info, log = luatexbase.errwarinf(_NAME)
+
+local floor = math.floor
+local has_attr = node.has_attribute
+
+-- jcr_table_main[chr_code] = index
+-- index : internal 0, 1, 2, ..., 216 0: 'other'
+-- external 1 2 216, (out of range): 'other'
+
+-- initialize
+local jcr_table_main = {}
+local jcr_cjk = 0; local jcr_noncjk = 1; local ucs_out = 0x110000
+
+for i=0x80 ,0xFF do jcr_table_main[i]=1 end
+for i=0x100,ucs_out-1 do jcr_table_main[i]=0 end
+
+-- EXT: add characters to a range
+function add_char_range(b,e,ind) -- ind: external range number
+ if ind<0 or ind>216 then
+ ltj.error('Invalid range number (' .. ind ..
+ '), should be in the range 1..216.',
+ {}); return
+ end
+ for i=math.max(0x80,b),math.min(ucs_out-1,e) do
+ jcr_table_main[i]=ind
+ end
+end
+
+function char_to_range(c) -- return the (external) range number
+ if c<0x80 or c>=ucs_out then return -1
+ else
+ local i = jcr_table_main[c] or 0
+ if i==0 then return 217 else return i end
+ end
+end
+
+function get_range_setting(i) -- i: internal range number
+ return floor(tex.getattribute(
+ luatexbase.attributes['ltj@kcat'..floor(i/31)])
+ /math.pow(2, i%31))%2
+end
+
+-- glyph_node p は和文文字か?
+function is_ucs_in_japanese_char(p)
+ local c = p.char
+ if c<0x80 then return false
+ else
+ local i=jcr_table_main[c]
+ return (floor(
+ has_attr(p, luatexbase.attributes['ltj@kcat'..floor(i/31)])
+ /math.pow(2, i%31))%2 ~= jcr_noncjk)
+ end
+end
+
+-- EXT
+function toggle_char_range(g, i) -- i: external range number
+ if i==0 then return
+ else
+ local kc
+ if i>0 then kc=0 else kc=1; i=-i end
+ if i>216 then i=0 end
+ local attr = luatexbase.attributes['ltj@kcat'..floor(i/31)]
+ local a = tex.getattribute(attr)
+ local k = math.pow(2, i%31)
+ tex.setattribute(g,attr,(floor(a/k/2)*2+kc)*k+a%k)
+ end
+end
+
+-- EOF
\ No newline at end of file
--- /dev/null
+--
+-- luatexja/inputbuf.lua
+--
+luatexbase.provides_module({
+ name = 'luatexja.inputbuf',
+ date = '2011/04/01',
+ version = '0.1',
+ description = 'Supressing a space by newline after Japanese characters',
+})
+module('luatexja.inputbuf', package.seeall)
+local err, warn, info, log = luatexbase.errwarinf(_NAME)
+
+local node_new = node.new
+local id_glyph = node.id('glyph')
+
+--- the following function is modified from jafontspec.lua (by K. Maeda).
+--- Instead of "%", we use U+FFFFF for suppressing spaces.
+function add_comment(buffer)
+ local i = utf.len(buffer)
+ while (i>0) and (tex.getcatcode(utf.byte(buffer, i))==1
+ or tex.getcatcode(utf.byte(buffer, i))==2) do
+ i=i-1
+ end
+ if i>0 then
+ local c = utf.byte(buffer, i)
+ local ct = tex.getcatcode(c)
+ if (ct==11) or (ct==12) then
+ local p = node.new(id_glyph)
+ p.char = c
+ if luatexja.charrange.is_ucs_in_japanese_char(p) then
+ buffer = buffer .. string.char(0xF3,0xBF,0xBF,0xBF) -- U+FFFFF
+ end
+ node.free(p)
+ end
+ end
+ return buffer
+end
+
+luatexbase.add_to_callback('process_input_buffer',
+ add_comment,'ltj.process_input_buffer')
+
+--EOF
\ No newline at end of file
module('luatexja.stack', package.seeall)
local err, warn, info, log = luatexbase.errwarinf(_NAME)
+local node_new = node.new
+local id_whatsit = node.id('whatsit')
+local sid_user = node.subtype('user_defined')
+
+local charprop_stack_table={}; charprop_stack_table[0]={}
+
+function get_stack_level()
+ local i = tex.getcount('ltj@@stack')
+ local j = tex.currentgrouplevel
+ if j > tex.getcount('ltj@@group@level') then
+ i = i+1 -- new stack level
+ tex.setcount('ltj@@group@level', j)
+ for k,v in pairs(charprop_stack_table) do -- clear the stack above i
+ if k>=i then charprop_stack_table[k]=nil end
+ end
+ charprop_stack_table[i] = table.fastcopy(charprop_stack_table[i-1])
+ tex.setcount('ltj@@stack', i)
+ local g = node_new(id_whatsit, sid_user)
+ g.user_id=30112; g.type=100; g.value=j; node.write(g)
+ end
+ return i
+end
+
+-- EXT
+function set_stack_table(g,m,c,p,lb,ub)
+ local i = get_stack_level()
+ if p<lb or p>ub then
+ ltj.error('Invalid code (' .. p .. '), should in the range '
+ .. tostring(lb) .. '..' .. tostring(ub) .. '.',
+ {"I'm going to use 0 instead of that illegal code value."})
+ p=0
+ elseif c<-1 or c>0x10FFFF then
+ ltj.error('Invalid character code (' .. c
+ .. '), should in the range -1.."10FFFF.',{})
+ return
+ elseif not charprop_stack_table[i][c] then
+ charprop_stack_table[i][c] = {}
+ end
+ charprop_stack_table[i][c][m] = p
+ if g=='global' then
+ for j,v in pairs(charprop_stack_table) do
+ if not charprop_stack_table[j][c] then charprop_stack_table[j][c] = {} end
+ charprop_stack_table[j][c][m] = p
+ end
+ end
+end
+
+-- EXT: store \ltj@tempskipa
+function set_stack_skip(g,c)
+ local i = get_stack_level()
+ local sp = tex.getskip('ltj@tempskipa')
+ if not charprop_stack_table[i][c] then
+ charprop_stack_table[i][c] = {}
+ end
+ charprop_stack_table[i][c].width = sp.width
+ charprop_stack_table[i][c].stretch = sp.stretch
+ charprop_stack_table[i][c].shrink = sp.shrink
+ charprop_stack_table[i][c].stretch_order = sp.stretch_order
+ charprop_stack_table[i][c].shrink_order = sp.shrink_order
+ if g=='global' then
+ for j,v in pairs(charprop_stack_table) do
+ if not charprop_stack_table[j][c] then charprop_stack_table[j][c] = {} end
+ charprop_stack_table[j][c].width = sp.width
+ charprop_stack_table[j][c].stretch = sp.stretch
+ charprop_stack_table[j][c].shrink = sp.shrink
+ charprop_stack_table[j][c].stretch_order = sp.stretch_order
+ charprop_stack_table[j][c].shrink_order = sp.shrink_order
+ end
+ end
+end
+
+-- mode: nil iff it is called in callbacks
+function get_skip_table(m, idx)
+ local i = charprop_stack_table[idx][m]
+ return i or { width = 0, stretch = 0, shrink = 0,
+ stretch_order = 0, shrink_order = 0 }
+end
+
+function get_penalty_table(m,c,d, idx)
+ local i = charprop_stack_table[idx][c]
+ if i then i=i[m] end
+ return i or d
+end
-- EOF
\ltjsetparameter{alxspmode={-1,inhibit}}
あ$a$あ
+う{}
+い
\medskip
{\tengt ■ltjgetparameter}