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

Модификация стандартных классов

Колонтитулы

Страницу документа, подготовленного с помощью LaTeX'а, можно рассматривать как состоящую из трех частей: тела страницы, верхнего колонтитула и нижнего колонтитула3Эта терминология не совпадает с традиционной, но удобна для наших целей... Мы знаем, что с помощью команды \pagestyle на оформление колонтитулов можно в какой-то мере влиять. Возможностей для этого, однако же, не слишком много. Сейчас мы увидим, как можно радикально менять вид колонтитулов.

За оформление верхних колонтитулов отвечают команды \@oddhead и \@evenhead. Точнее говоря, если стиль оформления документа "двусторонний", то команда \@oddhead задает верхний колонтитул на страницах с нечетными номерами, а команда \@evenhead — на страницах с четными номерами. Если же стиль оформления документа " односторонний", то \@oddhead задает все верхние колонтитулы, а команда \@evenhead на оформление документа вообще не влияет. Аналогично обстоит дело с \@oddfoot и \@evenfoot, отвечающими за нижние колонтитулы. Все четыре названные команды получают некоторое определение в LaTeX'овском стандарте, так что переопределять их надо с помощью \renewcommand.

Теперь обсудим, как вышеназванные команды влияют на оформление колонтитулов. Основной принцип таков. При оформлении страницы верхний колонтитул получается в результате исполнения команды

\hbox to\textwidth{\@evenhead}

(мы предположили, что стиль двусторонний и страница четная; в других случаях — с очевидными изменениями). Можно сказать, что в каждой из команд \@evenhead и ей подобных записан текст и TeX'овские команды, которые при верстке страницы будут подставлены в \hbox to \textwidth.

Пусть, например, мы готовим к изданию роман Л.Н.Толстого " Война и мир"; стиль документа выберем двусторонний. Предположим, что мы выбрали такое оформление:

  • на левой странице разворота в верхнем колонтитуле написано имя автора, прижатое (выключенное) вправо;
  • на правой странице разворота в верхнем колонтитуле написано название романа, прижатое (выключенное) влево;
  • В нижних колонтитулах по центру расположен номер страницы, окруженный тире.

Тогда надо переопределить команды для колонтитулов так:

\renewcommand{\@evenhead}{\hfil Л.Н.ТОЛСТОЙ}
\renewcommand{\@oddhead}{ВОЙНА И МИР\hfil}
\renewcommand{\@evenfoot}{\hfil --- \thepage ---\hfil}
\renewcommand{\@oddfoot}{\hfil --- \thepage ---\hfil}

Если мы хотим, чтобы каких-то колонтитулов вообще не было, то надо переопределить соответствующую команду на "ничего не делать", например, так:

\renewcommand{\@oddfoot}{}

Итак, мы научились менять оформление колонтитулов, переопределяя команду \@evenhead и ей подобные. А теперь — важное предупреждение: команда \pagestyle также переопределяет команды типа \@evenhead ; если вы проведете переопределения в своем стилевом пакете, то первой же командой \pagestyle ваши переопределения будут отменены. Стало быть, если уж вы переопределяете команды наподобие \@evenhead, то после этого переопределения командой \pagestyle в документе пользоваться не надо ( \thispagestyle можно).

Прежде чем перейти к более сложным вещам, скажем еще о трех стилевых параметрах. Во-первых, интервалы между колонтитулами и текстом регулируются параметрами со значением длины \headsep, задающим интервал между верхним колонтитулом и текстом, и \footskip, задающим расстояние между базисной линией последней строки в теле страницы и базисной линией нижнего колонтитула. Во-вторых, существует параметр \headheight, задающий высоту верхних колонтитулов. Если сумма высоты и глубины заданного вами колонтитула будет превышать \headheight, то при трансляции вы получите сообщение

Overfull \vbox occurred while \output was active.

Приведем пример, когда надо учитывать \headheight. Пусть мы хотим в том же издании "Войны и мира" отделять верхние колонтитулы от текста линейками. Разумный способ это сделать — передать в \hbox to \textwidth уже готовый блок шириной \textwidth, содержащий как текст колонтитула, так и линейку. Так как линейку под текстом удобно проводить в вертикальном режиме с помощью команды \hrule, в голову приходит вот что (здесь и далее мы для краткости приводим только определение \@evenhead ):

\renewcommand{\@evenhead}%
{\vbox{\hbox to\textwidth{\hfil Л.Н.ТОЛСТОЙ}\hrule}}

