为什么 \parbox 会丢失脚注?

为什么 \parbox 会丢失脚注?

动机大概是脚注会立即格式化,并且在 parbox 中\hsize不相等\textwidth(尽管与 minipage 不同,\textwidth它不会改变)。该机制大概只是使用本地定义而不是全局定义。翻看后source2e我找不到 的来源\@makefntext。我希望能够直接修复该问题。

无论如何,这是一种 MWE:

\documentclass{article}

\newcount\savefnused
\newcount\savefndone

\newcommand{\savefootnote}[2][\empty]% #1=number (optional), #2=text
{\ifx\empty#1\footnotemark\else\footnotemark[#1]\fi
 \global\advance\savefnused by 1
 \expandafter\xdef\csname savefnmark\the\savefnused\endcsname{\thefootnote}%
 \expandafter\xdef\csname savefntext\the\savefnused\endcsname{#2}%
}
\newcommand{\flushfootnote}{\loop\ifnum\savefndone<\savefnused
  \global\advance\savefndone by 1
  \footnotetext[\csname savefnmark\the\savefndone\endcsname]%
    {\csname savefntext\the\savefndone\endcsname}%
  \global\expandafter\let\csname savefnmark\the\savefndone\endcsname\relax
  \global\expandafter\let\csname savefntext\the\savefndone\endcsname\relax
\repeat}

\begin{document}
normal\footnote{normal}

\parbox{1in}{parbox\savefootnote{parbox}}
\flushfootnote

check counter\footnote{after}

\end{document}

答案1

我现在的理解是,这\insert\footins{...}将导致组内写入的任何内容都结束,\box\footins但仅在页面输出之后。此外,\global\insert这是不允许的。

\global@insert并没有精确地模仿\insert“迁移”,因为内容会立即显示出来,但它似乎对脚注来说已经足够好了。

\documentclass{article}
\usepackage{blindtext}

\makeatletter
\newcommand{\global@insert}[2]% #1=box number, #2=vertical list
{\bgroup
  \setbox\@tempboxa=\box#1
  \global\setbox#1=\vbox{\unvbox\@tempboxa #2}
\egroup}

\long\def\@footnotetext#1{\global@insert\footins{%
 \reset@font\footnotesize
 \interlinepenalty\interfootnotelinepenalty
 \splittopskip\footnotesep
 \splitmaxdepth \dp\strutbox \floatingpenalty \@MM
 \hsize\columnwidth \@parboxrestore
 \protected@edef\@currentlabel{%
 \csname p@footnote\endcsname\@thefnmark
 }%
 \color@begingroup
 \@makefntext{%
 \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
 \color@endgroup}}%
\makeatother

\begin{document}
normal\footnote{normal}

\begin{enumerate}
\item\parbox{1in}{parbox\footnote{parbox - \blindtext}}
\item test
\end{enumerate}

check counter\footnote{after}

\end{document}

这种方法在 之外使用普通脚注\parbox,但需要多做一些工作。基本上,它的工作原理与\footnotemark和类似,\footnotetext只是您不必跟踪哪个标记与哪个文本对应。

在 中,\parbox您需要添加\globalfootnotestrue切换模式。在 parbox 之后,您需要添加\copyinserts将脚注从 移动\parboxins\footins。由于 是\parbox牢不可破的,您不必担心会跳到错误的页面。

\documentclass{article}
\usepackage{blindtext}

\makeatletter
\newsavebox{\parboxins}
\newif\ifglobalfootnotes

\newcommand{\copyinserts}{\insert\footins{\unvbox\parboxins}%
  \globalfootnotesfalse}% should be redundant

\newcommand{\global@insert}[2]% #1=box number, #2=vertical list
{\bgroup
  \setbox\@tempboxa=\box#1
  \global\setbox#1=\vbox{\unvbox\@tempboxa #2}
\egroup}

\long\def\@footnotetext#1{%
 \protected@edef\@currentlabel{\csname p@footnote\endcsname\@thefnmark}%
 \ifglobalfootnotes \global@insert\parboxins{\@@footnotetext{#1}}%
 \else \insert\footins{\@@footnotetext{#1}}%
 \fi}

\long\def\@@footnotetext#1{%
 \color@begingroup
 \reset@font\footnotesize
 \interlinepenalty\interfootnotelinepenalty
 \splittopskip\footnotesep
 \splitmaxdepth \dp\strutbox \floatingpenalty \@MM
 \hsize\columnwidth \@parboxrestore
 \@makefntext{\rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
 \color@endgroup}
\makeatother

\begin{document}
normal\footnote{normal}

\begin{enumerate}
\item \parbox[t]{\linewidth}{\globalfootnotestrue
  parbox\footnote{parbox - \blindtext}}%
\copyinserts
\item test
\end{enumerate}

check counter\footnote{after}

\end{document}

相关内容