X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=src%2Fltj-direction.lua;h=133e3e87e59afafa93daa9f4325e03d1499cabbc;hb=87c0b418e8b10f5c13049bf4b3402725e02ecf6a;hp=42f1cb095f0677b8866a93f076fd0b7bcae24976;hpb=ab23049deb6fb90ca689fdf4924b3783f08f8f2e;p=luatex-ja%2Fluatexja.git diff --git a/src/ltj-direction.lua b/src/ltj-direction.lua index 42f1cb0..133e3e8 100644 --- a/src/ltj-direction.lua +++ b/src/ltj-direction.lua @@ -106,14 +106,14 @@ do end end function get_dir_count() - for i=tex_nest.ptr, 1, -1 do - local h = tex_nest[i].head.next - if h then - local t = get_dir_count_inner(h) - if t~=0 then return t end - end - end - return page_direction + for i=tex_nest.ptr, 1, -1 do + local h = tex_nest[i].head.next + if h then + local t = get_dir_count_inner(h) + if t~=0 then return t end + end + end + return page_direction end function get_adjust_dir_count() for i=tex_nest.ptr, 1, -1 do @@ -138,7 +138,6 @@ do local node_traverse = node.traverse local STCK = luatexja.userid_table.STCK local IHB = luatexja.userid_table.IHB - local sid_local = node.subtype('local_par') local id_local = node.id('local_par') local function test_list(h, lv) @@ -157,8 +156,6 @@ do elseif not(uid==IHB or uid==STCK) then flag = 0; break -- error end - elseif ps~=sid_local then - flag = 0; break end elseif p.id~=id_local then flag = 0; break @@ -171,6 +168,8 @@ do end end end + local node_next_node, node_tail_node = node.next, node.tail + local insert_after_node = node.insert_after function luatexja.direction.set_list_direction_hook(v) local lv = tex_nest.ptr -- must be >= 1 if not v then @@ -181,10 +180,12 @@ do elseif v=='adj' then v = get_adjust_dir_count() end - local h = to_direct(tex_nest[lv].head) - local w = dir_pool[v]() - insert_after(h, h, w) - tex_nest[lv].tail = to_node(node_tail(w)) + local h = tex_nest[lv].head + local hn = node.next(h) + hn = (hn and hn.id==id_local) and hn or h + local w = to_node(dir_pool[v]()) + insert_after_node(h, hn, w) + tex_nest[lv].tail = node_tail_node(w) ensure_tex_attr(attr_icflag, 0) ensure_tex_attr(attr_dir, 0) end @@ -199,14 +200,21 @@ do elseif v=='adj' then v,name = get_adjust_dir_count(), nil end + local current_nest = tex_nest[lv] if tex.currentgrouptype==6 then ltjb.package_error( 'luatexja', "You can't use `\\" .. name .. "' in an align", - "To change direction in an align, \n" - .. "you shold use \\hbox or \\vbox.") + "To change the direction in an align, \n" + .. "you shold use \\hbox or \\vbox.") + elseif current_nest.mode == ltjs.hmode or abs(current_nest.mode) == ltjs.mmode then + ltjb.package_error( + 'luatexja', + "Improper `\\" .. name .. "'", + 'You cannot change the direction in unrestricted horizontal mode \n' + .. 'nor math modes.') else - local h = (lv==0) and tex.lists.page_head or tex_nest[lv].head.next + local h = (lv==0) and tex.lists.page_head or current_nest.head.next local flag,w = test_list(h,lv) if flag==0 then if lv==0 and not page_direction then @@ -221,8 +229,15 @@ do elseif flag==1 then node_set_attr(w, attr_dir, v) if lv==0 then page_direction = v end - else - if lv==0 then page_direction = v end + elseif lv==0 then + page_direction = v + else -- flag == 2: need to create dir whatsit. + local h = current_nest.head + local hn = node.next(h) + hn = (hn and hn.id==id_local) and hn or h + local w = to_node(dir_pool[v]()) + insert_after_node(h,hn,w) + current_nest.tail = node_tail_node(w) end ensure_tex_attr(attr_icflag, 0) end @@ -237,7 +252,7 @@ local function create_dir_whatsit(hd, gc, new_dir) getsubtype(hd)==sid_user and getfield(hd, 'user_id')==DIR then set_attr(hd, attr_icflag, get_attr_icflag(hd) + PROCESSED_BEGIN_FLAG) - local n = node_next(hd) + local n =node_next(hd) if n then set_attr(n, attr_icflag, get_attr_icflag(n) + PROCESSED_BEGIN_FLAG) @@ -258,15 +273,22 @@ end -- hpack_filter, vpack_filter, post_line_break_filter -- の結果を組方向を明示するため,先頭に dir_node を設置 +local get_box_dir do local function create_dir_whatsit_hpack(h, gc) local hd = to_direct(h) - if gc=='fin_row' or gc == 'preamble' then + if gc=='fin_row' then if hd then + for p in traverse_id(15, hd) do -- unset + if get_box_dir(p, 0)==0 then + setfield(p, 'head', create_dir_whatsit(getlist(p), 'fin_row', ltjs.list_dir)) + end + end set_attr(hd, attr_icflag, PROCESSED_BEGIN_FLAG) ensure_tex_attr(attr_icflag, 0) end return h + elseif gc == 'preamble' then else adjust_badness(hd) return to_node(create_dir_whatsit(hd, gc, ltjs.list_dir)) @@ -279,7 +301,7 @@ end do local function create_dir_whatsit_parbox(h, gc) - stop_time_measure('tex_linebreak') + stop_time_measure('tex_linebreak'); -- start 側は ltj-debug.lua に local new_dir = ltjs.list_dir for line in traverse_id(id_hlist, to_direct(h)) do @@ -482,7 +504,7 @@ end -- 1st ret val: b の組方向 -- 2nd ret val はその DIR whatsit -local function get_box_dir(b, default) +function get_box_dir(b, default) start_time_measure('get_box_dir') local dir = has_attr(b, attr_dir) or 0 local bh = getfield(b,'head') @@ -515,7 +537,7 @@ do 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 + if b and getlist(to_direct(b)) then local box_dir = get_box_dir(to_direct(b), dir_yoko) if box_dir%dir_math_mod ~= list_dir then ltjb.package_error( @@ -686,6 +708,7 @@ do -- lastbox local node_prev = (node.direct~=node) and node.direct.getprev or node.prev + local id_glue = node.id('glue') local function lastbox_hook() start_time_measure('box_primitive_hook') local bn = tex_nest[tex_nest.ptr].tail @@ -693,6 +716,14 @@ do local b, head = to_direct(bn), to_direct(tex_nest[tex_nest.ptr].head) local bid = getid(b) if bid==id_hlist or bid==id_vlist then + local p = getlist(b) + -- alignment の各行の中身が入ったボックス + if p and getid(p)==id_glue and getsubtype(p)==12 then -- tabskip + local np = node_next(p); local npid = getid(np) + if npid==id_hlist or npid==id_vlist then + setfield(b, 'head', create_dir_whatsit(p, 'align', get_box_dir(np, 0))) + end + end local box_dir = get_box_dir(b, 0) if box_dir>= dir_node_auto then -- unwrap dir_node local p = node_prev(b) @@ -764,8 +795,8 @@ do luatexja.direction.get_box_dim = get_box_dim -- return value: (changed dimen of box itself?) - local scan_dimen, scan_int = luatexja.token.scan_dimen, luatexja.token.scan_int - local scan_keyword = luatexja.token.scan_keyword + local scan_dimen, scan_int = token.scan_dimen, token.scan_int + local scan_keyword = token.scan_keyword local function set_box_dim_common(key, s, l_dir) local s_dir, wh = get_box_dir(s, dir_yoko) s_dir = s_dir%dir_math_mod @@ -927,6 +958,9 @@ do local list_dir = get_dir_count() local a = tex_nest[tex_nest.ptr].tail local ad = to_direct(a) + if (not a) or getid(ad)~=id_ins then + a = node.tail(tex.lists.page_head); ad = to_direct(a) + end if a and getid(ad)==id_ins then local h = getfield(ad, 'head') if getid(h)==id_whatsit and @@ -948,7 +982,25 @@ end -- vsplit do - local split_dir_whatsit + local split_dir_whatsit, split_dir_head + local cat_lp = luatexbase.catcodetables['latex-package'] + local sprint, scan_int, tex_getbox = tex.sprint, token.scan_int, tex.getbox + function luatexja.direction.vsplit() + local n = scan_int(); + local p = to_direct(tex_getbox(n)) + split_dir_head = nil + if p then + local bh = getlist(p) + if getid(bh)==id_whatsit and getsubtype(bh)==sid_user and getfield(bh, 'user_id')==DIR + and node_next(bh) then + ltjs.list_dir = has_attr(bh, attr_dir) + local q = node_next(p) + setfield(p, 'head', node_remove(bh,bh,bh)) + split_dir_head = bh + end + end + sprint(cat_lp, '\\ltj@@orig@vsplit' .. tostring(n)) + end local function dir_adjust_vpack(h, gc) start_time_measure('direction_vpack') local hd = to_direct(h) @@ -957,19 +1009,11 @@ do hd = create_dir_whatsit_vbox(hd, gc) split_dir_whatsit = hd elseif gc=='split_off' 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 + if split_dir_head then + list_dir = has_attr(split_dir_head, attr_dir) + hd = insert_before(hd, hd, split_dir_head) + split_dir_head=nil 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) @@ -979,7 +1023,9 @@ do split_dir_whatsit=nil else adjust_badness(hd) - hd = process_dir_node(create_dir_whatsit_vbox(hd, gc), gc) + -- hd = process_dir_node(create_dir_whatsit_vbox(hd, gc), gc) + -- done in append_to_vpack callback + hd = create_dir_whatsit_vbox(hd, gc) split_dir_whatsit=nil end stop_time_measure('direction_vpack') @@ -1010,23 +1056,44 @@ do end end --- buildpage filter +-- append_to_vlist filter do - local function dir_adjust_buildpage(info) - if info=='box' then - local head = to_direct(tex.lists.contrib_head) - if head then - head = make_dir_whatsit(head, - node_tail(head), - get_dir_count(), - 'buildpage') - tex.lists.contrib_head = to_node(head) + local id_glue = node.id('glue') + local 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 +local setglue = luatexja.setglue + local function copy_glue (new_glue, old_glue, subtype, new_w) + setfield(new_glue, 'subtype', subtype) + local w,st,sp,sto,spo = getglue(to_direct(old_glue)) + setglue(new_glue, new_w or w, st, sp, sto, spo) + end + local node_write = node.direct.write + local function dir_adjust_append_vlist(b, loc, prev, mirrored) + local old_b = to_direct(b) + local new_b = loc=='box' and + make_dir_whatsit(old_b, old_b, get_dir_count(), 'append_vlist') or old_b + + if prev > -65536000 then + local d = tex.baselineskip.width - prev + - getfield(new_b, mirrored and 'depth' or 'height') + local g = node_new(id_glue) + if d < tex.lineskiplimit then + copy_glue(g, tex.lineskip, 1) + else + copy_glue(g, tex.baselineskip, 2, d); end + node_write(g) end + node_write(new_b) + tex.prevdepth = getfield(new_b, mirrored and 'height' or 'depth') + return nil -- do nothing on tex side end - ltjb.add_to_callback('buildpage_filter', - dir_adjust_buildpage, - 'ltj.direction', 10000) + ltjb.add_to_callback('append_to_vlist_filter', + dir_adjust_append_vlist, + 'ltj.direction', 10000) end -- finalize (executed just before \shipout) @@ -1047,7 +1114,7 @@ do [get_box_dir(b, dir_yoko)%dir_math_mod][new_dir][getid(b)]) do local cmd, arg, nn = v[1], v[2] if cmd=='kern' then - nn = node_new(id_kern) + nn = node_new(id_kern, 1) setfield(nn, 'kern', arg(w, h, d, dn_w, dn_h, dn_d)) elseif cmd=='whatsit' then nn = node_new(id_whatsit, arg) @@ -1099,7 +1166,6 @@ do finalize_inner(shipout_temp) setbox('global', "AtBeginShipoutBox", copy(getlist(shipout_temp))) setfield(shipout_temp, 'head',nil) - -- garbage collect --local m = collectgarbage('count') --if m>lua_mem_kb+20480 then