Why is an empty line added when insert is used?Whatsits: when are they used in practice?Make tocloft insert empty page after the ToCHow remove empty line between two subsections?Why does TeX attempt to insert 'missing' tokens?why I can't use footnote(insert) in nested boxes?Insert empty pages until certain page numberscrartcl / section / itemize: Why empty page?Why is the bye command not used by LaTeX?Empty last line before page breaks using mdframedHorizontal space problem when the float environment isn't used

How to determine the optimal threshold to achieve the highest accuracy

How could a medieval fortress manage large groups of migrants and travelers?

Why did Steve Rogers choose this character in Endgame?

Kepler space telescope planets detection

Why don't commercial aircraft adopt a slightly more seaplane-like design to allow safer ditching in case of emergency?

License validity of unreleased project

How fast does a character need to move to be effectively invisible?

Do dragons smell of lilacs?

Finding the package which provides a given command

Is it rude to refer to janitors as 'floor people'?

What happens when I team swap while I have Pokemon inside a gym?

Why is Katakana not pronounced Katagana?

Can you perfectly wrap a cube with this blocky shape?

Unix chat server making communication between terminals possible

How to delete certain lists from a nested list?

Why do candidates not quit if they no longer have a realistic chance to win in the 2020 US presidents election

What details should I consider before agreeing for part of my salary to be 'retained' by employer?

How to ask my office to remove the pride decorations without appearing anti-LGBTQ?

Animal Shelter Management C++

What is the meaning of [[:space:]] in bash?

Is there any conditions on a finite abelian group so that it cannot be class group of any number field?

When does Fisher's "go get more data" approach make sense?

Can I remove the doors before installing a sliding patio doors frame?

Does the Intel 8085 CPU use real memory addresses?



Why is an empty line added when insert is used?


Whatsits: when are they used in practice?Make tocloft insert empty page after the ToCHow remove empty line between two subsections?Why does TeX attempt to insert 'missing' tokens?why I can't use footnote(insert) in nested boxes?Insert empty pages until certain page numberscrartcl / section / itemize: Why empty page?Why is the bye command not used by LaTeX?Empty last line before page breaks using mdframedHorizontal space problem when the float environment isn't used






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








3















Consider the following example:



tracingonline=1
tracingoutput=1
gdefmakefootline gdefmakeheadline
inserttopinsvbox tovsizehrule height vsize width 300pt
end


The log file contains this:



Completed box being shipped out [1]
vbox(643.20255+0.0)x300.0
.vbox(643.20255+0.0)x300.0
..vbox(643.20255+0.0)x300.0
...rule(643.20255+0.0)x300.0


Completed box being shipped out [2]
vbox(643.20255+0.0)x469.75499
.vbox(643.20255+0.0)x469.75499, glue set 633.20255fill
..glue(topskip) 10.0
..hbox(0.0+0.0)x469.75499
..glue 0.0 plus 1.0fill


It is not clear where the elements on page 2 come from (topskip, line and vfill). This behavior is not documented in chapter 15 of The TeXbook.










