local dir_node_manual = luatexja.dir_table.dir_node_manual
-
-local function get_dir_count()
- return tex_getcount('ltj@dir@count')
-end
-luatexja.direction.get_dir_count = get_dir_count
-
+local get_dir_count
-- \tate, \yoko
do
- local node_next = node.next
- local node_set_attr = node.set_attribute
- local function set_list_direction(v, name)
- local lv, w = tex.nest[tex.nest.ptr], tex.lists.page_head
- if lv.mode == 1 and w then
- if w.id==id_whatsit and w.subtype==sid_user
- and w.user_id==DIR then
- node_set_attr(w, attr_dir, v)
-
- end
- else
- local w = node_next(to_direct(lv.head))
- if to_node(w) then
- if getid(w)==id_whatsit and getsubtype(w)==sid_user
- and getfield(w, 'user_id')==DIR then
- set_attr(w, attr_dir, v)
- tex_set_attr('global', attr_dir, 0)
- else
+ local abs = math.abs
+ function get_dir_count()
+ return tex_getcount('ltj@dir@count')
+ end
+ luatexja.direction.get_dir_count = get_dir_count
+
+ local node_next = node.next
+ local node_set_attr = node.set_attribute
+ local function set_list_direction(v, name)
+ local lv, w = tex.nest[tex.nest.ptr], tex.lists.page_head
+ if lv.mode == 1 and w then
+ if w.id==id_whatsit and w.subtype==sid_user
+ and w.user_id==DIR then
+ node_set_attr(w, attr_dir, v)
+ end
+ else
+ local w = node_next(to_direct(lv.head))
+ if to_node(w) then
+ if getid(w)==id_whatsit and getsubtype(w)==sid_user
+ and getfield(w, 'user_id')==DIR then
+ set_attr(w, attr_dir, v)
+ else
ltjb.package_error(
'luatexja',
"Use `\\" .. name .. "' at top of list",
'Direction change command by LuaTeX-ja is available\n'
- .. 'only when the current list is null.')
- end
- else
- local w = node_new(id_whatsit, sid_user)
- setfield(w, 'next', hd)
- setfield(w, 'user_id', DIR)
- setfield(w, 'type', 110)
- set_attr(w, attr_dir, v)
- Dnode.write(w)
- tex_set_attr('global', attr_dir, 0)
- end
- tex_set_attr('global', attr_icflag, 0)
- end
- end
- luatexja.direction.set_list_direction = set_list_direction
+ .. 'only when the current list is null.')
+ end
+ else
+ local w = node_new(id_whatsit, sid_user)
+ setfield(w, 'next', hd)
+ setfield(w, 'user_id', DIR)
+ setfield(w, 'type', 110)
+ set_attr(w, attr_dir, v)
+ Dnode.write(w)
+ end
+ tex_set_attr('global', attr_icflag, 0)
+ end
+ tex_set_attr('global', attr_dir, 0)
+ end
+ luatexja.direction.set_list_direction = set_list_direction
end
-- ボックスに dir whatsit を追加
luatexbase.add_to_callback('hpack_filter',
create_dir_whatsit_hpack, 'ltj.create_dir_whatsit', 10000)
+ local wh = {}
+ local id_glue, sid_parskip = node.id('glue'), 3
local function create_dir_whatsit_vbox(h, gc)
- local hd= to_direct(h)
+ local hd = to_direct(h)
ltjs.list_dir = get_dir_count()
- if getid(hd)==id_whatsit and getsubtype(hd)==sid_user
- and getfield(hd, 'user_id')==DIR then
- ltjs.list_dir = has_attr(hd, attr_dir)
- return h
- elseif gc=='fin_row' or gc == 'preamble' then
+ -- remove dir whatsit
+ for x in traverse_id(id_whatsit, hd) do
+ if getsubtype(x)==sid_user and getfield(x, 'user_id')==DIR then
+ wh[#wh+1]=x
+ end
+ end
+ if hd==wh[1] then
+ ltjs.list_dir = has_attr(hd,attr_dir)
+ local x = node_next(hd)
+ if getid(x)==id_glue and getsubtype(x)==sid_parskip then
+ node_remove(hd,x); node_free(x)
+ end
+ end
+ for i=1,#wh do hd = node_remove(hd, wh[i]); node_free(wh[i]); wh[i] = nil end
+ if gc=='fin_row' or gc == 'preamble' then
if hd then
set_attr(hd, attr_icflag, PROCESSED_BEGIN_FLAG)
tex_set_attr('global', attr_icflag, 0)
end
- return h
+ return to_node(hd)
+ elseif gc=='vtop' then
+ local w = create_dir_whatsit(hd, gc, ltjs.list_dir)
+ -- move dir whatsit after hd
+ local n = getfield(hd, 'next')
+ setfield(hd, 'next', w); setfield(w, 'next', n)
+ return to_node(hd)
else
return to_node(create_dir_whatsit(hd, gc, ltjs.list_dir))
end
local function create_dir_whatsit_parbox(h, gc)
stop_time_measure('tex_linebreak')
+ print('BEGIN POST_LINEBREAK', gc)
+ luatexja.ext_show_node_list(h, ' ', print)
-- start 側は ltj-debug.lua に
local new_dir, hd = ltjs.list_dir, to_direct(h)
for line in traverse_id(id_hlist, hd) do
set_attr(line, attr_dir, new_dir)
end
+ tex_set_attr('global', attr_dir, 0)
return to_node(create_dir_whatsit(hd, gc, new_dir))
end
- luatexbase.add_to_callback('post_linebreak_filter',
+ luatexbase.add_to_callback('post_linebreak_filter',
create_dir_whatsit_parbox, 'ltj.create_dir_whatsit', 10000)
end
[dir_dtou] = { -- dtou を
[dir_yoko] = { -- yoko 中で組む
width = get_h_d,
- height = zero,
- depth = get_w,
+ height = get_w,
+ depth = zero,
[id_hlist] = {
{ 'whatsit', sid_save },
{ 'rotate', '0 1 -1 0' },
- { 'kern', get_w_neg },
+ { 'kern', zero },
{ 'box', get_h },
+ { 'kern', get_w_neg },
{ 'whatsit', sid_restore },
},
[id_vlist] = {
- { 'kern', get_w },
+ { 'kern', zero },
{ 'whatsit', sid_save },
{ 'rotate', '0 1 -1 0' },
- { 'box', zero },
+ { 'box', get_w_neg },
{ 'kern', get_h_d_neg },
{ 'whatsit', sid_restore },
},
local dir = has_attr(b, attr_dir) or 0
local bh = getlist(b)
local c
- if bh and getid(bh)==id_whatsit
- and getsubtype(bh)==sid_user and getfield(bh, 'user_id')==DIR then
- c = bh
- if dir==0 then
- dir = has_attr(bh, attr_dir)
- set_attr(b, attr_dir, dir)
- tex_set_attr('global', attr_dir, 0)
+ 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
+ if dir==0 then
+ dir = has_attr(bh, attr_dir)
+ set_attr(b, attr_dir, dir)
+ tex_set_attr('global', attr_dir, 0)
+ end
end
+ bh = node_next(bh)
end
return (dir==0 and default or dir), c
end
-- dir_node に包まれている「本来の中身」を取り出し,
-- dir_node を全部消去
-local function unwrap_dir_node(b, head)
- -- head: nil or nil-nil
- -- if head is non-nil, return values are (new head), (next of b), (contents)
+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)
local bh = getlist(b)
local bc = node_next(node_next(node_next(bh)))
local nh, nb
nh, nb = node_remove(nh, b)
setfield(b, 'next', nil)
setfield(b, 'head', nil)
- luatexja.ext_show_node(to_node(b), ' ', print)
- --node_free(b) -- TODO: これを入れると test51-vtest が途中で泊まる
+ node_free(b)
end
- local d, wh = get_box_dir(bc, 0)
+ local shift_old, b_dir, wh = nil, get_box_dir(bc, 0)
if wh then
Dnode.flush_list(getfield(wh, 'value'))
setfield(wh, 'value', nil)
end
- return nh, nb, bc
+ -- recalc. info
+ local info = dir_node_aux[b_dir][box_dir%dir_node_auto][getid(bc)]
+ for _,v in ipairs(info) do
+ if v[1]=='box' then
+ shift_old = v[2](
+ getfield(bc,'width'), getfield(bc, 'height'), getfield(bc, 'depth'))
+ break
+ end
+ end
+ setfield(bc, 'shift', getfield(bc, 'shift') - shift_old)
+ return nh, nb, bc, b_dir
end
-- is_manual: 寸法変更に伴うものか?
local db = node_new(getid(b))
set_attr(db, attr_dir,
new_dir + (is_manual and dir_node_manual or dir_node_auto))
+ tex_set_attr('global', attr_dir, 0)
set_attr(db, attr_icflag, PROCESSED)
set_attr(b, attr_icflag, PROCESSED)
setfield(db, 'dir', getfield(b, 'dir'))
if box_dir==new_dir then
return head, node_next(b), b, false
elseif box_dir%dir_node_auto == new_dir then
--- TODO. we have to free all other ...
+ local bc = node_next(node_next(node_next(bh)))
+ local _, dnc = get_box_dir(b, 0)
+ if dnc then -- free all other dir_node
+ Dnode.flush_list(getfield(dnc, 'value'))
+ setfield(dnc, 'value', nil)
+ end
set_attr(b, attr_dir, box_dir%dir_node_auto + dir_node_auto)
return head, node_next(b), b, true
else
local nh, nb, ret, flag
if box_dir>= dir_node_auto then -- unwrap
- nh, nb, ret = unwrap_dir_node(b, head)
- head, b = nh, ret;
- bh = getlist(b);
- box_dir, dn = get_box_dir(b, ltjs.list_dir)
- if box_dir==new_dir then
- return head, nb, b, fals
- end
+ local b_dir
+ head, nb, b, b_dir = unwrap_dir_node(b, head, box_dir)
+ bh = getlist(b)
+ if b_dir==new_dir then -- no need to create new dir_node
+ return head, nb, b, false
+ else box_dir = b_dir end
end
local db
local dnh = getfield(dn, 'value')
db=x; break
end
end
+ Dnode.flush_list(dnh)
db = db or create_dir_node(b, box_dir, new_dir, false)
local w = getfield(b, 'width')
local h = getfield(b, 'height')
elseif b_dir%dir_node_auto==l_dir then
setdimen('ltj@tempdima', getfield(s, key))
else
- get_box_dim_common(
- key,
- node_next(node_next(node_next(getlist(s)))),
- l_dir)
+ get_box_dim_common(key,
+ node_next(node_next(node_next(getlist(s)))), l_dir)
end
else
setdimen('ltj@tempdima', 0)
elseif b_dir%dir_node_auto == l_dir then
setfield(s, key, tex.getdimen('ltj@tempdima'))
if b_dir<dir_node_manual then
+ set_attr(s, attr_dir, b_dir%dir_node_auto + dir_node_manual)
end
else
local sid, sl = getid(s), getlist(s)
if set_box_dim_common(key, b, l_dir) then
local bw, bh, bd
= getfield(b,'width'), getfield(b, 'height'), getfield(b, 'depth')
- -- re-calculate shifting info
+ -- re-calculate shift
for i,v in ipairs(info[sid]) do
if getid(sl)==id_kern then
setfield(sl, 'kern', v[2](bw,bh,bd) )
luatexja.direction.set_box_dim = set_box_dim
end
+-- \ifydir, \iftdir, \ifddir
+do
+ local cat_lp = luatexbase.catcodetables['latex-package']
+ local getbox = tex.getbox
+ local function dir_conditional(n, mode)
+ local s = getbox(n)
+ local res = false
+ if s then
+ s = to_direct(s)
+ local b_dir = get_box_dir(s, dir_yoko)
+ if b_dir<dir_node_auto then
+ res = (b_dir==mode)
+ else
+ local b_dir = get_box_dir(
+ node_next(node_next(node_next(getlist(s)))), dir_yoko)
+ res = (b_dir==mode)
+ end
+ end
+ tex.sprint(cat_lp, '\\if' .. tostring(res))
+ end
+ luatexja.direction.dir_conditional = dir_conditional
+end
+
-- 縦書き用字形への変換テーブル
local font_vert_table = {} -- key: fontnumber
do