如何用 TeX 编写两遍系统?

如何用 TeX 编写两遍系统?

第 400 页TeXbook(“肮脏的伎俩”部分) 据说:

输出例程还可以根据手稿中发生的情况在文件上写下注释。可以设计一个双程系统,其中 TeX 仅在第一程期间收集信息;实际排版可以在第二程期间完成,用于\read恢复第一程期间写入的信息。

这种两遍系统最简单的例子是什么?它解决了以下练习 14.28 中的问题。电子书

...因为线的深度取决于断线的细节,而这些细节直到断线之后才知道。

以下内容可作为模板:

\def\marginalstar{\vadjust{\kern-R\smash{\llap{* }}\kernR}}
\nopagenumbers
\hsize0.8in
\noindent
Quick brown fox eats a
\marginalstar
big fat
mouse.
\bye

在哪里R在第一遍中计算并在第二遍中使用。

答案1

你可以\pfdsavepos在使用时使用 来测量前一行的深度\vadjust。但这不是经典的 TeX,这是来自 pdfTeX 扩展:

This is the line in the paragraph%
\pdfsavepos\write16{\the\pdflastypos}%
\vadjust{\pdfsavepos\write16{\the\pdflastypos}}
this continues the line in the paragraph,
this continues the line in the paragraph.

您可以将结果写入输出文件(将 16 替换为更合适的数字),然后在下一步中再次读取此文件。文件中的信息(来自此示例)的形式如下:

49989344
49861913

这意味着测量线的深度为49989344-49861913 = 127431 sp。这约为 1.944pt。

编辑因为线程的名称,我展示了此功能的完整实现:

\newcount\marnum   \newcount\tmpnum
\newwrite\marfile  \newread\testin

\def\marX#1#2{\advance\marnum by1 \tmpnum=#1 \advance\tmpnum by-#2
   \expandafter \edef \csname mar:\the\marnum\endcsname{\the\tmpnum}}

\openin\testin=\jobname.mar
\ifeof\testin \message{Warning: file \jobname.mar does not exist, TeX me again}%
\else \closein\testin \input \jobname.mar \fi

\immediate\openout\marfile=\jobname.mar
\marnum=0

\def\marginalnote#1{\global\advance\marnum by1
  \expandafter\ifx\csname mar:\the\marnum\endcsname \relax
     \def\kernR{0pt}\else\edef\kernR{\csname mar:\the\marnum\endcsname sp}\fi
  \pdfsavepos\write\marfile{\string\marX{\the\pdflastypos}}%
  \vadjust{\pdfsavepos\write\marfile{{\the\pdflastypos}}%
     \kern-\kernR\smash{\llap{#1 }}\kern\kernR}}

This is the line in the paragraph%
\marginalnote{XX}
this continues the line in the paragraph,
this continues the line in the paragraph.

Second m. note:\marginalnote{YY}

\end

所有边注在文档中都有唯一编号\marnum。如果临时文件\jobname.mar存在,则使用 读取该文件\input,并使用 保存信息\marX到宏中\mar:mar-num\marginalnote如果存在,则读取此信息,否则使用R=0pt

相关内容