share|improve this question






























    3















    Consider the following example:



    tracingonline=1
    tracingoutput=1
    gdefmakefootline gdefmakeheadline
    inserttopinsvbox tovsizehrule height vsize width 300pt
    end


    The log file contains this:



    Completed box being shipped out [1]
    vbox(643.20255+0.0)x300.0
    .vbox(643.20255+0.0)x300.0
    ..vbox(643.20255+0.0)x300.0
    ...rule(643.20255+0.0)x300.0


    Completed box being shipped out [2]
    vbox(643.20255+0.0)x469.75499
    .vbox(643.20255+0.0)x469.75499, glue set 633.20255fill
    ..glue(topskip) 10.0
    ..hbox(0.0+0.0)x469.75499
    ..glue 0.0 plus 1.0fill


    It is not clear where the elements on page 2 come from (topskip, line and vfill). This behavior is not documented in chapter 15 of The TeXbook.










    share|improve this question


























      3












      3








      3








      Consider the following example:



      tracingonline=1
      tracingoutput=1
      gdefmakefootline gdefmakeheadline
      inserttopinsvbox tovsizehrule height vsize width 300pt
      end


      The log file contains this:



      Completed box being shipped out [1]
      vbox(643.20255+0.0)x300.0
      .vbox(643.20255+0.0)x300.0
      ..vbox(643.20255+0.0)x300.0
      ...rule(643.20255+0.0)x300.0


      Completed box being shipped out [2]
      vbox(643.20255+0.0)x469.75499
      .vbox(643.20255+0.0)x469.75499, glue set 633.20255fill
      ..glue(topskip) 10.0
      ..hbox(0.0+0.0)x469.75499
      ..glue 0.0 plus 1.0fill


      It is not clear where the elements on page 2 come from (topskip, line and vfill). This behavior is not documented in chapter 15 of The TeXbook.










      share|improve this question
















      Consider the following example:



      tracingonline=1
      tracingoutput=1
      gdefmakefootline gdefmakeheadline
      inserttopinsvbox tovsizehrule height vsize width 300pt
      end


      The log file contains this:



      Completed box being shipped out [1]
      vbox(643.20255+0.0)x300.0
      .vbox(643.20255+0.0)x300.0
      ..vbox(643.20255+0.0)x300.0
      ...rule(643.20255+0.0)x300.0


      Completed box being shipped out [2]
      vbox(643.20255+0.0)x469.75499
      .vbox(643.20255+0.0)x469.75499, glue set 633.20255fill
      ..glue(topskip) 10.0
      ..hbox(0.0+0.0)x469.75499
      ..glue 0.0 plus 1.0fill


      It is not clear where the elements on page 2 come from (topskip, line and vfill). This behavior is not documented in chapter 15 of The TeXbook.







      floats page-breaking tex-core plain-tex






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jul 8 at 14:52









      Peter Mortensen

      5563 silver badges7 bronze badges




      5563 silver badges7 bronze badges










      asked Jul 8 at 5:39









      Igor LiferenkoIgor Liferenko

      2,5568 silver badges30 bronze badges




      2,5568 silver badges30 bronze badges




















          2 Answers
          2






          active

          oldest

          votes


















          4














          I'll try to explain this using quotes from the TeXbook.



          Summary



          When the main vertical list isn't empty at the point where the end token is digested, TeX inserts the equivalent of linevfillpenalty-'10000000000 into the main vertical list, exercises the page builder and prepares to read end again (TeXbook pp. 264 and 283). In your example, this line brings the first box to the main vertical list, because the insertion item is not a box item. As a consequence, TeX prepends topskip glue to this box, which is 10pt here. This topskip glue is a valid breakpoint because it is immediately preceded by the insertion item; the associated cost is zero. The next legal breakpoint is the vfill glue following the hbox that corresponds to the aforementioned line. The cost associated with this vfill glue is infinite because the associated penalty is zero and the page would be overfull should a break occur at the vfill item (i.e., b = ∞; this is because the insertion plus the topskip glue plus the empty hbox are 10 points too high in total to fit on the page). Therefore TeX breaks a new page at the best breakpoint seen so far, which is the topskip glue. Thus, page 1 only contains material from the insertion (the output routine wraps this material inside two vboxes). Page 2 contains a new topskip glue item, the empty hbox and the vfill glue item.



          Analysis



          As said above, if the main vertical list isn't empty at the point where the end token is digested, TeX inserts the equivalent of linevfillpenalty-'10000000000 into the main vertical list, exercises the page builder and prepares to read end again. In your example, this brings 10 points of topskip glue followed by an empty hbox to hsize onto the current page (among others). In this particular case, the topskip glue item is a valid breakpoint1 and TeX immediately computes the associated cost (remember that it is exercising the page builder as part of the special end processing); it finds that this cost is zero, because the insertion is exactly vsize high. Thus, the conditions for starting a new page are not fulfilled yet (TeXbook p. 112, § 2).



          Therefore, TeX continues with the implicitly-added items. After the empty hbox comes the vfill glue: it moves these two items from “recent contributions” to the “current page” list. The hbox is not a legal breakpoint, but the vfill item is, since it is immediately preceded by a non-discardable item (the hbox). TeX computes the cost c associated with this second legal breakpoint and finds c = ∞, because there is 10pt material in excess on the current page, up to and excluding the breakpoint (the page goal was decreased by vsize and became 0pt when the insertion item was moved to the “current page,” and the page total went from 0pt to 10pt with the topskip glue and remained unchanged after the empty hbox). According to the rules given on p. 112 of the TeXbook, this causes TeX to decide that it is time to break a new page at the best remembered breakpoint, which is the one at the topskip glue (associated cost: 0).



          This glue item from topskip, the empty hbox and the vfill glue item are thus all put back at the top of the “recent contributions” list, followed by the penalty-'10000000000 item that has been waiting there all the time since end inserted it (cf. long paragraph p. 125). Since holdinginserts is 0 by default, the insertion item is then removed from the “current page,” its contents is appended to boxtopins with no interline glue, the items remaining on the “current page” (none here!) are put together in box255, and finally the output routine is invoked and ships out page 1.



          Then TeX starts page 2. The first thing it does is to exercise the page builder, since an output routine has just ended (cf. p. 122, § 2, item (e), reproduced in footnote 3). So, TeX tries to move items from “recent contributions” to the “current page.” The glue item from topskip that was put back at the top of the “recent contributions” is discarded at this occasion (there is no box yet on the “current page”) and immediately replaced by a new topskip glue item,2 since the hbox item that follows it will be the first box on the current page. TeX moves this box to the current page, followed by the vfill glue item and the penalty-'10000000000. The vfill glue is a legal breakpoint, but it doesn't fulfill the conditions given p. 112 for finishing the page (the associated values are p=0 and c=100000). The penalty item that follows, on the other hand, does fulfill them (p ≤ −10000).



          All remaining items except the breakpoint, namely the penalty-'10000000000, thus went on page 2. This penalty item is changed into a penalty10000 and put back at the top of the “recent contributions” (TeXbook p. 125), but immediately discarded as the page builder is exercised (again due to § 2 of p. 122, item (e), as reproduced in footnote 3). Because of this, the main vertical list is finally empty and since the output routine executed shipout for page 2, deadcycles is 0 when TeX sees end for the second time. According to the TeXbook p. 283, this terminates the job.



          Confirmation of the analysis with experiments



          TeXbook p. 264:




          When TeX sees an end command, it terminates the job only if the main vertical list has been entirely output and if deadcycles=0. Otherwise it inserts the equivalent of



          line vfill penalty-'10000000000


          into the main vertical list, and prepares to read the end token again.




          Notes:



          • This corresponds to the code posted by David Carlisle.


          • On page 283, Knuth adds the precision that the page builder is exercised after the aforementioned box/glue/penalty combination has been added to the main vertical list.


          We can show that in your example, TeX sees the end token before the main vertical list has been emptied. In order to do this, insert showlists before end in your example and you'll see:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:5: OK.
          l.5 showlists


          In contrast, if you insert nullbreakshowlists before end, you'll see:



          ### vertical mode entered at line 0
          prevdepth 0.0

          ./insert.tex:5: OK.
          l.5 nullbreakshowlists


          That is an empty vertical list (displayed after page 1 and an underfull page 2 have been shipped out). So, getting back to your example: when TeX sees end, it doesn't consider yet that the page is full (it would indeed be possible to “rewind” using a box followed by negative kerns or skips), so it doesn't call the output routine yet. We can insert some more diagnostic tools to confirm the precisions I added here:



          tracingonline=1
          tracingoutput=1
          tracingmacros=2
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          showlists
          end


          which prints:



          %% goal height=643.20255, max depth=4.0

          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:7: OK.
          l.7 showlists

          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=10.0 g=0.0 b=* p=0 c=*
          output->plainoutput

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)

          Completed box being shipped out [1]
          vbox(643.20255+0.0)x300.0
          .vbox(643.20255+0.0)x300.0
          ..vbox(643.20255+0.0)x300.0
          ...rule(643.20255+0.0)x300.0


          advancepageno ->ifnum pageno <z@ global advance pageno m@ne else global advance pageno @ne fi
          %% goal height=643.20255, max depth=4.0
          % t=10.0 g=643.20255 b=10000 p=0 c=100000#
          % t=10.0 plus 1.0fill g=643.20255 b=0 p=-1073741824 c=-1073741824#
          output->plainoutput

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)

          Completed box being shipped out [2]
          vbox(643.20255+0.0)x469.75499
          .vbox(643.20255+0.0)x469.75499, glue set 633.20255fill
          ..glue(topskip) 10.0
          ..hbox(0.0+0.0)x469.75499
          ..glue 0.0 plus 1.0fill


          The %% goal height=643.20255, max depth=4.0 line is printed when




          the first box or insertion enters the current page list




          (TeXbook p. 113). This is your insert, okay. Right after that, showlists indeed shows this insert on the current page:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0

          (...)



          This is because, according to the TeXbook p. 281:




          TeX also exercises the page builder (see below), after an insert has been appended in vertical mode.




          So, the page builder has been exercised before TeX even read showlists. The insert has been moved right away from the “recent contributions” to the “current page.” But TeX doesn't consider yet that the page has to be finished, it won't invoke the output routine yet! Indeed, remember what comes next in the log:



          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=10.0 g=0.0 b=* p=0 c=*
          output->plainoutput


          The first line with g=0 clearly shows that the insert has been put on the current page, otherwise the page goal would still be 643.20255 points. Now, remember what is said in the TeXbook p. 114:




          TeX inserts special glue just before the first box on each page. This special glue is equal to topskip, except that the natural space has been decreased by the height of the first box, or it has been set to zero in lieu of a negative value.




          The % t=0.0 g=0.0 b=0 p=0 c=0# line corresponds to the topskip glue automatically inserted before the box equivalent to line. It is a legal breakpoint because of the quote from footnote 1 below, and was printed when the page builder was exercised as part of the special processing of end (otherwise, it would have been printed after the hbox command had been digested by TeX, according to the TeXbook p. 282). However, the conjunction of p=0 and c=0 at the end of that line implies that TeX sees no reason to break a new page at the best breakpoint seen so far (marked with #: first legal breakpoint here). Indeed, remember paragraph 2 of page 112:




          If the resulting c is less than or equal to the smallest cost seen so far on the current page, TeX remembers the current breakpoint as the best so far. And if c = ∞ or if p ≤ −10000, TeX seizes the initiative and breaks the page at the best remembered breakpoint.




          (the last “if” is most probably an “if and only if”). The topskip breakpoint being a glue item, its associated p value is 0; since the insertion is exactly vsize high, breaking at this topskip item would cause a page badness equal to zero (b=0), therefore the cost c associated with the first breakpoint is indeed c=0 according to the b + p + q expression from page 111 (insertpenalties is zero after the insert).



          So, after putting the topskip glue on the “current page” due to the special end processing and computing the cost associated with this potential breakpoint, TeX is still waiting for more material before deciding that a page break has to happen. So, it takes the next items inserted in “recent contributions” by end, and moves them one by one to the “current page”. The hbox isn't a breakpoint, it is simply moved; the vfill is also moved—there is no reason to discard it—and is a legal breakpoint, since it is preceded by a non-discardable item (the hbox). The page builder computes its associated cost:



          % t=10.0 g=0.0 b=* p=0 c=*


          This line being printed for a glue item, the associated p value is 0, thus p < 10000. Because of the topskip glue item (10 points) and the empty hbox, breaking at the vfill glue item would cause an overfull page, hence b=* and the computed cost c=*. This decides TeX to break the page at the best remembered breakpoint (the topskip) and finally invoke the output routine for page 1:



          output->plainoutput 

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)


          So, you get a second page containing the (new) topskip glue item, an empty hbox equivalent to line and another glue item from vfill (all wrapped in two vboxes: one from plainoutput and one from pagebody).



          You would like to do something to shipout page 1 after the insertion, but before end added the equivalent of line vfill penalty-'10000000000, right? First idea: append a penalty after the insert that forces page breaking, e.g., with break (which is equivalent to penalty -10000). Alas, this doesn't work because:



          1. A penalty seen in vertical mode causes TeX to exercise the page builder (TeXbook p. 280), and therefore to try to move things from the “recent contributions” to the “current page”.



          2. This sentence from p. 112 of the TeXbook:




            Whenever TeX is moving an item from the top of the “recent contributions” to the bottom of the “current page,” it discards a discardable item (glue, kern, or penalty) if the current page does not contain any boxes.




            which is the case here (the insertion item on the “current page” isn't a box item).



          Indeed, if we try:



          tracingonline=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          break
          showlists
          end


          we get to see:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:5: OK.
          l.5 showlists


          As before, the “current page” has the insertion at the point where showlists is executed, but the penalty has been discarded, as could be guessed from the previous quote. Compare this with:



          tracingonline=1
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          topskip=0ptnullpenalty100
          showlists
          end


          which gives:



          %% goal height=643.20255, max depth=4.0
          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=0.0 g=0.0 b=0 p=100 c=100

          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          glue(topskip) 0.0
          hbox(0.0+0.0)x0.0
          penalty 100
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth 0.0


          Because of the null (an empty hbox), the penalty wasn't discarded this time; it got onto the current page and was noted as being a legal breakpoint (t=0.0 g=0.0 b=0 p=100 c=100), though not the best seen so far (that one has the trailing #). And thanks to the topskip=0pt, we got all this on page 1 (with a positive topskip, we would have had c = ∞ for the penalty100 breakpoint, thus again a page break at the topskip glue, then a second page). With topskip=0pt, the insertion, the topskip glue and the null box all fit on the first page. Therefore, all we need to do in order to get only one page of output as you probably wanted, is to trigger a page break after the null box. We can do this using a penalty, which won't be discarded this time since there is already a box on the “current page list.” Here we go:



          tracingonline=1
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          topskip=0ptnullbreak
          end


          which gives the following output:



          %% goal height=643.20255, max depth=4.0
          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=0.0 g=0.0 b=0 p=-10000 c=-10000#
          [1] )
          Output written on insert.pdf (1 page, 968 bytes).
          Transcript written on insert.log.

          TeX Output finished at Mon Jul 8 10:11:58


          One page of output, broken at the penalty -10000 from our break.




          Footnotes




          1. We are precisely in the case described page 114 of the TeXbook:




            If insertions occur before the first box, the topskip glue before that box is considered to be a valid breakpoint; this is the only case in which a completed page might not contain a box.




          2. This can be verified with code such as output=expandaftertheoutputglobaltopskip=6pt inserted before end and watching the TeX messages printed with tracingonline=1tracingpages=1tracingoutput=1relax (idea from Igor).



          3. Paragraph 2 of the TeXbook p. 122 gives the conditions in which the page builder is exercised:




            TeX is liable to invoke an output routine whenever it tries to move something from the list of recent contributions to the current page, because it might discover a page break with c = ∞ then. Here is a list of the times when that can happen: (a) At the beginning or end of a paragraph, provided that this paragraph is being contributed to the main vertical list. (b) At the beginning or end of a displayed equation within such a paragraph. (c) After completing an halign in vertical mode. (d) After contributing a box or penalty or insertion to the main vertical list. (e) After an output routine has ended.








          share|improve this answer

























          • There is an error in your answer: "It is this precise topskip that decides TeX to finally call the output routine for page 1: % t=10.0 g=0.0 b=* p=0 c=* ...". In fact, topskip decides here: % t=0.0 g=0.0 b=0 p=0 c=0#. % t=10.0 g=0.0 b=* p=0 c=* is decided by vfill. See p.113.

            – Igor Liferenko
            Jul 9 at 5:41











          • I stand by my assertion: the topskip causes 10 points “two much material” on the page (t=10.0 g=0.0); this explains the c=* which causes TeX to say “Oh, it's time to break a new page, let's find the best breakpoint we've seen so far and rewind.” The # marks the best breakpoint seen so far, and it is the topskip as show by the t=0.0 on the line ending with #. AFAICT, the vfill is not seen at all while processing page 1 of the original example.

            – frougon
            Jul 9 at 5:50












          • Please read this sentence on p.113: "However, the % lines are generated by the penalty or glue items that follow the hboxes, not by the boxes themselves." This means that the first % can be caused only by glue (and this is confirmed by the fact that showlists is between %% and %). And the glue is, of course, topskip. It causes the first % line. Then comes empty hbox, which stands 10pt lower. Next % can be caused also only by glue. And that glue is vfill.

            – Igor Liferenko
            Jul 9 at 5:57











          • (was too long to add to the previous comment) The breakpoint itself doesn't stay on the page that is about to be finished: TeX always breaks “right before the chosen breakpoint”; that is why the line ending with # has t=0.0 instead of t=10.0.

            – frougon
            Jul 9 at 5:58











          • BTW, it's possible to see that old topskip is indeed discarded and new topskip is used by adding this before end: topskip=5ptoutput=expandaftertheoutputglobaltopskip=6pt

            – Igor Liferenko
            Jul 9 at 6:05


















          4














          It is tex-the-program's final endgame to flush out the insert:



          tex.web has



          @ We don't want to leave |main_control| immediately when a |stop| command
          is sensed, because it may be necessary to invoke an .\output routine
          several times before things really grind to a halt. (The output routine
          might even say `.\gdef\end...', to prolong the life of the job.)
          Therefore |its_all_over| is |true| only when the current page
          and contribution list are empty, and when the last output was not a
          ``dead cycle.''

          @<Declare act...@>=
          function its_all_over:boolean; do this when .\end or .\dump occurs
          label exit;
          begin if privileged then
          begin if (page_head=page_tail)and(head=tail)and(dead_cycles=0) then
          begin its_all_over:=true; return;
          end;
          back_input; we will try to end again after ejecting residual material
          tail_append(new_null_box);
          width(tail):=hsize;
          tail_append(new_glue(fill_glue));
          tail_append(new_penalty(-@'10000000000));@/
          build_page; append .\hbox to \hsize\vfill\penalty-'10000000000
          ^^^^^^^^^^^^^^^^^^^^^^
          end;
          its_all_over:=false;
          exit:end;





          share|improve this answer























          • This is mentioned on p.264 of TeXbook. I guess the meaning is that if insert which occupies the whole page is used, there has to be some additional text, so second page is inevitable. Still, I'm not sure I completely understand how the explanation on p.264 applies to OP.

            – Igor Liferenko
            Jul 8 at 7:26











          • @IgorLiferenko in your case when it hits end the main vertical list is not empty (there is an insert node left) so the clause on page 262 means the the line is added and end is called again

            – David Carlisle
            Jul 8 at 7:50













          Your Answer








          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "85"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f499060%2fwhy-is-an-empty-line-added-when-insert-is-used%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          4














          I'll try to explain this using quotes from the TeXbook.



          Summary



          When the main vertical list isn't empty at the point where the end token is digested, TeX inserts the equivalent of linevfillpenalty-'10000000000 into the main vertical list, exercises the page builder and prepares to read end again (TeXbook pp. 264 and 283). In your example, this line brings the first box to the main vertical list, because the insertion item is not a box item. As a consequence, TeX prepends topskip glue to this box, which is 10pt here. This topskip glue is a valid breakpoint because it is immediately preceded by the insertion item; the associated cost is zero. The next legal breakpoint is the vfill glue following the hbox that corresponds to the aforementioned line. The cost associated with this vfill glue is infinite because the associated penalty is zero and the page would be overfull should a break occur at the vfill item (i.e., b = ∞; this is because the insertion plus the topskip glue plus the empty hbox are 10 points too high in total to fit on the page). Therefore TeX breaks a new page at the best breakpoint seen so far, which is the topskip glue. Thus, page 1 only contains material from the insertion (the output routine wraps this material inside two vboxes). Page 2 contains a new topskip glue item, the empty hbox and the vfill glue item.



          Analysis



          As said above, if the main vertical list isn't empty at the point where the end token is digested, TeX inserts the equivalent of linevfillpenalty-'10000000000 into the main vertical list, exercises the page builder and prepares to read end again. In your example, this brings 10 points of topskip glue followed by an empty hbox to hsize onto the current page (among others). In this particular case, the topskip glue item is a valid breakpoint1 and TeX immediately computes the associated cost (remember that it is exercising the page builder as part of the special end processing); it finds that this cost is zero, because the insertion is exactly vsize high. Thus, the conditions for starting a new page are not fulfilled yet (TeXbook p. 112, § 2).



          Therefore, TeX continues with the implicitly-added items. After the empty hbox comes the vfill glue: it moves these two items from “recent contributions” to the “current page” list. The hbox is not a legal breakpoint, but the vfill item is, since it is immediately preceded by a non-discardable item (the hbox). TeX computes the cost c associated with this second legal breakpoint and finds c = ∞, because there is 10pt material in excess on the current page, up to and excluding the breakpoint (the page goal was decreased by vsize and became 0pt when the insertion item was moved to the “current page,” and the page total went from 0pt to 10pt with the topskip glue and remained unchanged after the empty hbox). According to the rules given on p. 112 of the TeXbook, this causes TeX to decide that it is time to break a new page at the best remembered breakpoint, which is the one at the topskip glue (associated cost: 0).



          This glue item from topskip, the empty hbox and the vfill glue item are thus all put back at the top of the “recent contributions” list, followed by the penalty-'10000000000 item that has been waiting there all the time since end inserted it (cf. long paragraph p. 125). Since holdinginserts is 0 by default, the insertion item is then removed from the “current page,” its contents is appended to boxtopins with no interline glue, the items remaining on the “current page” (none here!) are put together in box255, and finally the output routine is invoked and ships out page 1.



          Then TeX starts page 2. The first thing it does is to exercise the page builder, since an output routine has just ended (cf. p. 122, § 2, item (e), reproduced in footnote 3). So, TeX tries to move items from “recent contributions” to the “current page.” The glue item from topskip that was put back at the top of the “recent contributions” is discarded at this occasion (there is no box yet on the “current page”) and immediately replaced by a new topskip glue item,2 since the hbox item that follows it will be the first box on the current page. TeX moves this box to the current page, followed by the vfill glue item and the penalty-'10000000000. The vfill glue is a legal breakpoint, but it doesn't fulfill the conditions given p. 112 for finishing the page (the associated values are p=0 and c=100000). The penalty item that follows, on the other hand, does fulfill them (p ≤ −10000).



          All remaining items except the breakpoint, namely the penalty-'10000000000, thus went on page 2. This penalty item is changed into a penalty10000 and put back at the top of the “recent contributions” (TeXbook p. 125), but immediately discarded as the page builder is exercised (again due to § 2 of p. 122, item (e), as reproduced in footnote 3). Because of this, the main vertical list is finally empty and since the output routine executed shipout for page 2, deadcycles is 0 when TeX sees end for the second time. According to the TeXbook p. 283, this terminates the job.



          Confirmation of the analysis with experiments



          TeXbook p. 264:




          When TeX sees an end command, it terminates the job only if the main vertical list has been entirely output and if deadcycles=0. Otherwise it inserts the equivalent of



          line vfill penalty-'10000000000


          into the main vertical list, and prepares to read the end token again.




          Notes:



          • This corresponds to the code posted by David Carlisle.


          • On page 283, Knuth adds the precision that the page builder is exercised after the aforementioned box/glue/penalty combination has been added to the main vertical list.


          We can show that in your example, TeX sees the end token before the main vertical list has been emptied. In order to do this, insert showlists before end in your example and you'll see:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:5: OK.
          l.5 showlists


          In contrast, if you insert nullbreakshowlists before end, you'll see:



          ### vertical mode entered at line 0
          prevdepth 0.0

          ./insert.tex:5: OK.
          l.5 nullbreakshowlists


          That is an empty vertical list (displayed after page 1 and an underfull page 2 have been shipped out). So, getting back to your example: when TeX sees end, it doesn't consider yet that the page is full (it would indeed be possible to “rewind” using a box followed by negative kerns or skips), so it doesn't call the output routine yet. We can insert some more diagnostic tools to confirm the precisions I added here:



          tracingonline=1
          tracingoutput=1
          tracingmacros=2
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          showlists
          end


          which prints:



          %% goal height=643.20255, max depth=4.0

          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:7: OK.
          l.7 showlists

          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=10.0 g=0.0 b=* p=0 c=*
          output->plainoutput

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)

          Completed box being shipped out [1]
          vbox(643.20255+0.0)x300.0
          .vbox(643.20255+0.0)x300.0
          ..vbox(643.20255+0.0)x300.0
          ...rule(643.20255+0.0)x300.0


          advancepageno ->ifnum pageno <z@ global advance pageno m@ne else global advance pageno @ne fi
          %% goal height=643.20255, max depth=4.0
          % t=10.0 g=643.20255 b=10000 p=0 c=100000#
          % t=10.0 plus 1.0fill g=643.20255 b=0 p=-1073741824 c=-1073741824#
          output->plainoutput

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)

          Completed box being shipped out [2]
          vbox(643.20255+0.0)x469.75499
          .vbox(643.20255+0.0)x469.75499, glue set 633.20255fill
          ..glue(topskip) 10.0
          ..hbox(0.0+0.0)x469.75499
          ..glue 0.0 plus 1.0fill


          The %% goal height=643.20255, max depth=4.0 line is printed when




          the first box or insertion enters the current page list




          (TeXbook p. 113). This is your insert, okay. Right after that, showlists indeed shows this insert on the current page:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0

          (...)



          This is because, according to the TeXbook p. 281:




          TeX also exercises the page builder (see below), after an insert has been appended in vertical mode.




          So, the page builder has been exercised before TeX even read showlists. The insert has been moved right away from the “recent contributions” to the “current page.” But TeX doesn't consider yet that the page has to be finished, it won't invoke the output routine yet! Indeed, remember what comes next in the log:



          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=10.0 g=0.0 b=* p=0 c=*
          output->plainoutput


          The first line with g=0 clearly shows that the insert has been put on the current page, otherwise the page goal would still be 643.20255 points. Now, remember what is said in the TeXbook p. 114:




          TeX inserts special glue just before the first box on each page. This special glue is equal to topskip, except that the natural space has been decreased by the height of the first box, or it has been set to zero in lieu of a negative value.




          The % t=0.0 g=0.0 b=0 p=0 c=0# line corresponds to the topskip glue automatically inserted before the box equivalent to line. It is a legal breakpoint because of the quote from footnote 1 below, and was printed when the page builder was exercised as part of the special processing of end (otherwise, it would have been printed after the hbox command had been digested by TeX, according to the TeXbook p. 282). However, the conjunction of p=0 and c=0 at the end of that line implies that TeX sees no reason to break a new page at the best breakpoint seen so far (marked with #: first legal breakpoint here). Indeed, remember paragraph 2 of page 112:




          If the resulting c is less than or equal to the smallest cost seen so far on the current page, TeX remembers the current breakpoint as the best so far. And if c = ∞ or if p ≤ −10000, TeX seizes the initiative and breaks the page at the best remembered breakpoint.




          (the last “if” is most probably an “if and only if”). The topskip breakpoint being a glue item, its associated p value is 0; since the insertion is exactly vsize high, breaking at this topskip item would cause a page badness equal to zero (b=0), therefore the cost c associated with the first breakpoint is indeed c=0 according to the b + p + q expression from page 111 (insertpenalties is zero after the insert).



          So, after putting the topskip glue on the “current page” due to the special end processing and computing the cost associated with this potential breakpoint, TeX is still waiting for more material before deciding that a page break has to happen. So, it takes the next items inserted in “recent contributions” by end, and moves them one by one to the “current page”. The hbox isn't a breakpoint, it is simply moved; the vfill is also moved—there is no reason to discard it—and is a legal breakpoint, since it is preceded by a non-discardable item (the hbox). The page builder computes its associated cost:



          % t=10.0 g=0.0 b=* p=0 c=*


          This line being printed for a glue item, the associated p value is 0, thus p < 10000. Because of the topskip glue item (10 points) and the empty hbox, breaking at the vfill glue item would cause an overfull page, hence b=* and the computed cost c=*. This decides TeX to break the page at the best remembered breakpoint (the topskip) and finally invoke the output routine for page 1:



          output->plainoutput 

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)


          So, you get a second page containing the (new) topskip glue item, an empty hbox equivalent to line and another glue item from vfill (all wrapped in two vboxes: one from plainoutput and one from pagebody).



          You would like to do something to shipout page 1 after the insertion, but before end added the equivalent of line vfill penalty-'10000000000, right? First idea: append a penalty after the insert that forces page breaking, e.g., with break (which is equivalent to penalty -10000). Alas, this doesn't work because:



          1. A penalty seen in vertical mode causes TeX to exercise the page builder (TeXbook p. 280), and therefore to try to move things from the “recent contributions” to the “current page”.



          2. This sentence from p. 112 of the TeXbook:




            Whenever TeX is moving an item from the top of the “recent contributions” to the bottom of the “current page,” it discards a discardable item (glue, kern, or penalty) if the current page does not contain any boxes.




            which is the case here (the insertion item on the “current page” isn't a box item).



          Indeed, if we try:



          tracingonline=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          break
          showlists
          end


          we get to see:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:5: OK.
          l.5 showlists


          As before, the “current page” has the insertion at the point where showlists is executed, but the penalty has been discarded, as could be guessed from the previous quote. Compare this with:



          tracingonline=1
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          topskip=0ptnullpenalty100
          showlists
          end


          which gives:



          %% goal height=643.20255, max depth=4.0
          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=0.0 g=0.0 b=0 p=100 c=100

          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          glue(topskip) 0.0
          hbox(0.0+0.0)x0.0
          penalty 100
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth 0.0


          Because of the null (an empty hbox), the penalty wasn't discarded this time; it got onto the current page and was noted as being a legal breakpoint (t=0.0 g=0.0 b=0 p=100 c=100), though not the best seen so far (that one has the trailing #). And thanks to the topskip=0pt, we got all this on page 1 (with a positive topskip, we would have had c = ∞ for the penalty100 breakpoint, thus again a page break at the topskip glue, then a second page). With topskip=0pt, the insertion, the topskip glue and the null box all fit on the first page. Therefore, all we need to do in order to get only one page of output as you probably wanted, is to trigger a page break after the null box. We can do this using a penalty, which won't be discarded this time since there is already a box on the “current page list.” Here we go:



          tracingonline=1
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          topskip=0ptnullbreak
          end


          which gives the following output:



          %% goal height=643.20255, max depth=4.0
          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=0.0 g=0.0 b=0 p=-10000 c=-10000#
          [1] )
          Output written on insert.pdf (1 page, 968 bytes).
          Transcript written on insert.log.

          TeX Output finished at Mon Jul 8 10:11:58


          One page of output, broken at the penalty -10000 from our break.




          Footnotes




          1. We are precisely in the case described page 114 of the TeXbook:




            If insertions occur before the first box, the topskip glue before that box is considered to be a valid breakpoint; this is the only case in which a completed page might not contain a box.




          2. This can be verified with code such as output=expandaftertheoutputglobaltopskip=6pt inserted before end and watching the TeX messages printed with tracingonline=1tracingpages=1tracingoutput=1relax (idea from Igor).



          3. Paragraph 2 of the TeXbook p. 122 gives the conditions in which the page builder is exercised:




            TeX is liable to invoke an output routine whenever it tries to move something from the list of recent contributions to the current page, because it might discover a page break with c = ∞ then. Here is a list of the times when that can happen: (a) At the beginning or end of a paragraph, provided that this paragraph is being contributed to the main vertical list. (b) At the beginning or end of a displayed equation within such a paragraph. (c) After completing an halign in vertical mode. (d) After contributing a box or penalty or insertion to the main vertical list. (e) After an output routine has ended.








          share|improve this answer

























          • There is an error in your answer: "It is this precise topskip that decides TeX to finally call the output routine for page 1: % t=10.0 g=0.0 b=* p=0 c=* ...". In fact, topskip decides here: % t=0.0 g=0.0 b=0 p=0 c=0#. % t=10.0 g=0.0 b=* p=0 c=* is decided by vfill. See p.113.

            – Igor Liferenko
            Jul 9 at 5:41











          • I stand by my assertion: the topskip causes 10 points “two much material” on the page (t=10.0 g=0.0); this explains the c=* which causes TeX to say “Oh, it's time to break a new page, let's find the best breakpoint we've seen so far and rewind.” The # marks the best breakpoint seen so far, and it is the topskip as show by the t=0.0 on the line ending with #. AFAICT, the vfill is not seen at all while processing page 1 of the original example.

            – frougon
            Jul 9 at 5:50












          • Please read this sentence on p.113: "However, the % lines are generated by the penalty or glue items that follow the hboxes, not by the boxes themselves." This means that the first % can be caused only by glue (and this is confirmed by the fact that showlists is between %% and %). And the glue is, of course, topskip. It causes the first % line. Then comes empty hbox, which stands 10pt lower. Next % can be caused also only by glue. And that glue is vfill.

            – Igor Liferenko
            Jul 9 at 5:57











          • (was too long to add to the previous comment) The breakpoint itself doesn't stay on the page that is about to be finished: TeX always breaks “right before the chosen breakpoint”; that is why the line ending with # has t=0.0 instead of t=10.0.

            – frougon
            Jul 9 at 5:58











          • BTW, it's possible to see that old topskip is indeed discarded and new topskip is used by adding this before end: topskip=5ptoutput=expandaftertheoutputglobaltopskip=6pt

            – Igor Liferenko
            Jul 9 at 6:05















          4














          I'll try to explain this using quotes from the TeXbook.



          Summary



          When the main vertical list isn't empty at the point where the end token is digested, TeX inserts the equivalent of linevfillpenalty-'10000000000 into the main vertical list, exercises the page builder and prepares to read end again (TeXbook pp. 264 and 283). In your example, this line brings the first box to the main vertical list, because the insertion item is not a box item. As a consequence, TeX prepends topskip glue to this box, which is 10pt here. This topskip glue is a valid breakpoint because it is immediately preceded by the insertion item; the associated cost is zero. The next legal breakpoint is the vfill glue following the hbox that corresponds to the aforementioned line. The cost associated with this vfill glue is infinite because the associated penalty is zero and the page would be overfull should a break occur at the vfill item (i.e., b = ∞; this is because the insertion plus the topskip glue plus the empty hbox are 10 points too high in total to fit on the page). Therefore TeX breaks a new page at the best breakpoint seen so far, which is the topskip glue. Thus, page 1 only contains material from the insertion (the output routine wraps this material inside two vboxes). Page 2 contains a new topskip glue item, the empty hbox and the vfill glue item.



          Analysis



          As said above, if the main vertical list isn't empty at the point where the end token is digested, TeX inserts the equivalent of linevfillpenalty-'10000000000 into the main vertical list, exercises the page builder and prepares to read end again. In your example, this brings 10 points of topskip glue followed by an empty hbox to hsize onto the current page (among others). In this particular case, the topskip glue item is a valid breakpoint1 and TeX immediately computes the associated cost (remember that it is exercising the page builder as part of the special end processing); it finds that this cost is zero, because the insertion is exactly vsize high. Thus, the conditions for starting a new page are not fulfilled yet (TeXbook p. 112, § 2).



          Therefore, TeX continues with the implicitly-added items. After the empty hbox comes the vfill glue: it moves these two items from “recent contributions” to the “current page” list. The hbox is not a legal breakpoint, but the vfill item is, since it is immediately preceded by a non-discardable item (the hbox). TeX computes the cost c associated with this second legal breakpoint and finds c = ∞, because there is 10pt material in excess on the current page, up to and excluding the breakpoint (the page goal was decreased by vsize and became 0pt when the insertion item was moved to the “current page,” and the page total went from 0pt to 10pt with the topskip glue and remained unchanged after the empty hbox). According to the rules given on p. 112 of the TeXbook, this causes TeX to decide that it is time to break a new page at the best remembered breakpoint, which is the one at the topskip glue (associated cost: 0).



          This glue item from topskip, the empty hbox and the vfill glue item are thus all put back at the top of the “recent contributions” list, followed by the penalty-'10000000000 item that has been waiting there all the time since end inserted it (cf. long paragraph p. 125). Since holdinginserts is 0 by default, the insertion item is then removed from the “current page,” its contents is appended to boxtopins with no interline glue, the items remaining on the “current page” (none here!) are put together in box255, and finally the output routine is invoked and ships out page 1.



          Then TeX starts page 2. The first thing it does is to exercise the page builder, since an output routine has just ended (cf. p. 122, § 2, item (e), reproduced in footnote 3). So, TeX tries to move items from “recent contributions” to the “current page.” The glue item from topskip that was put back at the top of the “recent contributions” is discarded at this occasion (there is no box yet on the “current page”) and immediately replaced by a new topskip glue item,2 since the hbox item that follows it will be the first box on the current page. TeX moves this box to the current page, followed by the vfill glue item and the penalty-'10000000000. The vfill glue is a legal breakpoint, but it doesn't fulfill the conditions given p. 112 for finishing the page (the associated values are p=0 and c=100000). The penalty item that follows, on the other hand, does fulfill them (p ≤ −10000).



          All remaining items except the breakpoint, namely the penalty-'10000000000, thus went on page 2. This penalty item is changed into a penalty10000 and put back at the top of the “recent contributions” (TeXbook p. 125), but immediately discarded as the page builder is exercised (again due to § 2 of p. 122, item (e), as reproduced in footnote 3). Because of this, the main vertical list is finally empty and since the output routine executed shipout for page 2, deadcycles is 0 when TeX sees end for the second time. According to the TeXbook p. 283, this terminates the job.



          Confirmation of the analysis with experiments



          TeXbook p. 264:




          When TeX sees an end command, it terminates the job only if the main vertical list has been entirely output and if deadcycles=0. Otherwise it inserts the equivalent of



          line vfill penalty-'10000000000


          into the main vertical list, and prepares to read the end token again.




          Notes:



          • This corresponds to the code posted by David Carlisle.


          • On page 283, Knuth adds the precision that the page builder is exercised after the aforementioned box/glue/penalty combination has been added to the main vertical list.


          We can show that in your example, TeX sees the end token before the main vertical list has been emptied. In order to do this, insert showlists before end in your example and you'll see:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:5: OK.
          l.5 showlists


          In contrast, if you insert nullbreakshowlists before end, you'll see:



          ### vertical mode entered at line 0
          prevdepth 0.0

          ./insert.tex:5: OK.
          l.5 nullbreakshowlists


          That is an empty vertical list (displayed after page 1 and an underfull page 2 have been shipped out). So, getting back to your example: when TeX sees end, it doesn't consider yet that the page is full (it would indeed be possible to “rewind” using a box followed by negative kerns or skips), so it doesn't call the output routine yet. We can insert some more diagnostic tools to confirm the precisions I added here:



          tracingonline=1
          tracingoutput=1
          tracingmacros=2
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          showlists
          end


          which prints:



          %% goal height=643.20255, max depth=4.0

          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:7: OK.
          l.7 showlists

          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=10.0 g=0.0 b=* p=0 c=*
          output->plainoutput

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)

          Completed box being shipped out [1]
          vbox(643.20255+0.0)x300.0
          .vbox(643.20255+0.0)x300.0
          ..vbox(643.20255+0.0)x300.0
          ...rule(643.20255+0.0)x300.0


          advancepageno ->ifnum pageno <z@ global advance pageno m@ne else global advance pageno @ne fi
          %% goal height=643.20255, max depth=4.0
          % t=10.0 g=643.20255 b=10000 p=0 c=100000#
          % t=10.0 plus 1.0fill g=643.20255 b=0 p=-1073741824 c=-1073741824#
          output->plainoutput

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)

          Completed box being shipped out [2]
          vbox(643.20255+0.0)x469.75499
          .vbox(643.20255+0.0)x469.75499, glue set 633.20255fill
          ..glue(topskip) 10.0
          ..hbox(0.0+0.0)x469.75499
          ..glue 0.0 plus 1.0fill


          The %% goal height=643.20255, max depth=4.0 line is printed when




          the first box or insertion enters the current page list




          (TeXbook p. 113). This is your insert, okay. Right after that, showlists indeed shows this insert on the current page:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0

          (...)



          This is because, according to the TeXbook p. 281:




          TeX also exercises the page builder (see below), after an insert has been appended in vertical mode.




          So, the page builder has been exercised before TeX even read showlists. The insert has been moved right away from the “recent contributions” to the “current page.” But TeX doesn't consider yet that the page has to be finished, it won't invoke the output routine yet! Indeed, remember what comes next in the log:



          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=10.0 g=0.0 b=* p=0 c=*
          output->plainoutput


          The first line with g=0 clearly shows that the insert has been put on the current page, otherwise the page goal would still be 643.20255 points. Now, remember what is said in the TeXbook p. 114:




          TeX inserts special glue just before the first box on each page. This special glue is equal to topskip, except that the natural space has been decreased by the height of the first box, or it has been set to zero in lieu of a negative value.




          The % t=0.0 g=0.0 b=0 p=0 c=0# line corresponds to the topskip glue automatically inserted before the box equivalent to line. It is a legal breakpoint because of the quote from footnote 1 below, and was printed when the page builder was exercised as part of the special processing of end (otherwise, it would have been printed after the hbox command had been digested by TeX, according to the TeXbook p. 282). However, the conjunction of p=0 and c=0 at the end of that line implies that TeX sees no reason to break a new page at the best breakpoint seen so far (marked with #: first legal breakpoint here). Indeed, remember paragraph 2 of page 112:




          If the resulting c is less than or equal to the smallest cost seen so far on the current page, TeX remembers the current breakpoint as the best so far. And if c = ∞ or if p ≤ −10000, TeX seizes the initiative and breaks the page at the best remembered breakpoint.




          (the last “if” is most probably an “if and only if”). The topskip breakpoint being a glue item, its associated p value is 0; since the insertion is exactly vsize high, breaking at this topskip item would cause a page badness equal to zero (b=0), therefore the cost c associated with the first breakpoint is indeed c=0 according to the b + p + q expression from page 111 (insertpenalties is zero after the insert).



          So, after putting the topskip glue on the “current page” due to the special end processing and computing the cost associated with this potential breakpoint, TeX is still waiting for more material before deciding that a page break has to happen. So, it takes the next items inserted in “recent contributions” by end, and moves them one by one to the “current page”. The hbox isn't a breakpoint, it is simply moved; the vfill is also moved—there is no reason to discard it—and is a legal breakpoint, since it is preceded by a non-discardable item (the hbox). The page builder computes its associated cost:



          % t=10.0 g=0.0 b=* p=0 c=*


          This line being printed for a glue item, the associated p value is 0, thus p < 10000. Because of the topskip glue item (10 points) and the empty hbox, breaking at the vfill glue item would cause an overfull page, hence b=* and the computed cost c=*. This decides TeX to break the page at the best remembered breakpoint (the topskip) and finally invoke the output routine for page 1:



          output->plainoutput 

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)


          So, you get a second page containing the (new) topskip glue item, an empty hbox equivalent to line and another glue item from vfill (all wrapped in two vboxes: one from plainoutput and one from pagebody).



          You would like to do something to shipout page 1 after the insertion, but before end added the equivalent of line vfill penalty-'10000000000, right? First idea: append a penalty after the insert that forces page breaking, e.g., with break (which is equivalent to penalty -10000). Alas, this doesn't work because:



          1. A penalty seen in vertical mode causes TeX to exercise the page builder (TeXbook p. 280), and therefore to try to move things from the “recent contributions” to the “current page”.



          2. This sentence from p. 112 of the TeXbook:




            Whenever TeX is moving an item from the top of the “recent contributions” to the bottom of the “current page,” it discards a discardable item (glue, kern, or penalty) if the current page does not contain any boxes.




            which is the case here (the insertion item on the “current page” isn't a box item).



          Indeed, if we try:



          tracingonline=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          break
          showlists
          end


          we get to see:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:5: OK.
          l.5 showlists


          As before, the “current page” has the insertion at the point where showlists is executed, but the penalty has been discarded, as could be guessed from the previous quote. Compare this with:



          tracingonline=1
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          topskip=0ptnullpenalty100
          showlists
          end


          which gives:



          %% goal height=643.20255, max depth=4.0
          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=0.0 g=0.0 b=0 p=100 c=100

          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          glue(topskip) 0.0
          hbox(0.0+0.0)x0.0
          penalty 100
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth 0.0


          Because of the null (an empty hbox), the penalty wasn't discarded this time; it got onto the current page and was noted as being a legal breakpoint (t=0.0 g=0.0 b=0 p=100 c=100), though not the best seen so far (that one has the trailing #). And thanks to the topskip=0pt, we got all this on page 1 (with a positive topskip, we would have had c = ∞ for the penalty100 breakpoint, thus again a page break at the topskip glue, then a second page). With topskip=0pt, the insertion, the topskip glue and the null box all fit on the first page. Therefore, all we need to do in order to get only one page of output as you probably wanted, is to trigger a page break after the null box. We can do this using a penalty, which won't be discarded this time since there is already a box on the “current page list.” Here we go:



          tracingonline=1
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          topskip=0ptnullbreak
          end


          which gives the following output:



          %% goal height=643.20255, max depth=4.0
          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=0.0 g=0.0 b=0 p=-10000 c=-10000#
          [1] )
          Output written on insert.pdf (1 page, 968 bytes).
          Transcript written on insert.log.

          TeX Output finished at Mon Jul 8 10:11:58


          One page of output, broken at the penalty -10000 from our break.




          Footnotes




          1. We are precisely in the case described page 114 of the TeXbook:




            If insertions occur before the first box, the topskip glue before that box is considered to be a valid breakpoint; this is the only case in which a completed page might not contain a box.




          2. This can be verified with code such as output=expandaftertheoutputglobaltopskip=6pt inserted before end and watching the TeX messages printed with tracingonline=1tracingpages=1tracingoutput=1relax (idea from Igor).



          3. Paragraph 2 of the TeXbook p. 122 gives the conditions in which the page builder is exercised:




            TeX is liable to invoke an output routine whenever it tries to move something from the list of recent contributions to the current page, because it might discover a page break with c = ∞ then. Here is a list of the times when that can happen: (a) At the beginning or end of a paragraph, provided that this paragraph is being contributed to the main vertical list. (b) At the beginning or end of a displayed equation within such a paragraph. (c) After completing an halign in vertical mode. (d) After contributing a box or penalty or insertion to the main vertical list. (e) After an output routine has ended.








          share|improve this answer

























          • There is an error in your answer: "It is this precise topskip that decides TeX to finally call the output routine for page 1: % t=10.0 g=0.0 b=* p=0 c=* ...". In fact, topskip decides here: % t=0.0 g=0.0 b=0 p=0 c=0#. % t=10.0 g=0.0 b=* p=0 c=* is decided by vfill. See p.113.

            – Igor Liferenko
            Jul 9 at 5:41











          • I stand by my assertion: the topskip causes 10 points “two much material” on the page (t=10.0 g=0.0); this explains the c=* which causes TeX to say “Oh, it's time to break a new page, let's find the best breakpoint we've seen so far and rewind.” The # marks the best breakpoint seen so far, and it is the topskip as show by the t=0.0 on the line ending with #. AFAICT, the vfill is not seen at all while processing page 1 of the original example.

            – frougon
            Jul 9 at 5:50












          • Please read this sentence on p.113: "However, the % lines are generated by the penalty or glue items that follow the hboxes, not by the boxes themselves." This means that the first % can be caused only by glue (and this is confirmed by the fact that showlists is between %% and %). And the glue is, of course, topskip. It causes the first % line. Then comes empty hbox, which stands 10pt lower. Next % can be caused also only by glue. And that glue is vfill.

            – Igor Liferenko
            Jul 9 at 5:57











          • (was too long to add to the previous comment) The breakpoint itself doesn't stay on the page that is about to be finished: TeX always breaks “right before the chosen breakpoint”; that is why the line ending with # has t=0.0 instead of t=10.0.

            – frougon
            Jul 9 at 5:58











          • BTW, it's possible to see that old topskip is indeed discarded and new topskip is used by adding this before end: topskip=5ptoutput=expandaftertheoutputglobaltopskip=6pt

            – Igor Liferenko
            Jul 9 at 6:05













          4












          4








          4







          I'll try to explain this using quotes from the TeXbook.



          Summary



          When the main vertical list isn't empty at the point where the end token is digested, TeX inserts the equivalent of linevfillpenalty-'10000000000 into the main vertical list, exercises the page builder and prepares to read end again (TeXbook pp. 264 and 283). In your example, this line brings the first box to the main vertical list, because the insertion item is not a box item. As a consequence, TeX prepends topskip glue to this box, which is 10pt here. This topskip glue is a valid breakpoint because it is immediately preceded by the insertion item; the associated cost is zero. The next legal breakpoint is the vfill glue following the hbox that corresponds to the aforementioned line. The cost associated with this vfill glue is infinite because the associated penalty is zero and the page would be overfull should a break occur at the vfill item (i.e., b = ∞; this is because the insertion plus the topskip glue plus the empty hbox are 10 points too high in total to fit on the page). Therefore TeX breaks a new page at the best breakpoint seen so far, which is the topskip glue. Thus, page 1 only contains material from the insertion (the output routine wraps this material inside two vboxes). Page 2 contains a new topskip glue item, the empty hbox and the vfill glue item.



          Analysis



          As said above, if the main vertical list isn't empty at the point where the end token is digested, TeX inserts the equivalent of linevfillpenalty-'10000000000 into the main vertical list, exercises the page builder and prepares to read end again. In your example, this brings 10 points of topskip glue followed by an empty hbox to hsize onto the current page (among others). In this particular case, the topskip glue item is a valid breakpoint1 and TeX immediately computes the associated cost (remember that it is exercising the page builder as part of the special end processing); it finds that this cost is zero, because the insertion is exactly vsize high. Thus, the conditions for starting a new page are not fulfilled yet (TeXbook p. 112, § 2).



          Therefore, TeX continues with the implicitly-added items. After the empty hbox comes the vfill glue: it moves these two items from “recent contributions” to the “current page” list. The hbox is not a legal breakpoint, but the vfill item is, since it is immediately preceded by a non-discardable item (the hbox). TeX computes the cost c associated with this second legal breakpoint and finds c = ∞, because there is 10pt material in excess on the current page, up to and excluding the breakpoint (the page goal was decreased by vsize and became 0pt when the insertion item was moved to the “current page,” and the page total went from 0pt to 10pt with the topskip glue and remained unchanged after the empty hbox). According to the rules given on p. 112 of the TeXbook, this causes TeX to decide that it is time to break a new page at the best remembered breakpoint, which is the one at the topskip glue (associated cost: 0).



          This glue item from topskip, the empty hbox and the vfill glue item are thus all put back at the top of the “recent contributions” list, followed by the penalty-'10000000000 item that has been waiting there all the time since end inserted it (cf. long paragraph p. 125). Since holdinginserts is 0 by default, the insertion item is then removed from the “current page,” its contents is appended to boxtopins with no interline glue, the items remaining on the “current page” (none here!) are put together in box255, and finally the output routine is invoked and ships out page 1.



          Then TeX starts page 2. The first thing it does is to exercise the page builder, since an output routine has just ended (cf. p. 122, § 2, item (e), reproduced in footnote 3). So, TeX tries to move items from “recent contributions” to the “current page.” The glue item from topskip that was put back at the top of the “recent contributions” is discarded at this occasion (there is no box yet on the “current page”) and immediately replaced by a new topskip glue item,2 since the hbox item that follows it will be the first box on the current page. TeX moves this box to the current page, followed by the vfill glue item and the penalty-'10000000000. The vfill glue is a legal breakpoint, but it doesn't fulfill the conditions given p. 112 for finishing the page (the associated values are p=0 and c=100000). The penalty item that follows, on the other hand, does fulfill them (p ≤ −10000).



          All remaining items except the breakpoint, namely the penalty-'10000000000, thus went on page 2. This penalty item is changed into a penalty10000 and put back at the top of the “recent contributions” (TeXbook p. 125), but immediately discarded as the page builder is exercised (again due to § 2 of p. 122, item (e), as reproduced in footnote 3). Because of this, the main vertical list is finally empty and since the output routine executed shipout for page 2, deadcycles is 0 when TeX sees end for the second time. According to the TeXbook p. 283, this terminates the job.



          Confirmation of the analysis with experiments



          TeXbook p. 264:




          When TeX sees an end command, it terminates the job only if the main vertical list has been entirely output and if deadcycles=0. Otherwise it inserts the equivalent of



          line vfill penalty-'10000000000


          into the main vertical list, and prepares to read the end token again.




          Notes:



          • This corresponds to the code posted by David Carlisle.


          • On page 283, Knuth adds the precision that the page builder is exercised after the aforementioned box/glue/penalty combination has been added to the main vertical list.


          We can show that in your example, TeX sees the end token before the main vertical list has been emptied. In order to do this, insert showlists before end in your example and you'll see:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:5: OK.
          l.5 showlists


          In contrast, if you insert nullbreakshowlists before end, you'll see:



          ### vertical mode entered at line 0
          prevdepth 0.0

          ./insert.tex:5: OK.
          l.5 nullbreakshowlists


          That is an empty vertical list (displayed after page 1 and an underfull page 2 have been shipped out). So, getting back to your example: when TeX sees end, it doesn't consider yet that the page is full (it would indeed be possible to “rewind” using a box followed by negative kerns or skips), so it doesn't call the output routine yet. We can insert some more diagnostic tools to confirm the precisions I added here:



          tracingonline=1
          tracingoutput=1
          tracingmacros=2
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          showlists
          end


          which prints:



          %% goal height=643.20255, max depth=4.0

          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:7: OK.
          l.7 showlists

          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=10.0 g=0.0 b=* p=0 c=*
          output->plainoutput

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)

          Completed box being shipped out [1]
          vbox(643.20255+0.0)x300.0
          .vbox(643.20255+0.0)x300.0
          ..vbox(643.20255+0.0)x300.0
          ...rule(643.20255+0.0)x300.0


          advancepageno ->ifnum pageno <z@ global advance pageno m@ne else global advance pageno @ne fi
          %% goal height=643.20255, max depth=4.0
          % t=10.0 g=643.20255 b=10000 p=0 c=100000#
          % t=10.0 plus 1.0fill g=643.20255 b=0 p=-1073741824 c=-1073741824#
          output->plainoutput

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)

          Completed box being shipped out [2]
          vbox(643.20255+0.0)x469.75499
          .vbox(643.20255+0.0)x469.75499, glue set 633.20255fill
          ..glue(topskip) 10.0
          ..hbox(0.0+0.0)x469.75499
          ..glue 0.0 plus 1.0fill


          The %% goal height=643.20255, max depth=4.0 line is printed when




          the first box or insertion enters the current page list




          (TeXbook p. 113). This is your insert, okay. Right after that, showlists indeed shows this insert on the current page:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0

          (...)



          This is because, according to the TeXbook p. 281:




          TeX also exercises the page builder (see below), after an insert has been appended in vertical mode.




          So, the page builder has been exercised before TeX even read showlists. The insert has been moved right away from the “recent contributions” to the “current page.” But TeX doesn't consider yet that the page has to be finished, it won't invoke the output routine yet! Indeed, remember what comes next in the log:



          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=10.0 g=0.0 b=* p=0 c=*
          output->plainoutput


          The first line with g=0 clearly shows that the insert has been put on the current page, otherwise the page goal would still be 643.20255 points. Now, remember what is said in the TeXbook p. 114:




          TeX inserts special glue just before the first box on each page. This special glue is equal to topskip, except that the natural space has been decreased by the height of the first box, or it has been set to zero in lieu of a negative value.




          The % t=0.0 g=0.0 b=0 p=0 c=0# line corresponds to the topskip glue automatically inserted before the box equivalent to line. It is a legal breakpoint because of the quote from footnote 1 below, and was printed when the page builder was exercised as part of the special processing of end (otherwise, it would have been printed after the hbox command had been digested by TeX, according to the TeXbook p. 282). However, the conjunction of p=0 and c=0 at the end of that line implies that TeX sees no reason to break a new page at the best breakpoint seen so far (marked with #: first legal breakpoint here). Indeed, remember paragraph 2 of page 112:




          If the resulting c is less than or equal to the smallest cost seen so far on the current page, TeX remembers the current breakpoint as the best so far. And if c = ∞ or if p ≤ −10000, TeX seizes the initiative and breaks the page at the best remembered breakpoint.




          (the last “if” is most probably an “if and only if”). The topskip breakpoint being a glue item, its associated p value is 0; since the insertion is exactly vsize high, breaking at this topskip item would cause a page badness equal to zero (b=0), therefore the cost c associated with the first breakpoint is indeed c=0 according to the b + p + q expression from page 111 (insertpenalties is zero after the insert).



          So, after putting the topskip glue on the “current page” due to the special end processing and computing the cost associated with this potential breakpoint, TeX is still waiting for more material before deciding that a page break has to happen. So, it takes the next items inserted in “recent contributions” by end, and moves them one by one to the “current page”. The hbox isn't a breakpoint, it is simply moved; the vfill is also moved—there is no reason to discard it—and is a legal breakpoint, since it is preceded by a non-discardable item (the hbox). The page builder computes its associated cost:



          % t=10.0 g=0.0 b=* p=0 c=*


          This line being printed for a glue item, the associated p value is 0, thus p < 10000. Because of the topskip glue item (10 points) and the empty hbox, breaking at the vfill glue item would cause an overfull page, hence b=* and the computed cost c=*. This decides TeX to break the page at the best remembered breakpoint (the topskip) and finally invoke the output routine for page 1:



          output->plainoutput 

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)


          So, you get a second page containing the (new) topskip glue item, an empty hbox equivalent to line and another glue item from vfill (all wrapped in two vboxes: one from plainoutput and one from pagebody).



          You would like to do something to shipout page 1 after the insertion, but before end added the equivalent of line vfill penalty-'10000000000, right? First idea: append a penalty after the insert that forces page breaking, e.g., with break (which is equivalent to penalty -10000). Alas, this doesn't work because:



          1. A penalty seen in vertical mode causes TeX to exercise the page builder (TeXbook p. 280), and therefore to try to move things from the “recent contributions” to the “current page”.



          2. This sentence from p. 112 of the TeXbook:




            Whenever TeX is moving an item from the top of the “recent contributions” to the bottom of the “current page,” it discards a discardable item (glue, kern, or penalty) if the current page does not contain any boxes.




            which is the case here (the insertion item on the “current page” isn't a box item).



          Indeed, if we try:



          tracingonline=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          break
          showlists
          end


          we get to see:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:5: OK.
          l.5 showlists


          As before, the “current page” has the insertion at the point where showlists is executed, but the penalty has been discarded, as could be guessed from the previous quote. Compare this with:



          tracingonline=1
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          topskip=0ptnullpenalty100
          showlists
          end


          which gives:



          %% goal height=643.20255, max depth=4.0
          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=0.0 g=0.0 b=0 p=100 c=100

          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          glue(topskip) 0.0
          hbox(0.0+0.0)x0.0
          penalty 100
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth 0.0


          Because of the null (an empty hbox), the penalty wasn't discarded this time; it got onto the current page and was noted as being a legal breakpoint (t=0.0 g=0.0 b=0 p=100 c=100), though not the best seen so far (that one has the trailing #). And thanks to the topskip=0pt, we got all this on page 1 (with a positive topskip, we would have had c = ∞ for the penalty100 breakpoint, thus again a page break at the topskip glue, then a second page). With topskip=0pt, the insertion, the topskip glue and the null box all fit on the first page. Therefore, all we need to do in order to get only one page of output as you probably wanted, is to trigger a page break after the null box. We can do this using a penalty, which won't be discarded this time since there is already a box on the “current page list.” Here we go:



          tracingonline=1
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          topskip=0ptnullbreak
          end


          which gives the following output:



          %% goal height=643.20255, max depth=4.0
          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=0.0 g=0.0 b=0 p=-10000 c=-10000#
          [1] )
          Output written on insert.pdf (1 page, 968 bytes).
          Transcript written on insert.log.

          TeX Output finished at Mon Jul 8 10:11:58


          One page of output, broken at the penalty -10000 from our break.




          Footnotes




          1. We are precisely in the case described page 114 of the TeXbook:




            If insertions occur before the first box, the topskip glue before that box is considered to be a valid breakpoint; this is the only case in which a completed page might not contain a box.




          2. This can be verified with code such as output=expandaftertheoutputglobaltopskip=6pt inserted before end and watching the TeX messages printed with tracingonline=1tracingpages=1tracingoutput=1relax (idea from Igor).



          3. Paragraph 2 of the TeXbook p. 122 gives the conditions in which the page builder is exercised:




            TeX is liable to invoke an output routine whenever it tries to move something from the list of recent contributions to the current page, because it might discover a page break with c = ∞ then. Here is a list of the times when that can happen: (a) At the beginning or end of a paragraph, provided that this paragraph is being contributed to the main vertical list. (b) At the beginning or end of a displayed equation within such a paragraph. (c) After completing an halign in vertical mode. (d) After contributing a box or penalty or insertion to the main vertical list. (e) After an output routine has ended.








          share|improve this answer















          I'll try to explain this using quotes from the TeXbook.



          Summary



          When the main vertical list isn't empty at the point where the end token is digested, TeX inserts the equivalent of linevfillpenalty-'10000000000 into the main vertical list, exercises the page builder and prepares to read end again (TeXbook pp. 264 and 283). In your example, this line brings the first box to the main vertical list, because the insertion item is not a box item. As a consequence, TeX prepends topskip glue to this box, which is 10pt here. This topskip glue is a valid breakpoint because it is immediately preceded by the insertion item; the associated cost is zero. The next legal breakpoint is the vfill glue following the hbox that corresponds to the aforementioned line. The cost associated with this vfill glue is infinite because the associated penalty is zero and the page would be overfull should a break occur at the vfill item (i.e., b = ∞; this is because the insertion plus the topskip glue plus the empty hbox are 10 points too high in total to fit on the page). Therefore TeX breaks a new page at the best breakpoint seen so far, which is the topskip glue. Thus, page 1 only contains material from the insertion (the output routine wraps this material inside two vboxes). Page 2 contains a new topskip glue item, the empty hbox and the vfill glue item.



          Analysis



          As said above, if the main vertical list isn't empty at the point where the end token is digested, TeX inserts the equivalent of linevfillpenalty-'10000000000 into the main vertical list, exercises the page builder and prepares to read end again. In your example, this brings 10 points of topskip glue followed by an empty hbox to hsize onto the current page (among others). In this particular case, the topskip glue item is a valid breakpoint1 and TeX immediately computes the associated cost (remember that it is exercising the page builder as part of the special end processing); it finds that this cost is zero, because the insertion is exactly vsize high. Thus, the conditions for starting a new page are not fulfilled yet (TeXbook p. 112, § 2).



          Therefore, TeX continues with the implicitly-added items. After the empty hbox comes the vfill glue: it moves these two items from “recent contributions” to the “current page” list. The hbox is not a legal breakpoint, but the vfill item is, since it is immediately preceded by a non-discardable item (the hbox). TeX computes the cost c associated with this second legal breakpoint and finds c = ∞, because there is 10pt material in excess on the current page, up to and excluding the breakpoint (the page goal was decreased by vsize and became 0pt when the insertion item was moved to the “current page,” and the page total went from 0pt to 10pt with the topskip glue and remained unchanged after the empty hbox). According to the rules given on p. 112 of the TeXbook, this causes TeX to decide that it is time to break a new page at the best remembered breakpoint, which is the one at the topskip glue (associated cost: 0).



          This glue item from topskip, the empty hbox and the vfill glue item are thus all put back at the top of the “recent contributions” list, followed by the penalty-'10000000000 item that has been waiting there all the time since end inserted it (cf. long paragraph p. 125). Since holdinginserts is 0 by default, the insertion item is then removed from the “current page,” its contents is appended to boxtopins with no interline glue, the items remaining on the “current page” (none here!) are put together in box255, and finally the output routine is invoked and ships out page 1.



          Then TeX starts page 2. The first thing it does is to exercise the page builder, since an output routine has just ended (cf. p. 122, § 2, item (e), reproduced in footnote 3). So, TeX tries to move items from “recent contributions” to the “current page.” The glue item from topskip that was put back at the top of the “recent contributions” is discarded at this occasion (there is no box yet on the “current page”) and immediately replaced by a new topskip glue item,2 since the hbox item that follows it will be the first box on the current page. TeX moves this box to the current page, followed by the vfill glue item and the penalty-'10000000000. The vfill glue is a legal breakpoint, but it doesn't fulfill the conditions given p. 112 for finishing the page (the associated values are p=0 and c=100000). The penalty item that follows, on the other hand, does fulfill them (p ≤ −10000).



          All remaining items except the breakpoint, namely the penalty-'10000000000, thus went on page 2. This penalty item is changed into a penalty10000 and put back at the top of the “recent contributions” (TeXbook p. 125), but immediately discarded as the page builder is exercised (again due to § 2 of p. 122, item (e), as reproduced in footnote 3). Because of this, the main vertical list is finally empty and since the output routine executed shipout for page 2, deadcycles is 0 when TeX sees end for the second time. According to the TeXbook p. 283, this terminates the job.



          Confirmation of the analysis with experiments



          TeXbook p. 264:




          When TeX sees an end command, it terminates the job only if the main vertical list has been entirely output and if deadcycles=0. Otherwise it inserts the equivalent of



          line vfill penalty-'10000000000


          into the main vertical list, and prepares to read the end token again.




          Notes:



          • This corresponds to the code posted by David Carlisle.


          • On page 283, Knuth adds the precision that the page builder is exercised after the aforementioned box/glue/penalty combination has been added to the main vertical list.


          We can show that in your example, TeX sees the end token before the main vertical list has been emptied. In order to do this, insert showlists before end in your example and you'll see:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:5: OK.
          l.5 showlists


          In contrast, if you insert nullbreakshowlists before end, you'll see:



          ### vertical mode entered at line 0
          prevdepth 0.0

          ./insert.tex:5: OK.
          l.5 nullbreakshowlists


          That is an empty vertical list (displayed after page 1 and an underfull page 2 have been shipped out). So, getting back to your example: when TeX sees end, it doesn't consider yet that the page is full (it would indeed be possible to “rewind” using a box followed by negative kerns or skips), so it doesn't call the output routine yet. We can insert some more diagnostic tools to confirm the precisions I added here:



          tracingonline=1
          tracingoutput=1
          tracingmacros=2
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          showlists
          end


          which prints:



          %% goal height=643.20255, max depth=4.0

          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:7: OK.
          l.7 showlists

          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=10.0 g=0.0 b=* p=0 c=*
          output->plainoutput

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)

          Completed box being shipped out [1]
          vbox(643.20255+0.0)x300.0
          .vbox(643.20255+0.0)x300.0
          ..vbox(643.20255+0.0)x300.0
          ...rule(643.20255+0.0)x300.0


          advancepageno ->ifnum pageno <z@ global advance pageno m@ne else global advance pageno @ne fi
          %% goal height=643.20255, max depth=4.0
          % t=10.0 g=643.20255 b=10000 p=0 c=100000#
          % t=10.0 plus 1.0fill g=643.20255 b=0 p=-1073741824 c=-1073741824#
          output->plainoutput

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)

          Completed box being shipped out [2]
          vbox(643.20255+0.0)x469.75499
          .vbox(643.20255+0.0)x469.75499, glue set 633.20255fill
          ..glue(topskip) 10.0
          ..hbox(0.0+0.0)x469.75499
          ..glue 0.0 plus 1.0fill


          The %% goal height=643.20255, max depth=4.0 line is printed when




          the first box or insertion enters the current page list




          (TeXbook p. 113). This is your insert, okay. Right after that, showlists indeed shows this insert on the current page:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0

          (...)



          This is because, according to the TeXbook p. 281:




          TeX also exercises the page builder (see below), after an insert has been appended in vertical mode.




          So, the page builder has been exercised before TeX even read showlists. The insert has been moved right away from the “recent contributions” to the “current page.” But TeX doesn't consider yet that the page has to be finished, it won't invoke the output routine yet! Indeed, remember what comes next in the log:



          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=10.0 g=0.0 b=* p=0 c=*
          output->plainoutput


          The first line with g=0 clearly shows that the insert has been put on the current page, otherwise the page goal would still be 643.20255 points. Now, remember what is said in the TeXbook p. 114:




          TeX inserts special glue just before the first box on each page. This special glue is equal to topskip, except that the natural space has been decreased by the height of the first box, or it has been set to zero in lieu of a negative value.




          The % t=0.0 g=0.0 b=0 p=0 c=0# line corresponds to the topskip glue automatically inserted before the box equivalent to line. It is a legal breakpoint because of the quote from footnote 1 below, and was printed when the page builder was exercised as part of the special processing of end (otherwise, it would have been printed after the hbox command had been digested by TeX, according to the TeXbook p. 282). However, the conjunction of p=0 and c=0 at the end of that line implies that TeX sees no reason to break a new page at the best breakpoint seen so far (marked with #: first legal breakpoint here). Indeed, remember paragraph 2 of page 112:




          If the resulting c is less than or equal to the smallest cost seen so far on the current page, TeX remembers the current breakpoint as the best so far. And if c = ∞ or if p ≤ −10000, TeX seizes the initiative and breaks the page at the best remembered breakpoint.




          (the last “if” is most probably an “if and only if”). The topskip breakpoint being a glue item, its associated p value is 0; since the insertion is exactly vsize high, breaking at this topskip item would cause a page badness equal to zero (b=0), therefore the cost c associated with the first breakpoint is indeed c=0 according to the b + p + q expression from page 111 (insertpenalties is zero after the insert).



          So, after putting the topskip glue on the “current page” due to the special end processing and computing the cost associated with this potential breakpoint, TeX is still waiting for more material before deciding that a page break has to happen. So, it takes the next items inserted in “recent contributions” by end, and moves them one by one to the “current page”. The hbox isn't a breakpoint, it is simply moved; the vfill is also moved—there is no reason to discard it—and is a legal breakpoint, since it is preceded by a non-discardable item (the hbox). The page builder computes its associated cost:



          % t=10.0 g=0.0 b=* p=0 c=*


          This line being printed for a glue item, the associated p value is 0, thus p < 10000. Because of the topskip glue item (10 points) and the empty hbox, breaking at the vfill glue item would cause an overfull page, hence b=* and the computed cost c=*. This decides TeX to break the page at the best remembered breakpoint (the topskip) and finally invoke the output routine for page 1:



          output->plainoutput 

          plainoutput ->shipout vbox makeheadline pagebody makefootline advancepageno ifnum outputpenalty >-@MM else dosupereject fi

          (...)


          So, you get a second page containing the (new) topskip glue item, an empty hbox equivalent to line and another glue item from vfill (all wrapped in two vboxes: one from plainoutput and one from pagebody).



          You would like to do something to shipout page 1 after the insertion, but before end added the equivalent of line vfill penalty-'10000000000, right? First idea: append a penalty after the insert that forces page breaking, e.g., with break (which is equivalent to penalty -10000). Alas, this doesn't work because:



          1. A penalty seen in vertical mode causes TeX to exercise the page builder (TeXbook p. 280), and therefore to try to move things from the “recent contributions” to the “current page”.



          2. This sentence from p. 112 of the TeXbook:




            Whenever TeX is moving an item from the top of the “recent contributions” to the bottom of the “current page,” it discards a discardable item (glue, kern, or penalty) if the current page does not contain any boxes.




            which is the case here (the insertion item on the “current page” isn't a box item).



          Indeed, if we try:



          tracingonline=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          break
          showlists
          end


          we get to see:



          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth ignored

          ./insert.tex:5: OK.
          l.5 showlists


          As before, the “current page” has the insertion at the point where showlists is executed, but the penalty has been discarded, as could be guessed from the previous quote. Compare this with:



          tracingonline=1
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          topskip=0ptnullpenalty100
          showlists
          end


          which gives:



          %% goal height=643.20255, max depth=4.0
          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=0.0 g=0.0 b=0 p=100 c=100

          ### vertical mode entered at line 0
          ### current page:
          insert253, natural size 643.20255; split(10.0,16383.99998); float cost 0
          .vbox(643.20255+0.0)x300.0
          ..rule(643.20255+0.0)x300.0
          glue(topskip) 0.0
          hbox(0.0+0.0)x0.0
          penalty 100
          total height 0.0
          goal height 0.0
          insert253 adds 643.20255
          prevdepth 0.0


          Because of the null (an empty hbox), the penalty wasn't discarded this time; it got onto the current page and was noted as being a legal breakpoint (t=0.0 g=0.0 b=0 p=100 c=100), though not the best seen so far (that one has the trailing #). And thanks to the topskip=0pt, we got all this on page 1 (with a positive topskip, we would have had c = ∞ for the penalty100 breakpoint, thus again a page break at the topskip glue, then a second page). With topskip=0pt, the insertion, the topskip glue and the null box all fit on the first page. Therefore, all we need to do in order to get only one page of output as you probably wanted, is to trigger a page break after the null box. We can do this using a penalty, which won't be discarded this time since there is already a box on the “current page list.” Here we go:



          tracingonline=1
          tracingpages=1
          gdefmakefootline gdefmakeheadline
          inserttopinsvbox tovsizehrule height vsize width 300pt
          topskip=0ptnullbreak
          end


          which gives the following output:



          %% goal height=643.20255, max depth=4.0
          % t=0.0 g=0.0 b=0 p=0 c=0#
          % t=0.0 g=0.0 b=0 p=-10000 c=-10000#
          [1] )
          Output written on insert.pdf (1 page, 968 bytes).
          Transcript written on insert.log.

          TeX Output finished at Mon Jul 8 10:11:58


          One page of output, broken at the penalty -10000 from our break.




          Footnotes




          1. We are precisely in the case described page 114 of the TeXbook:




            If insertions occur before the first box, the topskip glue before that box is considered to be a valid breakpoint; this is the only case in which a completed page might not contain a box.




          2. This can be verified with code such as output=expandaftertheoutputglobaltopskip=6pt inserted before end and watching the TeX messages printed with tracingonline=1tracingpages=1tracingoutput=1relax (idea from Igor).



          3. Paragraph 2 of the TeXbook p. 122 gives the conditions in which the page builder is exercised:




            TeX is liable to invoke an output routine whenever it tries to move something from the list of recent contributions to the current page, because it might discover a page break with c = ∞ then. Here is a list of the times when that can happen: (a) At the beginning or end of a paragraph, provided that this paragraph is being contributed to the main vertical list. (b) At the beginning or end of a displayed equation within such a paragraph. (c) After completing an halign in vertical mode. (d) After contributing a box or penalty or insertion to the main vertical list. (e) After an output routine has ended.









          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jul 10 at 7:30

























          answered Jul 8 at 8:47









          frougonfrougon

          4,9621 gold badge10 silver badges20 bronze badges




          4,9621 gold badge10 silver badges20 bronze badges












          • There is an error in your answer: "It is this precise topskip that decides TeX to finally call the output routine for page 1: % t=10.0 g=0.0 b=* p=0 c=* ...". In fact, topskip decides here: % t=0.0 g=0.0 b=0 p=0 c=0#. % t=10.0 g=0.0 b=* p=0 c=* is decided by vfill. See p.113.

            – Igor Liferenko
            Jul 9 at 5:41











          • I stand by my assertion: the topskip causes 10 points “two much material” on the page (t=10.0 g=0.0); this explains the c=* which causes TeX to say “Oh, it's time to break a new page, let's find the best breakpoint we've seen so far and rewind.” The # marks the best breakpoint seen so far, and it is the topskip as show by the t=0.0 on the line ending with #. AFAICT, the vfill is not seen at all while processing page 1 of the original example.

            – frougon
            Jul 9 at 5:50












          • Please read this sentence on p.113: "However, the % lines are generated by the penalty or glue items that follow the hboxes, not by the boxes themselves." This means that the first % can be caused only by glue (and this is confirmed by the fact that showlists is between %% and %). And the glue is, of course, topskip. It causes the first % line. Then comes empty hbox, which stands 10pt lower. Next % can be caused also only by glue. And that glue is vfill.

            – Igor Liferenko
            Jul 9 at 5:57











          • (was too long to add to the previous comment) The breakpoint itself doesn't stay on the page that is about to be finished: TeX always breaks “right before the chosen breakpoint”; that is why the line ending with # has t=0.0 instead of t=10.0.

            – frougon
            Jul 9 at 5:58











          • BTW, it's possible to see that old topskip is indeed discarded and new topskip is used by adding this before end: topskip=5ptoutput=expandaftertheoutputglobaltopskip=6pt

            – Igor Liferenko
            Jul 9 at 6:05

















          • There is an error in your answer: "It is this precise topskip that decides TeX to finally call the output routine for page 1: % t=10.0 g=0.0 b=* p=0 c=* ...". In fact, topskip decides here: % t=0.0 g=0.0 b=0 p=0 c=0#. % t=10.0 g=0.0 b=* p=0 c=* is decided by vfill. See p.113.

            – Igor Liferenko
            Jul 9 at 5:41











          • I stand by my assertion: the topskip causes 10 points “two much material” on the page (t=10.0 g=0.0); this explains the c=* which causes TeX to say “Oh, it's time to break a new page, let's find the best breakpoint we've seen so far and rewind.” The # marks the best breakpoint seen so far, and it is the topskip as show by the t=0.0 on the line ending with #. AFAICT, the vfill is not seen at all while processing page 1 of the original example.

            – frougon
            Jul 9 at 5:50












          • Please read this sentence on p.113: "However, the % lines are generated by the penalty or glue items that follow the hboxes, not by the boxes themselves." This means that the first % can be caused only by glue (and this is confirmed by the fact that showlists is between %% and %). And the glue is, of course, topskip. It causes the first % line. Then comes empty hbox, which stands 10pt lower. Next % can be caused also only by glue. And that glue is vfill.

            – Igor Liferenko
            Jul 9 at 5:57











          • (was too long to add to the previous comment) The breakpoint itself doesn't stay on the page that is about to be finished: TeX always breaks “right before the chosen breakpoint”; that is why the line ending with # has t=0.0 instead of t=10.0.

            – frougon
            Jul 9 at 5:58











          • BTW, it's possible to see that old topskip is indeed discarded and new topskip is used by adding this before end: topskip=5ptoutput=expandaftertheoutputglobaltopskip=6pt

            – Igor Liferenko
            Jul 9 at 6:05
















          There is an error in your answer: "It is this precise topskip that decides TeX to finally call the output routine for page 1: % t=10.0 g=0.0 b=* p=0 c=* ...". In fact, topskip decides here: % t=0.0 g=0.0 b=0 p=0 c=0#. % t=10.0 g=0.0 b=* p=0 c=* is decided by vfill. See p.113.

          – Igor Liferenko
          Jul 9 at 5:41





          There is an error in your answer: "It is this precise topskip that decides TeX to finally call the output routine for page 1: % t=10.0 g=0.0 b=* p=0 c=* ...". In fact, topskip decides here: % t=0.0 g=0.0 b=0 p=0 c=0#. % t=10.0 g=0.0 b=* p=0 c=* is decided by vfill. See p.113.

          – Igor Liferenko
          Jul 9 at 5:41













          I stand by my assertion: the topskip causes 10 points “two much material” on the page (t=10.0 g=0.0); this explains the c=* which causes TeX to say “Oh, it's time to break a new page, let's find the best breakpoint we've seen so far and rewind.” The # marks the best breakpoint seen so far, and it is the topskip as show by the t=0.0 on the line ending with #. AFAICT, the vfill is not seen at all while processing page 1 of the original example.

          – frougon
          Jul 9 at 5:50






          I stand by my assertion: the topskip causes 10 points “two much material” on the page (t=10.0 g=0.0); this explains the c=* which causes TeX to say “Oh, it's time to break a new page, let's find the best breakpoint we've seen so far and rewind.” The # marks the best breakpoint seen so far, and it is the topskip as show by the t=0.0 on the line ending with #. AFAICT, the vfill is not seen at all while processing page 1 of the original example.

          – frougon
          Jul 9 at 5:50














          Please read this sentence on p.113: "However, the % lines are generated by the penalty or glue items that follow the hboxes, not by the boxes themselves." This means that the first % can be caused only by glue (and this is confirmed by the fact that showlists is between %% and %). And the glue is, of course, topskip. It causes the first % line. Then comes empty hbox, which stands 10pt lower. Next % can be caused also only by glue. And that glue is vfill.

          – Igor Liferenko
          Jul 9 at 5:57





          Please read this sentence on p.113: "However, the % lines are generated by the penalty or glue items that follow the hboxes, not by the boxes themselves." This means that the first % can be caused only by glue (and this is confirmed by the fact that showlists is between %% and %). And the glue is, of course, topskip. It causes the first % line. Then comes empty hbox, which stands 10pt lower. Next % can be caused also only by glue. And that glue is vfill.

          – Igor Liferenko
          Jul 9 at 5:57













          (was too long to add to the previous comment) The breakpoint itself doesn't stay on the page that is about to be finished: TeX always breaks “right before the chosen breakpoint”; that is why the line ending with # has t=0.0 instead of t=10.0.

          – frougon
          Jul 9 at 5:58





          (was too long to add to the previous comment) The breakpoint itself doesn't stay on the page that is about to be finished: TeX always breaks “right before the chosen breakpoint”; that is why the line ending with # has t=0.0 instead of t=10.0.

          – frougon
          Jul 9 at 5:58













          BTW, it's possible to see that old topskip is indeed discarded and new topskip is used by adding this before end: topskip=5ptoutput=expandaftertheoutputglobaltopskip=6pt

          – Igor Liferenko
          Jul 9 at 6:05





          BTW, it's possible to see that old topskip is indeed discarded and new topskip is used by adding this before end: topskip=5ptoutput=expandaftertheoutputglobaltopskip=6pt

          – Igor Liferenko
          Jul 9 at 6:05













          4














          It is tex-the-program's final endgame to flush out the insert:



          tex.web has



          @ We don't want to leave |main_control| immediately when a |stop| command
          is sensed, because it may be necessary to invoke an .\output routine
          several times before things really grind to a halt. (The output routine
          might even say `.\gdef\end...', to prolong the life of the job.)
          Therefore |its_all_over| is |true| only when the current page
          and contribution list are empty, and when the last output was not a
          ``dead cycle.''

          @<Declare act...@>=
          function its_all_over:boolean; do this when .\end or .\dump occurs
          label exit;
          begin if privileged then
          begin if (page_head=page_tail)and(head=tail)and(dead_cycles=0) then
          begin its_all_over:=true; return;
          end;
          back_input; we will try to end again after ejecting residual material
          tail_append(new_null_box);
          width(tail):=hsize;
          tail_append(new_glue(fill_glue));
          tail_append(new_penalty(-@'10000000000));@/
          build_page; append .\hbox to \hsize\vfill\penalty-'10000000000
          ^^^^^^^^^^^^^^^^^^^^^^
          end;
          its_all_over:=false;
          exit:end;





          share|improve this answer























          • This is mentioned on p.264 of TeXbook. I guess the meaning is that if insert which occupies the whole page is used, there has to be some additional text, so second page is inevitable. Still, I'm not sure I completely understand how the explanation on p.264 applies to OP.

            – Igor Liferenko
            Jul 8 at 7:26











          • @IgorLiferenko in your case when it hits end the main vertical list is not empty (there is an insert node left) so the clause on page 262 means the the line is added and end is called again

            – David Carlisle
            Jul 8 at 7:50















          4














          It is tex-the-program's final endgame to flush out the insert:



          tex.web has



          @ We don't want to leave |main_control| immediately when a |stop| command
          is sensed, because it may be necessary to invoke an .\output routine
          several times before things really grind to a halt. (The output routine
          might even say `.\gdef\end...', to prolong the life of the job.)
          Therefore |its_all_over| is |true| only when the current page
          and contribution list are empty, and when the last output was not a
          ``dead cycle.''

          @<Declare act...@>=
          function its_all_over:boolean; do this when .\end or .\dump occurs
          label exit;
          begin if privileged then
          begin if (page_head=page_tail)and(head=tail)and(dead_cycles=0) then
          begin its_all_over:=true; return;
          end;
          back_input; we will try to end again after ejecting residual material
          tail_append(new_null_box);
          width(tail):=hsize;
          tail_append(new_glue(fill_glue));
          tail_append(new_penalty(-@'10000000000));@/
          build_page; append .\hbox to \hsize\vfill\penalty-'10000000000
          ^^^^^^^^^^^^^^^^^^^^^^
          end;
          its_all_over:=false;
          exit:end;





          share|improve this answer























          • This is mentioned on p.264 of TeXbook. I guess the meaning is that if insert which occupies the whole page is used, there has to be some additional text, so second page is inevitable. Still, I'm not sure I completely understand how the explanation on p.264 applies to OP.

            – Igor Liferenko
            Jul 8 at 7:26











          • @IgorLiferenko in your case when it hits end the main vertical list is not empty (there is an insert node left) so the clause on page 262 means the the line is added and end is called again

            – David Carlisle
            Jul 8 at 7:50













          4












          4








          4







          It is tex-the-program's final endgame to flush out the insert:



          tex.web has



          @ We don't want to leave |main_control| immediately when a |stop| command
          is sensed, because it may be necessary to invoke an .\output routine
          several times before things really grind to a halt. (The output routine
          might even say `.\gdef\end...', to prolong the life of the job.)
          Therefore |its_all_over| is |true| only when the current page
          and contribution list are empty, and when the last output was not a
          ``dead cycle.''

          @<Declare act...@>=
          function its_all_over:boolean; do this when .\end or .\dump occurs
          label exit;
          begin if privileged then
          begin if (page_head=page_tail)and(head=tail)and(dead_cycles=0) then
          begin its_all_over:=true; return;
          end;
          back_input; we will try to end again after ejecting residual material
          tail_append(new_null_box);
          width(tail):=hsize;
          tail_append(new_glue(fill_glue));
          tail_append(new_penalty(-@'10000000000));@/
          build_page; append .\hbox to \hsize\vfill\penalty-'10000000000
          ^^^^^^^^^^^^^^^^^^^^^^
          end;
          its_all_over:=false;
          exit:end;





          share|improve this answer













          It is tex-the-program's final endgame to flush out the insert:



          tex.web has



          @ We don't want to leave |main_control| immediately when a |stop| command
          is sensed, because it may be necessary to invoke an .\output routine
          several times before things really grind to a halt. (The output routine
          might even say `.\gdef\end...', to prolong the life of the job.)
          Therefore |its_all_over| is |true| only when the current page
          and contribution list are empty, and when the last output was not a
          ``dead cycle.''

          @<Declare act...@>=
          function its_all_over:boolean; do this when .\end or .\dump occurs
          label exit;
          begin if privileged then
          begin if (page_head=page_tail)and(head=tail)and(dead_cycles=0) then
          begin its_all_over:=true; return;
          end;
          back_input; we will try to end again after ejecting residual material
          tail_append(new_null_box);
          width(tail):=hsize;
          tail_append(new_glue(fill_glue));
          tail_append(new_penalty(-@'10000000000));@/
          build_page; append .\hbox to \hsize\vfill\penalty-'10000000000
          ^^^^^^^^^^^^^^^^^^^^^^
          end;
          its_all_over:=false;
          exit:end;






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jul 8 at 7:07









          David CarlisleDavid Carlisle

          515k44 gold badges1168 silver badges1936 bronze badges




          515k44 gold badges1168 silver badges1936 bronze badges












          • This is mentioned on p.264 of TeXbook. I guess the meaning is that if insert which occupies the whole page is used, there has to be some additional text, so second page is inevitable. Still, I'm not sure I completely understand how the explanation on p.264 applies to OP.

            – Igor Liferenko
            Jul 8 at 7:26











          • @IgorLiferenko in your case when it hits end the main vertical list is not empty (there is an insert node left) so the clause on page 262 means the the line is added and end is called again

            – David Carlisle
            Jul 8 at 7:50

















          • This is mentioned on p.264 of TeXbook. I guess the meaning is that if insert which occupies the whole page is used, there has to be some additional text, so second page is inevitable. Still, I'm not sure I completely understand how the explanation on p.264 applies to OP.

            – Igor Liferenko
            Jul 8 at 7:26











          • @IgorLiferenko in your case when it hits end the main vertical list is not empty (there is an insert node left) so the clause on page 262 means the the line is added and end is called again

            – David Carlisle
            Jul 8 at 7:50
















          This is mentioned on p.264 of TeXbook. I guess the meaning is that if insert which occupies the whole page is used, there has to be some additional text, so second page is inevitable. Still, I'm not sure I completely understand how the explanation on p.264 applies to OP.

          – Igor Liferenko
          Jul 8 at 7:26





          This is mentioned on p.264 of TeXbook. I guess the meaning is that if insert which occupies the whole page is used, there has to be some additional text, so second page is inevitable. Still, I'm not sure I completely understand how the explanation on p.264 applies to OP.

          – Igor Liferenko
          Jul 8 at 7:26













          @IgorLiferenko in your case when it hits end the main vertical list is not empty (there is an insert node left) so the clause on page 262 means the the line is added and end is called again

          – David Carlisle
          Jul 8 at 7:50





          @IgorLiferenko in your case when it hits end the main vertical list is not empty (there is an insert node left) so the clause on page 262 means the the line is added and end is called again

          – David Carlisle
          Jul 8 at 7:50

















          draft saved

          draft discarded
















































          Thanks for contributing an answer to TeX - LaTeX Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f499060%2fwhy-is-an-empty-line-added-when-insert-is-used%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Get product attribute by attribute group code in magento 2get product attribute by product attribute group in magento 2Magento 2 Log Bundle Product Data in List Page?How to get all product attribute of a attribute group of Default attribute set?Magento 2.1 Create a filter in the product grid by new attributeMagento 2 : Get Product Attribute values By GroupMagento 2 How to get all existing values for one attributeMagento 2 get custom attribute of a single product inside a pluginMagento 2.3 How to get all the Multi Source Inventory (MSI) locations collection in custom module?Magento2: how to develop rest API to get new productsGet product attribute by attribute group code ( [attribute_group_code] ) in magento 2

          Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

          Magento 2.3: How do i solve this, Not registered handle, on custom form?How can i rewrite TierPrice Block in Magento2magento 2 captcha not rendering if I override layout xmlmain.CRITICAL: Plugin class doesn't existMagento 2 : Problem while adding custom button order view page?Magento 2.2.5: Overriding Admin Controller sales/orderMagento 2.2.5: Add, Update and Delete existing products Custom OptionsMagento 2.3 : File Upload issue in UI Component FormMagento2 Not registered handleHow to configured Form Builder Js in my custom magento 2.3.0 module?Magento 2.3. How to create image upload field in an admin form