如何在 \filbreak 之后恢复正常流程

如何在 \filbreak 之后恢复正常流程
\documentclass[a4paper]{article}
\usepackage{lipsum}
\begin{document}
  \lipsum[1-4]\filbreak
  \textbf{This should fit on page 1}~\lipsum[5]\filbreak\lipsum[6-10]\filbreak
  \textbf{This should not fit on page 2}~\lipsum[11-12]\filbreak\lipsum[13-19]
\end{document}

问题在于最后的 \filbreak在这个例子中。它会刷新\lipsum[13-19]到下一页。我想\filbreak用命令替换最后一个\stopfilbreak,这样由于\lipsum[11-12]实际上不适合放在第 2 页,所以它会\lipsum[11-12]放在第 3 页上,然后放在第 3 页上\lipsum[13-19](第 3 页)。现在它设置\lipsum[13-19]在第 4 页。

我想要一个命令\stopfilbreak,让 LaTeX 解释“如果可能,将内容放在和 之间\filbreak\stopfilbreak放在同一页上,否则就在这里分页,放到新页上”。后面的内容\stopfilbreak不应该受到影响。

也就是说:我想要一个在使用后恢复正常流程的命令\filbreak


请注意,介于\filbreak和之间的内容可能\stopfilbreak会大于页面宽度,因此minipage不起作用。

以下是一些我认为可能有助于回答我的问题的背景信息:


背景信息

目的\filbreak

TeXbook 表示,这\filbreak大致意味着

“在此处分页并用空白填充底​​部,除非还有空间容纳更多后面跟着 \filbreak 的副本。”

也就是说,如果我们考虑被\filbreaks “包围”的内容,如果页面上有空间,它会插入该内容,但如果没有空间,它会转到下一页。

\filbreak在实践中

\filbreak由 定义\par\vfil\penalty-200\vfilneg。据我了解,这会结束当前段落,然后用可拉伸的空白填充页面,然后在页面底部/新页面顶部显示此处“中断”很便宜。如果程序随后决定在此处中断,则 不会执行\vfilneg任何操作,因为没有\vfil“否定”,但如果没有,则会\vfilneg将“光标”放回原位。


我没有\filbreak按照预期使用它。我的 VC 示例中的所有内容都按预期工作,这表明我可能问错了问题?

答案1

我之前发布过一个完全错误的答案,随后又删除了它;现在我用下面的答案替换它,它不仅至少有一定道理,而且似乎也能按预期工作!(:-)

% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly 
                                 % declare the paper format.

\usepackage[T1]{fontenc}         % Not always necessary, but recommended.
% End of standard header.  What follows pertains to the problem at hand.

\usepackage{lipsum}

\makeatletter

\@ifdefinable\@My@filbreak@counter{\newcount\@My@filbreak@counter}
\global \@My@filbreak@counter = 0
\@ifdefinable\@My@filbreak@mark{\newmarks\@My@filbreak@mark}

\renewcommand*\filbreak{%
    \par
    \global \advance \@My@filbreak@counter \@ne
    \marks\@My@filbreak@mark{\number\@My@filbreak@counter}%
    \vfil
    \penalty -200
    \vfilneg
}

\newcommand*\@My@finish@stopfilbreak{}

\newcommand*\stopfilbreak{%
    \par
    \ifnum \prevdepth >\@m \else \prevdepth \z@ \fi
    \nobreak \null
    \nobreak \vskip -\baselineskip
    \penalty \z@
    \begingroup
        \output{%
            % \typeout{>>> \topmarks\@My@filbreak@mark
            %         \space vs \number\@My@filbreak@counter}%
            \typeout{t: \the\pagetotal, g: \the\pagegoal}%
            \unvbox\@cclv
            \ifnum 0\topmarks\@My@filbreak@mark <\@My@filbreak@counter
                % the last "\filbreak" is still on the current page
                \gdef\@My@finish@stopfilbreak{%
                    \vfil\break % force page break
                }%
            \else
                % the page has changed since the last "\filbreak"
                \gdef\@My@finish@stopfilbreak{%
                    \penalty\z@ % allow page break but don't force it
                }%
            \fi
        }%
        \break
    \endgroup
    \@My@finish@stopfilbreak
}

\makeatother

\newcommand*{\mylipsum}[1]{\par\textbf{#1}~-- \lipsum*[#1]\par}

% \tracingpages = 1



\begin{document}
    \mylipsum{1}
    \filbreak
    \mylipsum{2}
    \filbreak
    \mylipsum{3}
    \filbreak
    \mylipsum{4}
    \filbreak
    \mylipsum{5}
    \filbreak
    \mylipsum{6}
    \filbreak
    \mylipsum{7}
    \filbreak
    \mylipsum{8}
    \mylipsum{9}
    \mylipsum{10}
    % \mylipsum{11}
    \indent One.\par
    \indent Two.\par
    \indent Three.\par
    \indent Four.\par
    % \indent Five.\par
    % \indent Six.\par
    % \mylipsum{12}
    \stopfilbreak
    \mylipsum{13}
    \mylipsum{14}
    \mylipsum{15}
    \mylipsum{16}
\end{document}

尝试取消注释以下行% \mylipsum{11}或以下行% \indent Five.\par

现在,我太累了,无法详细解释代码的工作原理;也许我明天会复习这个答案,现在我只是暗示一下大概的想法。我们使用一个自定义\marks系统,即\marks\@my@filbreak@mark,来检测最后一个\filbreakbefore是否\stopfilbreak与后者出现在同一页上,如果是,我们强制分页;否则,\stopfilbreaks只插入一个允许断点。

我把这个答案的先前版本留在编辑列表中,以便每个人都能思考它是多么的愚蠢……

相关内容