diff options
Diffstat (limited to 'macros/luatex/generic/lua-widow-control/lua-widow-control.lua')
-rw-r--r-- | macros/luatex/generic/lua-widow-control/lua-widow-control.lua | 92 |
1 files changed, 61 insertions, 31 deletions
diff --git a/macros/luatex/generic/lua-widow-control/lua-widow-control.lua b/macros/luatex/generic/lua-widow-control/lua-widow-control.lua index 0f23f42592..1ef86174c4 100644 --- a/macros/luatex/generic/lua-widow-control/lua-widow-control.lua +++ b/macros/luatex/generic/lua-widow-control/lua-widow-control.lua @@ -102,6 +102,7 @@ local insert_token = token.put_next or token.putnext local last = node.slide local linebreak = tex.linebreak local new_node = node.new +local remove = node.remove local set_attribute = node.set_attribute or node.setattribute local string_char = string.char local tex_box = tex.box @@ -137,6 +138,7 @@ lwc.colours = { ]] local contrib_head, emergencystretch, + hold_head, info, insert_attribute, max_cost, @@ -152,10 +154,12 @@ if lmtx then contrib_head = "contributehead" shrink_order = "shrinkorder" stretch_order = "stretchorder" + hold_head = "holdhead" else contrib_head = "contrib_head" shrink_order = "shrink_order" stretch_order = "stretch_order" + hold_head = "hold_head" end if context then @@ -194,8 +198,8 @@ elseif plain or latex or optex then debug("Plain/LaTeX") luatexbase.provides_module { name = lwc.name, - date = "2022/07/28", --%%slashdate - version = "2.2.1", --%%version + date = "2022/08/23", --%%slashdate + version = "2.2.2", --%%version description = [[ This module provides a LuaTeX-based solution to prevent @@ -309,7 +313,7 @@ end --- @param args table? --- subtype: number = The node subtype --- reverse: bool = Whether we should iterate backwards ---- @return node +--- @return node? local function next_of_type(head, id, args) args = args or {} @@ -332,6 +336,13 @@ local function next_of_type(head, id, args) head = head.prev end end + + -- Needed for the special `tex.lists` nodes + if head and head.id == id and + (head.subtype == args.subtype or args.subtype == nil) + then + return head + end end @@ -629,6 +640,14 @@ local function mark_inserts(head) then local hlist_before = next_of_type(insert, hlist_id, { reverse = true} ) + local insert_class + if lmtx then + -- FIXME: temporarily hardcode the main "footnote" class + insert_class = 4 -- insert.index + else + insert_class = insert.subtype + end + --[[ We tag the first element of the hlist/line with an integer that holds the insert class and the first and last indices of the inserts contained in the line. This won't work if @@ -638,7 +657,7 @@ local function mark_inserts(head) set_attribute( hlist_before.list, insert_attribute, - insert.subtype * INSERT_CLASS_MULTIPLE + + insert_class * INSERT_CLASS_MULTIPLE + insert_indices[1] * INSERT_FIRST_MULTIPLE + insert_indices[#insert_indices] ) @@ -837,45 +856,52 @@ local function get_inserts(last_line) break end - --[[ With LuaMetaTeX, the subtype of `insert` nodes is always zero, - so we cannot detect their class therefore we can't fix any moved - footnotes. - ]] - if lmtx then - warning("!!!Incorrect footnotes on page " .. pagenum() .. "!!!") - return {} - end - -- Demux the insert values local class = line_value // INSERT_CLASS_MULTIPLE local first_index = (line_value % INSERT_CLASS_MULTIPLE) // INSERT_FIRST_MULTIPLE local last_index = line_value % INSERT_FIRST_MULTIPLE -- Get the output box containing the insert boxes - local insert_box = tex_box[class] + local insert_box - local m = insert_box.list - while m do -- Iterate through the insert box - local box_value - box_value, m = find_attribute(m, insert_attribute) + if lmtx then + insert_box = tex.getinsertcontent(class) + else + insert_box = tex_box[class] + end - if not m then - break - end + -- Get any portions of the insert held over until the next page + local split_insert = next_of_type( + tex_lists[hold_head], + insert_id, + { subtype = class } + ) - if abs(box_value) >= first_index and - abs(box_value) <= last_index - then - -- Remove the respective contents from the insert box - insert_box.list = node.remove(insert_box.list, m) + for i, insert in ipairs { insert_box, split_insert } do + local m = insert and insert.list + + while m do -- Iterate through the insert box + local box_value + box_value, m = find_attribute(m, insert_attribute) - if box_value > 0 then - selected_inserts[#selected_inserts + 1] = copy(inserts[box_value]) + if not m then + break end - m = free(m) - else - m = m.next + if abs(box_value) >= first_index and + abs(box_value) <= last_index + then + -- Remove the respective contents from the insert box + insert.list = remove(insert.list, m) + + if box_value > 0 and i == 1 then + table.insert(selected_inserts, copy(inserts[box_value])) + end + + m = free(m) + else + m = m.next + end end end @@ -883,6 +909,10 @@ local function get_inserts(last_line) tex_box[class] = nil end + if split_insert and not split_insert.list then + remove(tex_lists[hold_head], split_insert) + end + n = n.next end |