OSDN Git Service

get rid of attr_orig_char
[luatex-ja/luatexja.git] / src / ltj-direction.lua
index b45a7d7..e29503b 100644 (file)
@@ -148,13 +148,35 @@ do
               flag = 0; break
            end
         end
-        if flag==1 then -- move dir_whatsit w
-           return 1,w -- TODO
+        if flag==1 then -- dir_whatsit already exists
+           return 1,w
         else
            return flag
         end
       end
    end
+   function luatexja.direction.set_list_direction_hook(v)
+      local lv = tex_nest.ptr -- must be >= 1
+      if not v then
+         v = get_dir_count()
+        if abs(tex_nest[lv-1].mode) == ltjs.mmode and v == dir_tate then
+           v = dir_utod
+        end
+      elseif v=='adj' then
+         v = get_adjust_dir_count()
+      end
+      local h = to_direct(tex_nest[lv].head)
+      local w = node_new(id_whatsit, sid_user)
+      setfield(w, 'next', nil)
+      setfield(w, 'user_id', DIR)
+      setfield(w, 'type', 110)
+      set_attr(w, attr_dir, v)
+      insert_after(h, h, w)
+      tex_nest[lv].tail = to_node(node_tail(w))
+      tex_set_attr('global', attr_icflag, 0)
+      tex_set_attr('global', attr_dir, 0)
+   end
+
    local function set_list_direction(v, name)
       local lv = tex_nest.ptr
       if not v then
@@ -256,7 +278,7 @@ do
       for line in traverse_id(id_hlist, hd) do
          local nh = getlist(line)
         setfield(line, 'head', create_dir_whatsit(nh, gc, new_dir) )
-        set_attr(line, attr_dir, new_dir)
+        --set_attr(line, attr_dir, new_dir)
       end
       tex_set_attr('global', attr_dir, 0)
       return h
@@ -461,36 +483,60 @@ local function get_box_dir(b, default)
    local bh = getfield(b,'head')
    -- b は insert node となりうるので getlist() は使えない
    local c
-   for i=1,2 do
-      if bh and getid(bh)==id_whatsit
-      and getsubtype(bh)==sid_user and getfield(bh, 'user_id')==DIR then
+   for bh in traverse_id(id_whatsit, bh) do
+      if getsubtype(bh)==sid_user and getfield(bh, 'user_id')==DIR then
         c = bh
-        dir = (dir==0) and has_attr(bh, attr_dir) or dir
+        dir = (dir==0) and has_attr(bh, attr_dir) or dir
       end
-      bh = node_next(bh)
    end
+   -- for i=1,2 do
+   --    if bh and getid(bh)==id_whatsit
+   --    and getsubtype(bh)==sid_user and getfield(bh, 'user_id')==DIR then
+   --   c = bh
+   --   dir = (dir==0) and has_attr(bh, attr_dir) or dir
+   --    end
+   --    bh = node_next(bh)
+   -- end
    stop_time_measure('get_box_dir')
    return (dir==0 and default or dir), c
 end
 
 do
    local getbox = tex.getbox
-   local function check_dir(reg_num)
+   local dir_backup
+   function luatexja.direction.unbox_check_dir(is_copy)
       start_time_measure('box_primitive_hook')
       local list_dir = get_dir_count()%dir_math_mod
       local b = getbox(tex_getcount('ltj@tempcnta'))
       if b then
         local box_dir = get_box_dir(to_direct(b), dir_yoko)
         if box_dir%dir_math_mod ~= list_dir then
-          --  print('NEST', tex_nest.ptr, tex_getcount('ltj@tempcnta'))
-          --  luatexja.ext_show_node_list(
-           --     (tex_nest.ptr==0) and tex.lists.page_head or tex_nest[tex_nest.ptr].head,
-           --     'LIST' .. tostring(list_dir) .. '> ', print)
-          -- luatexja.ext_show_node_list(b, 'BOX' .. tostring(box_dir) .. '> ', print)
            ltjb.package_error(
               'luatexja',
               "Incompatible direction list can't be unboxed",
               'I refuse to unbox a box in differrent direction.')
+            tex.sprint(cat_lp, '\\@gobbletwo')
+        else
+           dir_backup = nil
+           local bd = to_direct(b)
+           local hd = getlist(bd)
+           local nh = hd
+           while hd do
+              if getid(hd)==id_whatsit and getsubtype(hd)==sid_user
+                 and getfield(hd, 'user_id')==DIR then
+                    local d = hd
+                    nh, hd = node_remove(nh, hd)
+                    if is_copy and (not dir_backup) then
+                       dir_backup = d
+                       setfield(dir_backup, 'next', nil)
+                    else
+                       node_free(d)
+                    end
+              else
+                 hd = node_next(hd)
+              end
+           end
+           setfield(bd, 'head', nh)
         end
       end
       if luatexja.global_temp and tex.globaldefs~=luatexja.global_temp then
@@ -498,7 +544,17 @@ do
       end
       stop_time_measure('box_primitive_hook')
    end
-   luatexja.direction.check_dir = check_dir
+   function luatexja.direction.uncopy_restore_whatsit()
+      local b = getbox(tex_getcount('ltj@tempcnta'))
+      if b then
+        local bd = to_direct(b)
+        if dir_backup then
+           setfield(dir_backup, 'next', getlist(bd))
+           setfield(bd, 'head', dir_backup)
+           dir_backup = nil
+        end
+      end
+   end
 end
 
 -- dir_node に包まれている「本来の中身」を取り出し,
@@ -506,7 +562,6 @@ end
 local function unwrap_dir_node(b, head, box_dir)
    -- b: dir_node, head: the head of list, box_dir:
    -- return values are (new head), (next of b), (contents), (dir of contents)
-               luatexja.ext_show_node(to_node(b), '>> ', print)
    local bh = getlist(b)
    local nh, nb
    if head then
@@ -593,6 +648,7 @@ do
            end
         end
         Dnode.flush_list(getfield(dn, 'value'))
+        setfield(dn, 'value', nil)
         db = db or create_dir_node(b, box_dir, new_dir, false)
         local w = getfield(b, 'width')
         local h = getfield(b, 'height')
@@ -811,10 +867,8 @@ do
         if box_dir%dir_math_mod ~= list_dir then
            setbox(
               'ltj@afbox',
-              to_node(
-                 copy_list(make_dir_whatsit(sd, sd, list_dir, 'box_move'))
-                 -- without copy_list, we get a segfault
-              )
+              to_node(copy_list(make_dir_whatsit(sd, sd, list_dir, 'box_move')))
+              -- copy_list しないとリストの整合性が崩れる……?
            )
         end
       end
@@ -827,30 +881,65 @@ end
 do
    local function glyph_from_packed(h)
       local b = getlist(h)
-      return (getid(b)==id_kern)
-        and node_next(node_next(node_next(node_next(b)))) or b
+      return (getid(b)==id_kern or (getid(b)==id_whatsit and getsubtype(b)==sid_save) )
+        and node_next(node_next(node_next(b))) or b
    end
    luatexja.direction.glyph_from_packed = glyph_from_packed
 end
 
--- adjust and insertion
-local id_adjust = node.id('adjust')
-function luatexja.direction.check_adjust_direction()
-   start_time_measure('box_primitive_hook')
-   local list_dir = get_adjust_dir_count()
-   local a = tex_nest[tex_nest.ptr].tail
-   local ad = to_direct(a)
-   if a and getid(ad)==id_adjust then
-      local adj_dir = get_box_dir(ad)
-      if list_dir~=adj_dir then
-         ltjb.package_error(
-                 'luatexja',
-                 'Direction Incompatible',
-                 "\\vadjust's argument and outer vlist must have same direction.")
-         Dnode.last_node()
+-- adjust
+do
+   local id_adjust = node.id('adjust')
+   function luatexja.direction.check_adjust_direction()
+      start_time_measure('box_primitive_hook')
+      local list_dir = get_adjust_dir_count()
+      local a = tex_nest[tex_nest.ptr].tail
+      local ad = to_direct(a)
+      if a and getid(ad)==id_adjust then
+        local adj_dir = get_box_dir(ad)
+        if list_dir~=adj_dir then
+           ltjb.package_error(
+              'luatexja',
+              'Direction Incompatible',
+              "\\vadjust's argument and outer vlist must have same direction.")
+           Dnode.last_node()
+        end
+      end
+      stop_time_measure('box_primitive_hook')
+   end
+end
+
+-- insert
+do
+   local id_ins = node.id('ins')
+   local id_rule = node.id('rule')
+   function luatexja.direction.populate_insertion_dir_whatsit()
+      start_time_measure('box_primitive_hook')
+      local list_dir = get_dir_count()
+      local a = tex_nest[tex_nest.ptr].tail
+      local ad = to_direct(a)
+      if a and getid(ad)==id_ins then
+        local h = getfield(ad, 'head')
+        if getid(h)==id_whatsit and
+           getsubtype(h)==sid_user and getfield(h, 'user_id')==DIR then
+              local n = h; h = node_remove(h,h)
+              node_free(n)
+        end
+        for box_rule in traverse(h) do
+           if getid(box_rule)<id_rule then
+              local w = node_new(id_whatsit, sid_user)
+              setfield(w, 'next', nil)
+              setfield(w, 'user_id', DIR)
+              setfield(w, 'type', 110)
+              set_attr(w, attr_dir, list_dir)
+              h = insert_before(h, box_rule, w)
+           end
+        end
+        tex_set_attr('global', attr_dir, 0)
+        setfield(ad, 'head', h)
       end
+      stop_time_measure('box_primitive_hook')
    end
-   stop_time_measure('box_primitive_hook')
 end
 
 -- vsplit
@@ -864,14 +953,19 @@ do
         hd = create_dir_whatsit_vbox(hd, gc)
         split_dir_whatsit = hd
       elseif gc=='split_off'  then
-        local bh=hd
-        for i=1,2 do
-           if bh and getid(bh)==id_whatsit
-           and getsubtype(bh)==sid_user and getfield(bh, 'user_id')==DIR then
+        for  bh in traverse_id(id_whatsit, hd) do
+           if getsubtype(bh)==sid_user and getfield(bh, 'user_id')==DIR then
               ltjs.list_dir  = has_attr(bh, attr_dir); break
            end
-           bh = node_next(bh)
         end
+        -- local bh=hd
+        -- for i=1,2 do
+        --    if bh and getid(bh)==id_whatsit
+        --    and getsubtype(bh)==sid_user and getfield(bh, 'user_id')==DIR then
+        --       ltjs.list_dir  = has_attr(bh, attr_dir); break
+        --    end
+        --    bh = node_next(bh)
+        -- end
         if split_dir_whatsit then
            -- adjust direction of 'split_keep'
            set_attr(split_dir_whatsit, attr_dir, ltjs.list_dir)
@@ -972,6 +1066,11 @@ do
          setfield(db, 'head', db_head)
       end
    end
+
+   local shipout_temp =  node_new(id_hlist)
+   set_attr(shipout_temp, attr_dir, dir_yoko)
+   tex_set_attr('global', attr_dir, 0)
+
    finalize_inner = function (box)
       for n in traverse(getlist(box)) do
          local nid = getid(n)
@@ -982,11 +1081,21 @@ do
             else
                finalize_inner(n)
             end
-         end
+        end
       end
    end
    local getbox = tex.getbox
+   local setbox, copy = Dnode.setbox, Dnode.copy
    function luatexja.direction.finalize()
-      finalize_inner(to_direct(tex.getbox("AtBeginShipoutBox")))
+      local a = to_direct(tex.getbox("AtBeginShipoutBox"))
+      local a_dir = get_box_dir(a, dir_yoko)
+      if a_dir~=dir_yoko then
+         local b = create_dir_node(a, a_dir, dir_yoko, false)
+         setfield(b, 'head', a); a = b
+      end
+      setfield(shipout_temp, 'head', a)
+      finalize_inner(shipout_temp)
+      setbox('global', "AtBeginShipoutBox", copy(getlist(shipout_temp)))
+      setfield(shipout_temp, 'head',nil)
    end
 end