OSDN Git Service

Bugfix in beginpar_node.
[luatex-ja/luatexja.git] / src / ltj-jfmglue.lua
index eec0142..be9515e 100644 (file)
@@ -3,8 +3,8 @@
 --
 luatexbase.provides_module({
   name = 'luatexja.jfmglue',
-  date = '2012/04/02',
-  version = '0.3',
+  date = '2012/04/25',
+  version = '0.4',
   description = 'Insertion process of JFM glues and kanjiskip',
 })
 module('luatexja.jfmglue', package.seeall)
@@ -52,6 +52,11 @@ local id_pbox = node.id('hlist') + 512        -- already processed nodes (by \un
 local id_pbox_w = node.id('hlist') + 513      -- cluster which consists of a whatsit
 local sid_user = node.subtype('user_defined')
 
+local sid_start_link = node.subtype('pdf_start_link')
+local sid_start_thread = node.subtype('pdf_start_thread')
+local sid_end_link = node.subtype('pdf_end_link')
+local sid_end_thread = node.subtype('pdf_end_thread')
+
 local ITALIC = 1
 local PACKED = 2
 local KINSOKU = 3
@@ -193,6 +198,7 @@ local function check_box(box_ptr, box_end)
            last_char = p; found_visible_node = true; p=node_next(p)
            if (not p) or p==box_end then return found_visible_node end
         until p.id~=id_glyph
+        pid = p.id
       end
       if pid==id_hlist then
         if has_attr(p, attr_icflag)==PACKED then
@@ -272,7 +278,7 @@ end
 
 local function calc_np_pbox()
    local uid = has_attr(lp, attr_uniqid)
-   Np.first = lp; Np.id = id_pbox
+   Np.first = Np.first or lp; Np.id = id_pbox
    lpa = KINSOKU -- dummy=
    while lp~=last and lpa>=PACKED and lpa~=BOXBDD
       and has_attr(lp, attr_uniqid) == uid do
@@ -284,17 +290,17 @@ end
 
 local calc_np_auxtable = {
    [id_glyph] = function() 
-                  Np.first = lp
+                  Np.first = Np.first or lp
                   if lp.font == has_attr(lp, attr_curjfnt) then 
                      Np.id = id_jglyph 
                   else 
                      Np.id = id_glyph 
                   end
-                  Np.first = lp; Np.nuc = lp; set_attr_icflag_processed(lp)
+                  Np.nuc = lp; set_attr_icflag_processed(lp)
                   lp = node_next(lp); check_next_ickern(); return true
                end,
    [id_hlist] = function() 
-                  Np.first = lp; Np.last = lp; Np.nuc = lp; 
+                  Np.first = Np.first or lp; Np.last = lp; Np.nuc = lp; 
                   set_attr_icflag_processed(lp)
                   if lp.shift~=0 then 
                      Np.id = id_box_like
@@ -304,12 +310,12 @@ local calc_np_auxtable = {
                   lp = node_next(lp); return true
                end,
    [id_vlist] = function()
-                  Np.first = lp; Np.nuc = lp; Np.last = lp;
+                  Np.first = Np.first or lp; Np.nuc = lp; Np.last = lp;
                   Np.id = id_box_like; set_attr_icflag_processed(lp); 
                   lp = node_next(lp); return true
                end,
    [id_rule] = function()
-                 Np.first = lp; Np.nuc = lp; Np.last = lp;
+                 Np.first = Np.first or lp; Np.nuc = lp; Np.last = lp;
                  Np.id = id_box_like; set_attr_icflag_processed(lp); 
                  lp = node_next(lp); return true
               end,
@@ -326,30 +332,37 @@ local calc_np_auxtable = {
                    return false
                 end,
    [id_disc] = function()
-                 Np.first = lp; Np.nuc = lp; set_attr_icflag_processed(lp); 
+                 Np.first = Np.first or lp; 
+          Np.nuc = lp; set_attr_icflag_processed(lp); 
                  Np.last = lp; Np.id = id_disc; lp = node_next(lp); return true
               end,
    [id_whatsit] = function() 
                  if lp.subtype==sid_user then
-             if lp.user_id==30111 then
-                local lq = node_next(lp)
-                head = node_remove(head, lp); node_free(lp); lp = lq; ihb_flag = true
-             else
-                set_attr_icflag_processed(lp)
-                luatexbase.call_callback("luatexja.jfmglue.whatsit_getinfo"
-                                        , Np, lp, Nq, box_stack_level)
-                lp = node_next(lp)
-                if Np.nuc then 
-                   Np.id = id_pbox_w; Np.first = Np.nuc; Np.last = Np.nuc; return true
-                end
+                    if lp.user_id==30111 then
+                       local lq = node_next(lp)
+                       head = node_remove(head, lp); node_free(lp); lp = lq; ihb_flag = true
+                    else
+                       set_attr_icflag_processed(lp)
+                       luatexbase.call_callback("luatexja.jfmglue.whatsit_getinfo"
+                                                , Np, lp, Nq, box_stack_level)
+                       lp = node_next(lp)
+                       if Np.nuc then 
+                          Np.id = id_pbox_w; Np.first = Np.nuc; Np.last = Np.nuc; return true
+                       end
+                    end
+                 else
+             -- we do special treatment for these whatsit nodes.
+             if lp.subtype == sid_start_link or lp.subtype == sid_start_thread then
+                Np.first = lp 
+             elseif lp.subtype == sid_end_link or lp.subtype == sid_end_thread then
+                Nq.last = lp; Np.first = nil
              end
-          else
-            set_attr_icflag_processed(lp)
+                    set_attr_icflag_processed(lp); lp = node_next(lp)
                  end
                  return false
                  end,
    [id_math] = function()
-                 Np.first = lp; Np.nuc = lp; 
+                 Np.first = Np.first or lp; Np.nuc = lp; 
                  set_attr_icflag_processed(lp); lp  = node_next(lp) 
                  while lp.id~=id_math do 
                     set_attr_icflag_processed(lp); lp  = node_next(lp) 
@@ -359,11 +372,11 @@ local calc_np_auxtable = {
                  return true
               end,
    [id_glue] = function()
-                 Np.first = lp; Np.nuc = lp; set_attr_icflag_processed(lp); 
+                 Np.first = Np.first or lp; Np.nuc = lp; set_attr_icflag_processed(lp); 
                  Np.last = lp; Np.id = id_glue; lp = node_next(lp); return true
               end,
    [id_kern] = function() 
-                 Np.first = lp
+                 Np.first = Np.first or lp
                  if lp.subtype==2 then
                     set_attr_icflag_processed(lp); lp = node_next(lp)
                     set_attr_icflag_processed(lp); lp = node_next(lp)
@@ -386,7 +399,7 @@ local calc_np_auxtable = {
                     lp = node_next(lp); return false
                  end,
    [13] = function()
-                 Np.first = lp; Np.nuc = lp; Np.last = lp;
+                 Np.first = Np.first or lp; Np.nuc = lp; Np.last = lp;
                  Np.id = id_box_like; set_attr_icflag_processed(lp); 
                  lp = node_next(lp); return true
               end,
@@ -763,6 +776,7 @@ local function handle_np_jachar()
       handle_penalty_normal(0, Np.pre, g); real_insert(0, g)
    elseif Nq.pre then 
       g = get_OA_skip() or get_xkanjiskip(Np) -- O_A->X
+      if Nq.id==id_hlist then Nq.post = 0 end
       handle_penalty_normal(Nq.post, Np.pre, g); real_insert(0, g)
    else
       g = get_OA_skip() -- O_A
@@ -783,6 +797,7 @@ end
 local function handle_nq_jachar()
    local g
    if Np.pre then 
+      if Np.id==id_hlist then Np.pre = 0 end
       g = get_OB_skip() or get_xkanjiskip(Nq) -- O_B->X
       g = lineend_fix(g)
       handle_penalty_normal(Nq.post, Np.pre, g); real_insert(Nq.lend, g)
@@ -821,11 +836,21 @@ local function handle_nq_ja_hlist()
    end
 end
 
+-- Nq が前側のクラスタとなることによる修正
+local function adjust_nq()
+   if Nq.id==id_glyph then after_alchar(Nq)
+   elseif Nq.id==id_hlist or Nq.id==id_pbox or Nq.id==id_disc then after_hlist(Nq)
+   elseif Nq.id == id_pbox_w then 
+      luatexbase.call_callback("luatexja.jfmglue.whatsit_after",
+                              false, Nq, Np, box_stack_level)
+   end
+end
+
 -------------------- 開始・終了時の処理
 
 -- リスト末尾の処理
 local function handle_list_tail()
-   Np = Nq
+   adjust_nq(); Np = Nq
    if mode then
       -- the current list is to be line-breaked:
       if Np.id == id_jglyph or (Np.id==id_pbox and Np.met) then 
@@ -850,9 +875,7 @@ local function handle_list_tail()
            head = node_insert_after(head, Np.last, g)
         end
       end
-      head = node_remove(head, last); node_free(last);-- remove the sentinel
    end
-   node_free(kanji_skip); node_free(xkanji_skip)
 end
 
 -- リスト先頭の処理
@@ -912,13 +935,22 @@ local function init_var()
    end
 end
 
--- Nq が前側のクラスタとなることによる修正
-local function adjust_nq()
-   if Nq.id==id_glyph then after_alchar(Nq)
-   elseif Nq.id==id_hlist or Nq.id==id_pbox or Nq.id==id_disc then after_hlist(Nq)
-   elseif Nq.id == id_pbox_w then 
-      luatexbase.call_callback("luatexja.jfmglue.whatsit_after",
-                              false, Nq, Np, box_stack_level)
+local function cleanup()
+   -- adjust attr_icflag for avoiding error
+   tex.attribute[attr_icflag] = -(0x7FFFFFFF)
+   node_free(kanji_skip); node_free(xkanji_skip)
+   if mode then
+      local h = node_next(head)
+      if h.id == id_penalty and h.penalty == 10000 then
+        h = h.next
+        if h.id == id_glue and h.subtype == 15 and not h.next then
+           return false
+        end
+      end
+      return head
+   else
+      head = node_remove(head, last); node_free(last);-- remove the sentinel
+      return head
    end
 end
 -------------------- 外部から呼ばれる関数
@@ -930,8 +962,7 @@ function main(ahead, amode)
    if Np then 
       extract_np(); handle_list_head()
    else
-      if not mode then head = node_remove(head, last); node_free(last) end
-      return head
+      return cleanup()
    end
    calc_np()
    while Np do
@@ -949,9 +980,7 @@ function main(ahead, amode)
       calc_np()
    end
    handle_list_tail()
-   -- adjust attr_icflag
-   tex.attribute[attr_icflag] = -(0x7FFFFFFF)
-   return head
+   return cleanup()
 end
 
 -- \inhibitglue
@@ -971,8 +1000,8 @@ function create_beginpar_node()
 end
 
 local function whatsit_callback(Np, lp, Nq, bsl)
-   if Np.nuc then return Np 
-   elseif lp.user_id == 30114 then
+   if Np and Np.nuc then return Np 
+   elseif Np and lp.user_id == 30114 then
       Np.first = lp; Np.nuc = lp; Np.last = lp
       Np.char = 'parbdd'
       Np.met = nil