1# -*- mode: Perl -*-
2# /=====================================================================\ #
3# |  AmSTeX.pool                                                        | #
4# | Implementation for LaTeXML                                          | #
5# |=====================================================================| #
6# | Part of LaTeXML:                                                    | #
7# |  Public domain software, produced as part of work done by the       | #
8# |  United States Government & not subject to copyright in the US.     | #
9# |---------------------------------------------------------------------| #
10# | Thanks to the arXMLiv group for initial implementation              | #
11# |    http://arxmliv.kwarc.info/                                       | #
12# | Released to the Public Domain                                       | #
13# |---------------------------------------------------------------------| #
14# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
15# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
16# \=========================================================ooo==U==ooo=/ #
17package LaTeXML::Package::Pool;
18use strict;
19use warnings;
20use LaTeXML::Package;
21
22#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
23#  This is the `pool' for AmSTeX (_not_ AMS LaTeX)
24# It should be loaded by LoadPool("AmSTeX"), or
25# indirectly via \input amstex
26# (from TeX mode, ie. before and without LaTeX.pool being loaded)
27# This should put LaTeXML into "amstex mode"
28#
29# Since amstex uses \documentstyle, we _must_ define it here to
30# keep TeX.pool from anticipating LaTeX mode and loading LaTeX.pool!
31#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
32RequireResource('ltx-amsart.css');    # hopefully close enough...
33
34DefConstructorI('\AmSTeX', undef, 'AMSTeX');
35DefMacro('\fmtname',    'AmS-TeX');
36DefMacro('\fmtversion', '2.1');
37Let('\plainfmtversion', '\fmtversion');
38
39DefPrimitive('\define SkipSpaces Token UntilBrace {}', sub {
40    my ($stomach, $cs, $params, $body) = @_;
41    $params = parseDefParameters($cs, $params);    # in TeX.pool
42    if (LookupDefinition($cs)) {
43      Info('ignore', $cs, $stomach,
44        "Ignoring redefinition (\\define) of '" . ToString($cs) . "'");
45      return; }
46    DefMacroI($cs, $params, $body);
47    return; });
48
49DefPrimitive('\redefine SkipSpaces Token UntilBrace {}', sub {
50    my ($stomach, $cs, $params, $body) = @_;
51    $params = parseDefParameters($cs, $params);    # in TeX.pool
52    DefMacroI($cs, $params, $body);
53    return; });
54
55DefPrimitive('\predefine Token Token', sub {
56    Let($_[1], $_[2]); });
57
58DefPrimitive('\undefine Token', sub {
59    my ($stomach, $cs) = @_;
60    Let($_[1], '\relax'); });
61
62#======================================================================
63# Style choices
64
65DefConstructor('\documentstyle  Semiverbatim',
66  "<?latexml class='#1' amstex='true'?>",
67  afterDigest => sub {
68    my ($stomach, $whatsit) = @_;
69    my $style = ToString($whatsit->getArg(1));
70    # Load the package, but note that we're pretending it's a class (to some extent!)
71    RequirePackage($style, type => 'sty', notex => 1, as_class => 1)
72      || RequirePackage('amsppt');
73    return; });
74
75DefMacro('\NoPageNumbers', '');
76
77DefMacro('\BlackBoxes',   '');    # These control whether overfull boxes show black; Ignorable
78DefMacro('\NoBlackBoxes', '');
79
80DefMacro('\TagsAsMath', '');
81DefMacro('\TagsAsText', '');
82
83DefMacro('\TagsOnLeft',  '');
84DefMacro('\TagsOnRight', '');
85
86DefMacro('\CenteredTagsOnSplits',    '');
87DefMacro('\TopOrBottomTagsOnSplits', '');
88
89DefMacro('\LimitsOnInts',    '');
90DefMacro('\NoLimitsOnInts',  '');
91DefMacro('\LimitsOnNames',   '');
92DefMacro('\NoLimitsOnNames', '');
93DefMacro('\LimitsOnSums',    '');
94DefMacro('\NoLimitsOnSums',  '');
95
96# These presumably load fonts (or commands?)
97DefMacro('\UseAMSsymbols', '');
98DefMacro('\loadbold',      '');
99DefMacro('\loadeufb',      '');
100DefMacro('\loadeufm',      '');
101DefMacro('\loadeurb',      '');
102DefMacro('\loadeurm',      '');
103DefMacro('\loadeusb',      '');
104DefMacro('\loadeusm',      '');
105DefMacro('\loadmathfont',  '');
106DefMacro('\loadmsam',      '');
107DefMacro('\loadmsbm',      '');
108Let('\font@', '\font');    # Close enough?
109
110DefMacro('\boldnotloaded{}', '');
111
112DefMacro('\galleys',  '');
113DefMacro('\flushpar', '\par\noindent');
114
115DefMacro('\pagewidth{Dimension}',   '');
116DefMacro('\pageheight{Dimension}',  '');
117DefMacro('\hcorrection{Dimension}', '');
118DefMacro('\vcorrection{Dimension}', '');
119
120#======================================================================
121# The Document
122DefConstructor('\document', "<ltx:document>",
123  afterDigest => sub { AssignValue(inPreamble => 0); });
124DefConstructor('\enddocument', "</ltx:document>",
125  beforeDigest => sub {
126    $_[0]->getGullet->flush;
127    return; });
128
129#======================================================================
130# Front Matter
131
132DefMacro('\topmatter',             '');
133DefMacro('\endtopmatter',          '');
134DefMacro('\title Until:\endtitle', '\@add@frontmatter{ltx:title}{#1}');
135DefConstructor('\@personname{}', "<ltx:personname>#1</ltx:personname>",
136  bounded => 1, mode => 'text');
137DefMacro('\author Until:\endauthor', '\@add@frontmatter{ltx:creator}[role=author]{\@personname{#1}}');
138DefConstructor('\@institute{}', "<ltx:contact role='institute'>#1</ltx:contact>", bounded => 1);
139DefMacro('\thanks Until:\endthanks',     '\@add@to@frontmatter{ltx:creator}{\@institute{#1}}');
140DefMacro('\abstract Until:\endabstract', '\@add@frontmatter{ltx:abstract}{#1}');
141
142#======================================================================
143# Document structure
144# See amsppt.sty or ...
145DefMacro('\nofrills', '');
146
147DefPrimitive('\comment', sub {
148    my ($stomach, $line) = @_;
149    my $gullet = $stomach->getGullet;
150    $gullet->readRawLine;    # IGNORE 1st line (after the \begin{$name} !!!
151    while (defined($line = $gullet->readRawLine) && ($line ne '\endcomment')) {
152    }
153    return; });
154
155Let('\plainproclaim', '\proclaim');
156Let('\plainfootnote', '\footnote');
157RawTeX('\newbox\tocbox@');
158#======================================================================
159# Text level stuff
160
161DefMacro('\newline', "\n");
162
163DefPrimitiveI('\textfonti', undef, '',
164  font => { family => 'serif', series => 'medium', shape => 'upright' });
165DefPrimitiveI('\textfontii', undef, '',
166  font => { family => 'serif', series => 'medium', shape => 'upright', size => 9 });
167
168DefConstructor('\spreadlines {Dimension}', '');
169
170DefPrimitive('\pagebreak',      undef);
171DefPrimitive('\nopagebreak',    undef);
172DefPrimitive('\smallpagebreak', undef);
173DefPrimitive('\medpagebreak',   undef);
174DefPrimitive('\bigpagebreak',   undef);
175
176DefPrimitive('\allowlinebreak',     undef);
177DefPrimitive('\allowmathbreak',     undef);
178DefPrimitive('\linebreak',          undef);
179DefPrimitive('\nolinebreak',        undef);
180DefPrimitive('\mathbreak',          undef);
181DefPrimitive('\nomathbreak',        undef);
182DefPrimitive('\allowdisplaybreaks', undef);
183DefPrimitive('\allowdisplaybreak',  undef);
184
185DefMacro('\tie', '\unskip\nobreak\ ');
186Let('\graveaccent', "\\`");
187Let('\acuteaccent', "\\'");
188Let('\tildeaccent', "\\~");
189Let('\hataccent',   "\\^");
190Let('\underscore',  "\\_");
191Let('\B',           "\\=");
192Let('\D',           "\\.");
193
194DefMacro('\.', '. ');
195
196#======================================================================
197# Math stuff.
198
199# We'd like to be able to leverage the ams (LaTeX) packages we've already written.
200# However, they were written in the context of LaTeX, and assume LaTeX.pool was loaded.
201# We either need to duplicate them, or alter them to be aware of LaTeX vs AMSTeX mode!
202# Especially, DefEnvironment is to be avoided! (or usurped!!)
203
204# We need stuff from amsmath, BUT it shouldn't define "environments",
205# rather \foo ... \endfoo....
206# But, of course, DefEnvironment, DOES do that!
207# Will this work????
208# The question is whether AMSTeX's \foo..\endfoo incorporates \begingroup/\endgroup pairs?
209# MOST Likely, all of amsmath will need to be redone here, since the argument patterns are
210# so different!  The rest are probably OK.
211RequirePackage('amsmath');
212RequirePackage('amssymb');
213RequirePackage('amsfonts');
214RequirePackage('amsopn');
215RequirePackage('amsxtra');
216RequirePackage('amscd');
217
218Let('\dsize',  '\displaystyle');
219Let('\tsize',  '\textstyle');
220Let('\ssize',  '\scriptstyle');
221Let('\sssize', '\scriptscriptstyle');
222Let('\tag',    '\eqno');
223DefMath('\and', '\&', role => 'ADDOP', meaning => 'and');
224DefConstructor("\\\\",
225  "?#isMath(<ltx:XMHint name='newline'/>)(<ltx:break/>)",
226  reversion => Tokens(T_CS("\\\\"), T_CR));
227
228# This is an analog to \align's template, but hopefully we can just ignore it???
229DefMacro("\\format Until:\\\\", '');
230
231DefConstructor('\text {}',
232  "<ltx:text _noautoclose='1'>#1</ltx:text>", mode => 'text');
233
234DefConstructor('\overset Until:\to {}',
235  "<ltx:XMApp>"
236    . "<ltx:XMWrap role='OVERACCENT'>#1</ltx:XMWrap>"
237    . "<ltx:XMArg>#2</ltx:XMArg>"
238    . "</ltx:XMApp>");
239DefConstructor('\underset Until:\to {}',
240  "<ltx:XMApp>"
241    . "<ltx:XMWrap role='UNDERACCENT'>#1</ltx:XMWrap>"
242    . "<ltx:XMArg>#2</ltx:XMArg>"
243    . "</ltx:XMApp>");
244
245DefMacro('\oversetbrace Until:\to {}',  '\overbrace{#2}^{#1}');
246DefMacro('\undersetbrace Until:\to {}', '\underbrace{#2}^{#1}');
247
248Let('\overarrow',  '\overrightarrow');
249Let('\underarrow', '\underrightarrow');
250
251DefConstructor('\frac InFractionStyle InFractionStyle',
252  "<ltx:XMApp>"
253    . "<ltx:XMTok meaning='divide' role='FRACOP' mathstyle='#mathstyle'/>"
254    . "<ltx:XMArg>#1</ltx:XMArg><ltx:XMArg>#2</ltx:XMArg>"
255    . "</ltx:XMApp>",
256  sizer      => sub { fracSizer($_[0]->getArg(1), $_[0]->getArg(2)); },
257  properties => { mathstyle => sub { LookupValue('font')->getMathstyle; } });
258
259DefConstructor('\Cal{}', '#1', bounded => 1, requireMath => 1,
260  font => { family => 'caligraphic', series => 'medium', shape => 'upright' });
261
262# \bold in amsfonts
263DefConstructor('\roman{}', '#1', bounded => 1, requireMath => 1,
264  font => { family => 'serif', series => 'medium', shape => 'upright' });
265DefConstructor('\italic{}', '#1', bounded => 1, requireMath => 1,
266  font => { shape => 'italic', series => 'medium', shape => 'upright' });
267DefConstructor('\slanted{}', '#1', bounded => 1, requireMath => 1,
268  font => { shape => 'slanted', series => 'medium', shape => 'upright' });
269DefConstructor('\boldkey{}', '#1', bounded => 1, requireMath => 1,
270  font => { series => 'bold', family => 'typewriter', series => 'medium', shape => 'upright' });
271
272# holy cow...
273DefMacro('\thickfrac', sub {
274    ($_[0]->ifNext('\thickness') ? T_CS('\@thickfrac') : T_CS('\frac')); });
275DefMacro('\@thickfrac Token Number {}{}', '\genfrac{}{}{#2}{}{#3}{#4}');
276
277DefMacro('\thickfracwithdelims{}{}', sub {
278    (($_[0]->ifNext('\thickness') ? T_CS('\@thickfracwithdelims') : T_CS('\fracwithdelims')), $_[1], $_[2]); });
279DefMacro('\@thickfracwithdelims {}{} Token Number {}{}', '\genfrac{#1}{#2}{#4}{}{#5}{#6}');
280
281DefMacro('\spcheck',  '^{\vee}');
282DefMacro('\sptilde',  '^{\sim}');
283DefMacro('\spacute',  "^{'}");
284DefMacro('\spgrave',  "^{`}");
285DefMacro('\spdot',    "^{.}");
286DefMacro('\spddot',   "^{..}");
287DefMacro('\spdddot',  "^{...}");
288DefMacro('\spddddot', "^{....}");
289DefMacro('\spbreve',  "^{\\hbox{\\u{}}}");
290DefMacro('\spbar',    "^{-}");
291DefMacro('\spvec',    "^{\\rightarrow}");
292
293# \boldsymbol{}
294# Note this is really messed up.  \boldsymbol doesn't necessarily just expand,
295# it recognizes certain arguments specially.  Among other things this allows perversities like:
296#   \redefine\cdot{\boldsymbol\cdot}
297DefMathI('\lx@ams@boldsymbol@cdot', undef, "\x{22C5}", role => 'MULOP',
298  bounded => 1, font => { forcebold => 1 });
299DefMathI('\lx@ams@boldsymbol@prime', undef, "\x{2032}", role => 'SUPOP', locked => 1,
300  bounded => 1, font => { forcebold => 1 });
301DefMathI('\lx@ams@boldsymbol@lbrack', undef, '[', role => 'OPEN', stretchy => 'false',
302  bounded => 1, font => { forcebold => 1 });
303DefMathI('\lx@ams@boldsymbol@rbrack', undef, ']', role => 'CLOSE', stretchy => 'false',
304  bounded => 1, font => { forcebold => 1 });
305DefMathI('\lx@ams@boldsymbol@lbrace', undef, '{', role => 'OPEN', stretchy => 'false', alias => '\{',
306  bounded => 1, font => { forcebold => 1 });
307DefMathI('\lx@ams@boldsymbol@rbrace', undef, '}', role => 'CLOSE', stretchy => 'false', alias => '\}',
308  bounded => 1, font => { forcebold => 1 });
309DefMathI('\lx@ams@boldsymbol@surd', undef, "\x{221A}", role => 'OPERATOR', meaning => 'square-root',
310  bounded => 1, font => { forcebold => 1 });
311DefMathI('\lx@ams@boldsymbol@S', undef, UTF(0xa7),
312  bounded => 1, font => { forcebold => 1 });
313DefMathI('\lx@ams@boldsymbol@P', undef, UTF(0xB6),
314  bounded => 1, font => { forcebold => 1 });
315DefMathI('\lx@ams@boldsymbol@dag', undef, "\x{2020}",
316  bounded => 1, font => { forcebold => 1 });
317DefMathI('\lx@ams@boldsymbol@ddag', undef, "\x{2021}",
318  bounded => 1, font => { forcebold => 1 });
319
320DefConstructor('\lx@ams@boldsymbol@{}', '#1',
321  bounded => 1, requireMath => 1, font => { forcebold => 1 });
322
323DefMacro('\boldsymbol DefToken', sub {
324    my ($gullet, $token) = @_;
325    my $name   = ToString($token); $name =~ s/^\\//;
326    my $btoken = T_CS('\lx@ams@boldsymbol@' . $name);
327    return (IsDefined($btoken) ? ($btoken) : (T_CS('\lx@ams@boldsymbol@'), $token)); });
328
329# Ignore these?
330DefRegister('\buffer' => Dimension(0));
331DefMacro('\ChangeBuffer Dimension', '\buffer#2\relax');
332DefMacro('\ResetBuffer',            '');
333DefMacro('\shave{}',                '#1');
334DefMacro('\botshave{}',             '#1');
335DefMacro('\topshave{}',             '#1');
336
337DefMacro('\minCDarrowwidth Dimension',  '');
338DefMacro('\pretend Until:\haswidth {}', '#1');
339
340DefMacro('\snug', '');
341DefConstructor('\topsmash{}', "#1");
342DefConstructor('\botsmash{}', "#1");
343
344DefConstructor('\spreadmatrixlines Dimension', '');
345
346DefMacro('\MultlineGap Dimension', '');
347DefMacro('\multlinegap Dimension', '');
348DefMacro('\nomultlinegap',         '');
349
350DefMacro('\innerhdotsfor Number Match:\after {}', sub {
351    (map { '\hdots' } 1 .. $_[1]->valueOf); });
352DefMacro('\spacehdots Number Match:\for Number', sub {
353    (map { '\hdots' } 1 .. $_[1]->valueOf); });
354DefMacro('\spaceinnerhdots Number Match:\for Number Match:\after {}', sub {
355    (map { '\hdots' } 1 .. $_[1]->valueOf); });
356
357DefMacro('\foldedtext', sub {
358    my ($gullet) = @_;
359    if ($gullet->ifNext('\foldedwidth')) {
360      $gullet->readToken; $gullet->readDimension; }    # ignore?
361    T_CS('\text'); });
362
363Let('\topfoldedtext', '\foldedtext');
364Let('\botfoldedtext', '\foldedtext');
365
366# Maybe?
367DefMacro('\Sb Until:\endSb', '_{\substack{#1}}');
368DefMacro('\Sp Until:\endSp', '^{\substack{#1}}');
369Let('\endSb', '\relax');
370Let('\endSp', '\relax');
371
372DefMacro('\thetag', sub { T_OTHER(LookupValue('EQUATIONROW_NUMBER')); });    # ?
373
374DefMacro('\topaligned', '\aligned[t]');
375Let('\endtopaligned', '\endaligned');
376DefMacro('\botaligned', '\aligned[b]');
377Let('\endbotaligned', '\endaligned');
378
379# close enough?
380DefMacro('\accentedsymbol{}{}', '\def#1{#2}');
381
382# Tricky:
383#  \cfrac, \lcfrac, \endcfrac
384DefConstructor('\cfrac', '',
385  afterDigest => sub {
386    my ($stomach) = @_;
387    $stomach->bgroup;
388    Let(T_CS("\\\\"), T_CS('\lx@cfrac')); });
389DefConstructor('\endcfrac', '',
390  afterDigest => sub {
391    my ($stomach) = @_;
392    $stomach->egroup; });
393
394# These really need a way to pass denomalign=left|right to the MathML!
395Let('\lcfrac', '\cfrac');
396Let('\rcfrac', '\cfrac');
397
398DefMacro('\lx@cfrac',
399  '\lx@generalized@over{\\\\}{meaning=continued-fraction,role=MULOP}\displaystyle');
400
401#======================================================================
402# Bibliography
403# See amsppt.sty
404
405#======================================================================
406# Dubious
407RawTeX(<<'EoTeX');
408\def\vspace@{\def\vspace##1{\crcr\noalign{\vskip##1\relax}}}
409\newdimen\captionwidth@
410\newdimen\smallcaptionwidth@
411\newdimen\ex@
412\newdimen\buffer@
413\newdimen\spreadmlines@
414\newdimen\lwidth@
415\newdimen\rwidth@
416\newdimen\maxlwidth@
417\newdimen\maxrwidth@
418\newdimen\totwidth@
419\newdimen\lineht@
420\newdimen\gwidth@
421\newdimen\gmaxwidth@
422\newdimen\glineht@
423\newdimen\multlinegap@
424\newdimen\multlinetaggap@
425\newdimen\mwidth@
426\newdimen\mlineht@
427\newdimen\ltwidth@
428\newdimen\rtwidth@
429\newdimen\accentdimen@
430\newdimen\minaw@
431\newdimen\minCDaw@
432\newdimen\bigaw@
433\newdimen\pmbraise@
434\newtoks\hashtoks@
435EoTeX
436
437DefMacro('\printoptions',    '');
438DefMacro('\showallocations', '');
439DefMacro('\syntax',          '');
4401;
441