Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Here are some cases where when there is stuff inside a vbox, the baselineskips are sometimes there and sometimes not. Or maybe it's something else that is producing the differences?

\setbox0\vbox{% halign is vertical mode material?
  \halign{& \strut$#\hfil$\cr
    a& b& c\cr
    d& e& f\cr
    g& h& i\cr}}% each cell expands out to \hbox{...
\setbox1\hbox{% valign is horizontal mode material?
  \valign{& \hbox{\strut$#\hfil$}\cr
    a& d& g\cr
    b& e& h\cr
    c& f& i\cr}}% each cell expands out to \vbox{\hbox{...
\hbox{\box0\box1}
\vbox{When there is just text inside a \vbox{vbox,}
  it uses the whole hsize and indents}
\vbox{\hbox{except when}\hbox{it consists}\hbox{of consecutive}\hbox{hboxes}}
\bye

enter image description here

I've run into this on numerous times but never really understood what is happening or how can I fix it.

(The question Why is \baselineskip not inserted before an \unvbox? might have something to do with this?)

share|improve this question
    
It's somewhat nasty of you to put that \vbox{vbox,} :-) But now that I understood it, I see that it nicely demonstrates how the whole hsize and indents are used by this \vbox. –  Hendrik Vogt Jun 19 '12 at 11:04
    
Shouldn't the update better be a followup question? –  egreg Jul 12 '12 at 16:30
    
@egreg: Asking the exact same question? I don't know, I thought we were against that sort of thing? –  morbusg Jul 12 '12 at 16:35
    
The space, of course, depends on \smallskip; however, setting \dp0 is useless, as you \unvbox0. Also you're forgetting to set \dimen255=\prevdepth after the \smallskip in \bquo. The original question had \halign and \valign: it's a very different setting. –  egreg Jul 12 '12 at 16:40
1  
@HiggsBoson: you noticed ;) –  morbusg Jul 12 '12 at 17:15

2 Answers 2

up vote 7 down vote accepted

Let's simplify your example. The main point is here

\hsize=6cm % just to get a two line paragraph
\vbox{When there is just text inside a vbox
  it uses the whole hsize and indents}
\vbox{\hbox{except when}\hbox{it consists}\hbox{of consecutive}\hbox{hboxes}}

A \vbox has depth equal to the depth of the last item inside it. Thus both vboxes have depth zero, because by chance the second line in the first box has no descender and the same holds for \hbox{hboxes}.

All the rest contributes to the height of the \vbox. Thus, when TeX wants to pile the two vboxes over each other, it computes the interline glue. But, clearly, the height of the second \vbox is larger than \baselineskip, so the rule imposes TeX to insert \lineskip glue (default value 1pt).

Let's see a picture obtained by setting \lineskip to 20pt, just to see that it's inserted:

enter image description here

How do we solve the problem? Here's the answer:

\hsize=6cm % just to get a two line paragraph
\vbox{When there is just text inside a vbox
  it uses the whole hsize and indents\strut}
\nointerlineskip
\vbox{\hbox{\strut except when}\hbox{it consists}\hbox{of consecutive}\hbox{hboxes}}

enter image description here

Just inhibit the \baselineskip-\lineskiplimit-\lineskip computations with \nointerlineskip and ensure that the two lines are correctly separated by using struts. This won't work, though, if either the \vbox above has large depth or the first box in the \vbox below has large height.


Let's tackle now the \halign and \valign problem. The input

\setbox0=\vbox{% halign is vertical mode material
  \halign{& \strut$#\hfil$\cr
    a& b& c\cr
    d& e& f\cr
    g& h& i\cr}}% each cell expands out to \hbox{...

is equivalent to do

\setbox0=\vbox{
  \hbox{\hskip0pt
        \hbox to X{\strut$a\hfil$}\hskip0pt
        \hbox to X{\strut$b\hfil$}\hskip0pt
        \hbox to X{\strut$c\hfil$}\hskip0pt}
  \hbox{\hskip0pt
        \hbox to X{\strut$d\hfil$}\hskip0pt
        \hbox to X{\strut$e\hfil$}\hskip0pt
        \hbox to X{\strut$f\hfil$}\hskip0pt}
  \hbox{\hskip0pt
        \hbox to X{\strut$g\hfil$}\hskip0pt
        \hbox to X{\strut$h\hfil$}\hskip0pt
        \hbox to X{\strut$i\hfil$}\hskip0pt}
}

where X stands for the maximum width of the cells (computed by TeX) and \hskip0pt comes from the default value of \tabskip.

This has the same property as before: the depth of the box is the depth of the last box inside it (so it's the depth of the strut) and the rest contributes to the height. The reference point is the same as the last box reference point, so the math mode "g", "h" and "i" sit on the baseline determined by this reference point.

What about the \valign? The input

\setbox2=\hbox{% valign is horizontal mode material
  \valign{& \hbox{\strut$#\hfil$}\cr
    a& d& g\cr
    b& e& h\cr
    c& f& i\cr}}% each cell expands out to \vbox{\hbox{...
\hbox{\box0\box1}

is equivalent to

\setbox2=\hbox{%
  \vbox{\vskip0pt
        \vbox to X{\hbox{\strut$a\hfil$}}\vskip0pt
        \vbox to X{\hbox{\strut$d\hfil$}}\vskip0pt
        \vbox to X{\hbox{\strut$g\hfil$}}\vskip0pt}%
  \vbox{\vskip0pt
        \vbox to X{\hbox{\strut$b\hfil$}}\vskip0pt
        \vbox to X{\hbox{\strut$e\hfil$}}\vskip0pt
        \vbox to X{\hbox{\strut$h\hfil$}}\vskip0pt}%
  \vbox{\vskip0pt
        \vbox to X{\hbox{\strut$c\hfil$}}\vskip0pt
        \vbox to X{\hbox{\strut$f\hfil$}}\vskip0pt
        \vbox to X{\hbox{\strut$i\hfil$}}\vskip0pt}%
  }

where X is the maximum height of the cells (in this case it's \ht\strutbox). But here the "bad thing" happens! The reference point is determined by the last item, which is glue. So the bottom of the $g$ sits on the line determined thereby.

Just do

\noindent\rlap{\vrule height0.4pt width 4cm}\vrule\box2

(where in place of X you write \ht\strutbox) and you'll realize the fact.

Here it is: the first is the \valign, the second the "equivalent" box.

enter image description here

share|improve this answer
    
Thank you! Although, I am still puzzled on how to fix the halign/valign; there are struts in place there. –  morbusg Jun 19 '12 at 12:38
    
@morbusg I've added the analysis you asked for. –  egreg Jun 19 '12 at 13:09

A version of your input with better alignment is

\setbox0\vbox{% halign is vertical mode material?
  \halign{& \strut$#\hfil$\cr
    a& b& c\cr
    d& e& f\cr
    \strut g& h& i\cr}\kern0pt}% each cell expands out to \hbox{...
\setbox2\hbox{% valign is horizontal mode material?
  \valign{& \hbox{\strut$#\hfil$}\cr
    a& d& g\cr
    b& e& h\cr
    c& f& i\cr}}% each cell expands out to \vbox{\hbox{...
\hbox{\box0\box2\strut}
\nointerlineskip
\vbox{\strut When there is just text inside a \hbox{vbox,}
  it uses the whole hsize and indents\strut}
\nointerlineskip
\vbox{\hbox{\strut except when}\hbox{it consists}\hbox{of consecutive}\hbox{hboxes}}
\tracingoutput2
\bye

this uses box2 rather than box1 which doesn't change anything, but using odd numbered registers for local assignments is naughty:-)

the two alignments have the same total vertical size but the first one had zero depth, adding kern 0pt at the end of the vertical list of the second one, pushes all the size into the height so they match up.

Using a vbox mid-paragraph as in your example rarely does anything useful so I just changed it to an hbox. (The paragraph set in the inner vbox will be set to lines of \hsize wide so they will never really fit in the outer paragraph which is being set to the same measure.)

enter image description here

share|improve this answer
    
That \kern0pt trick is pretty neat. I've no idea how can it do anything. –  morbusg Jun 19 '12 at 13:51
    
The depth of a \vbox is zero if the last thing in the list is a non negative skip or kern. –  David Carlisle Jun 19 '12 at 14:02
    
I was wondering why is using odd numbered registers naughty? –  morbusg Jul 12 '12 at 13:45
    
@morbusg plain and latex reserve registers 0-10 for scratch use but even ones should only be used for local assignments and odd ones for global. If you break this rule (which is in the TeXBook) then either an inner macro will make a global assignment to your scratch register and mess you up, or it won't but you will have local and global assignments to the same register which causes TeX to use unlimited amounts of save stack and give up with a fatal error if you do it too much –  David Carlisle Jul 12 '12 at 13:58
    
Cool, thanks for the that! :) I do have the TeXbook, but I must've missed that information. –  morbusg Jul 12 '12 at 15:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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