Опубликован: 07.02.2007 | Доступ: свободный | Студентов: 4014 / 1341 | Оценка: 4.56 / 3.95 | Длительность: 23:09:00
Специальности: Художник
Лекция 8:

Блоки и клей

Блоковые переменные

В тех случаях, когда один и тот же фрагмент текста (например, фрагмент псевдорисунка, являющийся аргументом команды \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}
\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. Используется она так:

\sbox{\blok}{Рак}
Однажды Лебедь,
\copy\blok{} и Щука\ldots
\sbox{\blok}{Рак}
Однажды Лебедь,
\copy\blok{} и Щука\ldots

Обратите внимание, что при использовании команды \copy имя блоковой переменной не заключается в фигурные скобки! Различие между \copy и \usebox такое же, как между \hbox и \mbox: будучи употребленными внутри абзаца (или, скажем, в аргументе команд \put, \hbox или \mbox ), эти две команды действуют совершенно одинаково, а вот будучи употребленным между абзацами, LaTeX'овское \usebox начинает новый абзац, в то время как TeX'овское \copy просто подверстывает блок к странице, нового абзаца не начиная. Эту разницу следует иметь в виду, когда вы работаете с командой \leaders: выгоднее сверстать блок один раз и записать его в блоковую переменную, а затем в команде \leaders писать просто \copy. Пример:

\savebox{\blok}[1cm]{$*$}
\hbox to \textwidth
{\leaders\copy\blok\hfil}
\savebox{\blok}[1cm]{$*$}
\hbox to \textwidth
{\leaders\copy\blok\hfil}

В этой ситуации по TeXническим причинам сказать \usebox нельзя.

Для тех, кто будет читать следующую лекцию, скажем еще об одной конструкции, связанной с блоковыми переменными. Именно, если \blok — блоковая переменная, то можно " измерить" ширину, высоту и глубину блока, записанного в этой переменной, с помощью TeX'овских команд \wd, \ht и \dp. Точнее говоря, сочетания \wd\blok, \ht\blok и \dp\blok можно использовать в точности так же, как TeX'овские параметры со значением длины, значения которых равны ширине, высоте и глубине блока:

\sbox{\blok}{12345}\copy\blok\\
\hbox to \wd\blok{\hfil 345}\\
\hbox to \wd\blok{\hfil 45}
\sbox{\blok}{12345}\copy\blok\\
\hbox to \wd\blok{\hfil 345}\\
\hbox to \wd\blok{\hfil 45}

Для большинства элементарных приложений в LaTeX'е вполне хватает возможностей измерения блоков, предоставляемых командой \settowidth и ее аналогами, но в "Модификация стандартных классов" нам встретятся ситуации, в которых без \wd не обойтись.

Нина Казачек
Нина Казачек
Василий Майоров
Василий Майоров