在第 23 章“输出例程”中有一个警告:
最好不要随意修改 \hsize 和 \vsize,除非是在作业刚开始时,或者从 TeX 内存中弹出所有页面之后。
但在电子书本身就有几个\hsize
改变的例子:
1) 在 story.tex 练习中,\hsize 在一个 tex 作业中被设置多次。
\hsize=4in \input story
\hsize=3in \input story
...
我认为,这个案例是“合法的”,因为\eject
它在故事的结尾被调用。tex
更多示例:
2)在第115页\hsize
内设置\topinsert
。
3)在第223页\hsize
内设置\vbox
。
在哪些情况下修改是“合法的”\hsize
,以及为什么会出现这个警告电子书? 有没有例子可以说明如果我们\hsize
在一个“糟糕”的地方改变,会出现什么问题?
答案1
什么是\hsize
?
原始参数\hsize
是 TeX 将段落拆分为行所使用的长度(同时考虑到\leftskip
,\rightskip
以及来自\hangindent
和 的段落形状指令) \hangafter
。
当段落被分割成行时,TeX 会将一组宽度的水平框添加到当前垂直列表中。如果使用和,\hsize
宽度将有所不同,并将反映每行的实际宽度。\hangindent
\hangafter
\parshape
使用时,就像\hsize
为每一行指定不同的一样。
考虑一下代码
\input plipsum
\hsize=300pt
\showboxbreadth=1000 \showboxdepth=0
\lipsum{1}
\showlists
\hsize=200pt
\lipsum{2}
\showlists
\bye
第一个\showlists
命令输出
### vertical mode entered at line 0
### current page:
\glue(\topskip) 3.05556
\hbox(6.94444+1.94444)x300.0, glue set - 0.62798 []
\penalty 150
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x300.0, glue set 0.38911 []
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x300.0, glue set - 0.17653 []
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x300.0, glue set 0.24695 []
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x300.0, glue set 0.36536 []
\penalty 150
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x300.0, glue set 227.0554fil []
total height 70.0
goal height 643.20255
prevdepth 1.94444, prevgraf 6 lines
因此我们看到一个由六行组成的段落,对应六个 300pt 宽的框。
第二\showlists
条指令输出
### vertical mode entered at line 0
### current page:
\glue(\topskip) 3.05556
\hbox(6.94444+1.94444)x300.0, glue set - 0.62798 []
\penalty 150
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x300.0, glue set 0.38911 []
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x300.0, glue set - 0.17653 []
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x300.0, glue set 0.24695 []
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x300.0, glue set 0.36536 []
\penalty 150
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x300.0, glue set 227.0554fil []
\glue(\parskip) 0.0 plus 1.0
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x200.0, glue set 0.68265 []
\penalty 250
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x200.0, glue set - 0.56822 []
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x200.0, glue set 0.02776 []
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x200.0, glue set 0.76903 []
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x200.0, glue set 1.07141 []
\glue(\baselineskip) 3.11111
\hbox(6.94444+1.94444)x200.0, glue set 0.93843 []
\penalty 100
\glue(\baselineskip) 3.11111
\hbox(6.94444+0.0)x200.0, glue set 0.1729 []
\penalty 100
\glue(\baselineskip) 5.05556
\hbox(6.94444+1.94444)x200.0, glue set 0.93886 []
\penalty 250
\glue(\baselineskip) 5.75002
\hbox(4.30554+0.0)x200.0, glue set 179.41664fil []
total height 178.0 plus 1.0
goal height 643.20255
prevdepth 0.0, prevgraf 9 lines
前六行就在那里,依次查找\parskip
以查看第二段从哪里开始。我们有九行,宽度均为 200pt。
在哪里进行更改是合法的\hsize
?
任何地方。除非\parshape
正在使用,否则 TeX 将使用扫描\hsize
时的当前值\par
来将段落分成行。
当然,这个设置\hsize
会尊重 TeX 分组(如果你不够狡猾,无法进行全局设置)。所以如果我们尝试
{\hsize=1pt \nopar\lipsum{1}}\par
我们得到的结果与之前完全相同,因为\hsize
当找到时,对 的更改将被遗忘。请注意,在构建段落时,\par
不能有两个不同的值(当然,除非)。\hsize
\parshape
是否\hsize
影响页面形状?
这不是 TeX 的设计。但是,输出例程可以并且可能会使用标准\hsize
来设置页眉和页脚。例如,\plainoutput
\makeheadline
\line{\vbox to 8.5pt{}\the\headline}
并且\line
是\hbox to \hsize
。
所以,这就是 Knuth 警告的主要含义:如果你\hsize
在页面中间进行更改,则可能会出现意外结果,具体取决于输出例程何时开始运行。
\hsize
在内部进行更改\vbox
始终是安全的,因为在辅助垂直列表中工作时执行页面构建器永远不会调用输出例程。