# The revenge of the vboxes

Yes, they're back. With a vengeance. Those pesky little buggers we call \vboxes which I've fought against previously. (And Bruno, too.)

\parskip=0pt
\def\unquo{\unvbox0\smallskip}
\def\bquo#{\smallskip\dimen255=\prevdepth\setbox0\vbox\bgroup\prevdepth=\dimen255
\narrower\noindent\strut\aftergroup\unquo\let\next= }

\hsize=20pc
Some text which goes on for a while, in fact, hopefully long enough to
produce a line break.
\bquo{A quote which goes on for a while, so long in fact, that I was hoping to
see a line break somewhere durin this ouote.}
And then some more text.
\bye


No! What is that space? Not the same amount as before the quote I can tell you that much. Sure you'll tell me \smallskipamount is 3pt plus 1pt minus 1pt, but that can't be 2pt. No way.

-
the vertical space after a vbox depends on the depth of the vbox. since this one has no descenders (as it would if you had "quote" instead of "ouote"), it would be the same as the skip above the box. you might add in a strut just before the \unvbox0 in \unquo. not tested, thus not formalized as an answer. – barbara beeton Jul 12 '12 at 17:12
not precisely relevant, but another place where depth matters was illulstrated in a tugboat warnings column; see the second page. – barbara beeton Jul 12 '12 at 17:15
@barbara: yeah, I actually had tried a \strut before the \unvbox, but I guess what happens then is that the \strut creates a new empty line. – morbusg Jul 12 '12 at 17:23
yes, that would happen if you have already gotten out of horizontal mode. which i guess you have since the box has been closed off with no obvious place to put the strut. maybe @DavidCarlisle has an idea of how to sneak it in. – barbara beeton Jul 12 '12 at 17:32

You need to reset the \prevdepth: doing \unvbox0 doesn't do it.

The TeXbook, page 282:

\unvbox<8 bit number>, … The value of \prevdepth is not affected.

On the other hand, doing \box will affect the \prevdepth (same page), so we solve the issue by detaching the last box and reattaching it with \box.

\parskip=0pt
\def\unquo{\unvbox0 \setbox0=\lastbox\nointerlineskip\box0 \smallskip}
\def\bquo#{\smallskip\dimen255=\prevdepth\setbox0\vbox\bgroup\prevdepth=\dimen255
\narrower\noindent\strut\aftergroup\unquo\let\next= }

\hsize=20pc

\dimen0=5\baselineskip
\def\ruler{\leavevmode\smash{\vrule height 0pt depth \dimen0}\kern-0.4pt}

\ruler
Some text which goes on for a while, in fact, hopefully long enough to
produce a line break.
\bquo{A quote which goes on for a while, so long in fact, that I was hoping to
see a line break somewhere durin this quote.}
And then some more text.
\bye


I've added a ruler which has the desired length to show that the spacing is correct.

The \unquo macro can also be defined more compactly by

\def\unquo{\unvbox0 \nointerlineskip\lastbox\smallskip}


Of course the same result can be obtained by saying

\long\def\bquo#1{\smallskip{\narrower#1\par}\smallskip}

-
Nice! That compact version is really neat, thanks! :) – morbusg Jul 12 '12 at 17:43
If I understand correctly, it isn't the same result (tex.stackexchange.com/a/13436/1410). – morbusg Jul 12 '12 at 18:26
@morbusg If you really want that \bquo is followed by a brace, then \def\bquo#{\bquoaux}\long\def\bquoaux#1{\smallskip{\narrower#1\par}\smallskip} will do. – egreg Jul 12 '12 at 18:31
@egreg: note that in general \setbox0\lastbox\box0 can be replaced by \lastbox. Knuth's alignment macros in plain.tex are the only place where I saw that used: see one of my older questions on \lastbox. I'm not sure if it can be done in your case, since I've read your code too fast to follow what's happening with the \nointerlineskip in between. – Bruno Le Floch Jul 12 '12 at 20:21
@BrunoLeFloch Indeed, I remembered that thread. The \nointerlineskip is just an assignment, and \lastbox finds correctly the required item. Since the baseline skip had already been set when building the \vbox, the trick seems to work. – egreg Jul 12 '12 at 20:24

You'll get the same spacing if you change ouote to guote so it has the same depth as the first.

\tracingoutput1
\tracingonline2
\showboxdepth3


The difference is the baselinskip values before the rows starting with A. \unvbox doesn't propagate the depth in the way you need.:

