latex中脚注及其超链接实现的原理解析
说明
latex脚注及其超链接的实现主要涉及latex内核及hyperref宏包,可以参考source2e.PDF和hyperref.PDF。
原理解析
基本的脚注实现
latex文档中latex2e源码的实现脚注一般是没有超链接的,它主要的工作包括:
a. 文档中的脚注标记
b. 在页面下方利用\footins
插入脚注的文本
这里我们仅看不带脚注记号参数的\footnote
宏的伪代码或代码:
\footnote{NOTE} ==
BEGIN
\stepcounter{\@mpfn}
begingroup
\protect == \noexpand
\@thefnmark :=G eval (\thempfn)
endgroup
\@footnotemark
\@footnotetext{NOTE}
END
\@footnotemark ==
BEGIN
\leavevmode
IF hmode THEN \@x@sf := \the\spacefactor FI
\@makefnmark % put number in main text
IF hmode THEN \spacefactor := \@x@sf FI
END
\long\def\@footnotetext#1{\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}}%
\long\def\@makefntext#1{%
\parindent 1em\noindent \hb@xt@ 1.8em{\hss \@makefnmark}#1}
可以看到脚注标记是由\@footnotemark
插入,而脚注文本是由\@footnotetext{NOTE}
实现的。
从\@makefntext
宏的定义可以看到脚注文本的具体输出内容和段落格式。输出内容包括:\@makefnmark
和#1
段落格式是\noindent
加\hb@xt@
其实就是\hbox to
即1.8em的盒子中放入了脚注的标记。
这是脚注的基本逻辑,其中是没有超链接的,而这正是hyperref宏包所实现的。
脚注的超链接实现
超链接一般来说,通常需要链接的起点及其对应的连接的锚点,从前述的代码中我们没有看到任何这样的信息。而这正是hyperref来实现的。我们来看看它的代码:
首先hyperref将\@footnotetext
和\@footnotemark
的定义保存在加H@
的对应宏中。
\let\H@@footnotetext\@footnotetext
\let\H@@footnotemark\@footnotemark
接着重定义\@footnotetext
和\@footnotemark
来加入超链接的起点和锚点:
其中起点\hyper@linkstart
在脚注标记中加入,脚注标记完全是重定义,而没有使用原来定义相关的内容。
锚点在脚注文本中加入,脚注文本使用了\H@@footnotetext
,说明它使用了原来的定义,
只是在其输入参数中加入了锚点\hyper@@anchor
,然后原来的输入参数没做任何的处理。
\def\@footnotemark{%
\leavevmode
\ifhmode\edef\@x@sf{\the\spacefactor}\nobreak\fi
\stepcounter{Hfootnote}%
\global\let\Hy@saved@currentHref\@currentHref
\hyper@makecurrent{Hfootnote}%
\global\let\Hy@footnote@currentHref\@currentHref
\global\let\@currentHref\Hy@saved@currentHref
\hyper@linkstart{link}{\Hy@footnote@currentHref}%
\@makefnmark
\hyper@linkend
\ifhmode\spacefactor\@x@sf\fi
\relax
}%
\long\def\@footnotetext#1{%
\H@@footnotetext{%
\ifHy@nesting
\expandafter\ltx@firstoftwo
\else
\expandafter\ltx@secondoftwo
\fi
{%
\expandafter\hyper@@anchor\expandafter{%
\Hy@footnote@currentHref
}{#1}%
}{%
\Hy@raisedlink{%
\expandafter\hyper@@anchor\expandafter{%
\Hy@footnote@currentHref
}{\relax}%
}%
\let\@currentHref\Hy@footnote@currentHref
\let\@currentlabelname\@empty
#1%
}%
}%
}%
这样我们可以知道在使用了hyperref来实现脚注的超链接过程中,hyperref使用了一个替换的手段,相当于在\@footnotetext
增加了超链接锚点。
因此我们修稿脚注文本的段落格式,如果通过修改latex的原有的\@footnotetext
定义一定是会存在问题的,因为他的定义已经被hyperref完全重定义了。但其实脚注文本格式还是原来的定义,只是hyperref把它放到了\H@@footnotetext
中,因此我们要修改脚注的段落格式,那么必须要通过重定义\H@@footnotetext
来实现。
以上就是latex中脚注超链接的实现原理,如果单纯从latex2e来看我们是不能知道的,结合hyperref的代码,我们去掉多余的附加功能的,抓住代码实现的关键进行分析,就可以得到上面的结论。