A new font selection scheme for TEX macro packages (Basic Macros)^{∗}

Frank Mittelbach  Rainer Schöpf

March 27, 1996

This file contains the main implementation of the ‘low level’ font selection commands. See other parts of the L^{A}TEX distribution, or The L^{A}TEX Companion for higher level documentation of the L^{A}TEX ‘New’ Font Selection Scheme.

Warning: The macro documentation is still basically the documentation from the first NFSS release and therefore in some cases probably not completely accurate.

1 Autoloading parts of NFSS

This code is set up in a way that some parts of it can be kept separate and will only be loaded if needed.

If we are producing an autoload version of L^{A}TEX 2ε then all those parts with def1 or def2 docstrip guards will be placed into the autoloadable files autofss1.sty

and autofss2.sty.

The ‘2ekernel’ code ensures that a \usepackage{autofss1} is essentially ignored if a ‘full’ format is being used that has picture mode already in the format.

Note the autofss2 loading is currently disabled.

 1 ⟨2ekernel⟩\expandafter\let\csname ver@autofss1.sty\endcsname\fmtversion

The autoload file autofss2 is a specialty because it contains code which will be completely local, ie loaded every time again.

2 Preliminary macros

We define a number of macros that will be used later.

∗This file has version number v3.0o dated 1995/12/06

\@nomath \@nomath is used by most macros that will have no effect in math mode. It issues a warning message.

