OSDN Git Service

Rewrited process_input_buffer callback (ticket #25231).
authorHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Wed, 1 Jun 2011 02:40:10 +0000 (11:40 +0900)
committerHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Wed, 1 Jun 2011 02:40:10 +0000 (11:40 +0900)
And moved several processes into new files:
  - LuaTeX-ja stack system => stack.lua
  - Handling he range of Japanese characters => charrange.lua
  - Suppressing spaces by linebreak => inputbuf.lua

15 files changed:
doc/jfmglue.pdf
doc/sample1.pdf
doc/sample1.tex
src/luatexja-base.sty
src/luatexja-cctbreg.sty
src/luatexja-core.lua
src/luatexja-core.sty
src/luatexja-jfmglue.lua
src/luatexja-jfont.lua
src/luatexja-xkanji.lua
src/luatexja/charrange.lua [new file with mode: 0644]
src/luatexja/inputbuf.lua [new file with mode: 0644]
src/luatexja/stack.lua
test/test03-after.pdf
test/test03-after.tex

index 65ba66f..59a3d9d 100644 (file)
Binary files a/doc/jfmglue.pdf and b/doc/jfmglue.pdf differ
index 346f99e..1042b05 100644 (file)
Binary files a/doc/sample1.pdf and b/doc/sample1.pdf differ
index b4e3f0e..c792fb9 100644 (file)
@@ -446,12 +446,27 @@ Lua\TeX-jaパッケージでは,次のような流れで実際の処理を行
 改行した箇所には自動的に空白が入るようになっている.
 だが,日本語ではそのような振る舞いは不自然であり,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}
 
index 4e43ab5..c47e5d5 100644 (file)
@@ -23,7 +23,9 @@
 %% Load Lua modules.
 \RequireLuaModule{luatexja.base}
 \RequireLuaModule{luatexja.tangle}
+\RequireLuaModule{luatexja.charrange}
 \RequireLuaModule{luatexja.stack}
+\RequireLuaModule{luatexja.inputbuf}
 
 %%------------------ Tiny helpers
 
index 390cbb7..d072b79 100644 (file)
@@ -93,7 +93,7 @@
 
 \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
 
index 19db1b4..ce76678 100644 (file)
@@ -30,9 +30,6 @@ local lang_ja_token = token.create('ltj@japanese')
 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
 
 
@@ -108,92 +105,7 @@ end
 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 
@@ -206,11 +118,11 @@ function ltj.ext_get_parameter_unary(k)
    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
@@ -234,7 +146,7 @@ end
 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 
@@ -243,15 +155,15 @@ function ltj.ext_get_parameter_binary(k,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
@@ -268,23 +180,9 @@ 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 
@@ -329,10 +227,6 @@ local function main1_set_box_stack_level(head, mode)
 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)
index 242b36a..83c90dd 100644 (file)
     \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
 }
index 03c5f69..7512d1f 100644 (file)
@@ -34,7 +34,6 @@ local attr_icflag = luatexbase.attributes['ltj@icflag']
 -- 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.
@@ -148,9 +147,9 @@ local function ins_gk_head()
         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
@@ -268,7 +267,7 @@ local function ins_gk_any_JA()
         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
@@ -277,7 +276,7 @@ local function ins_gk_any_JA()
                          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
@@ -296,8 +295,8 @@ local function ins_gk_any_JA()
       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
@@ -317,7 +316,7 @@ local function ins_gk_JA_any()
         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)
@@ -360,7 +359,7 @@ local function add_widow_penalty()
    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
index 0960740..c4b7779 100644 (file)
@@ -1,6 +1,5 @@
 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']
@@ -130,8 +129,8 @@ function ltj.ext_jfontdefY() -- for horizontal font
    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
@@ -170,75 +169,6 @@ function fonts.define.read(name, size, id)
 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
 ------------------------------------------------------------------------
 
@@ -249,7 +179,7 @@ function ltj.ext_append_italic()
       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)
index 65e349b..f295600 100644 (file)
@@ -53,9 +53,6 @@ local after_wchar = 2 -- nr is a Japanese glyph_node
 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))
@@ -70,7 +67,7 @@ end
 
 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
@@ -128,8 +125,10 @@ local function insert_xkanjiskip_node(q, f, p)
            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)
@@ -139,7 +138,7 @@ local function insert_xkanjiskip_node(q, f, p)
 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
 
@@ -150,8 +149,8 @@ local function insert_kanji_ascii_xkskip(q, p)
       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
@@ -163,7 +162,7 @@ local function set_insert_skip_after_achar(p)
       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
@@ -214,10 +213,12 @@ local function insert_kanji_skip(ope, p)
       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)
diff --git a/src/luatexja/charrange.lua b/src/luatexja/charrange.lua
new file mode 100644 (file)
index 0000000..c1356ac
--- /dev/null
@@ -0,0 +1,79 @@
+--
+-- 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
diff --git a/src/luatexja/inputbuf.lua b/src/luatexja/inputbuf.lua
new file mode 100644 (file)
index 0000000..d7f01db
--- /dev/null
@@ -0,0 +1,42 @@
+--
+-- 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
index 564957f..530db90 100644 (file)
@@ -10,5 +10,88 @@ luatexbase.provides_module({
 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
index 8454ed6..c7829e5 100644 (file)
Binary files a/test/test03-after.pdf and b/test/test03-after.pdf differ
index f90a4ff..3ec690e 100644 (file)
@@ -67,6 +67,8 @@ xspmode
 
 \ltjsetparameter{alxspmode={-1,inhibit}}
 あ$a$あ
+う{}
+い
 
 \medskip
 {\tengt ■ltjgetparameter}