# -*- mode: Perl -*-
# /=====================================================================\ #
# |  sv support                                                         | #
# | Implementation for LaTeXML                                          | #
# |=====================================================================| #
# | Part of LaTeXML:                                                    | #
# |  Public domain software, produced as part of work done by the       | #
# |  United States Government & not subject to copyright in the US.     | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Package::Pool;
use strict;
use warnings;
use LaTeXML::Package;

# Only if option natbib!
RequirePackage('natbib');
RequirePackage('inst_support');

#======================================================================
# Frontmatter
DefRegister('\titlerunning', Tokens());
DefMacro('\titrun',     Tokens());
DefMacro('\subtitle{}', '\@add@frontmatter{ltx:subtitle}{#1}');

DefRegister('\authorrunning', Tokens());
DefMacro('\authrun', Tokens());

DefMacro('\emailname', 'E-mail');
DefConstructor('\@@@email{}', "^ <ltx:contact role='email' name='#name'>#1</ltx:contact>",
  properties => { (name => Digest(T_CS('\emailname'))) });
DefMacro('\email Semiverbatim', '\@add@to@frontmatter{ltx:creator}{\@@@email{#1}}');
DefMacro('\mailname',           '\textit{Correspondence}');
DefConstructor('\@@@mail{}', "^ <ltx:contact role='address' name='#name'>#1</ltx:contact>",
  properties => { (name => Digest(T_CS('\mailname'))) });
DefMacro('\mail{}', '\@add@to@frontmatter{ltx:creator}{\@@@mail{#1}}');

DefMacro('\keywordname',  '\textbf{Keywords}');
DefMacro('\keywords{}',   '\@add@frontmatter{ltx:keywords}[name={\keywordname}]{#1}');
DefMacro('\subclassname', '\textbf{Mathematics Subject Classification (2000)}');
DefMacro('\subclass{}', '\@add@frontmatter{ltx:classification}[scheme=MSC,name={\subclassname}]{#1}');
DefMacro('\CRclassname', '\textbf{CR Subject Classification}');
DefMacro('\CRclass{}',  '\@add@frontmatter{ltx:classification}[scheme=CR,name={\CRclassname}]{#1}');
DefMacro('\ESMname',    '\textbf{Electronic Supplementary Material}');
DefMacro('\ESM{}',      '\@add@frontmatter{ltx:note}[role=supplemental,name={\ESMname}]{#1}');
DefMacro('\PACSname',   '\textbf{PACS}');
DefMacro('\PACS{}',     '\@add@frontmatter{ltx:classification}[scheme=pacs,name={\PACSname}]{#1}');
DefMacro('\headnote{}', '\@add@frontmatter{ltx:note}{#1}');
DefMacro('\dedication{}',  '\@add@frontmatter{ltx:note}[role=dedicatory]{#1}');
DefMacro('\offprints{}',   '\@add@frontmatter{ltx:note}[role=offprints]{#1}');
DefMacro('\journalname{}', '\@add@frontmatter{ltx:note}[role=journal]{#1}');
DefMacro('\papertype{}',   '\@add@frontmatter{ltx:classification}[scheme=papertype]{#1}');

Let('\journalopt', '\@empty');

# svjour covers several specific journal styles.
# And SOME (but not all!) of those journal styles call for \abstract{...}
# instead of the abstract environment!
# Moreover, those that do expect the abstract to appear in the Preamble,
# so that it gets included in maketitle.

# We'll try just redefining \abstract (and leave the abstract environment
# for when people need and actually use \begin[abstract}...)

Let('\@orig@abstract', '\abstract');
DefMacro('\abstract OptionalMatch:*', sub {
    if ($_[1])                     { T_CS('\lx@ignore@sv@abstract'); }
    elsif ($_[0]->ifNext(T_BEGIN)) { T_CS('\@abstract@with@arg'); }
    else                           { T_CS('\@orig@abstract'); } });

# Just ignore \abstract* (what's it for?)
DefMacro('\lx@ignore@sv@abstract{}', '');
DefMacro('\@abstract@with@arg{}',    '\@add@frontmatter{ltx:abstract}[name={\abstractname}]{#1}');

DefMacro('\makereferee', Tokens());

DefMacro('\ackname', 'Acknowledgements');
DefConstructor('\acknowledgements', "<ltx:acknowledgements name='#name'>",
  properties => { (name => Digest(T_CS('\ackname'))) });
DefMacro('\acknowledgement', '\acknowledgements');
DefConstructor('\endacknowledgements', "</ltx:acknowledgements>");
DefConstructor('\endacknowledgement',  "</ltx:acknowledgements>");
Tag("ltx:acknowledgements", autoClose => 1);

DefMacro('\noteaddname', 'Note added in proof');
DefMacro('\notename',    'Note');
DefEnvironment('{noteadd}', "<ltx:note name='#name'>#body</ltx:note>",
  properties => { (name => Digest(T_CS('\noteaddname'))) });

