第 5.9.6 节TeX 按主题分类展示了一种算法,通过反复使用 删除最后一行,将 vbox 分解为 hbox 形式的单独行\lastbox
。还有类似的命令用于删除框的其他组件,\unskip
即\unkern
和\unpenalty
。
不幸的是,在尝试剖析水平盒时,同样的方法似乎不起作用。以下示例说明了这个问题:
\documentclass{article}
\begin{document}
\def\inspect{%
\unhbox0
\count0=\lastnodetype
\setbox1=\lastbox
\fbox{\box1}, \the\count0
}
\setbox0=\hbox{abc}\hbox{\inspect}
\setbox0=\hbox{ab\hbox{c}}\hbox{\inspect}
\end{document}
输出:
当我们尝试使用\lastbox
从第一个 hbox 中删除最后一个字符时,结果只是一个空框。使用 打印节点类型可以说明原因:最后一个字符不是框,而是“char 节点”(节点类型 0)。当将 包装到 extra 中\lastnodetype
时,结果正如预期的那样是“hlist 节点”(节点类型 1)。c
\hbox
是否有一种仅在 (La)TeX/e-TeX 中的方法可以遍历已构建的 hbox 的内容,类似于 vbox 方法?e-TeX 文档列出了列表中可能出现的 16 种节点类型,但我只能看到一种方法来删除其中五种节点,只要它们已添加到列表中。
答案1
如果没有 LuaTeX,这是不可能的。
当然,使用 LuaTeX 很容易,但你必须决定如何存储字形,因为没有用于存储孤立glyph
节点的 TeX 寄存器。(字形节点是 LuaTeX 中的字符节点等价物,如果你使用 存储它们,你会丢失有关字体的信息\chardef
)
一个选项是将字形节点包装在\hbox
盒子寄存器中存储:
\documentclass{article}
\newcommand\setlastcharbox{\directlua{
local nest = tex.nest[tex.nest.ptr]
local tail = nest.tail
if tail.id == node.id'glyph' then
tail.prev.next = nil
nest.tail = tail.prev
tex.box[token.scan_int()] = node.hpack(tail)
print(tail)
else
tex.box[token.scan_int()] = nil
end
}}
\begin{document}
\def\inspect{%
\unhbox0
\count0=\lastnodetype
\setlastcharbox1
\fbox{\box1}, \the\count0
}
\setbox0=\hbox{}\hbox{\inspect}
\setbox0=\hbox{abc}\hbox{\inspect}
\end{document}