У такого определения есть, однако, два недостатка. Во-первых, так как линейки в вертикальном режиме добавляются "впритык" к предшествующему блоку, у нас нет гарантии, что линейка не подойдет к тексту слишком близко; если бы к тому же текст в колонтитулах на разных страницах варьировался, как в дальнейших примерах, то может случиться и так, что две соседние линейки на развороте окажутся на разной высоте (из-за того, что в колонтитуле на одной странице будет буквы вроде у, опускающиеся ниже базисной линии, а на другой — нет). Средство от этого недостатка — добавить \strut в наш блок:

\renewcommand{\@evenhead}%
{\vbox{\hbox to\textwidth{\hfil \strut
Л.Н.ТОЛСТОЙ}\hrule}}

Второй недостаток — это то, что к размеру блока с текстом добавится ширина линейки, в результате чего этот размер превысит \headheight и мы будем получать уйму сообщений об overfull'е. Чтобы уйти от этого, надо еще чуть-чуть схитрить:

\renewcommand{\@evenhead}%
{\raisebox{0pt}[\headheight][0pt]{% начало блока
\vbox{\hbox to\textwidth{\hfil \strut
Л.Н.ТОЛСТОЙ}\hrule}}% конец блока
}% конец макроопределения

Понятно ли, что происходит? С помощью \raisebox мы заставляем TeX считать, что блок имеет высоту \headheight (нам даже незачем вникать, чему она фактически равна) и нулевую глубину (чтобы в сумме получилось то, что надо). Теперь ни о каких переполнениях речи не будет; пробел между колонтитулом и текстом можно при желании изменить, изменив значение \headsep.

Для нижних колонтитулов параметра, аналогичного \headheight, нет, так что смело делайте их любой высоты.

Кстати говоря, команду \@evenhead в этом примере можно было бы переопределить более простым образом, без \vbox, с использованием команды \underline. Наш способ, однако, более гибок: например, мы можем регулировать толщину линейки, чего с \underline не добьешься.

Итак, мы научились создавать собственные колонтитулы. Однако в LaTeX'овском стандарте в колонтитулы обычно помещается не только номер страницы, но и, например, номер и заглавие текущего раздела. Давайте научимся делать и это.

Чтобы передать в колонтитул какую-то информацию из текста, в LaTeX'е используются команды \markboth и \markright. Разберем, как они работают. Команда \markboth, требующая двух обязательных аргументов, запоминает пару " пометок" — два фрагмента текста (возможно, с TeX'овскими командами). Например, если мы скажем (где-нибудь между абзацами)

\markboth{Кот}{Пес}

то поместим между этими абзацами пару пометок: "левую пометку" Кот и "правую пометку" Пес. Сами по себе эти пометки никак не отражаются на печати. Однако же в определениях команд \@oddhead и ей подобных мы можем на эти пометки ссылаться. Именно, в этих определениях команда \leftmark дает левую пометку, а команда \rightmark — правую пометку. Например, если мы переопределим верхние колонтитулы как

\renewcommand{\@evenhead}{\leftmark\hfil}
\renewcommand{\@oddhead}{\hfil\rightmark}

то, начиная с той страницы, на которую попали наши пометки, в левом верхнем колонтитуле будет стоять выключенное влево слово "Кот", а в правом — выключенное вправо слово " Пес"4Точнее говоря, так будет, если в тексте нет команд типа \section: эти команды, как мы увидим ниже, автоматически вставляют в текст свои пометки, что усложняет картину.. Кстати, если никаких пометок в тексте нет, то как \leftmark, так и \rightmark дают " пустой" текст.

До сих пор мы молчаливо предполагали, что на каждой странице присутствует только одна пара пометок. Что будет, если таких пар пометок попадет на страницу несколько? Ответ: команда \leftmark в этом случае означает левую пометку из самой верхней пары пометок, попавших на страницу, а команда \rightmark означает правую пометку из самой нижней пары пометок, попавших на данную страницу. С другой стороны, если на страницу вообще ни одна пара пометок не попала, то \leftmark и \rightmark означают соответственно левую и правую пометки из последней пары пометок, встретившихся до этого.

Поясним сказанное примером. Пусть пометки

\markboth{x}{y} и \markboth{z}{t}

попали (в указанном порядке) на страницу 1, на страницу 2 вообще никаких пометок не попало, на страницу 3 попали целые три пары пометок:

