Saturday, September 4, 2010

Computing the maximum width of two boxes

On occasion, one has cause to compare two boxes and compute the maximum of the two widths. If the two boxes are 0 and 2, then the standard way to do that is something like
\ifdim\wd0>\wd2
    \dimen0 \wd0
\else
    \dimen0 \wd2
\fi
Of course, this works perfectly well. But sometimes, you want something that's a little less easy to read. Thus, I propose
\dimen0 \wd\ifdim\wd0>\wd2 0 \else2 \fi
The spaces around the numbers are to keep TeX from reading more input looking for additional digits.

Friday, August 27, 2010

http://tex.stackexchange.com/

New stack exchange site for TeX and LaTeX. I've probably spent too much time there. I've been meaning to write more here...and I will soon.

Wednesday, May 12, 2010

BibTeX hacking

I've avoided editing bst files but I finally encountered something that I felt needed to change. When abbreviating the name Foo Bar Baz, the abbrv bibliography style produces
F.~B.~Baz
which has too much space between the F and the B for my tastes. After making a copy of abbrv.bst (and renaming it), we can change the argument to the format.name$ function (see Section 18) from "{f.~}{vv~}{ll}{, jj}" to "{f{.\nobreak\,}.~}{vv~}{, jj}" to produce a nonbreaking thin space between the F. and the B. I hope I never again have to edit a a bst.

Sunday, May 9, 2010

Including overly large graphics

Sometimes a graphic (or table or what have you) is simply too large to fit on the page without extending into the margins. Here's a simple way to center the graphic in the page without getting any Overfull hbox warnings.
\par
\hbox to\textwidth{\hss\includegraphics{foo}\hss}%
\par
The two \par aren't really essential. They're just to ensure the graphic is in a paragraph by itself. Replace \includegraphics with any other centered material. Note that this actually causes the graphic to extend an equal amount into the margins. If the margins aren't the same size, this is not centering on the page, but it's probably what you want anyway.

Monday, April 5, 2010

Ordinal numbers

Ever want TeX to write an ordinal number correctly? There are a number of fairly complicated solutions on the web so I decided to write one that was easy to read and follow.
\def\ord#1{\begingroup
        \count@=#1\relax
        \the\count@
        \ifnum\count@>99
                \count0\count@
                \divide\count0 by100
                \multiply\count0 by100
                \advance\count@ by-\count0
        \fi
        \ifnum\count@>19
                \count0\count@
                \divide\count0 by10
                \multiply\count0 by10
                \advance\count@ by-\count0
        \fi
        \ifcase\count@ th%
                \or st%
                \or nd%
                \or rd%
                \else th%
        \fi
\endgroup}
Note that this requires @ to be a letter, so \makeatletter or \catcode`@11. The first \ifnum block mods out by 100 since that plays no role in determining the ordinal suffix. The next block mods out by 10 if \count@ is at least 20. This is because 10th through 19th use th but 20th through 99th only examine the ones digit. Lastly, if the one's digit is 0, 4, 5, 6, 7, 8, or 9, (or the tens digit is 1) use th, otherwise use st, nd, or rd as appropriate. Using old-style superscripts requires a trivial modification.

Default units

In the previous post, I mentioned that when changing font sizes, there is a neat hack that allows the font size macros to have default units. That is the subject of today's brief post. The setup is you want to devise a macro that sets a dimension register to a particular value. For example,
\newdimen\foo
\newcommand*\set[1]{\foo#1\relax}
Now if you know that most of the time the units used are in points—as is the case with the font size macros—you can add the units in the \set macro,
\newcommand*\set[1]{\foo#1 pt\relax}
This works unless you want to sometimes specify your own units. At this point, we can use the \afterassignment primitive and a macro with a delimited argument to scoop up the default units. This is exactly what the \@defaultunits macro does.
\def\@defaultunits{\afterassignment\remove@to@nnil}
\def\remove@to@nill#1\@nnil{}
We can change our \set macro to be
\newcommand*\set[1]{\@defaultunits\foo#1 pt\relax\@nnil}
Let's take a look to see what this does in two cases.
\set{10}
\set{10ex}
In the first case, \set expands which causes \@defaultunits to expand and the \afterassignment is set to \remove@to@nnil. Next, \foo 10 pt\relax causes the dimension register specified by \foo to be set to 10pt and now \remove@to@nnil expands which gobbles up the \@nnil and \set is finished.

In the second case, \@defaultunits expands and \afterassignment is set as before. This time, \foo 10ex causes the dimension register to be set to 10ex and \remove@to@nnil expands which gobbles the pt\relax\@nnil and \set is finished. The \relax is more crucial if the register being set is a skip register rather than a dimension register since the pt by itself is not sufficient for the assignment but the \relax causes TeX to stop looking for more skip specification tokens. Less brief than I intended.

Wednesday, March 31, 2010

Global font size changes

The question of how to change the font size for a row in a table came up recently. It's tricky since each cell in a tabular is in its own group. My thought was a global font size change for the row that needed it and then a global change back. Since commands like \tiny actually perform many different assignments, \global\tiny does not do what we need. TeX provides an \afterassignment primitive that takes the next token and places it after the next assignment. For example,
\afterassignment\TeX
\count255=3
\the\count255
acts like
\count255=3
\TeX
\the\count255
The basic idea is to use \afterassignment with a helper macro which uses \afterassignment and \global.
\def\helper{\afterassignment\helper\global}
This doesn't quite work since there's no good way to stop it. Modifying it slightly to make it conditional allows us to turn it off:
\newif\ifhelper
\def\helper{\ifhelper\afterassignment\helper\global\fi}
Two more snags remain. First, the font size changing macros actually make use of \afterassignment to allow default units (a neat trick in its own right) and \global\afterassignment is an error so we need to reimplement it. Similarly, vrule is used and \global \vrule is an error so we have to work around that. The final snag is that the first time TeX executes one of the font size commands like \tiny it performs extra work and that extra work doesn't play so nicely with our hack. The workaround for this is to simply execute the font size changing macro first. The complete code looks like this.
\newif\ifhelper
\makeatletter
\def\unithelper#1\@nnil{\global\helpertrue\helper}
\def\helper{\ifhelper\afterassignment\helper\global\fi}
\newcommand*\globalfontsize[1]{%
\begingroup
       #1%
       \def\@defaultunits{\helperfalse\afterassignment\unithelper\global}%
       \let\realvrule\vrule
       \def\vrule{\helperfalse\global\helpertrue\afterassignment\helper\realvrule}%
       \global\helpertrue
       \helper#1%
       \helperfalse
\endgroup}
\makeatother
\newcommand*\globaltiny{\globalfontsize\tiny}
\newcommand*\globalnormalsize{\globalfontsize\normalsize}
Now we can use \globaltiny and \globalnormalsize in the table to change the font for the whole row.