OSDN Git Service

use node.direct.{g/s}etdata
[luatex-ja/luatexja.git] / src / luatexja.lua
index 074d050..8134976 100644 (file)
@@ -12,21 +12,64 @@ luatexja.load_lua = load_lua
 function luatexja.load_module(name) require('ltj-' .. name.. '.lua') end
 
 do
-   local setfield = node.direct.setfield
+    local dnode = node.direct
+    local getfield, traverse = dnode.getfield, dnode.traverse
+    local node_new, set_attr, get_attr = dnode.new, dnode.set_attribute, dnode.get_attribute
+    local set_attrlist, get_attrlist = dnode.setattributelist, dnode.getattributelist
+    local unset_attr = dnode.unset_attribute
+    local attr_icflag = luatexbase.attributes['ltj@icflag']
+    local function node_inherit_attr(n, b, a)
+        if b or a then
+            local attrlist = get_attrlist(b or a)
+            local nic = get_attr(n, attr_icflag)
+            set_attrlist(n, attrlist); set_attr(n, attr_icflag, nic)
+            if b and a then
+                for na in traverse(attrlist) do
+                    local id = getfield(na, 'number')
+                    if id and id~=attr_icflag and getfield(na, 'value')~=get_attr(a, id) then
+                        unset_attr(n, id)
+                    end
+                end
+            end
+        end
+        return n
+    end
+    luatexja.node_inherit_attr = node_inherit_attr
+    luatexja.dnode_new = function (id, subtype, b, a)
+        return node_inherit_attr(node_new(id, subtype), b, a)
+    end
+end
+do
+   local dnode = node.direct
+   local setfield = dnode.setfield
    luatexja.setglue = node.direct.setglue or
    function(g,w,st,sh,sto,sho)
       setfield(g,'width', w or 0); setfield(g,'stretch',st or 0); setfield(g,'shrink', sh or 0)
       setfield(g,'stretch_order',sto or 0)
       setfield(g,'shrink_order', sho or 0)
    end
-   local getfield = node.direct.getfield
+   for _,v in pairs({'char', 'depth', 'dir', 'font', 'height', 'kern', 'lang', 'next',
+                      'nucleus', 'offsets', 'penalty', 'shift', 'sub', 'subtype', 'sup'}) do
+         if not dnode['set'..v] then
+             dnode['set'..v] = function(n, ...) return setfield(n, v, ...) end
+         end
+   end
+   local getfield = dnode.getfield
    luatexja.getglue = node.direct.getglue or
    function(g)
       return getfield(g,'width'), getfield(g,'stretch'), getfield(g,'shrink'),
              getfield(g,'stretch_order'), getfield(g,'shrink_order')
    end
+   for _,v in pairs({'box', 'components', 'char', 'depth', 'font', 'height', 'kern', 'lang',
+                     'list', 'next', 'nucleus', 'offsets', 'penalty', 'prev', 'shift', 'sub',
+                     'subtype', 'sup', 'whd', 'width', 'dir'}) do
+         if not dnode['get'..v] then
+             dnode['get'..v] = function(n, ...) return getfield(n, v, ...) end
+         end
+    end
 end
 
+
 --- 以下は全ファイルで共有される定数
 local icflag_table = {}
 luatexja.icflag_table = icflag_table
@@ -42,6 +85,9 @@ icflag_table.LINEEND         = 72
 icflag_table.PROCESSED       = 73
 icflag_table.IC_PROCESSED    = 74
 icflag_table.BOXBDD          = 75
+icflag_table.SPECIAL_JAGLUE  = 76
+-- 段落組版中のノードリストでは通常のノード (not whatsit) だが
+-- 和文処理グルー挿入プロセスで長さが決定されるもの
 icflag_table.PROCESSED_BEGIN_FLAG = 4096 -- sufficiently large power of 2
 
 local stack_ind = {}
@@ -83,8 +129,13 @@ dir_table.dir_utod = dir_table.dir_tate + dir_table.dir_math_mod
 
 local load_module = luatexja.load_module
 load_module 'base';      local ltjb = luatexja.base
