+
+-- 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
+end
+
+-- vsplit
+do
+ local split_dir_whatsit
+ local function dir_adjust_vpack(h, gc)
+ start_time_measure('direction_vpack')
+ local hd = to_direct(h)
+ if gc=='split_keep' then
+ -- supply dir_whatsit
+ 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
+ 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)
+ end
+ split_dir_whatsit=nil
+ elseif gc=='preamble' then
+ split_dir_whatsit=nil
+ else
+ adjust_badness(hd)
+ hd = process_dir_node(create_dir_whatsit_vbox(hd, gc), gc)
+ split_dir_whatsit=nil
+ end
+ stop_time_measure('direction_vpack')
+ return to_node(hd)
+ end
+ luatexbase.add_to_callback('vpack_filter',
+ dir_adjust_vpack,
+ 'ltj.direction', 10000)
+end
+
+do
+ -- supply direction whatsit to the main vertical list "of the next page"
+ local function dir_adjust_pre_output(h, gc)
+ return to_node(create_dir_whatsit_vbox(to_direct(h), gc))
+ end
+ luatexbase.add_to_callback('pre_output_filter',
+ dir_adjust_pre_output,
+ 'ltj.direction', 10000)
+
+ function luatexja.direction.remove_end_whatsit()
+ local h=tex.lists.page_head
+ if h and (not h.next) and
+ h.id==id_whatsit and h.subtype==sid_user and
+ h.user_id == DIR then
+ tex.lists.page_head = nil
+ node.free(h)
+ end
+ end
+end
+
+-- buildpage filter
+do
+ local function dir_adjust_buildpage(info)
+ if info=='box' then
+ local head = to_direct(tex.lists.contrib_head)
+ local nb
+ if head then
+ head, _, nb
+ = make_dir_whatsit(head,
+ node_tail(head),
+ get_dir_count(),
+ 'buildpage')
+ tex.lists.contrib_head = to_node(head)
+ end
+ end
+ end
+ luatexbase.add_to_callback('buildpage_filter',
+ dir_adjust_buildpage,
+ 'ltj.direction', 10000)
+end
+
+-- finalize (executed just before \shipout)
+-- we supply correct pdfsavematrix nodes etc. inside dir_node
+do
+ local finalize_inner
+ local function finalize_dir_node(db,new_dir)
+ local b = getlist(db)
+ finalize_inner(b)
+ local box_dir = get_box_dir(b, dir_yoko)%dir_math_mod
+ setfield(db, 'head', nil)
+ local w = getfield(b, 'width')
+ local h = getfield(b, 'height')
+ local d = getfield(b, 'depth')
+ local dn_w = getfield(db, 'width')
+ local dn_h = getfield(db, 'height')
+ local dn_d = getfield(db, 'depth')
+ local db_head, db_tail = nil
+ for _,v in ipairs(dir_node_aux[box_dir][new_dir][getid(b)]) do
+ local cmd, arg, nn = v[1], v[2]
+ if cmd=='kern' then
+ nn = node_new(id_kern)
+ setfield(nn, 'kern', arg(w, h, d, dn_w, dn_h, dn_d))
+ elseif cmd=='whatsit' then
+ nn = node_new(id_whatsit, arg)
+ elseif cmd=='rotate' then
+ nn = node_new(id_whatsit, sid_matrix)
+ setfield(nn, 'data', arg)
+ elseif cmd=='box' then
+ nn = b; setfield(b, 'next', nil)
+ setfield(nn, 'shift', arg(w, h, d, dn_w, dn_h, dn_d))
+ end
+ if db_head then
+ insert_after(db_head, db_tail, nn)
+ db_tail = nn
+ else
+ db_head, db_tail = nn, nn
+ end
+ 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)
+ if (nid==id_hlist or nid==id_vlist) then
+ local ndir = get_box_dir(n, dir_yoko)
+ if ndir>=dir_node_auto then -- n is dir_node
+ finalize_dir_node(n, ndir%dir_math_mod)
+ else
+ finalize_inner(n)
+ end
+ end
+ end
+ end
+ local getbox = tex.getbox
+ local setbox, copy = Dnode.setbox, Dnode.copy
+ function luatexja.direction.finalize()
+ 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