在 Plain TeX 中,如何使垂直框可破坏,我可以单独处理/测量它们吗?我想做的是,我有一部分文本,需要单独处理(无缩进、较窄、彩色背景,使用\hrule
/ \vrule
)并使其可破坏。
另外我对如何自动制动水平盒感兴趣
答案1
A\vbox
本身不可拆分。但将其分配给盒子寄存器允许 TeX 使用\vsplit
操作将其拆分。
\newbox\totalbox
\newbox\partialbox
\newdimen\partialboxdim
\setbox\totalbox=\vbox{<settings><text>}
<measurements setting \partialboxdim to the available space>
\setbox\partialbox=\vsplit\totalbox to \partialdim
\addcoloredbackground{\unvbox\partialbox}
<measurements setting \partialboxdim to the available space>
...
这是方案,您必须提供 \addcoloredbackground 宏和测量值,可能基于\pagegoal
和\pagetotal
。TeXbook 和 TeX by Topic 有关于 的示例\vsplit
。
让我们稍微扩展一下;我假设你有一个\colorthisbox
宏,它为一个框添加彩色背景,并要求其上方和下方有 3pt 的额外空间。策略是首先收集要加框的文本:
\newbox\totalbox
\newbox\partialbox
\newdimen\partialboxdim
\def\startcoloredbox{\par\bigskip
\setbox\totalbox=\vbox\bgroup\advance\hsize by -6pt}
\def\endcoloredbox{\egroup\splitcoloredbox}
此时我们有了全部文本;现在我们开始拆分:
\def\splitcoloredbox{\ifvoid\totalbox\finishcoloredbox
\else\continuesplitting\fi}
\def\finishcoloredbox{\bigskip}
宏\finishcoloredbox
应该提供最后的润色,我只放了一个\bigskip
。宏\continuesplitting
是该过程的核心:它首先测量可用空间,但首先它将一个\null
框放置在主垂直列表中,因为当前页面为空时,\pagegoal
等于\maxdimen
。6pt
是为打印彩色框保留的额外空间。如果 box 的(剩余)部分\totalbox
低于可用空间,我们只需将 box 设置为它,否则我们会从填充可用空间所需的内容\partialbox
中分离出来;然后我们将控制权传递给,但在第二种情况下我们添加,因为我们确定我们已经到达页面的底部并且我们想从带有 的新页面开始。处理后我们再次调用。\totalbox
\colorthisbox
\eject
\pagetotal=0pt
\splitcoloredbox
\def\continuesplitting{\null % In case this starts a new page
\dimen255=\dimexpr\pagegoal-\pagetotal-\pageshrink-6pt\relax
\ifdim\ht\totalbox<\dimen255
\setbox\partialbox=\box\totalbox
\colorthisbox
\else
\setbox\partialbox=\vsplit\totalbox to\dimen255
\colorthisbox\eject
\fi
\splitcoloredbox}
\colorthisbox
这是我用于测试的定义;重要的是它将所有内容都封闭在一个盒子(\hbox
或\vbox
)中,以免启动水平模式。
\def\colorthisbox{\hbox{\fbox{\vbox{\unvbox\partialbox}}}}
(是的,测试是在 LaTeX 中完成的,因为\lipsum
)。这\vbox{\unvbox\partialbox}
部分很重要,因为它可以避免盒子未满的情况。
答案2
一个实验
这种打破垂直框的方法对我有帮助。我试图弄清楚我在一个块中要处理多少行。我通常使用包lineno
及其\linelabel
和\lineref
命令。这些命令类似于它们的\label
和\ref
对应命令。我能够使用此方法获得多行。如果我需要多个部分,我会在命令\label
旁边使用 common \linelabel
。
但是当我通过 排版时\parbox
,这种方法不起作用。我们可以使用包\internallinenumbers
中的内部命令列出行号lineno
,但我不知道如何引用它们。
因此,我将段落保存到垂直框中,并开始按 分割行\baselineskip
。一旦该框的高度 ( \myboxtemp
) 等于 ,0pt
我就完成了。我附上了一个示例,其中我旋转了线条并将其着色为不同颜色。行数存储在名为 的计数器中\mycounter
。
\documentclass[a4paper]{article}
\usepackage[nopar]{kantlipsum}
\parindent=0pt
\usepackage{tikz}
\usepackage{xcolor}
\usepackage{lineno}
\pagestyle{empty}
\begin{document}
\newdimen\mujtemp
\mujtemp=\textwidth
\advance\mujtemp by -35mm
\section{My section}
\linenumbers
My first line.\par My second line.\linelabel{myfavoriteline}\label{mysection}
\par My third line.\par
\nolinenumbers
I am referring to line~\lineref{myfavoriteline}, section~\ref{mysection} on page~\pageref{myfavoriteline}.
\bigskip
\newsavebox{\mojkovo}%
\savebox{\mojkovo}{\parbox{\mujtemp}{%
\kant[1]%
\internallinenumbers
}}%
\usebox{\mojkovo}
\bigskip
\newbox\mybox
\setbox\mybox=\hbox{\usebox{\mojkovo}}
width \the\wd\mybox, height \the\ht\mybox, depth \the\dp\mybox
\vspace{6mm}\par
\setbox\mybox=\vbox to \vsize{\rightskip=35mm\kant[1]}%
\newbox\myboxtemp
\newcount\mycounter\mycounter=0%
\loop
\advance\mycounter by 1%
\setbox\myboxtemp=\vsplit\mybox to \baselineskip%
\makebox[35mm][l]{\ifnum\mycounter<10 0\fi
\the\mycounter---\the\ht\myboxtemp\ \the\dp\myboxtemp\ }
\ifnum\ht\myboxtemp=0 There are no more lines!\fi
{\color{green}\vbox to 1\baselineskip
{%
\begin{tikzpicture}[remember picture, overlay]
\begin{pgfinterruptboundingbox}
\pgfmathparse{8*\the\mycounter+30}
\let\myaddition=\pgfmathresult
\node[anchor=west, rotate=2.5*\the\mycounter, color=green!50!black!\myaddition]{\usebox\myboxtemp};
\end{pgfinterruptboundingbox}
\end{tikzpicture}%
}}\par%
\ifnum\mycounter<18\repeat
\end{document}
编辑:这是我重写代码并将其缩减为 Plain TeX 格式的最佳尝试。我们不能使用\newsavebox
、\savebox
和\usebox
命令,因为这些是 LaTeX 格式命令,请参阅了解latex.ltx
更多详细信息。我不知道如何从包中加载段落kantlipsum
,所以我提取了一小部分代码。我附上了源代码和页面预览。
%! pdftex boxes-plain.tex
\hsize=345pt % Taken from LaTeX...
\parindent=0pt
{\bf From kantlipsum package:}\par\vskip2mm
\def\mypara{As any dedicated reader can clearly see, the Ideal of practical reason is a representation of, as far as I know, the things in themselves; as I have shown elsewhere, the phenomena should only be used as a canon for our understanding. The paralogisms of practical reason are what first give rise to the architectonic of practical reason. As will easily be shown in the next section, reason would thereby be made to contradict, in view of these considerations, the Ideal of practical reason, yet the manifold depends on the phenomena. Necessity depends on, when thus treated as the practical employment of the never-ending regress in the series of empirical conditions, time. Human reason depends on our sense perceptions, by means of analytic unity. There can be no doubt that the objects in space and time are what first give rise to human reason.}
\newbox\mybox
\setbox\mybox=\vbox{\rightskip=35mm\mypara}
\copy\mybox
\vskip2mm
\newbox\myboxtemp
\newcount\mycounter
\mycounter=0
\loop
\advance\mycounter by 1%
\setbox\myboxtemp=\vsplit\mybox to \baselineskip
\hbox to\hsize{Line number \the\mycounter\hfill}%
\copy\myboxtemp
\ifnum\ht\myboxtemp=0{\it There are no more lines! I am escaping from the loop.}\fi
\ifnum\ht\myboxtemp>0\repeat
\bye