+if tex.outputmode==0 then
+    ltjb.package_error('luatexja',
+      'DVI output is not supported in LuaTeX-ja',
+      'Use lua*tex instead dvilua*tex.')
+end
 load_module 'rmlgbm';    local ltjr = luatexja.rmlgbm -- must be 1st
-if luatexja_debug then load_module('debug') end
+if luatexja_debug then load_module 'debug' end
 load_module 'lotf_aux';  local ltju = luatexja.lotf_aux
 load_module 'charrange'; local ltjc = luatexja.charrange
 load_module 'stack';     local ltjs = luatexja.stack
@@ -113,11 +164,11 @@ local floor = math.floor
 local function print_scaled(s)
    local out, delta = '', 10
    if s<0 then s, out = -s, out..'-' end
-   out=out..tostring(floor(s/65536)) .. '.'
+   out=out..tostring(s//65536) .. '.'
    s=10*(s%65536)+5
    repeat
       if delta>65536 then s=s+32768-50000 end
-      out=out .. tostring(floor(s/65536))
+      out=out .. tostring(s//65536)
       s=10*(s%65536); delta=delta*10
    until s<=delta
    return out
@@ -135,12 +186,12 @@ local function print_glue(d,order)
 end
 
 local function print_spec(p)
-   local out=print_scaled(p.width)..'pt'
-   if p.stretch~=0 then
-      out=out..' plus '..print_glue(p.stretch,p.stretch_order)
+   local out=print_scaled(p.width or p[1])..'pt'
+   if (p.stretch or p[2])~=0 then
+      out=out..' plus '..print_glue(p.stretch or p[2], p.stretch_order or p[4])
    end
-   if p.shrink~=0 then
-      out=out..' minus '..print_glue(p.shrink,p.shrink_order)
+   if (p.shrink or p[3])~=0 then
+      out=out..' minus '..print_glue(p.shrink or p[3], p.shrink_order or p[5])
    end
 return out
 end
@@ -149,14 +200,16 @@ end
 ------------------------------------------------------------------------
 -- CODE FOR GETTING/SETTING PARAMETERS
 ------------------------------------------------------------------------
+local getcount, texwrite = tex.getcount, tex.write
+local cnt_stack = luatexbase.registernumber 'ltj@@stack'
 
 -- EXT: print parameters that don't need arguments
 do
    local tex_getattr = tex.getattribute
-   local function getattr(a)
-      local r = tex_getattr(a)
-      return (r==-0x7FFFFFFF) and 0 or r
-   end 
+   local function getattr(a, d)
+      local r = tex_getattr(a); d = d or 0
+      return (r==-0x7FFFFFFF) and d or r
+   end
    luatexja.unary_pars = {
       yalbaselineshift = function(t)
          return print_scaled(getattr('ltj@yablshift'))..'pt'
@@ -180,10 +233,10 @@ do
          return ltjs.get_stack_table(stack_ind.JWP, 0, t)
       end,
       autospacing = function(t)
-         return getattr('ltj@autospc')
+         return getattr('ltj@autospc', 1)
       end,
       autoxspacing = function(t)
-         return getattr('ltj@autoxspc')
+         return getattr('ltj@autoxspc', 1)
       end,
       differentjfm = function(t)
          local f, r = luatexja.jfmglue.diffmet_rule, '???'
@@ -199,7 +252,7 @@ do
       end,
       direction = function()
          local v = ltjd.get_dir_count()
-         if math.abs(tex.nest[tex.nest.ptr].mode) == ltjs.mmode and v == dir_table.dir_tate then
+         if math.abs(tex.getnest().mode) == ltjs.mmode and v == dir_table.dir_tate then
             v = dir_table.dir_utod
          end
          return v
@@ -212,9 +265,9 @@ do
    function luatexja.ext_get_parameter_unary()
       local k= scan_arg()
       if unary_pars[k] then
-         tex.write(tostring(unary_pars[k](tex.getcount('ltj@@stack'))))
+         texwrite(tostring(unary_pars[k](getcount(cnt_stack))))
       end
-      ltjb.stop_time_measure('get_par')
+      ltjb.stop_time_measure 'get_par'
    end
 end
 
@@ -233,8 +286,8 @@ do
             c=0 -- external range 217 == internal range 0
          elseif c==31*ltjc.ATTR_RANGE then c=0
          end
-      -- 負の値は <U+0080 の文字の文字範囲,として出てくる.この時はいつも欧文文字なので 1 を返す
-         return (c<0) and 1 or ltjc.get_range_setting(c)
+         -- 負の値は <U+0080 の文字の文字範囲,として出てくる.この時はいつも欧文文字なので 1 を返す
+         if c<0 then return 1 else return (ltjc.get_range_setting(c)==0) and 0 or 1 end
       end,
       prebreakpenalty = function(c, t)
          return ltjs.get_stack_table(stack_ind.PRE + ltjb.in_unicode(c, true), 0, t)
@@ -267,9 +320,9 @@ do
    binary_pars.alxspmode = binary_pars.jaxspmode
    function luatexja.ext_get_parameter_binary(k, c)
       if binary_pars[k] then
-         tex.write(tostring(binary_pars[k](c,tex.getcount('ltj@@stack'))))
+         texwrite(tostring(binary_pars[k](c, getcount(cnt_stack))))
       end
-      ltjb.stop_time_measure('get_par')
+      ltjb.stop_time_measure 'get_par'
    end
 end
 
@@ -287,15 +340,16 @@ do
    local to_node = node.direct.tonode
    local to_direct = node.direct.todirect
    local ensure_tex_attr = ltjb.ensure_tex_attr
-
+   local slide = node.slide
    -- mode = true iff main_process is called from pre_linebreak_filter
    local function main_process(head, mode, dir, gc)
       ensure_tex_attr(attr_icflag, 0)
       if gc == 'fin_row' then return head
       else
-            start_time_measure('jfmglue')
+            start_time_measure 'jfmglue'
+            slide(head);
             local p = ltjj.main(to_direct(head),mode, dir)
-            stop_time_measure('jfmglue')
+            stop_time_measure 'jfmglue'
             return to_node(p)
       end
    end
@@ -324,31 +378,27 @@ do
    ltjb.add_to_callback('hpack_filter', adjust_icflag, 'ltj.adjust_icflag', 1)
 end
 
--- cleanup process
-function luatexja.ext_cleanup()
-   ltjf.cleanup_size_cache(); ltjd.remove_end_whatsit()
-end
-
 -- lastnodechar
 do
-   local id_glyph = node.id('glyph')
+   local getnest = tex.getnest
+   local id_glyph = node.id 'glyph'
    function luatexja.pltx_composite_last_node_char()
-      local n = tex.nest[tex.nest.ptr].tail
+      local n = getnest()
       local r = '-1'
       if n then
          if n.id==id_glyph then
-            while n.componetns and  n.subtype and n.subtype%4 >= 2 do
+            while n.components and  n.subtype and n.subtype%4 >= 2 do
                n = node.tail(n)
             end
             r = tostring(n.char)
          end
       end
-      tex.sprint(r)
+      tex.sprint(-2, r)
    end
 end
 
 do
-    local cache_ver = 1 -- must be same as ltj-kinsoku.tex
+    local cache_ver = 4 -- must be same as ltj-kinsoku.tex
     local cache_outdate_fn = function (t) return t.version~=cache_ver end
     local t = ltjs.charprop_stack_table
     function luatexja.load_kinsoku()
@@ -369,29 +419,29 @@ do
 
 local node_type = node.type
 local node_next = node.next
-local has_attr = node.has_attribute
-
-local id_penalty = node.id('penalty')
-local id_glyph = node.id('glyph')
-local id_glue = node.id('glue')
-local id_kern = node.id('kern')
-local id_hlist = node.id('hlist')
-local id_vlist = node.id('vlist')
-local id_rule = node.id('rule')
-local id_math = node.id('math')
-local id_whatsit = node.id('whatsit')
-local sid_user = node.subtype('user_defined')
+local get_attr = node.get_attribute
+
+local id_penalty = node.id 'penalty'
+local id_glyph = node.id 'glyph'
+local id_glue = node.id 'glue'
+local id_kern = node.id 'kern'
+local id_hlist = node.id 'hlist'
+local id_vlist = node.id 'vlist'
+local id_rule = node.id 'rule'
+local id_math = node.id 'math'
+local id_whatsit = node.id 'whatsit'
+local sid_user = node.subtype 'user_defined'
 
 local prefix, inner_depth
 local utfchar = utf.char
 local function debug_show_node_X(p,print_fn, limit, inner_depth)
    local k = prefix
    local s
-   local pt, pic = node_type(p.id), (has_attr(p, attr_icflag) or 0) % icflag_table.PROCESSED_BEGIN_FLAG
+   local pt, pic = node_type(p.id), (get_attr(p, attr_icflag) or 0) % icflag_table.PROCESSED_BEGIN_FLAG
    local base = prefix .. string.format('%X', pic) .. ' ' .. pt .. ' ' .. tostring(p.subtype) .. ' '
    if pt == 'glyph' then
-      s = base .. ' ' 
-          .. (p.char<0xF0000 and utfchar(p.char) or '') 
+      s = base .. ' '
+          .. (p.char<0xF0000 and utfchar(p.char) or '')
           .. string.format(' (U+%X) ', p.char)
           .. tostring(p.font) .. ' (' .. print_scaled(p.height) .. '+'
           .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width)
@@ -404,11 +454,11 @@ local function debug_show_node_X(p,print_fn, limit, inner_depth)
       if pt=='ins' then
          s = base .. '(' .. print_scaled(p.height) .. '+'
             .. print_scaled(p.depth) .. ')'
-            .. ', dir=' .. tostring(node.has_attribute(p, attr_dir))
+            .. ', dir=' .. tostring(node.get_attribute(p, attr_dir))
       else
          s = base .. '(' .. print_scaled(p.height) .. '+'
             .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width)
-            .. ', dir=' .. tostring(node.has_attribute(p, attr_dir))
+            .. ', dir=' .. tostring(node.get_attribute(p, attr_dir))
       end
       if (p.shift or 0)~=0 then
          s = s .. ', shifted ' .. print_scaled(p.shift)
@@ -436,7 +486,7 @@ local function debug_show_node_X(p,print_fn, limit, inner_depth)
    elseif pt=='rule' then
       s = base .. '(' .. print_scaled(p.height) .. '+'
          .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width)