\markboth{u}{v},
\markboth{a}{b} и
\markboth{m}{n},

а на страницах 4 и дальнейших никаких новых пометок не появлялось. Тогда значения команд \leftmark и \rightmark в процессе обработки этих страниц были таковы:

Страница \leftmark \rightmark
1 x t
2 z t
3 u n
4 и далее m n

Наряду с командой \markboth, которая ставит в тексте новую пару пометок, есть еще и команда \markright с одним аргументом, которая ставит в тексте пару пометок таким образом: левый элемент в этой паре — такой же, как был в предыдущей паре пометок, а правый — тот, что задан в аргументе команды \markright. Например, если сначала идет команда

\markboth{Кот}{Пес}

а затем команда

\markright{Собака}

(и в промежутке между этими командами никаких других пометок в текст не вносится), то это равносильно тому, как если бы вторая из этих команд была

\markboth{Кот}{Собака}

Выше мы уже отмечали, что команды типа \section ставят в тексте пометки автоматически. Понять, как это делается и как можно влиять на этот процесс, проще всего на примере. Сделаем такие предположения о документе: класс — article, разделы и подразделы нумеруются (иными словами, значение счетчика {secnumdepth} больше единицы), действует стилевая опция twoside и в преамбуле была дана команда \pagestyle{headings}.

Во-первых, отметим, что в этом случае пометки в текст вставляют только команды \section и \subsection. При этом команда \section ставит пометки, автоматически выполняя команду \sectionmark, имеющую один обязательный аргумент — заглавие раздела (если команда \section была дана без необязательного аргумента) или вариант заглавия, заданный в необязательном аргументе команды \section (если таковой присутствует). Вот как определена \sectionmark (на место #1 будет подставляться вариант заглавия, идущий в колонтитулы):

\newcommand{\sectionmark}[1]{\markboth{%
\MakeUppercase{\thesection\hspace{1em}#1}}% левая пометка
{}% правая пометка (она пуста)
}% конец макроопределения

Здесь используется LaTeX'овская команда \MakeUppercase, которую мы ранее не рассматривали. Не вдаваясь в подробности, скажем, что эта команда переводит все буквы в тексте5Но не в именах команд; что будет с русскими буквами, зависит от русификации., попавшем в ее аргумент, из строчных в прописные. Коль о том зашла речь, отметим, что есть еще и команда \MakeLowercase, которая наоборот переводит все буквы в тексте, попавшем в ее аргумент, из прописных в строчные. (Не пытайтесь, пожалуйста, использовать \MakeUppercase и \MakeLowercase вне аргументов \markboth или \markright, если не любите неприятных сюрпризов.) Если вы не хотите, чтобы в колонтитулах строчные буквы заменялись на прописные, можно при переопределении просто опустить команду \MakeUppercase (так и было сделано при оформлении книги, которую вы читаете).

Команда \subsectionmark, определяющая вид пометок, автоматически вставляемых в текст командой \subsection, определена следующим образом:

\newcommand{\subsectionmark}[1]{\markright
{\thesubsection\hspace{1em}#1}}

Здесь также аргумент #1 — это заглавие подраздела (точнее, его вариант для колонтитулов).

Итак, в рассматриваемом нами случае команда \section вносит в текст следующую пару пометок: заглавие раздела, в котором все буквы заменены на прописные, в качестве левой пометки, и пустой текст в качестве правой пометки. Команда же \subsection вносит в текст пару пометок, в которой левая пометка такая же, как в предыдущей паре, а правая — заглавие подраздела (точнее, его вариант для колонтитулов), причем на сей раз "в натуральном виде", без замены строчных букв на прописные. Как уже отмечалось выше, команды \subsubsection и более мелкие никаких пометок в текст не вносят.

Посмотрим, как в этом стиле используются пометки. Колонтитулы на четных страницах в этом случае определены так:

\newcommand{\@evenhead}{\thepage\hfil
              \normalfont\slshape\leftmark}

Тем самым на страницах с четными номерами (они будут левыми на развороте) колонтитул будет выглядеть следующим образом: выключенный влево номер страницы (прямым шрифтом) и заглавие текущего раздела (наклонным шрифтом, прописными буквами) — выключенное вправо6Точнее говоря, это будет заглавие либо текущего раздела, либо первого из разделов, начинающихся на этой странице — см. выше обсуждение \leftmark и \rightmark .: ведь никаких других левых пометок в тексте нет!

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