Let('\orithanks', '\thanks');
DefMacro('\runheadhook', Tokens());
DefMacro('\svlanginfo',  Tokens());
DefMacro('\makeheadbox', Tokens());      # Should be covered by frontmatter/maketitle
DefMacro('\authdepth',   '2');
DefMacro('\authorfont',  '\bfseries');
DefMacro('\stripauthor', Tokens());      # ?
DefRegister('\instindent' => Dimension(0));
DefMacro('\combirun',       Tokens());
DefMacro('\combirunning{}', Tokens());

DefMacro('\validfor',            Tokens());
DefMacro('\ClassInfoNoLine{}{}', Tokens());
DefMacro('\ProcessRunnHead',     Tokens());
DefMacro('\fnmsep',              Tokens());    # ?
DefMacro('\institutename',       Tokens());    # ?
#======================================================================
DefMacro('\nocaption{}',    Tokens());
DefMacro('\sidecaption {}', Tokens());

DefMacro('\capstrut',     Tokens());
DefMacro('\captionstyle', '\normalfont\small');
DefRegister('\figcapgap' => Dimension('3pt'));
DefRegister('\tabcapgap' => Dimension('5.5pt'));
DefRegister('\figgap'    => Dimension('1cc'));

DefMacro('\tableheadseprule', '\hrule');
DefMacro('\floatlegendstyle', '\bfseries');
DefMacro('\leftlegendglue',   Tokens());

DefPrimitive('\normalthmheadings',  sub { AssignValue('thm@swap' => 0); });
DefPrimitive('\reversethmheadings', sub { AssignValue('thm@swap' => 1); });
DefRegister('\spthmsep' => Dimension('5pt'));

# \spnewtheorem*{env}[numberedlike]{caption}[within]{capfont}{bodyfont}
# NOTE: Can I use latex's \newtheoremstyle, or do I need to copy & adapt it?
# Seems to be the same as \newtheoremstyle, but with additonal capfont & bodyfont
DefMacro('\spnewtheorem OptionalMatch:* {}[]{}[] {}{}', sub {
    my ($stomach, $flag, $thmset, $otherthmset, $type, $reset, $capfont, $bodyfont) = @_;
    $thmset      = ToString($thmset);
    $otherthmset = $otherthmset && ToString($otherthmset);
    $type        = undef unless $type->unlist;
    $reset       = $reset ? ToString($reset) : undef;

    my $counter = $otherthmset || $thmset;
    my $swap    = LookupValue('thm@swap');
    my $style   = ToString(LookupRegister('\thm@style'));

    if (!$otherthmset) {
      NewCounter($counter, $reset,
        idprefix => "Thm$counter");
      DefMacroI(T_CS("\\the$counter"), undef,
        "\\csname the$reset\\endcsname\\\@thmcountersep\\arabic{$counter}",
        scope => 'global')
        if $reset; }

# Swap causes you to get the odd (to me) order "4.1 Lemma", which breaks our new localization methods!!!
    DefEnvironmentI($thmset, "OptionalUndigested",
      "<ltx:theorem xml:id='#id' class='#class'>"
        . "#tags"
        . "<ltx:title font='#titlefont' _force_font='true'>#title</ltx:title>"
        . "#body",
      afterConstruct => sub { $_[0]->maybeCloseElement('ltx:theorem'); },
      beforeDigest   => sub {
        my $stylecmd = T_CS('\th@' . $style);
        if (!IsDefined($stylecmd)) {
          Warn('unexpected', $style, $_[0], "Unknown theoremstyle '$style'");
          $stylecmd = T_CS('\th@plain'); }
        Digest(Tokens($stylecmd)); },
      afterDigestBegin => sub { Digest($bodyfont); },
      properties       => sub {
        my %ctr   = ($counter ? ($flag ? RefStepID($counter) : RefStepCounter($counter)) : ());
        my $title = Digest(Tokens(T_BEGIN, $capfont->unlist,
            T_CS('\lx@tag'), T_BEGIN,
            ($swap
              ? (($flag ? () : (T_CS('\the' . $counter))),
                (!$flag && $type ? (T_SPACE)       : ()),
                ($type           ? ($type->unlist) : ()))
              : (($type ? ($type->unlist) : ()),
                (!$flag && $type ? (T_SPACE) : ()),
                ($flag           ? ()        : (T_CS('\the' . $counter))))),
            T_END,
            ($type && $_[1] ? (T_SPACE, T_OTHER('(')) : ()),
            ($_[1]          ? $_[1]->unlist           : ()),
            ($type && $_[1] ? (T_OTHER(')'))          : ()),
            T_CS('\the'), T_CS('\thm@headpunct'),
            T_END));
        (%ctr,
          title     => $title,
          titlefont => $title->getFont,
          class     => 'ltx_theorem_' . CleanClassName($thmset)); },
      scope => 'global');
});