-         .. ', dir=' .. tostring(node.has_attribute(p, attr_dir))
+         .. ', dir=' .. tostring(node.get_attribute(p, attr_dir))
       print_fn(s)
    elseif pt=='disc' then
       print_fn(s)
@@ -500,7 +550,7 @@ local function debug_show_node_X(p,print_fn, limit, inner_depth)
          else
             s = s .. ' userid:' .. t .. '(node list)'
             if p.user_id==uid_table.DIR then
-               s = s .. ' dir: ' .. tostring(node.has_attribute(p, attr_dir))
+               s = s .. ' dir: ' .. tostring(node.get_attribute(p, attr_dir))
             end
             print_fn(s)
             local bid = inner_depth
@@ -518,7 +568,7 @@ local function debug_show_node_X(p,print_fn, limit, inner_depth)
             s = s .. ' stream=' .. p.stream
             print_fn(s)
             for i=1,#p.data do
-               print_fn(s .. '  [' .. i .. '] = ' .. tostring(p.data[i].csname))
+               print_fn(s .. '  [' .. i .. '] = ' .. tostring(p.data[i] and p.date[i].csname))
             end
          elseif p.subtype==16 then
             s = s .. ' mode=' .. p.mode .. ', literal="' .. p.data .. '"'
@@ -551,6 +601,9 @@ local function debug_show_node_X(p,print_fn, limit, inner_depth)
             debug_show_node_X(q, print_fn, limit, inner_depth)
          end
       end
+   elseif pt == 'attribute' then
+      s = base .. ' [' .. p.number .. '] = ' .. p.value
+      print_fn(s)
    else
       print_fn(base)
    end