# Underfull hbox with \hbox to <dimen> but not with \halign

When using the \halign primitive, cells in the same column all have the same width. Hence, if one entry is very large (abcdefg below), the others will be stretched to the same size. If an entry contains no glue, then it is not stretched. Namely,

\halign{#\cr abcdefg\cr a b\cr ab\cr}


gives

abcdefg
a     b
ab


This can be emulated by applying \hbox to <wd>{...} to each entry. However, when there is no glue, \halign produces no Underfull hbox warning, whereas \hbox to <wd>{...} does.

• Am I correct that \halign does the equivalent of \hbox to <dim>{...} to resize the entries?

• I would like to avoid spurious Underfull hbox warnings. How can I test for the absence of glue in a \hbox?

-
To quote TeX by Topic, "TeX first calculates widths...of all entires; then it typesets the whole alignment using in each column...the maximum width...of entries in that column..." So yes, basically \hbox to width{...}. As for absence of glue, what would you do if you discovered that an hbox has glue? –  TH. Apr 17 '11 at 5:06
Why you are not just simply add some glue e.g. \hfill by yourself? –  Martin Scharrer Apr 17 '11 at 7:53
@Martin: If I add \hfill myself, that would make the second line of my example into ab----- (with - replaced by spaces), which is incorrect. A solution may be to put \hskip 0pt plus 1sp, but even that is not quite right. –  Bruno Le Floch Apr 17 '11 at 14:12

You can test whether an \hbox is underfull without getting a message using something like

\begingroup
\setbox0=\hbox{...}
\hbadness=10000 % suppress Underfull \hbox' messages
\setbox0=\hbox to <wd>{\unhbox0 }
\endgroup


so \mybadness will expand to 10000 if the \hbox to <wd> is underfull. See the TeXbook, p. 229. By giving different values to <wd> you can also test if the glue is infinite or not.

-
Reasonable plan: as I've said, my reading of the code suggests that \halign is basically doing \hbox to but with warnings turned off. –  Joseph Wright Apr 17 '11 at 8:37
Than you @egreg. I am using this, with <wd> taken to be \dimexpr \wd0 + 1sp. If there is no stretch in the cell, then it will have a badness of 10000, and if there is even 1sp of stretch, the badness will be at most 100. –  Bruno Le Floch Apr 17 '11 at 20:04
Actually, thinking about it some more, I simply need to turn off the warnings, so \begingroup \hbadness=10000 \setbox0=\hbox to <wd>{\unhbox0}\ht0=... \dp0=... \box0 \endgroup does precisely what I want. –  Bruno Le Floch Apr 17 '11 at 20:41

This seems to be one for tex.web to me. The alignment code is made more complex than simple boxing operations by the need to handle \span correctly. However, the general flow is pretty clear. TeX works through the rows, typesetting everything to natural width but in unset boxes (i.e. the glue is not set at this stage). At each stage, the width of the current box is compared to that in the preamble. If the current box is wider, then this value is stored in the preamble for further use. All of the unset boxes are themselves stored in one box per row.

Once TeX gets to the end of the alignment, it goes through each row and sets the glue. The key routine seems to be

@ @<Make the unset node |r| into an |hlist_node| of width |w|...@>=
begin height(r):=height(q); depth(r):=depth(q);
if t=width(r) then
begin glue_sign(r):=normal; glue_order(r):=normal;
set_glue_ratio_zero(glue_set(r));
end
else if t>width(r) then
begin glue_sign(r):=stretching;
if glue_stretch(r)=0 then set_glue_ratio_zero(glue_set(r))
else glue_set(r):=unfloat((t-width(r))/glue_stretch(r));
@^real division@>
end
else  begin glue_order(r):=glue_sign(r); glue_sign(r):=shrinking;
if glue_shrink(r)=0 then set_glue_ratio_zero(glue_set(r))
else if (glue_order(r)=normal)and(width(r)-t>glue_shrink(r)) then
set_glue_ratio_one(glue_set(r))
else glue_set(r):=unfloat((width(r)-t)/glue_shrink(r));
end;
width(r):=w; type(r):=hlist_node;
end


The important point for the current question is that this is coded just for alignments, even though the concept is pretty much the same as for \hbox to <dim>. Thus the code used in an alignment does not include a check for underfull boxes.

You can see that the overall effect of the \halign code is the same as \hbox to <dim> by using \tracingall and looking at the boxes, for example

\tracingall
\halign{#\cr abcdefg\cr a b\cr ab\cr}
\newbox\testbox
\setbox\testbox=\hbox{abcdefg}
\setbox\testbox=\hbox to \wd\testbox{a b}
\box\testbox
\bye


You'll see that the glue situation is identical in the two a b cases: it's just that the warning is omitted in the \halign case.

-
thank you for digging into tex.web. Basically, what I need is to do the test if glue_stretch(r)=0` myself. –  Bruno Le Floch Apr 17 '11 at 20:05