\vtop is a useful TeX primitive. When it's needed, it
is pretty much indispensable. (Newbies - \vtop aligns
a box on its top line, \vbox on its last.)
It's useful because sometime we want a horizontal line
of boxes, with their top lines aligned.
Here's an example. \hbox{\vtop{...}\vtop{...}\vtop{...}}:
xxxx xxxx xxxx
xxxx xxx
xx
Now suppose \vtop were not there. In other words
\let\vtop\undefined
One might say that one would want an extension of TeX
to have fairly general primitives that would allow
one to define a macro that pretty much behaved like
\vtop.
So the question is: What are these primitives?
--
Jonathan
Well, to begin with, consider the box that \vtop and \vbox produce. It
has three components to its size -- the height, depth, and width -- and
then its sub-boxes are located relative to its anchor.
So, the question is, if \vtop were not a primitive, what would its input
look like, and how would it process it. Following that chain of thought
loosely, one gets to the thought that, essentially, what \vtop and \vbox
and so forth do is accumulate \hboxes and stack them.
Or, roughly, \vtop and \vbox do this:
1. Accumulate an \hbox => box1
2. If there's no more material, exit
3. Accumulate an \hbox => box2
4. Combine box1 and box2 => box1
5. Goto 2.
The specifics of step 4 amount to the distinction between \vtop and
\vbox -- in both cases, the horizontal origin for the two boxes are the
same and the vertical spacing is determined by their depth and height
respectively. However, the new origin is different.
Thus, one could envision a primitive which takes a box and adds its
contents, in a shifted manner, to an existing box. This can also be
used for \hbox, of course.
(Note that, in combination with an empty box, this primitive can be used
to shift boxes around; there is no need for a different primitive for that.)
This gets combined with some means of iterating. Specifically, for the
horizontal boxes that make up a \vbox, one needs to pull items off the
stream until one leaves horizontal mode. For a \vbox, one needs to
apply this repeatedly to the argument, with appropriate application of
box-combining commands in the interim. I think most of this can be done
with existing TeX primitives and tail-recursion already, though I'm not
completely sure about the iteration-until-out-of-horizontal-mode part.
I suspect that a version of the box-combining "primitive" could probably
be written using existing TeX, allowing you to experiment with this.
- Brooks
--
The "bmoses-nospam" address is valid; no unmunging needed.
<snip>
> I suspect that a version of the box-combining "primitive" could probably
> be written using existing TeX, allowing you to experiment with this.
Thank you, Brooks, for contributing to this discussion.
Much appreciated (even if snipped).
There is an explanation of \vtop in The TeXbook, page 81. My
understanding of this - not tested - is that
\setbox 0 = \vtop{ vertical material}
and
\setbox 0 = \vbox{ vertical material} % XXX
\ht 0 = <magic1>
\dp 0 = <magic2>
are equivalent, where <magic1> is the height of the
first item in the vertical material, and
<magic1> + <magic2>
is equal the \ht 0 + \dp 0 at stage XXX.
Therefore, the key new primitive is the height of
the first item in the vertical list in a \vbox.
Indeed, from \vtop we can compute this value - it
is the \ht of the \vtop box.
Now let's generalise a little. Let's allow
access to all properties of all items in the vertical
list in a \vbox.
So the new primitive I was asking for is, I claim,
\vboxitem <number> <vertical box>
which
a) does not change the <vertical box>
b) adds to the current list a copy of the
<number> item in the <vertical box>.
We can then compute <magic1> as
\setbox 2 = \vbox{\vboxitem 1 \box 0}
<magic1> = \ht 2
By the way, one can just as well drop the 'vertical'
in the definition of \vboxitem, to give the more
general \boxitem.
One problem. I've not checked, but I am fairly sure
that without a change to the data structures of
TeX, the running time of \boxitem n will be linear
in n, and so running through a box will be
quadratic in the number of top-level items in the
box.
--
Jonathan
Hmm. That is an interesting approach. Unfortunately, I don't have much
familiarity at all with TeX's existing processes for doing things with
existing boxes (and, in particular, I know nearly nothing about clever
tricks for using them in practice), so I can't really comment further.
One thing I'll note, though, is that if you go that route you'll
definitely want a primitive that gives you the count of items within a box.
Thank you for saying that, Brooks. If the experts in clever tricks
are listening, I'd certainly like to hear their comments.
> One thing I'll note, though, is that if you go that route you'll
> definitely want a primitive that gives you the count of items within a box.
Maybe. Such a primitive would probably be best done if
each box held a count of the number of items within it.
There are two basic approaches to memory management for arrays.
The one is a linked (possibly doubly) list of nodes. The other
is to use contiguous memory (and when that memory runs out,
obtain a larger piece, and move the array over to the new
piece).
TeX, as I recall, uses the first. Python uses the second.
However, this is perhaps not in practice a real issue. Almost
all the time, I think, one will want to iterate over the
contents of the box. And for a box of size n this can
be done in linear time, even for a linked list, provided
one writes:
# O(n) for linked list arrays
for item in iter(box):
do_something_with(item)
instead of
# O(n^2) for linked list array
n = len(box)
for i in range(n):
do_something_with(box_item(i))
Which brings us back to your observation. I'm not at all
sure one will want a len primitive for boxes.
Thank you for your interest.
--
Jonathan
Well, you might not want one, but I'm pretty sure I would. :)
For one thing, those iteration loops -- if written in something like
TeX, which doesn't have anything approaching a "for X in Y" construct --
will require some way to determine when one has finished the iteration;
how are you imagining that being done? Or are you envisioning adding
primitives to TeX to enable the for-loop in the first piece of
pseudocode to be done directly?
Also, consider the recent "Breaking long lines in special ways" thread
(which you might find interesting as an example of things that are
currently not easy to do in TeX). That presented a situation where one
would want to look at only the last line in a paragraph (to measure it),
and also where one would want to know if a paragraph contained exactly
two lines or not. The latter is a pretty direct application of a
\len{box} macro, and the former wants \vboxitem{\len{box}}{box}.
I can imagine a number of other cases where I might want, say, the depth
of the last line of a box, and I don't really see any natural way to do
that without a length count.
(Well, okay, that's not true. You could use positive numbers to count
down from the top, and negative numbers to count up from the bottom, and
then it could be referenced as \vboxitem{-1}{box}, but that isn't easier
to implement.)
Your understanding is incorrect: changing the height and depth
of a box doesn't change its reference point: the box will still be
placed with the last item on the baseline. You need \raise
(or something like it) to change the positioning. Unfortunately,
\raise doesn't return a <box> (as in the syntax for box assignment,
TeXbook, pages 276--278).
>
> Therefore, the key new primitive is the height of
> the first item in the vertical list in a \vbox.
> Indeed, from \vtop we can compute this value - it
> is the \ht of the \vtop box.
Also needed would be a primative that returns a <box> with
the referrence point changed. One could use
\hbox{\raise ...\vbox{...}}
but that would add an extra boxing level.
Dan
>>There is an explanation of \vtop in The TeXbook, page 81. My
>>understanding of this - not tested - is that
>> \setbox 0 = \vtop{ vertical material}
>>and
>> \setbox 0 = \vbox{ vertical material} % XXX
>> \ht 0 = <magic1>
>> \dp 0 = <magic2>
>>are equivalent, where <magic1> is the height of the
>>first item in the vertical material, and
>> <magic1> + <magic2>
>>is equal the \ht 0 + \dp 0 at stage XXX.
>
>
> Your understanding is incorrect: changing the height and depth
> of a box doesn't change its reference point: the box will still be
> placed with the last item on the baseline.
Thank you, Dan, for your interest, and for joining in the
discussion.
I was suprised to hear this and so I tested the proposition.
===
\def\doit#1#2{%
\setbox0\vbox{\hrule width 1in height0.5in depth 0.5in}%
\ht0 #1
\dp0 #2
\box0
}
\hbox{\doit{0in}{1in}\doit{1in}{0in}\doit{0.5in}{0.5in}}
===
The test shows that I am right. We get three squares in a line,
vertically aligned low, high and middle.
However, this works only for \vbox. For \hbox (about which
I made no claim) one gets three squares in a line).
===
\def\doit#1#2{%
\setbox0\hbox{\vrule width 1in height0.5in depth 0.5in}%
\ht0 #1
\dp0 #2
\box0
}
\hbox{\doit{0in}{1in}\doit{1in}{0in}\doit{0.5in}{0.5in}}
===
I think, in this case, my not previously tested understanding
was correct.
--
Jonathan
You are correct.
I was surprised to find this inconsistency in TeX. I could only
find this explained in Appendix D "Dirty Tricks" in the TeXbook.
(I might add that changing the height alone is sufficient to shift
the reference point, but changing the depth is not. This is
reversed for \vtop.)
Chapter 12 contains quite a detailed explanation of how
the height and depth of a _constructed_ vbox is determined.
But I can find no mention of how changing the depth or height
_afterwards_ changes the position of the contents. In the
special case where the depth exceeds \boxmaxdepth, it is
stated that the height and depth are adjusted (and the
reference point moved), but I saw that as a special case.
After readind Appendix D, I can see how Chapter 12 could
_possibly_ be interpreted as providing an absolute relationship
between the height, depth and reference point, but I certainly
didn't interpret it that way.
Dan
Sorry, Dan, I'm not finding that. And if I did, I would
think it a bug in TeX.
=====
\def\Vbox#1#2{%
\setbox0\vbox{\hrule width 1in height0.5in depth 0.5in}%
\ht0 #1
\dp0 #2
\box0
}
\def\Vtop#1#2{%
\setbox0\vtop{\hrule width 1in height0.5in depth 0.5in}%
\ht0 #1
\dp0 #2
\box0
}
\hbox{\Vbox{0in}{0.5in}\Vbox{1in}{0.5in}\Vbox{0.5in}{0.5in}}
\hbox{\Vtop{0in}{0.5in}\Vtop{1in}{0.5in}\Vtop{0.5in}{0.5in}}
=====
Each of the above gives low, high and middle vertically
aligned squares.
Thank you for the pointer to Appendix D (page 388).
--
Jonathan
But you are changing both height and depth. I very
clearly was talking about changing only one. I quote
myself:
changing the height alone is sufficient to shift
the reference point, but changing the depth is not.
(and this time I actually did test it). Then I said
This is reversed for \vtop.
which refers to changing the depth only. Sadly I did not test
this and it turns out I was wrong. After a vertical box is
completed TeX doesn't care which command (\vbox or \vtop)
created it (as I should have realized).
Dan
> But you are changing both height and depth. I very
> clearly was talking about changing only one. I quote
> myself:
>
> changing the height alone is sufficient to shift
> the reference point, but changing the depth is not.
>
> (and this time I actually did test it). Then I said
>
> This is reversed for \vtop.
>
> which refers to changing the depth only. Sadly I did not test
> this and it turns out I was wrong. After a vertical box is
> completed TeX doesn't care which command (\vbox or \vtop)
> created it (as I should have realized).
I came to the same conclusion by a different route.
When the contents of boxes are written to the
log file, one gets \vbox but not \vtop. I was
interested in the inverse problem, of constructing
the box from the contents of the log file.
Hence my realisation that \vtop, although a
primitive of TeX, was in some sense not as
primitive as \vbox.
best regards
Jonathan
> I came to the same conclusion by a different route.
> When the contents of boxes are written to the
> log file, one gets \vbox but not \vtop. I was
> interested in the inverse problem, of constructing
> the box from the contents of the log file.
>
> Hence my realisation that \vtop, although a
> primitive of TeX, was in some sense not as
> primitive as \vbox.
\vbox, \vbox, wherefore art though \vbox?
What's in a name? That which we call a \vbox
By any other word would smell as vertical.
Uh, I mean that the label TeX chooses to tack onto a boxed vertical
list when showing it is not really related to the primitive in any
manner.
So I'd say that \vtop and \vbox exhibit pretty much the same level of
primitivity, even though the log file fancies to use the given name of
one of them for its output of a boxed vertical list.
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
UKTUG FAQ: <URL:http://www.tex.ac.uk/cgi-bin/texfaq2html>
> \vbox, \vbox, wherefore art though \vbox?
My track record with Early Modern English is abysmal in recent times.
I mean "wherefore art thou", of course.
> What's in a name? That which we call a \vbox
> By any other word would smell as vertical.
>
> Uh, I mean that the label TeX chooses to tack onto a boxed vertical
> list when showing it is not really related to the primitive in any
> manner.
>
> So I'd say that \vtop and \vbox exhibit pretty much the same level of
> primitivity, even though the log file fancies to use the given name of
> one of them for its output of a boxed vertical list.
Thank you for this, David. My view is that TeX
goes to some lengths to be as informative as it can
in the log file.
For example, it distinguishes between implicit and
explicit kerns. And where possible it attributes
glue to \baselineskip etc.
And so if TeX were capable of distiguishing vboxes
formed by \vbox and \vtop, the log file would record
this difference.
--
Jonathan
> TeX goes to some lengths to be as informative as it can
> in the log file.
> For example, it distinguishes between implicit and
> explicit kerns. And where possible it attributes
> glue to \baselineskip etc.
> And so if TeX were capable of distiguishing vboxes
> formed by \vbox and \vtop, the log file would record
> this difference.
Yes it is suggestive, though not proof.
In fact most of the boxes you see in traced output were
generated by neither \vbox nor \vtop (nor \hbox for those
labelled \hbox) but by TeX's internal mechanisms. (Plus
some by \vsplit).
--
Donald Arseneau as...@triumf.ca
> \vbox, \vbox, wherefore art though \vbox?
You misspelled "thought".
--
Donald Arseneau as...@triumf.ca
> David Kastrup <d...@gnu.org> writes:
>
>> \vbox, \vbox, wherefore art though \vbox?
>
> You misspelled "thought".
"thou" rather. I mentioned this already.
"thou" in the original; "thought" for a clever twist in this context :)
W
I hope no-one thinks it off-topic (smile), but here
is something I posted earlier to this thread. It
seems to me that a
\boxitem <number> <vertical box>
command would solve many problems. I'd welcome
opinion on this from any of the above.
==
Therefore, the key new primitive is the height of
the first item in the vertical list in a \vbox.
Indeed, from \vtop we can compute this value - it
is the \ht of the \vtop box.
Now let's generalise a little. Let's allow
access to all properties of all items in the vertical
list in a \vbox.
So the new primitive I was asking for is, I claim,
\vboxitem <number> <vertical box>
which
a) does not change the <vertical box>
b) adds to the current list a copy of the
<number> item in the <vertical box>.
We can then compute <magic1> as
\setbox 2 = \vbox{\vboxitem 1 \box 0}
<magic1> = \ht 2
By the way, one can just as well drop the 'vertical'
in the definition of \vboxitem, to give the more
general \boxitem.
One problem. I've not checked, but I am fairly sure
that without a change to the data structures of
TeX, the running time of \boxitem n will be linear
in n, and so running through a box will be
quadratic in the number of top-level items in the
box.
==
--
Jonathan