Блоки и клей
Блоковые переменные
В тех случаях, когда один и тот же фрагмент текста (например, фрагмент псевдорисунка, являющийся аргументом команды \multiput ) используется многократно, бывает полезно сверстать этот фрагмент раз и навсегда, а затем просто повторять его: это сэкономит как количество нажатий на клавиши, так и машинное время. Использование макроопределения в данном случае времени не сэкономит: если мы напишем, например,
\newcommand{\abcd}{\parbox{6cm}% {Когда в товарищах согласья нет, на лад их дело не пойдет, и выйдет из него не дело — только м\'ука.}}
то при каждой обработке команды \abcd это макроопределение будет заново развертываться, и TeX будет заново находить переносы и места разрыва строк в одном и том же отрывке из " Лебедя, рака и щуки". Чтобы не заставлять TeX много раз повторять идентичные операции по верстке текста, надо сделать так. Во-первых, определим "блоковую переменную", которая будет хранить сверстанный фрагмент текста. Это делается с помощью команды \newsavebox. Единственный аргумент этой команды - имя новой блоковой переменной, которое должно удовлетворять тем же условиям, что любые имена TeX'овских команд: либо backslash с одной не-буквой, либо backslash с последовательностью букв. Имя новой блоковой переменной не должно совпадать с именем уже существующей команды или переменной длины (если вы попытаетесь нарушить это правило, LaTeX выдаст сообщение об ошибке). Во-вторых, присвоим нашей блоковой переменной значение — блок, и будем в дальнейшем этот блок использовать.
Давайте приведем пример того, как можно этим пользоваться. Выше мы приводили пример псевдорисунка — наклонной решетки, и там же мы отметили, что экономнее было бы создать наклонный отрезок раз и навсегда, а затем только повторять его. Теперь мы можем объяснить, как это сделать. Создадим блоковую переменную под названием \blok, написав в преамбуле следующее:
\newsavebox{\blok}
Теперь сверстаем тот текст, который будет храниться в нашей блоковой переменной, и запишем его в эту переменную. Для этих целей используется команда \sbox с двумя обязательными аргументами: первый — имя блоковой переменной, второй — текст, который в нее записывается. Итак:
\sbox{\blok}{\line(1,5){10}}
А теперь можно воспользоваться нашей блоковой переменной. Чтобы напечатать содержимое блоковой переменной, используется команда \usebox с одним обязательным аргументом — именем переменной. В нашем случае мы используем блоковую переменную в аргументе команды \multiput:
![\newsavebox{\blok}
\sbox{\blok}{\line(1,5){10}}
\parindent=0pt
\begin{picture}(100,50)
\multiput(0,0)(10,0){10}%
{\usebox{\blok}}
\multiput(0,0)(2,10){6}%
{\line(1,0){90}}
\end{picture}](/sites/default/files/tex_cache/25882302c7975b8101a55861ead56fbf.png)
\begin{picture}(100,50) \multiput(0,0)(10,0){10}% {\usebox{\blok}} \multiput(0,0)(2,10){6}% {\line(1,0){90}} \end{picture}
Можно было бы сделать аналогичный трюк и с горизонтальными линейками решетки, но большой экономии это не даст: горизонтальные и вертикальные линейки на псевдорисунках LaTeX не собирает из отдельных символов, а создает "в один присест" с помощью команд \hrule и \vrule, что и так достаточно быстро.
Текст, присутствующий в аргументе команды \sbox, будет сверстан в виде блока так, как если бы этот текст был передан в качестве аргумента команде \hbox или \mbox. Тем самым в аргументе \sbox может быть все то же, что может присутствовать в аргументе \hbox или \mbox. Если команда \sbox была дана внутри группы, то по выходе из этой группы содержимое блоковой переменной забудется.
Наряду с командой \sbox есть еще и команда \savebox, относящаяся к ней примерно так же, как \makebox относится к \mbox: между первым и вторым обязательным аргументами команды \savebox могут присутствовать необязательные аргументы, имеющие тот же смысл и записывающиеся так же, как необязательные аргументы команды \makebox. Например,
\savebox{\пример}[4cm][r]{Слово}
даст тот же результат, что и
\sbox{\пример}{\makebox[4cm][r]{Слово}}
Наряду с LaTeX'овской командой \usebox есть похожая на нее, но не идентичная, TeX'овская команда \copy. Используется она так:
Обратите внимание, что при использовании команды \copy имя блоковой переменной не заключается в фигурные скобки! Различие между \copy и \usebox такое же, как между \hbox и \mbox: будучи употребленными внутри абзаца (или, скажем, в аргументе команд \put, \hbox или \mbox ), эти две команды действуют совершенно одинаково, а вот будучи употребленным между абзацами, LaTeX'овское \usebox начинает новый абзац, в то время как TeX'овское \copy просто подверстывает блок к странице, нового абзаца не начиная. Эту разницу следует иметь в виду, когда вы работаете с командой \leaders: выгоднее сверстать блок один раз и записать его в блоковую переменную, а затем в команде \leaders писать просто \copy. Пример:
В этой ситуации по TeXническим причинам сказать \usebox нельзя.
Для тех, кто будет читать следующую лекцию, скажем еще об одной конструкции, связанной с блоковыми переменными. Именно, если \blok — блоковая переменная, то можно " измерить" ширину, высоту и глубину блока, записанного в этой переменной, с помощью TeX'овских команд \wd, \ht и \dp. Точнее говоря, сочетания \wd\blok, \ht\blok и \dp\blok можно использовать в точности так же, как TeX'овские параметры со значением длины, значения которых равны ширине, высоте и глубине блока:
Для большинства элементарных приложений в LaTeX'е вполне хватает возможностей измерения блоков, предоставляемых командой \settowidth и ее аналогами, но в "Модификация стандартных классов" нам встретятся ситуации, в которых без \wd не обойтись.