
В главе 23 «Процедуры вывода» есть предупреждение:
Лучше не экспериментировать с \hsize и \vsize, за исключением самого начала задания или после того, как вы извлекли все страницы из памяти TeX.
Но вTeXbookесть несколько примеров, где \hsize
это изменено:
1) В упражнении с story.tex \hsize задается несколько раз в одном задании tex.
\hsize=4in \input story
\hsize=3in \input story
...
Я полагаю, что этот случай является «законным», поскольку \eject
он назван в конце story.tex
Еще несколько примеров:
2) На странице 115 \hsize
установлено внутри \topinsert
.
3) На странице 223 \hsize
установлено внутри \vbox
.
В каких контекстах «законно» вносить изменения \hsize
и почему появляется это предупреждение?TeXbook? Есть ли пример, показывающий, что может пойти не так, если мы изменим что-то \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
Итак, мы видим абзац, состоящий из шести строк, соответствующих шести полям шириной 300 пунктов.
Вторая \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
has \makeheadline
that does
\line{\vbox to 8.5pt{}\the\headline}
и \line
является \hbox to \hsize
.
Вот в чем заключается основной смысл предупреждения Кнута: если вы внесете изменения \hsize
в середине страницы, могут возникнуть неожиданные результаты, в зависимости от того, когда сработает процедура вывода.
Изменение \hsize
внутри \vbox
всегда безопасно, поскольку выполнение конструктора страниц при работе со вторичным вертикальным списком никогда не вызывает процедуру вывода.