This is TeX, Version 3.1415926 (TeX Live 2011/Cygwin) (format=tex 2012.5.4)  12 JUL 2012 18:21
**ssp
(./ssp.tex

Completed box being shipped out [1]
\vbox(667.20255+0.0)x240.0
.\vbox(0.0+0.0)x240.0, glue set 14.0fil
..\glue -22.5
..\hbox(8.5+0.0)x240.0, glue set 240.0fil
...\vbox(8.5+0.0)x0.0
...\glue 0.0 plus 1.0fil
..\glue 0.0 plus 1.0fil minus 1.0fil
.\vbox(643.20255+0.0)x240.0, glue set 567.20255fill
..\glue(\topskip) 3.05556
..\hbox(6.94444+1.94444)x240.0, glue set - 0.26826
...\hbox(0.0+0.0)x20.0
...\tenrm S
...\tenrm o
...\tenrm m
...\tenrm e
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm t
...\tenrm e
...\tenrm x
...\tenrm t
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm w
...\tenrm h
...\tenrm i
...\tenrm c
...\kern-0.27779
...\tenrm h
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm g
...\tenrm o
...etc.
..\penalty 400
..\glue(\baselineskip) 3.11111
..\hbox(6.94444+1.94444)x240.0, glue set 56.61072fil
...\tenrm f
...\tenrm u
...\tenrm l
...\tenrm l
...\tenrm y
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm l
...\tenrm o
...\tenrm n
...\tenrm g
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm e
...\tenrm n
...\tenrm o
...\tenrm u
...\tenrm g
...\tenrm h
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm t
...\tenrm o
...etc.
..\glue 3.0 plus 1.0 minus 1.0
..\glue(\baselineskip) 1.55556
..\hbox(8.5+3.5)x240.0, glue set 0.90999
...\glue(\leftskip) 20.0
...\rule(8.5+3.5)x0.0
...\tenrm A
...\glue 3.33333 plus 1.66498 minus 1.11221
...\tenrm q
...\tenrm u
...\tenrm o
...\tenrm t
...\tenrm e
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm w
...\tenrm h
...\tenrm i
...\tenrm c
...\kern-0.27779
...\tenrm h
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm g
...\tenrm o
...\kern0.27779
...etc.
..\penalty 150
..\glue(\baselineskip) 1.55556
..\hbox(6.94444+1.94444)x240.0, glue set 0.3171
...\glue(\leftskip) 20.0
...\tenrm i
...\tenrm n
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm f
...\tenrm a
...\tenrm c
...\tenrm t
...\tenrm ,
...\glue 3.33333 plus 2.08331 minus 0.88889
...\tenrm t
...\tenrm h
...\tenrm a
...\tenrm t
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm I
...\glue 3.33333 plus 1.66498 minus 1.11221
...\tenrm w
...\kern-0.27779
...\tenrm a
...etc.
..\penalty 150
..\glue(\baselineskip) 3.11111
..\hbox(6.94444+1.94444)x240.0, glue set 76.49979fil
...\glue(\leftskip) 20.0
...\tenrm s
...\tenrm o
...\tenrm m
...\tenrm e
...\tenrm w
...\tenrm h
...\tenrm e
...\tenrm r
...\tenrm e
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm d
...\tenrm u
...\tenrm r
...\tenrm i
...\tenrm n
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm t
...\tenrm h
...\tenrm i
...etc.
..\glue 3.0 plus 1.0 minus 1.0
..\glue(\parskip) 0.0
..\glue(\baselineskip) 3.11111
..\hbox(6.94444+0.0)x240.0, glue set 104.91646fil
...\hbox(0.0+0.0)x20.0
...\tenrm A
...\tenrm n
...\tenrm d
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm t
...\tenrm h
...\tenrm e
...\tenrm n
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm s
...\tenrm o
...\tenrm m
...\tenrm e
...\glue 3.33333 plus 1.66666 minus 1.11111
...\tenrm m
...\tenrm o
...\tenrm r
...\tenrm e
...\glue 3.33333 plus 1.66666 minus 1.11111
...etc.
..\glue 0.0 plus 1.0fill
.\glue(\baselineskip) 17.55556
.\hbox(6.44444+0.0)x240.0, glue set 117.5fil
..\glue 0.0 plus 1.0fil minus 1.0fil
..\tenrm 1
..\glue 0.0 plus 1.0fil minus 1.0fil

)
Output written on ssp.dvi (1 page, 540 bytes).

-
Yes, the typos were on purpose ("quote -> oute", "during -> durin"), so that there would be no descenders on the line. – morbusg Jul 12 '12 at 17:39
I guessed as much, but that should have told you the answer:-) that the difference is baselineskip (not) seeing the descender. – David Carlisle Jul 12 '12 at 18:11
Yeah, I did have a nagging feeling that I should know the answer by now, but I guess my mental image of what TeX is doing when stacking boxes is still lacking because I think I tried every other combination of things, but forgot to try the \nointerlineskip. Oh well, live and learn, I guess. :) – morbusg Jul 12 '12 at 18:19