Let('\spdefaulttheorem', '\spnewtheorem');

RawTeX(<<'EOTeX');
\def\theoremname{Theorem}
\spnewtheorem{theorem}{Theorem}[section]{\bfseries}{\itshape}
\def\claimname{Claim}
\spnewtheorem*{claim}{Claim}{\itshape}{\rmfamily}
\def\proofname{Proof}
\spnewtheorem*{proof}{Proof}{\itshape}{\rmfamily}
\spnewtheorem{case}{Case}{\itshape}{\rmfamily}
\def\conjecturename{Conjecture}
\spnewtheorem{conjecture}{Conjecture}{\itshape}{\rmfamily}
\def\corollaryname{Corollary}
\spnewtheorem{corollary}{Corollary}{\bfseries}{\itshape}
\def\definitionname{Definition}
\spnewtheorem{definition}{Definition}{\bfseries}{\rmfamily}
\def\examplename{Example}
\spnewtheorem{example}{Example}{\itshape}{\rmfamily}
\def\exercisename{Exercise}
\spnewtheorem{exercise}{Exercise}{\bfseries}{\rmfamily}
\def\lemmaname{Lemma}
\spnewtheorem{lemma}{Lemma}{\bfseries}{\itshape}
\def\notename{Note}
\spnewtheorem{note}{Note}{\itshape}{\rmfamily}
\def\problemname{Problem}
\spnewtheorem{problem}{Problem}{\bfseries}{\rmfamily}
\def\propertyname{Property}
\spnewtheorem{property}{Property}{\itshape}{\rmfamily}
\def\propositionname{Proposition}
\spnewtheorem{proposition}{Proposition}{\bfseries}{\itshape}
\def\questionname{Question};
\spnewtheorem{question}{Question}{\itshape}{\rmfamily}
\def\solutionname{Solution}
\spnewtheorem{solution}{Solution}{\bfseries}{\rmfamily}
\def\remarkname{Remark}
\spnewtheorem{remark}{Remark}{\itshape}{\rmfamily}
EOTeX

DefEnvironment('{theopargself*}', '#body');    # ?
DefEnvironment('{theopargself}',  '#body');    # ?

DefEnvironment('{translation}{}', "<ltx:quote role='translation' lang='#1'>#body</ltx:quote>");

#======================================================================
DefMacro('\qed', '\ltx@qed');
DefConstructor('\ltx@qed',
  "?#isMath(<ltx:XMTok role='PUNCT'>\x{220E}</ltx:XMTok>)(\x{220E})",
  reversion => '\qed');
Let('\smartqed',     '\qed');
Let('\squareforqed', '\qed');

DefMacro('\tens{}', '\ensuremath{\mathsf{#1}}');

#======================================================================
# Random text

DefMacro('\andname',         'and');
DefMacro('\chaptername',     'Chapter');
DefMacro('\contriblistname', 'List of Contributors');
DefMacro('\lastandname',     ', and');
DefMacro('\seename',         'see');
DefMacro('\etal',            'et al.');
DefMacro('\notused',         '~');

#======================================================================
DefRegister('\aftertext'         => Dimension('5pt'));
DefRegister('\betweenumberspace' => Dimension('3.33pt'));
DefRegister('\headerboxheight'   => Dimension('180pt'));
DefRegister('\headlineindent'    => Dimension('1.166cm'));

DefMacro('\runinend',        Tokens());
DefMacro('\floatcounterend', Tokens());
DefMacro('\sectcounterend',  Tokens());

# These should do 1 or 2 depending on twocolumn mode!
DefMacro('\columncase',     '\makeatletter\twocolteset');
DefMacro('\twocoltest{}{}', '#1\makeatother');

NewCounter('lastpage');
DefMacro('\getlastpagenumber', Tokens());
DefMacro('\islastpageeven',    Tokens());

DefMacro('\makesectrule',        Tokens());
DefMacro('\makesectruleori',     Tokens());
DefMacro('\nosectrule',          Tokens());
DefMacro('\restoresectrule',     Tokens());
DefMacro('\nothanksmarks',       Tokens());
DefMacro('\setitemindent{}',     Tokens());
DefMacro('\setitemitemindent{}', Tokens());
DefMacro('\thisbottomragged',    Tokens());

DefMacro('\rubric', Tokens());
DefRegister('\rubricwidth' => Dimension('0pt'));
DefMacro('\strich', Tokens());
DefRegister('\logodepth' => Dimension('1.2cm'));
DefMacro('\lastevenhead', Tokens());
#======================================================================
# Odd; they add an optional arg!
DefEnvironment('{description}[]',
  "<ltx:description  xml:id='#id'>#body</ltx:description>",
  properties => sub { beginItemize('description'); },
  locked     => 1);

#======================================================================
1;