14

On page 400 of The TeXbook ("Dirty tricks" part) it is said:

An output routine can also write notes on a file, based on what occurs in a manuscript. A two-pass system can be devised where TeX simply gathers information during the first pass; the actual typesetting can be done during the second pass, using \read to recover information that was written during the first.

What might be the simplest example of such a two-pass system which solves the following problem from exercise 14.28 of TeXbook?

... because the depth of the line depends on details of line breaking that aren't known until afterwards.

The following may be used as a template:

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

where R is to be calculated during the first pass and used in the second.

  • 11
    Why is there a close vote on this? Especially after 4 minutes? – percusse Sep 8 '15 at 11:01
  • 2
    by far the most commonly used implementation of such a system is the latex .aux file which is written on one pass and read on the next for tables of contents and cross referencing information but also widths of table columns, and anything else. – David Carlisle Sep 8 '15 at 11:07
  • @DavidCarlisle How to do it without extra layers, using only core of TeX? – Igor Liferenko Sep 8 '15 at 11:11
  • the latex source code is readable, and a good source of examples for many of the kinds of things you ask about. Of course latex isn't really an "extra layer" it is the same number of layers as plain tex, just that a more functional set of macros is loaded into the format. I may however post some plain code later if no one has answered, no time now:-) – David Carlisle Sep 8 '15 at 11:16
  • This should not be closed. Please wait at least 24 hours after asking the OP for improvements to the question before voting to close. Also, if you downvote, please don't forget to revert the vote after the question is improved. – Martin Schröder Sep 8 '15 at 22:28
12

You can use \pfdsavepos for measuring the depth of the previous line while using \vadjust. But this is not classical TeX, this is from pdfTeX extension:

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.

You can write the result to the output file (replace 16 by something more appropriate) and you can read this file again in the next step. The information in the file (from this example) is in the form:

49989344
49861913

This means that the depth of the measured line is 49989344-49861913 = 127431 sp. This is approximately 1.944pt.

Edit Because the name of the thread, I show a full implementation of this feature:

\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

All marginal notes have unique number in the document \marnum. If the temporary file \jobname.mar exists then it is read using \input and the information is saved using \marX to the macro \mar:mar-num. The \marginalnote reads this information if exists else it uses R=0pt.

  • Your solution is good. Is it possible to do it using only TeX? – Igor Liferenko Sep 8 '15 at 11:46
  • @IgorLiferenko No. \pdfsavepos in pdfTeX primitive. – wipet Sep 8 '15 at 12:02
  • Is it possible to add \par\showboxdepth0\showboxbreadth\maxdimen\showlists to the paragraph which has \vadjust during the first pass and see depth R of the hbox just before \hbox(0.0+0.0)x0.0 [] in the trace file? Or maybe there is a e-TeX solution? Maybe there is a trick in the output routine which will let to do it without creating an auxiliary file at all? And also is it possible to print "TeX me again" also when the data in .mar file is not up-to-date (not only when .mar file does not exist)? – Igor Liferenko Sep 8 '15 at 23:22
  • 1
    I just wanted to ask for an advice: Is it possible, in principle, to do marginal notes via \insert? Is it feasible to split marginal notes across a page automatically (like footnotes)? Or fully-functional marginal notes are impossible in TeX (e-TeX)? – Igor Liferenko Sep 10 '15 at 12:35
  • I have an idea how to do it using only TeX, but I do not know how to implement it. Is it possible to do this: we need to know the depth of the line on the first pass, thus we just care about line breaks, not pagebreaks. So on the first pass we call \eject in \vadjust and use special penalty value which carries the number of margin note. Then in special output routine we see \dp255 and record it in file, and on the second pass we read this depth (similar to this tex.stackexchange.com/questions/201104/…) – Igor Liferenko Sep 22 '15 at 11:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.