6

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?

3
  • 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, 2011 at 5:06
  • 1
    Why you are not just simply add some glue e.g. \hfill by yourself? Apr 17, 2011 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. Apr 17, 2011 at 14:12

2 Answers 2

7

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 }
\xdef\mybadness{\the\badness}
\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.

3
  • 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, 2011 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. Apr 17, 2011 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. Apr 17, 2011 at 20:41
4

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.

1
  • thank you for digging into tex.web. Basically, what I need is to do the test if glue_stretch(r)=0 myself. Apr 17, 2011 at 20:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .