texinfo.tex 210 KB
Newer Older
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
1
2
3
4
5
% texinfo.tex -- TeX macros to handle Texinfo files.
%
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
6
\def\texinfoversion{2004-01-05.16}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
7
%
8
% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
9
10
% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
% Foundation, Inc.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
%
% This texinfo.tex file is free software; you can redistribute it and/or
% modify it under the terms of the GNU General Public License as
% published by the Free Software Foundation; either version 2, or (at
% your option) any later version.
%
% This texinfo.tex file is distributed in the hope that it will be
% useful, but WITHOUT ANY WARRANTY; without even the implied warranty
% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
% General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this texinfo.tex file; see the file COPYING.  If not, write
% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
% Boston, MA 02111-1307, USA.
%
27
28
29
30
% As a special exception, when this file is read by TeX when processing
% a Texinfo source document, you may use the result without
% restriction.  (This has been our intent since Texinfo was invented.)
% 
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
31
32
% Please try the latest version of texinfo.tex before submitting bug
% reports; you can get the latest version from:
33
%   http://www.gnu.org/software/texinfo/ (the Texinfo home page), or
34
%   ftp://tug.org/tex/texinfo.tex
35
36
%     (and all CTAN mirrors, see http://www.ctan.org).
% The texinfo.tex in any given distribution could well be out
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
37
38
39
40
41
42
43
44
45
46
47
48
49
% of date, so if that's what you're using, please check.
%
% Send bug reports to bug-texinfo@gnu.org.  Please include including a
% complete document in each bug report with which we can reproduce the
% problem.  Patches are, of course, greatly appreciated.
%
% To process a Texinfo manual with TeX, it's most reliable to use the
% texi2dvi shell script that comes with the distribution.  For a simple
% manual foo.texi, however, you can get away with this:
%   tex foo.texi
%   texindex foo.??
%   tex foo.texi
%   tex foo.texi
50
51
%   dvips foo.dvi -o  # or whatever; this makes foo.ps.
% The extra TeX runs get the cross-reference information correct.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
52
53
54
% Sometimes one run after texindex suffices, and sometimes you need more
% than two; texi2dvi does it as many times as necessary.
%
55
56
57
% It is possible to adapt texinfo.tex for other languages, to some
% extent.  You can get the existing language-specific files from the
% full Texinfo distribution.
58
59
60
% 
% The GNU Texinfo home page is http://www.gnu.org/software/texinfo.

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
61
62
63
64
65
66
67
68
69

\message{Loading texinfo [version \texinfoversion]:}

% If in a .fmt file, print the version number
% and turn on active characters that we couldn't do earlier because
% they might have appeared in the input file name.
\everyjob{\message{[Texinfo version \texinfoversion]}%
  \catcode`+=\active \catcode`\_=\active}

70
71
72
73
74
75
76
77
\message{Basics,}
\chardef\other=12

% We never want plain's \outer definition of \+ in Texinfo.
% For @tex, we can use \tabalign.
\let\+ = \relax

% Save some plain tex macros whose names we will redefine.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
78
79
80
81
82
83
84
85
86
\let\ptexb=\b
\let\ptexbullet=\bullet
\let\ptexc=\c
\let\ptexcomma=\,
\let\ptexdot=\.
\let\ptexdots=\dots
\let\ptexend=\end
\let\ptexequiv=\equiv
\let\ptexexclam=\!
87
\let\ptexfootnote=\footnote
88
89
\let\ptexgtr=>
\let\ptexhat=^
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
90
\let\ptexi=\i
91
\let\ptexindent=\indent
92
\let\ptexnoindent=\noindent
93
\let\ptexinsert=\insert
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
94
\let\ptexlbrace=\{
95
96
\let\ptexless=<
\let\ptexplus=+
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
97
\let\ptexrbrace=\}
98
\let\ptexslash=\/
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
99
100
101
102
103
104
105
\let\ptexstar=\*
\let\ptext=\t

% If this character appears in an error message or help string, it
% starts a new line in the output.
\newlinechar = `^^J

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
106
107
108
109
110
111
112
113
114
% Use TeX 3.0's \inputlineno to get the line number, for better error
% messages, but if we're using an old version of TeX, don't do anything.
%
\ifx\inputlineno\thisisundefined
  \let\linenumber = \empty % Pre-3.0.
\else
  \def\linenumber{l.\the\inputlineno:\space}
\fi

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
% Set up fixed words for English if not already set.
\ifx\putwordAppendix\undefined  \gdef\putwordAppendix{Appendix}\fi
\ifx\putwordChapter\undefined   \gdef\putwordChapter{Chapter}\fi
\ifx\putwordfile\undefined      \gdef\putwordfile{file}\fi
\ifx\putwordin\undefined        \gdef\putwordin{in}\fi
\ifx\putwordIndexIsEmpty\undefined     \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
\ifx\putwordInfo\undefined      \gdef\putwordInfo{Info}\fi
\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi
\ifx\putwordMethodon\undefined  \gdef\putwordMethodon{Method on}\fi
\ifx\putwordNoTitle\undefined   \gdef\putwordNoTitle{No Title}\fi
\ifx\putwordof\undefined        \gdef\putwordof{of}\fi
\ifx\putwordon\undefined        \gdef\putwordon{on}\fi
\ifx\putwordpage\undefined      \gdef\putwordpage{page}\fi
\ifx\putwordsection\undefined   \gdef\putwordsection{section}\fi
\ifx\putwordSection\undefined   \gdef\putwordSection{Section}\fi
\ifx\putwordsee\undefined       \gdef\putwordsee{see}\fi
\ifx\putwordSee\undefined       \gdef\putwordSee{See}\fi
\ifx\putwordShortTOC\undefined  \gdef\putwordShortTOC{Short Contents}\fi
\ifx\putwordTOC\undefined       \gdef\putwordTOC{Table of Contents}\fi
%
\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi
\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi
\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi
\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi
\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi
\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi
\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi
\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi
\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi
\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi
\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi
\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi
%
\ifx\putwordDefmac\undefined    \gdef\putwordDefmac{Macro}\fi
\ifx\putwordDefspec\undefined   \gdef\putwordDefspec{Special Form}\fi
\ifx\putwordDefvar\undefined    \gdef\putwordDefvar{Variable}\fi
\ifx\putwordDefopt\undefined    \gdef\putwordDefopt{User Option}\fi
\ifx\putwordDeffunc\undefined   \gdef\putwordDeffunc{Function}\fi

155
156
157
158
159
160
161
162
163
164
% In some macros, we cannot use the `\? notation---the left quote is
% in some cases the escape char.
\chardef\colonChar = `\:
\chardef\commaChar = `\,
\chardef\dotChar   = `\.
\chardef\exclamChar= `\!
\chardef\questChar = `\?
\chardef\semiChar  = `\;
\chardef\underChar = `\_

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
165
166
167
168
\chardef\spaceChar = `\ %
\chardef\spacecat = 10
\def\spaceisspace{\catcode\spaceChar=\spacecat}

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
169
170
171
172
% Ignore a token.
%
\def\gobble#1{}

173
174
175
% The following is used inside several \edef's.
\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname}

176
% Hyphenation fixes.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
177
178
\hyphenation{ap-pen-dix}
\hyphenation{eshell}
179
180
\hyphenation{mini-buf-fer mini-buf-fers}
\hyphenation{time-stamp}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
181
182
183
\hyphenation{white-space}

% Margin to add to right of even pages, to left of odd pages.
184
185
\newdimen\bindingoffset
\newdimen\normaloffset
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
186
187
\newdimen\pagewidth \newdimen\pageheight

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
% For a final copy, take out the rectangles
% that mark overfull boxes (in case you have decided
% that the text looks ok even though it passes the margin).
%
\def\finalout{\overfullrule=0pt}

% @| inserts a changebar to the left of the current line.  It should
% surround any changed text.  This approach does *not* work if the
% change spans more than two lines of output.  To handle that, we would
% have adopt a much more difficult approach (putting marks into the main
% vertical list for the beginning and end of each change).
%
\def\|{%
  % \vadjust can only be used in horizontal mode.
  \leavevmode
  %
  % Append this vertical mode material after the current line in the output.
  \vadjust{%
    % We want to insert a rule with the height and depth of the current
    % leading; that is exactly what \strutbox is supposed to record.
    \vskip-\baselineskip
    %
    % \vadjust-items are inserted at the left edge of the type.  So
    % the \llap here moves out into the left-hand margin.
    \llap{%
      %
      % For a thicker or thinner bar, change the `1pt'.
      \vrule height\baselineskip width1pt
      %
      % This is the space between the bar and the text.
      \hskip 12pt
    }%
  }%
}

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
223
224
% Sometimes it is convenient to have everything in the transcript file
% and nothing on the terminal.  We don't just call \tracingall here,
225
226
227
% since that produces some useless output on the terminal.  We also make
% some effort to order the tracing commands to reduce output in the log
% file; cf. trace.sty in LaTeX.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
228
229
%
\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
\def\loggingall{%
  \tracingstats2
  \tracingpages1
  \tracinglostchars2  % 2 gives us more in etex
  \tracingparagraphs1
  \tracingoutput1
  \tracingmacros2
  \tracingrestores1
  \showboxbreadth\maxdimen \showboxdepth\maxdimen
  \ifx\eTeXversion\undefined\else % etex gives us more logging
    \tracingscantokens1
    \tracingifs1
    \tracinggroups1
    \tracingnesting2
    \tracingassigns1
  \fi
  \tracingcommands3  % 3 gives us more in etex
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
247
  \errorcontextlines16
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
248
249
250
251
}%

% add check for \lastpenalty to plain's definitions.  If the last thing
% we did was a \nobreak, we don't want to insert more space.
252
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount
  \removelastskip\penalty-50\smallskip\fi\fi}
\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount
  \removelastskip\penalty-100\medskip\fi\fi}
\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount
  \removelastskip\penalty-200\bigskip\fi\fi}

% For @cropmarks command.
% Do @cropmarks to get crop marks.
%
\newif\ifcropmarks
\let\cropmarks = \cropmarkstrue
%
% Dimensions to add cropmarks at corners.
% Added by P. A. MacKay, 12 Nov. 1986
%
\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines
\newdimen\cornerlong  \cornerlong=1pc
\newdimen\cornerthick \cornerthick=.3pt
\newdimen\topandbottommargin \topandbottommargin=.75in

% Main output routine.
\chardef\PAGE = 255
\output = {\onepageout{\pagecontents\PAGE}}

\newbox\headlinebox
\newbox\footlinebox

% \onepageout takes a vbox as an argument.  Note that \pagecontents
% does insertions, but you have to call it yourself.
\def\onepageout#1{%
  \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi
  %
  \ifodd\pageno  \advance\hoffset by \bindingoffset
  \else \advance\hoffset by -\bindingoffset\fi
  %
  % Do this outside of the \shipout so @code etc. will be expanded in
  % the headline as they should be, not taken literally (outputting ''code).
  \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
  \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
  %
  {%
    % Have to do this stuff outside the \shipout because we want it to
    % take effect in \write's, yet the group defined by the \vbox ends
    % before the \shipout runs.
    %
    \escapechar = `\\     % use backslash in output files.
    \indexdummies         % don't expand commands in the output.
    \normalturnoffactive  % \ in index entries must not stay \, e.g., if
                   % the page break happens to be in the middle of an example.
    \shipout\vbox{%
304
      % Do this early so pdf references go to the beginning of the page.
305
      \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi
306
      %
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
      \ifcropmarks \vbox to \outervsize\bgroup
        \hsize = \outerhsize
        \vskip-\topandbottommargin
        \vtop to0pt{%
          \line{\ewtop\hfil\ewtop}%
          \nointerlineskip
          \line{%
            \vbox{\moveleft\cornerthick\nstop}%
            \hfill
            \vbox{\moveright\cornerthick\nstop}%
          }%
          \vss}%
        \vskip\topandbottommargin
        \line\bgroup
          \hfil % center the page within the outer (page) hsize.
          \ifodd\pageno\hskip\bindingoffset\fi
          \vbox\bgroup
      \fi
      %
      \unvbox\headlinebox
      \pagebody{#1}%
      \ifdim\ht\footlinebox > 0pt
        % Only leave this space if the footline is nonempty.
        % (We lessened \vsize for it in \oddfootingxxx.)
        % The \baselineskip=24pt in plain's \makefootline has no effect.
        \vskip 2\baselineskip
        \unvbox\footlinebox
      \fi
      %
      \ifcropmarks
          \egroup % end of \vbox\bgroup
        \hfil\egroup % end of (centering) \line\bgroup
        \vskip\topandbottommargin plus1fill minus1fill
        \boxmaxdepth = \cornerthick
        \vbox to0pt{\vss
          \line{%
            \vbox{\moveleft\cornerthick\nsbot}%
            \hfill
            \vbox{\moveright\cornerthick\nsbot}%
          }%
          \nointerlineskip
          \line{\ewbot\hfil\ewbot}%
        }%
      \egroup % \vbox from first cropmarks clause
      \fi
    }% end of \shipout\vbox
353
  }% end of group with \normalturnoffactive
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  \advancepageno
  \ifnum\outputpenalty>-20000 \else\dosupereject\fi
}

\newinsert\margin \dimen\margin=\maxdimen

\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
{\catcode`\@ =11
\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
% marginal hacks, juha@viisa.uucp (Juha Takala)
\ifvoid\margin\else % marginal info is present
  \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
\dimen@=\dp#1 \unvbox#1
\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
}

% Here are the rules for the cropmarks.  Note that they are
% offset so that the space between them is truly \outerhsize or \outervsize
% (P. A. MacKay, 12 November, 1986)
%
\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
\def\nstop{\vbox
  {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
\def\nsbot{\vbox
  {\hrule height\cornerlong depth\cornerthick width\cornerthick}}

% Parse an argument, then pass it to #1.  The argument is the rest of
% the input line (except we remove a trailing comment).  #1 should be a
% macro which expects an ordinary undelimited TeX argument.
%
386
387
388
\def\parsearg{\parseargusing{}}
\def\parseargusing#1#2{%
  \def\next{#2}%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
389
390
  \begingroup
    \obeylines
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
391
    \spaceisspace
392
393
    #1%
    \parseargline\empty% Insert the \empty token, see \finishparsearg below.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
394
395
396
397
398
}

{\obeylines %
  \gdef\parseargline#1^^M{%
    \endgroup % End of the group started in \parsearg.
399
    \argremovecomment #1\comment\ArgTerm%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
400
401
402
  }%
}

403
404
% First remove any @comment, then any @c comment.
\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
405
406
407
408
409
\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm}

% Each occurence of `\^^M' or `<space>\^^M' is replaced by a single space.
%
% \argremovec might leave us with trailing space, e.g.,
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
410
%    @end itemize  @c foo
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
% This space token undergoes the same procedure and is eventually removed
% by \finishparsearg.
%
\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M}
\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M}
\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{%
  \def\temp{#3}%
  \ifx\temp\empty
    % We cannot use \next here, as it holds the macro to run;
    % thus we reuse \temp.
    \let\temp\finishparsearg
  \else
    \let\temp\argcheckspaces
  \fi
  % Put the space token in:
  \temp#1 #3\ArgTerm
}
428
429
430

% If a _delimited_ argument is enclosed in braces, they get stripped; so
% to get _exactly_ the rest of the line, we had to prevent such situation.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
431
% We prepended an \empty token at the very beginning and we expand it now,
432
% just before passing the control to \next.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
433
434
435
436
437
438
439
% (Similarily, we have to think about #3 of \argcheckspacesY above: it is
% either the null string, or it ends with \^^M---thus there is no danger
% that a pair of braces would be stripped.
%
% But first, we have to remove the trailing space token.
%
\def\finishparsearg#1 \ArgTerm{\expandafter\next\expandafter{#1}}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
440

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
441
% \parseargdef\foo{...}
442
443
444
%	is roughly equivalent to
% \def\foo{\parsearg\Xfoo}
% \def\Xfoo#1{...}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
445
%
446
447
448
% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my
% favourite TeX trick.  --kasal, 16nov03

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
449
450
\def\parseargdef#1{%
  \expandafter \doparseargdef \csname\string#1\endcsname #1%
451
}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
452
\def\doparseargdef#1#2{%
453
454
455
456
457
458
  \def#2{\parsearg#1}%
  \def#1##1%
}

% Several utility definitions with active space:
{
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
459
  \obeyspaces
460
461
462
463
464
465
466
467
468
469
470
471
472
473
  \gdef\obeyedspace{ }

  % Make each space character in the input produce a normal interword
  % space in the output.  Don't allow a line break at this space, as this
  % is used only in environments like @example, where each line of input
  % should produce a line of output anyway.
  %
  \gdef\sepspaces{\obeyspaces\let =\tie}

  % If an index command is used in an @example environment, any spaces
  % therein should become regular spaces in the raw index file, not the
  % expansion of \tie (\leavevmode \penalty \@M \ ).
  \gdef\unsepspaces{\let =\space}
}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
474
475
476
477


\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
% Define the framework for environments in texinfo.tex.  It's used like this:
% 
%   \envdef\foo{...}
%   \def\Efoo{...}
%   
% It's the responsibility of \envdef to insert \begingroup before the
% actual body; @end closes the group after calling \Efoo.  \envdef also
% defines \thisenv, so the current environment is known; @end checks
% whether the environment name matches.  The \checkenv macro can also be
% used to check whether the current environment is the one expected.
% 
% Non-false conditionals (@iftex, @ifset) don't fit into this, so they
% are not treated as enviroments; they don't open a group.  (The
% implementation of @end takes care not to call \endgroup in this
% special case.)
493

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
494

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
495
496
497
498
% At runtime, environments start with this:
\def\startenvironment#1{\begingroup\def\thisenv{#1}}
% initialize
\let\thisenv\empty
499

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
500
501
502
503
504
505
506
507
% ... but they get defined via ``\envdef\foo{...}'':
\long\def\envdef#1#2{\def#1{\startenvironment#1#2}}
\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}}

% Check whether we're in the right environment:
\def\checkenv#1{%
  \def\temp{#1}%
  \ifx\thisenv\temp
508
  \else
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
509
    \badenverr
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
510
511
512
  \fi
}

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
513
514
% Evironment mismatch, #1 expected:
\def\badenverr{%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
515
  \errhelp = \EMsimple
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
516
517
518
519
520
521
522
523
524
  \errmessage{This command can appear only \inenvironment\temp,
    not \inenvironment\thisenv}%
}
\def\inenvironment#1{%
  \ifx#1\empty
    out of any environment%
  \else
    in environment \expandafter\string#1%
  \fi
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
525
526
}

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
527
528
% @end foo executes the definition of \Efoo.
% But first, it executes a specialized version of \checkenv
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
529
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
530
531
532
533
534
535
536
537
\parseargdef\end{%
  \if 1\csname iscond.#1\endcsname
  \else
    % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03
    \expandafter\checkenv\csname#1\endcsname
    \csname E#1\endcsname
    \endgroup
  \fi
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
538
539
}

540
541
\newhelp\EMsimple{Press RETURN to continue.}

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561

%% Simple single-character @ commands

% @@ prints an @
% Kludge this until the fonts are right (grr).
\def\@{{\tt\char64}}

% This is turned off because it was never documented
% and you can use @w{...} around a quote to suppress ligatures.
%% Define @` and @' to be the same as ` and '
%% but suppressing ligatures.
%\def\`{{`}}
%\def\'{{'}}

% Used to generate quoted braces.
\def\mylbrace {{\tt\char123}}
\def\myrbrace {{\tt\char125}}
\let\{=\mylbrace
\let\}=\myrbrace
\begingroup
562
563
564
  % Definitions to produce \{ and \} commands for indices,
  % and @{ and @} for the aux file.
  \catcode`\{ = \other \catcode`\} = \other
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
565
  \catcode`\[ = 1 \catcode`\] = 2
566
567
568
569
570
571
  \catcode`\! = 0 \catcode`\\ = \other
  !gdef!lbracecmd[\{]%
  !gdef!rbracecmd[\}]%
  !gdef!lbraceatcmd[@{]%
  !gdef!rbraceatcmd[@}]%
!endgroup
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
572

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
573
574
575
% @comma{} to avoid , parsing problems.
\let\comma = ,

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
576
% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
577
% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
578
579
580
581
582
583
584
\let\, = \c
\let\dotaccent = \.
\def\ringaccent#1{{\accent23 #1}}
\let\tieaccent = \t
\let\ubaraccent = \b
\let\udotaccent = \d

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
585
% Other special characters: @questiondown @exclamdown @ordf @ordm
586
% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
587
588
\def\questiondown{?`}
\def\exclamdown{!`}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
589
590
\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}}
\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
591
592
593
594
595
596
597
598
599
600
601
602

% Dotless i and dotless j, used for accents.
\def\imacro{i}
\def\jmacro{j}
\def\dotless#1{%
  \def\temp{#1}%
  \ifx\temp\imacro \ptexi
  \else\ifx\temp\jmacro \j
  \else \errmessage{@dotless can be used only with i or j}%
  \fi\fi
}

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
% The \TeX{} logo, as in plain, but resetting the spacing so that a
% period following counts as ending a sentence.  (Idea found in latex.)
% 
\def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\spacefactor=3000 }

% @LaTeX{} logo.  Not quite the same results as the definition in
% latex.ltx, since we use a different font for the raised A; it's most
% convenient for us to use an explicitly smaller font, rather than using
% the \scriptstyle font (since we don't reset \scriptstyle and
% \scriptscriptstyle).
% 
\def\LaTeX{%
  L\kern-.36em
  {\setbox0=\hbox{T}%
   \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}%
  \kern-.15em
  \TeX
}

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
% Be sure we're in horizontal mode when doing a tie, since we make space
% equivalent to this in @example-like environments. Otherwise, a space
% at the beginning of a line will start with \penalty -- and
% since \penalty is valid in vertical mode, we'd end up putting the
% penalty on the vertical list instead of in the new paragraph.
{\catcode`@ = 11
 % Avoid using \@M directly, because that causes trouble
 % if the definition is written into an index file.
 \global\let\tiepenalty = \@M
 \gdef\tie{\leavevmode\penalty\tiepenalty\ }
}

% @: forces normal size whitespace following.
\def\:{\spacefactor=1000 }

% @* forces a line break.
\def\*{\hfil\break\hbox{}\ignorespaces}

640
641
642
% @/ allows a line break.
\let\/=\allowbreak

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
% @. is an end-of-sentence period.
\def\.{.\spacefactor=3000 }

% @! is an end-of-sentence bang.
\def\!{!\spacefactor=3000 }

% @? is an end-of-sentence query.
\def\?{?\spacefactor=3000 }

% @w prevents a word break.  Without the \leavevmode, @w at the
% beginning of a paragraph, when TeX is still in vertical mode, would
% produce a whole line of output instead of starting the paragraph.
\def\w#1{\leavevmode\hbox{#1}}

% @group ... @end group forces ... to be all on one page, by enclosing
% it in a TeX vbox.  We use \vtop instead of \vbox to construct the box
% to keep its height that of a normal line.  According to the rules for
% \topskip (p.114 of the TeXbook), the glue inserted is
% max (\topskip - \ht (first item), 0).  If that height is large,
% therefore, no glue is inserted, and the space between the headline and
% the text is small, which looks bad.
%
665
666
667
668
669
670
671
672
673
674
% Another complication is that the group might be very large.  This can
% cause the glue on the previous page to be unduly stretched, because it
% does not have much material.  In this case, it's better to add an
% explicit \vfill so that the extra space is at the bottom.  The
% threshold for doing this is if the group is more than \vfilllimit
% percent of a page (\vfilllimit can be changed inside of @tex).
%
\newbox\groupbox
\def\vfilllimit{0.7}
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
675
\envdef\group{%
676
  \ifnum\catcode`\^^M=\active \else
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
677
678
679
    \errhelp = \groupinvalidhelp
    \errmessage{@group invalid in context where filling is enabled}%
  \fi
680
  \startsavinginserts
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
681
  %
682
  \setbox\groupbox = \vtop\bgroup
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
683
684
685
686
687
688
689
690
691
    % Do @comment since we are called inside an environment such as
    % @example, where each end-of-line in the input causes an
    % end-of-line in the output.  We don't want the end-of-line after
    % the `@group' to put extra space in the output.  Since @group
    % should appear on a line by itself (according to the Texinfo
    % manual), we don't worry about eating any user text.
    \comment
}
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
% The \vtop produces a box with normal height and large depth; thus, TeX puts
% \baselineskip glue before it, and (when the next line of text is done)
% \lineskip glue after it.  Thus, space below is not quite equal to space
% above.  But it's pretty close.
\def\Egroup{%
    % To get correct interline space between the last line of the group
    % and the first line afterwards, we have to propagate \prevdepth.
    \endgraf % Not \par, as it may have been set to \lisppar.
    \global\dimen1 = \prevdepth
  \egroup           % End the \vtop.
  % \dimen0 is the vertical size of the group's box.
  \dimen0 = \ht\groupbox  \advance\dimen0 by \dp\groupbox
  % \dimen2 is how much space is left on the page (more or less).
  \dimen2 = \pageheight   \advance\dimen2 by -\pagetotal
  % if the group doesn't fit on the current page, and it's a big big
  % group, force a page break.
  \ifdim \dimen0 > \dimen2
    \ifdim \pagetotal < \vfilllimit\pageheight
      \page
    \fi
  \fi
  \box\groupbox
  \prevdepth = \dimen1
  \checkinserts
}
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
718
719
720
721
722
723
724
725
726
727
728
729
730
% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
% message, so this ends up printing `@group can only ...'.
%
\newhelp\groupinvalidhelp{%
group can only be used in environments such as @example,^^J%
where each line of input produces a line of output.}

% @need space-in-mils
% forces a page break if there is not space-in-mils remaining.

\newdimen\mil  \mil=0.001in

% Old definition--didn't work.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
731
%\parseargdef\need{\par %
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
732
733
734
735
736
737
738
%% This method tries to make TeX break the page naturally
%% if the depth of the box does not fit.
%{\baselineskip=0pt%
%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
%\prevdepth=-1000pt
%}}

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
739
\parseargdef\need{%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
  % Ensure vertical mode, so we don't make a big box in the middle of a
  % paragraph.
  \par
  %
  % If the @need value is less than one line space, it's useless.
  \dimen0 = #1\mil
  \dimen2 = \ht\strutbox
  \advance\dimen2 by \dp\strutbox
  \ifdim\dimen0 > \dimen2
    %
    % Do a \strut just to make the height of this box be normal, so the
    % normal leading is inserted relative to the preceding line.
    % And a page break here is fine.
    \vtop to #1\mil{\strut\vfil}%
    %
    % TeX does not even consider page breaks if a penalty added to the
    % main vertical list is 10000 or more.  But in order to see if the
    % empty box we just added fits on the page, we must make it consider
    % page breaks.  On the other hand, we don't want to actually break the
    % page after the empty box.  So we use a penalty of 9999.
    %
    % There is an extremely small chance that TeX will actually break the
    % page at this \penalty, if there are no other feasible breakpoints in
    % sight.  (If the user is using lots of big @group commands, which
    % almost-but-not-quite fill up a page, TeX will have a hard time doing
    % good page breaking, for example.)  However, I could not construct an
    % example where a page broke at this \penalty; if it happens in a real
    % document, then we can reconsider our strategy.
    \penalty9999
    %
    % Back up by the size of the box, whether we did a page break or not.
    \kern -#1\mil
    %
    % Do not allow a page break right after this kern.
    \nobreak
  \fi
}

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
778
% @br   forces paragraph break (and is undocumented).
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
779
780
781

\let\br = \par

782
% @page forces the start of a new page.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
783
784
785
786
787
788
789
790
791
792
793
%
\def\page{\par\vfill\supereject}

% @exdent text....
% outputs text on separate line in roman font, starting at standard page margin

% This records the amount of indent in the innermost environment.
% That's how much \exdent should take out.
\newskip\exdentamount

% This defn is used inside fill environments such as @defun.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
794
\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
795
796

% This defn is used inside nofill environments such as @example.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
797
\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount
798
  \leftline{\hskip\leftskip{\rm#1}}}}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828

% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current
% paragraph.  For more general purposes, use the \margin insertion
% class.  WHICH is `l' or `r'.
%
\newskip\inmarginspacing \inmarginspacing=1cm
\def\strutdepth{\dp\strutbox}
%
\def\doinmargin#1#2{\strut\vadjust{%
  \nobreak
  \kern-\strutdepth
  \vtop to \strutdepth{%
    \baselineskip=\strutdepth
    \vss
    % if you have multiple lines of stuff to put here, you'll need to
    % make the vbox yourself of the appropriate size.
    \ifx#1l%
      \llap{\ignorespaces #2\hskip\inmarginspacing}%
    \else
      \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}%
    \fi
    \null
  }%
}}
\def\inleftmargin{\doinmargin l}
\def\inrightmargin{\doinmargin r}
%
% @inmargin{TEXT [, RIGHT-TEXT]}
% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right;
% else use TEXT for both).
829
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
830
831
\def\inmargin#1{\parseinmargin #1,,\finish}
\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing.
832
  \setbox0 = \hbox{\ignorespaces #2}%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
  \ifdim\wd0 > 0pt
    \def\lefttext{#1}%  have both texts
    \def\righttext{#2}%
  \else
    \def\lefttext{#1}%  have only one text
    \def\righttext{#1}%
  \fi
  %
  \ifodd\pageno
    \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin
  \else
    \def\temp{\inleftmargin\lefttext}%
  \fi
  \temp
}

% @include file    insert text of that file as input.
850
851
852
853
854
855
856
857
858
859
860
861
862
%
\def\include{\parseargusing\filenamecatcodes\includezzz}
\def\includezzz#1{%
  \pushthisfilestack
  \def\thisfile{#1}%
  {%
    \makevalueexpandable
    \def\temp{\input #1 }%
    \expandafter
  }\temp
  \popthisfilestack
}
\def\filenamecatcodes{%
863
864
865
866
867
868
869
870
  \catcode`\\=\other
  \catcode`~=\other
  \catcode`^=\other
  \catcode`_=\other
  \catcode`|=\other
  \catcode`<=\other
  \catcode`>=\other
  \catcode`+=\other
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
  \catcode`-=\other
}

\def\pushthisfilestack{%
  \expandafter\pushthisfilestackX\popthisfilestack\StackTerm
}
\def\pushthisfilestackX{%
  \expandafter\pushthisfilestackY\thisfile\StackTerm
}
\def\pushthisfilestackY #1\StackTerm #2\StackTerm {%
  \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}%
}

\def\popthisfilestack{\errthisfilestackempty}
\def\errthisfilestackempty{\errmessage{Internal error:
  the stack of filenames is empty.}}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
887
888
889

\def\thisfile{}

890
891
892
% @center line
% outputs that line, centered.
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
893
894
895
896
897
898
899
900
901
\parseargdef\center{%
  \ifhmode
    \let\next\centerH
  \else
    \let\next\centerV
  \fi
  \next{\hfil \ignorespaces#1\unskip \hfil}%
}
\def\centerH#1{%
902
  {%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
903
    \hfil\break
904
905
    \advance\hsize by -\leftskip
    \advance\hsize by -\rightskip
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
906
907
    \line{#1}%
    \break
908
909
  }%
}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
910
\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
911
912
913

% @sp n   outputs n lines of vertical space

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
914
\parseargdef\sp{\vskip #1\baselineskip}
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
915
916
917
918
919
920
921
922
923
924
925
926
927
928

% @comment ...line which is ignored...
% @c is the same as @comment
% @ignore ... @end ignore  is another way to write a comment

\def\comment{\begingroup \catcode`\^^M=\other%
\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
\commentxxx}
{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}

\let\c=\comment

% @paragraphindent NCHARS
% We'll use ems for NCHARS, close enough.
929
930
931
% NCHARS can also be the word `asis' or `none'.
% We cannot feasibly implement @paragraphindent asis, though.
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
932
933
934
\def\asisword{asis} % no translation, these are keywords
\def\noneword{none}
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
935
\parseargdef\paragraphindent{%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
  \def\temp{#1}%
  \ifx\temp\asisword
  \else
    \ifx\temp\noneword
      \defaultparindent = 0pt
    \else
      \defaultparindent = #1em
    \fi
  \fi
  \parindent = \defaultparindent
}

% @exampleindent NCHARS
% We'll use ems for NCHARS like @paragraphindent.
% It seems @exampleindent asis isn't necessary, but
% I preserve it to make it similar to @paragraphindent.
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
952
\parseargdef\exampleindent{%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
953
954
955
956
957
958
959
960
961
962
963
  \def\temp{#1}%
  \ifx\temp\asisword
  \else
    \ifx\temp\noneword
      \lispnarrowing = 0pt
    \else
      \lispnarrowing = #1em
    \fi
  \fi
}

964
965
% @firstparagraphindent WORD
% If WORD is `none', then suppress indentation of the first paragraph
966
% after a section heading.  If WORD is `insert', then do indent at such
967
968
969
% paragraphs.
%
% The paragraph indentation is suppressed or not by calling
970
971
972
% \suppressfirstparagraphindent, which the sectioning commands do.
% We switch the definition of this back and forth according to WORD.
% By default, we suppress indentation.
973
974
975
976
977
978
%
\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent}
\newdimen\currentparindent
%
\def\insertword{insert}
%
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
979
\parseargdef\firstparagraphindent{%
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
  \def\temp{#1}%
  \ifx\temp\noneword
    \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent
  \else\ifx\temp\insertword
    \let\suppressfirstparagraphindent = \relax
  \else
    \errhelp = \EMsimple
    \errmessage{Unknown @firstparagraphindent option `\temp'}%
  \fi\fi
}

% Here is how we actually suppress indentation.  Redefine \everypar to
% \kern backwards by \parindent, and then reset itself to empty.
%
% We also make \indent itself not actually do anything until the next
% paragraph.
%
\gdef\dosuppressfirstparagraphindent{%
  \gdef\indent{%
999
1000
    \restorefirstparagraphindent
    \indent