-do
- local tex_getcount = tex.getcount
- local function set_dir_flag(h)
- local new_dir = ltjs.table_current_stack[DIR]
- local w = node_new(id_whatsit, sid_user)
- setfield(w, 'user_id', wh_DIR)
- setfield(w, 'type', 100)
- setfield(w, 'value', new_dir)
- setfield(w, 'next', to_direct(h))
- return to_node(w)
- end
- luatexbase.add_to_callback('hpack_filter', set_dir_flag, 'ltj.set_dir_flag', 10000)
- luatexbase.add_to_callback('vpack_filter',
- function (h)
- local box_set, cl = 0, tex.currentgrouplevel + 1
- for w in traverse_id(id_whatsit, to_direct(h)) do
- if getfield(w, 'value')==cl then box_set = 1; break end
- end
- ltjs.report_stack_level(tex_getcount('ltj@@stack') + box_set)
- return set_dir_flag(h)
- end, 'ltj.set_dir_flag', 1)
- luatexbase.add_to_callback('post_linebreak_filter',
- function (h)
- local new_dir = ltjs.table_current_stack[DIR]
- for line in traverse_id(id_hlist, to_direct(h)) do
- set_attr(line, attr_dir, new_dir)
- end
- return h
- end, 'ltj.set_dir_flag', 100)
+--
+local function adjust_badness(hd)
+ if not node_next(hd) and getid(hd)==id_whatsit and getsubtype(hd)==sid_user
+ and getfield(hd, 'user_id')==DIR then
+ -- avoid double whatsit
+ luatexja.global_temp=tex.globaldefs; tex.globaldefs=0
+ luatexja.hbadness_temp=tex.hbadness; tex.hbadness=10000
+ luatexja.vbadness_temp=tex.vbadness; tex.vbadness=10000
+ else
+ luatexja.global_temp = nil
+ luatexja.hbadness_temp=nil
+ luatexja.vbadness_temp=nil
+ end
+end
+
+local get_dir_count, get_adjust_dir_count
+do
+ local function get_dir_count_inner(h)
+ if h then
+ if h.id==id_whatsit and h.subtype==sid_user and h.user_id==DIR then
+ local ic = node.has_attribute(h, attr_icflag) or 0
+ return (ic<PROCESSED_BEGIN_FLAG)
+ and (node.has_attribute(h,attr_dir)%dir_node_auto) or 0
+ else
+ return 0
+ end
+ else
+ return 0
+ 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
+ end
+ function get_adjust_dir_count()
+ for i=tex_nest.ptr, 1, -1 do
+ local v = tex_nest[i]
+ local h, m = v.head.next, v.mode
+ if abs(m)== ltjs.vmode and h then
+ local t = get_dir_count_inner(h)
+ if t~=0 then return t end
+ end
+ end
+ return page_direction
+ end
+ luatexja.direction.get_dir_count = get_dir_count
+ luatexja.direction.get_adjust_dir_count = get_adjust_dir_count
+end
+
+
+-- \tate, \yoko,\dtou, \utod
+do
+ local node_next = node.next
+ local node_set_attr = node.set_attribute
+ 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 function test_list(h, lv)
+ if not h then
+ return 2 -- need to create dir_whatsit
+ else
+ local flag = 2 -- need to create dir_whatsit
+ local w
+ for p in node_traverse(h) do
+ if p.id==id_whatsit then
+ local ps = p.subtype
+ if ps==sid_user then
+ local uid= p.user_id
+ if uid==DIR then
+ flag = 1; w = w or p -- found
+ elseif not(uid==IHB or uid==STCK) then
+ flag = 0; break -- error
+ end
+ elseif ps~=sid_local then
+ flag = 0; break
+ end
+ else
+ flag = 0; break
+ end
+ end
+ 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 = dir_pool[v]()
+ insert_after(h, h, w)
+ tex_nest[lv].tail = to_node(node_tail(w))
+ ensure_tex_attr(attr_icflag, 0)
+ ensure_tex_attr(attr_dir, 0)
+ end
+
+ local function set_list_direction(v, name)
+ local lv = tex_nest.ptr
+ if not v then
+ v,name = get_dir_count(), nil
+ if lv>=1 and abs(tex_nest[lv-1].mode) == ltjs.mmode and v == dir_tate then
+ v = dir_utod
+ end
+ elseif v=='adj' then
+ v,name = get_adjust_dir_count(), nil
+ end
+ 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.")
+ else
+ local h = (lv==0) and tex.lists.page_head or tex_nest[lv].head.next
+ local flag,w = test_list(h,lv)
+ if flag==0 then
+ if lv==0 and not page_direction then
+ page_direction = v -- for first call of \yoko (in luatexja-core.sty)
+ else
+ ltjb.package_error(
+ 'luatexja',
+ "Use `\\" .. tostring(name) .. "' at top of list",
+ 'Direction change command by LuaTeX-ja is available\n'
+ .. 'only when the current list is null.')
+ end
+ 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
+ end
+ ensure_tex_attr(attr_icflag, 0)
+ end
+ ensure_tex_attr(attr_dir, 0)
+ end
+ luatexja.direction.set_list_direction = set_list_direction
+end
+
+-- ボックスに dir whatsit を追加
+local function create_dir_whatsit(hd, gc, new_dir)
+ if getid(hd)==id_whatsit and
+ 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)
+ if n then
+ set_attr(n, attr_icflag,
+ get_attr_icflag(n) + PROCESSED_BEGIN_FLAG)
+ end
+ ensure_tex_attr(attr_icflag, 0)
+ return hd
+ else
+ local w = dir_pool[new_dir]()
+ setfield(w, 'next', hd)
+ set_attr(w, attr_icflag, PROCESSED_BEGIN_FLAG)
+ set_attr(hd, attr_icflag,
+ get_attr_icflag(hd) + PROCESSED_BEGIN_FLAG)
+ ensure_tex_attr(attr_icflag, 0)
+ ensure_tex_attr(attr_dir, 0)
+ return w
+ end
+end
+
+-- hpack_filter, vpack_filter, post_line_break_filter
+-- の結果を組方向を明示するため,先頭に dir_node を設置
+do
+ local function create_dir_whatsit_hpack(h, gc)
+ local hd = to_direct(h)
+ if gc=='fin_row' or gc == 'preamble' then
+ if hd then
+ set_attr(hd, attr_icflag, PROCESSED_BEGIN_FLAG)
+ ensure_tex_attr(attr_icflag, 0)
+ end
+ return h
+ else
+ adjust_badness(hd)
+ return to_node(create_dir_whatsit(hd, gc, ltjs.list_dir))
+ end
+ end
+
+ luatexbase.add_to_callback('hpack_filter',
+ create_dir_whatsit_hpack, 'ltj.create_dir_whatsit', 10000)
+end
+
+do
+ local function create_dir_whatsit_parbox(h, gc)
+ 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
+ setfield(line, 'head', create_dir_whatsit(getlist(line), gc, new_dir) )
+ end
+ ensure_tex_attr(attr_dir, 0)
+ return h
+ end
+ luatexbase.add_to_callback('post_linebreak_filter',
+ create_dir_whatsit_parbox, 'ltj.create_dir_whatsit', 10000)
+end