\vbox
не переключает режимы и \hbox
не переключает режимы, что демонстрируют следующие две группы примеров.
Следующие два примера дают идентичный результат:
\hbox{A}
\end
\noindent A
\end
Следующие два примера также дают идентичный результат:
\vbox{\hrule width 1em}
\end
\noindent\vbox{\hrule width 1em}
\end
Кроме того, пустой контент переключает режим с вертикального на горизонтальный, как в \unhbox\voidb@x
. Тот же пустой контент можно получить с помощью \unvbox\voidb@x
. Но использование этого не переключает режим с вертикального на горизонтальный (см. следующие два примера). Почему?
\leavevmode\hbox{A}
\end
\catcode`\@=11
\unvbox\voidb@x\hbox{A}
\end
(В первом примере отступ добавлен, а во втором — нет.)
\vbox
может быть внутри абзаца, например \hbox
. Какую последовательность управления можно использовать для создания \vbox
как в середине, так и в начале абзаца?
решение1
Команда для запуска горизонтального режима с помощью a \vbox
— \leavevmode
. Зачем вам что-то еще?
Боюсь, ваше предположение неверно: не «пустое содержимое» вызывает смену режима. Этоименно так \unhbox
это так.
В отличие от \box
и \copy
, \unhbox
является горизонтальной командой, поэтому она запускает горизонтальный режим, если TeX находится в вертикальном режиме. Макрос \leavevmode
использует \voidb@x
так, чтобы ничего не добавлялось к горизонтальному списку (после того, как он, возможно, был запущен).
Аналоговая команда \unvbox
— это вертикальная команда изаканчиваетсяпараграф.
\catcode`@=11
\def\leavehmode{\unvbox\voidb@x}
\catcode`@=12
\everypar{PAR}% to show a paragraph has started
abc\leavehmode def
\bye
решение2
Не знаю, понятно это или нет, но давайте скажем прямо (из TeXbook):
|\leavevmode| is an abbreviation for `|\unhbox\voidbox|',
where |\voidbox| is a permanently empty box register.
Теперь, что \unhbox\voidbox
на самом деле делает? Давайте посмотрим вtex.web
:
@ @<Cases of |main_control| that build...@>=
vmode+start_par: new_graf(cur_chr>0);
vmode+letter,vmode+other_char,vmode+char_num,vmode+char_given,
vmode+math_shift,vmode+un_hbox,vmode+vrule,
vmode+accent,vmode+discretionary,vmode+hskip,vmode+valign,
vmode+ex_space,vmode+no_boundary:@t@>@;@/
begin back_input; new_graf(true);
end;
Как вы можете видеть, любая из этих комбинаций режима и чего-то еще начинает абзац, но vmode+un_vbox
не входит в их число.
Лично я нахожу интересным, что Кнут не начал vmode+<*>vbox
абзац, но vmode+valign
все же делает это.