2 ⟨∗2ekernel | autoload⟩

 3 \def\@nomath#1{\relax\ifmmode
 4 \@font@warning{Command \noexpand#1invalid in math mode}\fi}

5 ⟨/2ekernel | autoload⟩

\no@alphabet@error The macro \no@alphabet@error is called whenever the user requests a math alphabet that is not available in the current version. In math mode an error message is produced otherwise the command keeps silent. The argument is the name of the control sequence that identifies the math alphabet. The \relax at the beginning is necessary to prevent TEX from scanning too far in certain situations.

6 ⟨∗2ekernel | def1⟩

 7 \gdef\no@alphabet@error#1{\relax \ifmmode
 8  \@latex@error{Math\space alphabet\space identifier\space
 9  \noexpand#1is\space undefined\space in\space math\space
10  version\space `\math@version'}%
11  {Your\space requested\space math\space alphabet\space
12  is\space undefined\space in\space the\space current\space
13  math\space version.^^JCheck\space the\space spelling\space
14  or\space use\space the\space \noexpand\SetMathAlphabet\space
15  command.}
16  \fi}

17 ⟨/2ekernel | def1⟩ 18 ⟨∗autoload⟩

19 \gdef\no@alphabet@error{\relax \ifmmode
20  \expandafter\try@sizes\expandafter\no@alphabet@error \fi}

21 ⟨/autoload⟩

\new@mathgroup \mathgroup We also give a new name to \newfam and \fam to avoid verbal confusion (see the introduction).^{1}

22 ⟨∗2ekernel | autoload⟩

23 \def\new@mathgroup{\alloc@8\mathgroup\chardef\sixt@@n}
24 \let\mathgroup\fam
25 \let\newfam\new@mathgroup
26 \@onlypreamble\new@mathgroup

3 Macros for setting up the tables

\DeclareFontShape The macro \DeclareFontShape takes 6 arguments:
27 \def\DeclareFontShape{\begingroup

First we restore the catcodes of all characters used in the syntax.

28 \nfss@catcodes

1For the same reason it seems advisable to \let\fam and \newfam equal to \relax, but this is commented out to retain compatibility to existing style files.

We use \expandafter\endgroup to restore catcode in case something goes wrong with the argument parsing (suggested by Tim Van Zandt)

\DeclareFontShape
29 \expandafter\endgroup
30 \DeclareFontShape@}
31 \def\DeclareFontShape@#1#2#3#4#5#6{%
32 \expandafter\ifx\csname #1+#2\endcsname\relax
33  \@latex@error{Font family `#1+#2' unknown}\@eha
34 \else
35  \expandafter
36  \xdef\csname#1/#2/#3/#4\endcsname{\expandafter\noexpand
37  \csname #5\endcsname}%
38  \def\reserved@a{#6}%
39  \global
40  \expandafter\let\csname#5\expandafter\endcsname
41  \ifx\reserved@a\@empty
42  \@empty
43  \else
44  \reserved@a
45  \fi
46 \fi

47 }

\DeclareFixedFont Define a direct font switch that avoids all overhead.

48 \def\DeclareFixedFont#1#2#3#4#5#6{%
49 \begingroup
50  \math@fontsfalse
51  \every@math@size{}%
52  \fontsize{#6}\z@
53  \usefont{#2}{#3}{#4}{#5}%
54  \global\expandafter\let\expandafter#1\the\font
55 \endgroup

56 } 57 ⟨/2ekernel | autoload⟩

\do@subst@correction

58 ⟨∗2ekernel | autoload⟩

59 \def\do@subst@correction{%
60  \xdef\subst@correction{%
61  \font@name
62  \global\expandafter\font
63  \csname \curr@fontshape/\f@size\endcsname
64  \noexpand\fontname\font
65  \relax}%

Calling \subst@correction after the current group means calling it after we have loaded the substitution font which is done inside a group.

66  \aftergroup\subst@correction

67 }

\DeclareFontFamily
68 \def\DeclareFontFamily#1#2#3{%

If we want fast checking for the encoding scheme we can just check for \T@.. being defined.

69 % \@tempswafalse
70 % \def\reserved@b{#1}%
71 % \def\cdp@elt##1##2##3##4{\def\reserved@c{##1}%
72 %      \ifx\reserved@b\reserved@c \@tempswatrue\fi}%
73 % \cdp@list
74 % \if@tempswa
75 \@ifundefined{T@#1}%
76  {%
77  \@latex@error{Encoding scheme  `#1' unknown}\@eha
78  }%
79  {%

Now we have to define the macro \⟨#1 ⟩+⟨#2 ⟩ to contain #3. But since most of the time #3 will be empty we use \let in a tricky way rather than a simple \def since this will save internal memory. We store the argument #3 in a temporary

macro \reserved@a.
80  \def\reserved@a{#3}%

We compare \reserved@a with \@empty If these two are the same we \let the ‘extra’ macro equal to \@empty which is not the same a doing a \let to \reserved@a — the latter would blow one extra memory location rather then reusing the one

from \@empty.
81  \global
82  \expandafter\let\csname #1+#2\expandafter\endcsname
83  \ifx \reserved@a\@empty
84  \@empty
85  \else \reserved@a
86  \fi
87  }%

88 }

\cdp@list We initialize the code page list to be empty.

89 \let\cdp@list\@empty
90 \@onlypreamble\cdp@list
\cdp@elt
91 \let\cdp@elt\relax
92 \@onlypreamble\cdp@elt
\DeclareFontEncoding
93 \def\DeclareFontEncoding{%

First we start with ignoring all blanks and newlines since every surplus space in the second or third argument will come out in a weird place in the document.

94 \begingroup

 95 \nfss@catcodes
 96 \expandafter\endgroup
 97 \DeclareFontEncoding@}
 98 \@onlypreamble\DeclareFontEncoding
 99 \def\DeclareFontEncoding@#1#2#3{%
100 \expandafter
101 \ifx\csname T@#1\endcsname\relax
102  \def\cdp@elt{\noexpand\cdp@elt}%
103  \xdef\cdp@list{\cdp@list\cdp@elt{#1}%
104  {\default@family}{\default@series}%
105  {\default@shape}}%

To support encoding dependent commands (like accents) we initialise the command \⟨encoding⟩-cmd to be \@changed@cmd. (See ltoutenc.dtx for details.)

106  \expandafter\let\csname#1-cmd\endcsname\@changed@cmd
107 \else
108  \@font@info{Redeclaring font encoding #1}%
109 \fi
110 \global\@namedef{T@#1}{#2}%
111 \global\@namedef{M@#1}{\default@M#3}%

112 }

113 \@onlypreamble\DeclareFontEncoding@
\DeclareFontSubstitution
114 \def\DeclareFontSubstitution#1#2#3#4{%
115 \expandafter
116 \ifx\csname T@#1\endcsname\relax
117  \@latex@error{Encoding scheme  `#1' unknown}\@eha
118 \else
119  \begingroup
120  \def\reserved@a{#1}%
121  \toks@{}%
122  \def\cdp@elt##1##2##3##4{%
123  \def\reserved@b{##1}%
124  \ifx\reserved@a\reserved@b
125  \addto@hook\toks@{\cdp@elt{#1}{#2}{#3}{#4}}%
126  \else
127  \addto@hook\toks@{\cdp@elt{##1}{##2}{##3}{##4}}%
128  \fi}%
129  \cdp@list
130  \xdef\cdp@list{\the\toks@}%
131  \endgroup
132  \global
133  \@namedef{D@#1}{%
134  \def\default@family{#2}%
135  \def\default@series{#3}%
136  \def\default@shape{#4}%

137 }%

138 \fi

140 \@onlypreamble\DeclareFontSubstitution
\DeclareFontEncodingDefaults
141 \def\DeclareFontEncodingDefaults#1#2{%
142 \ifx\relax#1\else
143  \ifx\default@T\@empty\else
144  \@font@info{Overwriting encoding scheme text defaults}%
145  \fi
146  \gdef\default@T{#1}%
147 \fi
148 \ifx\relax#2\else
149  \ifx\default@M\@empty\else
150  \@font@info{Overwriting encoding scheme math defaults}%
151  \fi
152  \gdef\default@M{#2}%
153 \fi

154 }

155 \@onlypreamble\DeclareFontEncodingDefaults
\default@T \default@M
156 \let\default@T\@empty
157 \let\default@M\@empty
\DeclarePreloadSizes
158 \def\DeclarePreloadSizes#1#2#3#4#5{%
159 \@ifundefined{T@#1}%
160 {\@latex@error{Encoding scheme  `#1' unknown}\@eha}%

161 {%

Don’t know at the moment what this group here does!

162 \begingroup

We define a macro \reserved@f^{2} that grabs the next size and loads the corresponding font. This is done by delimiting \reserved@f’s only argument by the token , (comma).

163  \def\reserved@f##1,{%

The end of the list will be detected when there are no more elements, i.e. when \reserved@f’s argument is empty. The trick used here is explained in Appendix D of the TEXbook: if the argument is empty the \if will select the first clause and \let \reserved@f equal to \relax. (We use the > character here since it cannot appear in font file names.)

164  \if>##1>%
165  \let\reserved@f\relax
166  \else

2We cannot use \@tempa since it is needed in \pickup@font.

Otherwise, we define \font@name appropriately and call \pickup@font to do the work. Note that the requested \curr@fontshape combination must have been defined, or you will get an error. The definition of \font@name is carried out globally to be consistent with the rest of the code in this file.

167  \xdef\font@name{\csname#1/#2/#3/#4/##1\endcsname}%
168  \pickup@font

Now we forget the name of the font just loaded. More precisely, we set the corresponding control sequence to \relax. This means that later on, when the font is first used, the macro \define@newfont is called again to execute the ‘extra’ macro for this font.

169  \global\expandafter\let\font@name\relax
170  \fi

Finally we call \reserved@f again to process the next size. If \reserved@f was \let equal to \relax this will end the macro.

171  \reserved@f}%

We finish with reinserting the list of sizes after the \reserved@f macro and appending an empty element so that the end of the list is recognized properly.

172  \reserved@f#5,,%
173 \endgroup

174 }% 175 }

176 \@onlypreamble\DeclarePreloadSizes

\ifmath@fonts We need a switch to decide if we have to switch math fonts. For this purpose we provide \ifmath@fonts that can be set to true or false by the \S@... macros depending on if math fonts are provided for this size or not. The default is of course to switch all fonts.

177 \newif\ifmath@fonts \math@fontstrue
\DeclareMathSizes \DeclareMathSizes*  \DeclareMathSizes takes the text size, math text size, math script size, and math

scriptscript size as arguments and defines the right \S@… macro.

178 \def\DeclareMathSizes{%
179 \@ifstar{\@DeclareMathSizes\math@fontsfalse}%
180  {\@DeclareMathSizes{}}}
181 \@onlypreamble\DeclareMathSizes
\@DeclareMathSizes
182 \def\@DeclareMathSizes#1#2#3#4#5{%
183  \@defaultunits\dimen@#2pt\relax\@nnil
184  \def\reserved@a{#3}%
185  \ifx\reserved@a\@empty
186  \expandafter \let
187  \csname S@\strip@pt\dimen@\endcsname
188  \math@fontsfalse
189  \else
190  \expandafter \gdef

191  \csname S@\strip@pt\dimen@\endcsname
192  {\gdef\tf@size{#3}\gdef\sf@size{#4}%
193  \gdef\ssf@size{#5}%
194  #1%

195 }%

196  \fi}
197 \@onlypreamble\@DeclareMathSizes

4 Selecting a new font

4.1 Macros for the user

\fontencoding \f@encoding As we said in the introduction a font is described by four parameters. We first define macros to specify the wanted family, series, or shape. These are simply recorded in internal macros \f@family, \f@series, and \f@shape, resp. We use \edef’s so that the arguments can also be macros.

198 \DeclareRobustCommand\fontencoding[1]{%
199  \expandafter\ifx\csname T@#1\endcsname\relax
200  \@latex@error{Encoding scheme `#1' unknown}\@eha
201  \else
202  \edef\f@encoding{#1}%
203  \ifx\cf@encoding\f@encoding

If the new encoding is the same as the old encoding we have nothing to do. However, in case we had a sequence of several encoding changes without a \selectfont inbetween we can save processing by making sure that \enc@update is \relax.

204  \let\enc@update\relax
205  \else

If current and new encoding differ we define the macro \enc@update to contain all updates necessary at \selectfont time.

206  \let\enc@update\@@enc@update
207  \fi
208  \fi

209 }

\@@enc@update
210 \def\@@enc@update{%

When \@@enc@update is executed \f@encoding holds the encoding name for the new encoding and \cf@encoding the name of the last active encoding.

We start by setting the init command for encoding dependent macros to

\@changed@cmd.
211  \expandafter
212  \let
213  \csname\cf@encoding -cmd\endcsname
214  \@changed@cmd

Then we turn the one for the new encoding to \@current@cmd (see ltoutenc.dtx for further explanations).

215  \expandafter
216  \let
217  \csname\f@encoding-cmd\endcsname
218  \@current@cmd

We execute the default settings \default@T, followed by the one for the new encoding.

219  \default@T
220  \csname T@\f@encoding\endcsname

Finally we change the default substitution values, disable \enc@update and make \f@encoding officially the current encoding.

221  \csname D@\f@encoding\endcsname
222  \let\enc@update\relax
223  \let\cf@encoding\f@encoding

224 }

\enc@update The default action in \selectfont is to do nothing.

225 \let\enc@update\relax
\fontfamily
\f@family
\fontseries
\f@series
\fontshape
\f@shape

226 \DeclareRobustCommand\fontfamily[1]{\edef\f@family{#1}}
227 \DeclareRobustCommand\fontseries[1]{\edef\f@series{#1}}
228 \DeclareRobustCommand\fontshape [1]{\edef\f@shape{#1}}

Some handy abbreviation if you want to get some particular font in the current size. If also the size should change one has to issue a \fontsize comand first.

229 \def\usefont#1#2#3#4{\fontencoding{#1}\fontfamily{#2}%
230  \fontseries{#3}\fontshape{#4}\selectfont
231  \ignorespaces}
\linespread The comand \linespread changes the current \baselinestretch by calling
\set@fontsize. The values for \f@size and \f@baselineskip will be left un-

changed.

232 \DeclareRobustCommand\linespread[1]
233 {\set@fontsize{#1}\f@size\f@baselineskip}

\fontsize We also define a macro that allows to specify a size. In this case, however, we also need the value of \baselineskip. As the first argument to \set@fontsize we pass the current value of \baselinestretch. This will either match the internal value (in which case nothing changes, or it will be an updated value due to a user change of that macro using \renewcommand. If we would pass the internal \f@linespread such a change would be efectively overwritten by a size change.

234 \DeclareRobustCommand\fontsize[2]
235 {\set@fontsize\baselinestretch{#1}{#2}}

\f@linespread This macro holds the current internal value for \baselinestretch.

236 \let\f@family\@empty
237 \let\f@series\@empty
238 \let\f@shape\@empty
239 \let\f@size\@empty
240 \let\f@baselineskip\@empty
241 \let\f@linespread\@empty
\cf@encoding
242 \let\f@encoding\@empty
243 \let\cf@encoding\@empty

\@defaultunits The function \@defaultunits when wrapped around a dimen or skip assignment

supplies default units. Usage:

   \@defaultunits\dimen@=#1pt\relax\@nnil

Note: the \relax is *important*. Other units can be substituted for the ‘pt’ if desired.

We use \remove@to@nnil as an auxiliary macros for \@defaultunits. It just has to gobble the supplied default unit ‘pt’ or whatever, if it wasn’t used in the assignment.

244 \def\@defaultunits{\afterassignment\remove@to@nnil}

\strip@pt \rem@pt This macro strips the characters pt produced by using \the on a dimen register.

245 \begingroup
246 \catcode`P=12
247 \catcode`T=12
248 \lowercase{
249  \def\x{\def\rem@pt##1.##2PT{##1\ifnum##2>\z@.##2\fi}}}
250 \expandafter\endgroup\x
251 \def\strip@pt{\expandafter\rem@pt\the}
\mathversion \math@version  \mathversion takes the math version name as argument, defines \math@version

appropriately and switches to the font selected forcing a call to \glb@settings if the version is known to the system.

252 \DeclareRobustCommand\mathversion[1]
253  {\@nomath\mathversion
254  \expandafter\ifx\csname mv@#1\endcsname\relax
255  \@latex@error{Math version `#1' is not defined}\@eha\else
256  \edef\math@version{#1}%

We need to force a math font setup both now and at the point where we return to the previous math version. Forcing a math font setup can simply be done by setting \glb@currsize to an invalid value since this will trigger the setup when the formula starts.

257  \gdef\glb@currsize{}%

When the scope of the current \mathversion ends we need to restore the old setup. However this time we need to force it directly at least if we are inside math, otherwise we could wait. Another way to enhance this code here is todo the setting only if the version really has changed after all. This might be interesting

in case of amstext and boldsymbol.
258  \aftergroup\glb@settings
259  \fi}

If TEX would support a hook just before the end of a formula (opposite of \everymath so to speak) the implementation of the algorithm would be much simpler because in that case we would set up the correct math fonts at this point without having to worry about incorrect settings due to nesting. The same would be true if in L^{A}TEX the use of $ (as the primitive TEX command) would be impossible and instead only a higher-level interface would be available. Note that this does not mean that a $ couldn’t be the short-hand for starting and stopping that higher-level interface, it only means that the direct TEX function must be hidden.

Anyway, since we don’t have this and won’t have it in L^{A}TEX 2ε we need to implement it in a somewhat slower way.

We test for the current math font setup on entry of a formula, i.e., on the hooks \everymath and \everydisplay. But since these hooks may contain user data we provide ourselves with an internal version of these hooks which stays frozen.

\frozen@everymath \frozen@everydisplay New internal names for \everymath and \everydisplay.
260 \let\frozen@everymath\everymath
261 \let\frozen@everydisplay\everydisplay

\everymath \everydisplay Now we provide now user hooks that will be called in the frozen internals.

262 \newtoks\everymath
263 \newtoks\everydisplay

\frozen@everymath Now we define the behaviour of the frozen hooks: first check the math setup then call the user hook.

264 \frozen@everymath = {\check@mathfonts
265  \the\everymath}

\frozen@everydisplay Ditto for the display hook.

266 \frozen@everydisplay = {\check@mathfonts
267  \the\everydisplay}

\if@inmath To detect nested formulae we need a switch.

268 \newif\if@inmath

\curr@math@size This holds locally the current math size.

269 \let\curr@math@size\@empty

4.2 Macros for loading fonts

\pickup@font The macro \pickup@font which is used in \selectfont is very simple: if the font name is undefined (i.e. not known yet) it calls \define@newfont to load it.

270 \def\pickup@font{%

271  \expandafter \ifx \font@name \relax
272  \define@newfont
273  \fi}

\split@name \pickup@font assumes that \font@name is set but it is sometimes called when

\f@family, \f@series, \f@shape, or \f@size may have the wrong settings (see,

e.g., the definition of \getanddefine@fonts). Therefore we need a macro to extract font family, series, shape, and size from the font name. To this end we define \split@name which takes the font name as a list of characters of \catcode 12 (without the backslash at the beginning) delimited by the special control sequence \@nil. This is not very complicated: we first ensure that / has the right

\catcode
274 {\catcode`\/=12

and define \split@name so that it will define our private \f@encoding, \f@family,

\f@series, \f@shape, and \f@size macros.
275 \gdef\split@name#1/#2/#3/#4/#5\@nil{\def\f@encoding{#1}%
276  \def\f@family{#2}%
277  \def\f@series{#3}%
278  \def\f@shape{#4}%
279  \def\f@size{#5}}}

\curr@fontshape Abbreviation which may get removed again for speed.

280 \def\curr@fontshape{\f@encoding/\f@family/\f@series/\f@shape}

281 ⟨/2ekernel | autoload⟩

\define@newfont Now we can tackle the problem of defining a new font.

282 ⟨∗2ekernel | def2 | autoload⟩

283 \def\define@newfont{%

We have already mentioned that the token list that \split@name will get as argument must not start with a backslash. To reach this goal we will set the \escapechar to −1 so that the \string primitive will not generate an escape character. To keep this change local we open a group. We use \begingroup for this purpose since \define@newfont might be called in math mode, and an empty \bgroup… \egroup would add an empty Ord atom to the math list and thus affect the spacing.

Also locally redefine \typeout so that ‘No file ...fd’ Warnings become Font Info message just sent to the log file.

284 \begingroup
285  \let\typeout\@font@info
286  \escapechar\m@ne

Then we extract encoding scheme, family, series, shape, and size from the font name. Note the four \expandafter’s so that \font@name is expanded first, then

\string, and finally \split@name.
287  \expandafter\expandafter\expandafter
288  \split@name\expandafter\string\font@name\@nil

If the \curr@fontshape combination is not available, (i.e. undefined) we call the macro \wrong@fontshape to take care of this case. Otherwise \extract@font will load the external font for us.

289 %    \expandafter\ifx
290 %        \csname\curr@fontshape\endcsname \relax
291  \try@load@fontshape % try always
292 %    \fi
293  \expandafter\ifx
294  \csname\curr@fontshape\endcsname \relax
295  \wrong@fontshape\else

To allow substitution we call the curr@fontshape macro which usually will expand to \relax but may hold code for substitution (see \subst@fontshape definition).

296 %      \csname\curr@fontshape\endcsname
297  \extract@font\fi

We are nearly finished and must only restore the \escapechar by closing the group.

298 \endgroup}

299 ⟨/2ekernel | def2 | autoload⟩

As autofss2.sty only makes local definitions it is re-loaded for each font, to save some string memory in the kernel, and to speed up the loading of some packages which may load fonts The code is actually pre-loaded into the kernel and removed at \begin{document}. The \ifx test below ensures that if \usepackage{autofss2} apears in the preamble, then the code is not removed at this time. Can not use \AtBeginDocument here as it is not defined yet! Listing all the commands like this is not ideal as any changes to the autofss2.sty need to be reflected here, but this seems the most memory efficient mechanism as it avoids the use of an extra csname to store the list.

This is currently disabled, so the ‘autofss2’ code remains in the kernel, and autofss2.sty is not generated in the current public release.

300 ⟨∗autoloadxxx⟩

301 \expandafter\def\expandafter\@begindocumenthook\expandafter{%
302 \expandafter\ifx\csname ver@autofss2.sty\endcsname\relax
303 \gdef\define@newfont{%
304  \begingroup
305  \makeatletter\nfss@catcodes
306  \catcode`\#6\relax
307  \@@input autofss2.sty\relax\define@newfont
308  \endgroup}%
309 \begingroup
310  \def\do##1{\global\let##1\@undefined}%
311  \do\extract@sizefn
312  \do\try@simple@size
313  \do\set@simple@size@args
314  \do\extract@rangefontinfo
315  \do\is@range
316  \do\check@range

317  \do\check@single
318  \do\set@size@funct@args
319  \do\set@size@funct@args@
320  \do\try@size@range
321  \do\empty@sfcnt
322  \do\gen@sfcnt
323  \do\genb@sfcnt
324  \do\sub@sfcnt
325  \do\subf@sfcnt
326  \do\fixed@sfcnt
327 \endgroup
328 \fi}

329 ⟨/autoloadxxx⟩

330 ⟨∗2ekernel | autoload⟩

331 \def\try@load@fontshape{%
332 \expandafter
333 \ifx\csname \f@encoding+\f@family\endcsname\relax
334  \@font@info{Try loading font information for
335  \f@encoding+\f@family}%

We predefine this combination to be \@empty which means that next time we don’t try again unnecessary in case we don’t find a .fd file. If the file contains a \DeclareFontFamily command than this setting will be overwritten.

336  \global\expandafter\let
337  \csname\f@encoding+\f@family\endcsname\@empty
338  \makeatletter

Set the catcodes used in the syntax, but do it only once (this will be restored at the end of the font loading group).

339  \nfss@catcodes
340  \let\nfss@catcodes\relax
341  \@input@{\f@encoding\f@family.fd}%
342 \fi

343 }

\nfss@catcodes This macro should contain the standard \catcode assignments to all characters which are used in the commands found in an .fd file and which might have special \catcodes in the middle of a document. If necessary, this list can be extended in a package file using a suitable number of \expandafter, i.e.,

   \expandafter\def\expandafter\nfss@catcodes
         \expandafter{\nfss@catcodes <additional settings>}

Note, that this macro might get executed several times since it is also called by \DeclareFontShape, thus it probably should not be misused as a general purpose hook.

344 \def\nfss@catcodes{%

First we start with ignoring all blanks and newlines.

345  \catcode`\ 9\relax

346  \catcode`\^^I9\relax
347  \catcode`\^^M9\relax

Then we set up \, {, }, # and % in case an .fd file is loaded during a verbatim environment.

348  \catcode`\\\z@
349  \catcode`\{\@ne
350  \catcode`\}\tw@
351  \catcode`\#6\relax
352  \catcode`\^7\relax
353  \catcode`\%14\relax

The we make sure that the important syntax parts have the right \catcode.

354 \@makeother\<%
355 \@makeother\>%
356 \@makeother\*%
357 \@makeother\.%
358 \@makeother\-%
359 \@makeother\/%
360 \@makeother\[%
361 \@makeother\]%

362 }

\DeclareErrorFont Declare the last resort shape! We assume that in this fontshape there is a 10pt font but it doesn’t really matter. We only loose one macro name if the assumption is false. But at least the font should be there!

363 \def\DeclareErrorFont#1#2#3#4#5{%
364  \xdef\error@fontshape{%
365  \noexpand\expandafter\noexpand\split@name\noexpand\string
366  \expandafter\noexpand\csname#1/#2/#3/#4/#5\endcsname
367  \noexpand\@nil}%

Initialize all those internal variables which may or may not have values in the first seconds of NFSS’ bootstraping process. Later on such values will be updated when an encoding is selected, etc.

We definitely don’t want to set \f@encoding; we can set all the others since if they are left “blank” any selection would grap “error default values” as well. However, this probably should go also.

368 %      \gdef\f@encoding{#1}%
369  \gdef\default@family{#2}%
370  \gdef\default@series{#3}%
371  \gdef\default@shape{#4}%
372  \global\let\f@family\default@family
373  \global\let\f@series\default@series
374  \global\let\f@shape\default@shape
375  \gdef\f@size{#5}%
376  \gdef\f@baselineskip{#5pt}%

377 }

378 \@onlypreamble\DeclareErrorFont

\wrong@fontshape Before we come to the macro \extract@font we have to take care of unknown \curr@fontshape combinations. The general strategy is to issue a warning and to try a default shape, then a default series, and finally a default family. If this last one also fails TEX will go into an infinite loop. But if the defaults are set incorrectly one deserves nothing else!

379 \def\wrong@fontshape{%
380  \csname D@\f@encoding\endcsname      % install defaults if in math

We remember the wanted \curr@fontshape combination which we will need in a moment.

381  \edef\reserved@a{\csname\curr@fontshape\endcsname}%
382 \ifx\last@fontshape\reserved@a
383  \errmessage{Corrupted NFSS tables}%
384  \error@fontshape
385 \else

Then we warn the user about the mess and set the shape to its default.

386  \let\f@shape\default@shape

If the combination is not known, try the default series.

387  \expandafter\ifx\csname\curr@fontshape\endcsname\relax
388  \let\f@series\default@series

If this is still undefined, try the default family. Otherwise give up. We never try to change the encoding scheme!

389  \expandafter
390  \ifx\csname\curr@fontshape\endcsname\relax
391  \let\f@family\default@family
392  \fi \fi
393 \fi

At this point a valid \curr@fontshape combination must have been found. We inform the user about this fact.

The \expandafter\string here stops TEX adding the space that it usually puts after command names in messages. The similar construction with \@undefined just produces ‘undefined’, but saves a few tokens.

\@wrong@font@char is locally redefined in \UseTextSymbol from its normal (empty) definition, to report the symbol generating the font switch.

394  \@font@warning{Font shape `\expandafter\string\reserved@a'
395  \expandafter\@gobble\string\@undefined\MessageBreak
396  using `\curr@fontshape' instead\@wrong@font@char}%
397  \global\let\last@fontshape\reserved@a

We change \@defaultsubs to produce a warning at the end of the document. The macro \@defaultsubs is initially \relax but gets changed here if some default font substitution happens. It is then executed in \enddocument.

398  \gdef\@defaultsubs{%
399  \@font@warning{Some font shapes were not available, defaults
400  substituted.\@gobbletwo}}%

If we substitute a \curr@fontshape combination by the default one we don’t want the warning to be printed out whenever this (unknown) combination is used. Therefore we globally \let the macro corresponding to the wanted combination equal to its substitution. This requires the use of four \expandafter’s since \csname… \endcsname has to be expanded before \reserved@a (i.e. the requested combination), and this must happen before the \let is executed.

401  \global\expandafter\expandafter\expandafter\let
402  \expandafter\reserved@a
403  \csname\curr@fontshape\endcsname

Now we can redefine \font@name accordingly. This must be done globally since it might occur in the group opened by \define@newfont. If we would this definition were local the closing \endgroup there would restore the old meaning of \font@name and then switch to the wrong font at the end of \selectfont although the correct font was loaded.

404  \xdef\font@name{%
405  \csname\curr@fontshape/\f@size\endcsname}%

The last thing this macro does is to call \pickup@font again to load the font if it is not defined yet. At this point this code will loop endlessly if the defaults are not well defined.

406  \pickup@font}

\@wrong@font@char Normally empty but redefined in \UseTextSymbol so that the Font shape undefined message can refer to the symbol causing the problem.

407 \let\@wrong@font@char\@empty
\@@defaultsubs \@defaultsubs See above.
408 \let\@defaultsubs\relax

\strip@prefix In \extract@font we will need a way to recover the replacement text of a macro. This is done by the primitive \meaning together with the macro \strip@prefix (for the details see appendix D of the TEXbook, p. 382).

409 \def\strip@prefix#1>{}

5 Assigning math fonts to versions

\install@mathalphabet This is just another name for \gdef but we can redefine it if necessary later on.

410 \let\install@mathalphabet\gdef
\math@fonts
411 \let\math@fonts\@empty

\select@group \select@group has four arguments: the new ⟨math alphabet identifier⟩ (a control sequence), the ⟨math group number⟩, the extra macro for math mode and the \curr@fontshape definition macro name. We first check if we are in math mode.

412 %\def\select@group#1#2#3{\relax\ifmmode

We do these things locally using \begingroup instead of \bgroup to avoid the appearance of an empty Ord atom on the math list.

413 %  \begingroup

We set the math fonts for the family in question by calling \getanddefine@fonts in the correct environment.

414 %     \escapechar\m@ne
415 %    \getanddefine@fonts{\csname c@mv@\math@version\endcsname}#3%

We globally select the math fonts…

416 %    \globaldefs\@ne  \math@fonts

… and close the group to restore \globaldefs and \escapechar.

417 %  \endgroup

As long as no size or version change occurs the ⟨math alphabet identifier⟩ should simply switch to the installed math group instead of calling \select@group unnecessarily. So we globally redefine the first argument (the new ⟨math alphabet identifier⟩) to expand into a \mathgroup switch and then select this alphabet. Note that this redefinition will be overwritten by the next call to a version macro. The original code for the end of \select@group was

  \gdef#1{#3\mathgroup #2}#1\fi}

i.e. first redefining the ⟨math alphabet identifier⟩ and then calling the new definition to switch to the wanted ⟨math group⟩. Now we define the ⟨math alphabet identifier⟩ as a call to the \use@mathgroup command.

418 %  \xdef#1{\noexpand\use@mathgroup\noexpand#2%
419 %          {\number\csname c@mv@\math@version\endcsname}}%

But this is not sufficient, as we learned the hard way. The problem here is that the loading of the fonts that comprise the alphabet identifier #1, as well as the necessary math font assignments is deferred until it is used. This is OK so far, but if the fonts are switched within the current formula (which may happen if a sub-formula is a box that contains a math version switch) the font assignments for #1 are not restored unless #1 is used again. This is disastrous since TeX sees the wrong fonts at the end of the math formula, when it converts the math list into a horizontal list.

This is taken into account as follows: When a math alphabet identifier is used for the first time in a certain version it modifies the corresponding macro \mv@⟨version⟩ so that it calls \getanddefine@fonts directly in future as well. We use the macro \extract@alph@from@version to do this. It takes the math alphabet identifer #1 and the math version macro as arguments.

420 %     \expandafter\extract@alph@from@version
421 %        \csname mv@\math@version\expandafter\endcsname
422 %       \expandafter{\number\csname c@mv@\math@version\endcsname}%
423 %       #1%
424 %     \stepcounter{mv@\math@version}%

Finally, it is not possible to simply call the new definition since we have an argument (the third argument of \use@mathgroup or more exactly the argument od \math@egroup if the margid option is in force) which would swallow our closing \fi. So we use the \expandafter technique to remove the \fi before the

\use@mathgroup is expanded.
425 %\expandafter #1\fi}
\extract@alph@from@version We proceed to the definition of the macro \extract@alph@from@version. As

stated above, it takes a math alphabet identifier and a math version macro (e.g. \mv@normal) as its arguments.

426 \def\extract@alph@from@version#1#2#3{%

To extract and replace the definition of math alphabet identifier #3 in macro #1 we have to recall how this definition looks like: Somewhere in the replacement text of #1 there is the sequence

\install@mathalphabet⟨math alphabet identifier⟩ #3{%

⟨Definitions for ⟩#3} Hence, the first thing we do is to extract the tokens preceding this definitions, the definition itself, and the tokens following it. To this end we define one auxiliary

macro \reserved@a.
427  \def\reserved@a##1\install@mathalphabet#3##2##3\@nil{%

When \reserved@a is expanded, it will have the tokens preceding the definition in question in its first argument (##1), the following tokens in its third argument (##3), and the replacement text for the math alphabet identifier #3 in its second argument. (##2). This is then recorded for later use in a temporary macro

\reserved@b.
428  \def\reserved@b{##2}%

Additionally, we define a macro \reserved@c to reconstruct the definitions for the math version in question from the tokens that will remain unchanged (##1 and ##3) and the yet to build new definitions for the math alphabet identifier #3.

429  \def\reserved@c####1{\gdef#1{##1####1##3}}}%

Then we execute our auxiliary macro.

430  \expandafter\reserved@a#1\@nil

OK, so now we have to build the new definition for #3. To do so, we first extract the interesting parts out of the old one. The old definition looks like: \select@group⟨math alphabet identifier⟩

⟨math group number⟩⟨math extra part⟩

⟨curr@fontshape definition⟩

So we define a new temporary macro \reserved@a that extracts these parts.

431  \def\reserved@a\select@group#3##1##2\@nil{%

This macro can now directly rebuild the math version definition by calling

\reserved@c:
432  \reserved@c{%
433  \getanddefine@fonts{#2}##2%
434  \install@mathalphabet#3{%
435  \relax\ifmmode \else \non@alpherr#3\fi
436  \use@mathgroup##1{#2}}}%

In addtion it defines the alphabet the way it should be used from now on.

437  \gdef#3{\relax\ifmmode \else \non@alpherr#3\fi
438  \use@mathgroup##1{#2}}}%

Finally, we only have to call this macro \reserved@a on the old definitions

 recorded in \reserved@b:
439  \expandafter\reserved@a\reserved@b\@nil

440 }

\math@bgroup \math@egroup Here are the default definitions for \math@bgroup and \math@egroup. We use

\bgroup instead of \begingroup to avoid ‘leaking out’ of style changes. This has the side effect of always producing mathord atoms.

441 \let\math@bgroup\bgroup
442 \def\math@egroup#1{#1\egroup}

443 ⟨/2ekernel | autoload⟩

\calculate@math@sizes Here is the default definition for \calculate@math@sizes a more elaborate interface is under testing in mthscale.sty.

444 ⟨∗2ekernel | def1⟩

445 \gdef\calculate@math@sizes{%
446 \@font@info{Calculating\space math\space sizes\space for\space
447  size\space <\f@size>}%
448 \dimen@\f@size \p@
449 \@tempdimb \defaultscriptratio \dimen@
450 \dimen@ \defaultscriptscriptratio \dimen@
451 \expandafter\xdef\csname S@\f@size\endcsname{%
452  \gdef\noexpand\tf@size{\f@size}%
453  \gdef\noexpand\sf@size{\strip@pt\@tempdimb}%
454  \gdef\noexpand\ssf@size{\strip@pt\dimen@}%
455  \noexpand\math@fontstrue}}

456 ⟨/2ekernel | def1⟩ 457 ⟨∗autoload⟩

458 \def\calculate@math@sizes{\try@sizes\calculate@math@sizes}

459 ⟨/autoload⟩

\defaultscriptratio \defaultscriptscriptratio The default ratio for math sizes is:
 1 to \defaultscriptratio to \defaultscriptscriptratio.

By default this is 1 to .7 to .5.

460 ⟨∗2ekernel | autoload⟩

461 \def\defaultscriptratio{.7}
462 \def\defaultscriptscriptratio{.5}

\noaccents@ If we don’t have a definition for \noaccents@ we provide a dummy.

463 \ifx\noaccents@\@undefined
464 \let\noaccents@\@empty
465 \fi
\showhyphens  \showhyphens must be redefined since the version in plain.tex uses \tenrm.

466 ⟨/2ekernel | autoload⟩ 467 ⟨∗2ekernel | autoerr⟩

468 \gdef\showhyphens#1{%
469 \setbox0\vbox{%
470  \color@begingroup
471  \parfillskip\z@skip\hsize\maxdimen
472  \normalfont
473  \pretolerance\m@ne\tolerance\m@ne\hbadness\z@\showboxdepth\z@\ #1%
474  \color@endgroup}}

475 ⟨/2ekernel | autoerr⟩

476 ⟨autoload⟩\def\showhyphens{\@autoerr\showhyphens}

477 ⟨∗2ekernel | autoload⟩

\addto@hook We need a macro to add tokens to a hook.

478 \long\def\addto@hook#1#2{#1\expandafter{\the#1#2}}
\@vpt
479 \def\@vpt{5}
\@vipt
480 \def\@vipt{6}
\@viipt
481 \def\@viipt{7}
\@viiipt
482 \def\@viiipt{8}
\@ixpt
483 \def\@ixpt{9}
\@xpt
484 \def\@xpt{10}
\@xipt
485 \def\@xipt{10.95}
\@xiipt
486 \def\@xiipt{12}
\@xivpt
487 \def\@xivpt{14.4}
\@xviipt
488 \def\@xviipt{17.28}
\@xxpt
489 \def\@xxpt{20.74}
\@xxvpt
490 \def\@xxvpt{24.88}

491 ⟨/2ekernel | autoload⟩