# -*- mode: Perl -*-
# /=====================================================================\ #
# |  longtable                                                          | #
# | 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;

#======================================================================
# NOTE: The way the headers & footers are captured causes trailing \hlines
# to generate empty rows.
#======================================================================
# Environment \begin{longtable}[align]{pattern} ... \end{longtable}
DefMacro('\longtable[]{}',
  '\lx@longtable@bindings{#2}\@@longtable[#1]{#2}\@start@alignment');
DefMacro('\endlongtable',
  '\@finish@alignment\@end@tabular');
# {longtable*} is defined in revtex4-1 to be able to span a two column document
DefMacro('\csname longtable*\endcsname []{}',
  '\lx@longtable@bindings{#2}\@@longtable[#1]{#2}\@start@alignment');
DefMacro('\csname endlongtable*\endcsname',
  '\@finish@alignment\@end@tabular');

DefMacro('\@gobble@optional[]', Tokens());

DefConstructor('\@@longtable [] Undigested DigestedBody',
  "<ltx:table xml:id='#id' inlist='lot' labels='#label'>"
    . "#tags"
    . "?#headcaption(<ltx:caption>#headcaption</ltx:caption>)"
    . "?#headtoccaption(<ltx:toccaption>#headtoccaption</ltx:toccaption>)"
    . "#3"
    . "?#footcaption(<ltx:caption>#footcaption</ltx:caption>)"
    . "?#foottoccaption(<ltx:toccaption>#foottoccaption</ltx:toccaption>)"
    . "</ltx:table>",
  reversion    => '\begin{longtable}[#1]{#2}#3\end{longtable}',
  beforeDigest => sub { $_[0]->bgroup; Let('\pagebreak', '\@gobble@optional'); },
  afterDigest  => sub {
    my ($stomach, $whatsit) = @_;
    $whatsit->setProperties(%{ LookupValue('LONGTABLE_PROPERTIES') || {} });
    # Insert caption and toccaption, if any were encountered.
    if (my $captions = LookupValue('LONGTABLE_HEAD_CAPTIONS') || LookupValue('LONGTABLE_CAPTIONS')) {
      my ($toccaption, $caption) = @$captions;
      $whatsit->setProperty(headcaption    => $caption)    if $caption;
      $whatsit->setProperty(headtoccaption => $toccaption) if $toccaption; }
    if (my $captions = LookupValue('LONGTABLE_FOOT_CAPTIONS')) {
      my ($toccaption, $caption) = @$captions;
      $whatsit->setProperty(footcaption    => $caption)    if $caption;
      $whatsit->setProperty(foottoccaption => $toccaption) if $toccaption; }
    my $alignment = LookupValue('Alignment');
    # Reinsert the head and foot into the alignment.
    if (my $head = LookupValue('LONGTABLE_HEAD')) {
      $alignment->prependRows(@{$head}); }
    if (my $foot = LookupValue('LONGTABLE_FOOT')) {
      $alignment->appendRows(@{$foot}); }
    return; },
  mode => 'text');

DefPrimitive('\lx@longtable@bindings AlignmentTemplate', sub { longtableBindings($_[1]); });

sub longtableBindings {
  my ($template) = @_;
  tabularBindings($template, guess_headers => 0);
  Let('\endfirsthead', '\lx@longtable@endfirsthead');
  Let('\endhead',      '\lx@longtable@endhead');
  Let('\endfoot',      '\lx@longtable@endfoot');
  Let('\endlastfoot',  '\lx@longtable@endlastfoot');
  Let('\caption',      '\lx@longtable@caption');
  Let('\label',        '\lx@longtable@label');
  Let('\kill',         '\lx@longtable@kill@marker');
  AssignValue(LONGTABLE_LABEL         => undef, 'global');    # Clear these vars.
  AssignValue(LONGTABLE_CAPTIONS      => undef, 'global');
  AssignValue(LONGTABLE_HEAD_CAPTIONS => undef, 'global');
  AssignValue(LONGTABLE_FOOT_CAPTIONS => undef, 'global');
  AssignValue(LONGTABLE_HEAD          => undef, 'global');
  AssignValue(LONGTABLE_FOOT          => undef, 'global');
  ## properties happen too late!!!
  AssignValue(LONGTABLE_PROPERTIES => { RefStepCounter('table') }, 'global');

  return; }

#======================================================================
# These macros appear within the longtable, at the beginning.
# They cut of the previous lines to be used as headers or footers.

DefMacro('\lx@longtable@endfirsthead', '\crcr\noalign{\lx@longtable@grab{FIRSTHEAD}}');
DefMacro('\lx@longtable@endhead',      '\crcr\noalign{\lx@longtable@grab{HEAD}}');
DefMacro('\lx@longtable@endfoot',      '\crcr\noalign{\lx@longtable@grab{FOOT}}');
DefMacro('\lx@longtable@endlastfoot',  '\crcr\noalign{\lx@longtable@grab{LASTFOOT}}');
DefMacro('\lx@longtable@kill',         '\crcr\noalign{\lx@longtable@kill@marker}');

DefPrimitive('\lx@longtable@grab{}', sub {
    my ($stomach, $name) = @_;
    $name = ToString($name);
    my $alignment = LookupValue('Alignment');
    # Remove all preceding rows.
    my @rows = ();
    while (my $row = $alignment->removeRow) {
      map { $$_{thead}{column} = 1; } $row->columns;
      unshift(@rows, $row); }
    if (($name eq 'FIRSTHEAD') || (($name eq 'HEAD') && !LookupValue('LONGTABLE_HEAD'))) {
      AssignValue(LONGTABLE_HEAD => [@rows], 'global');
      if (my $caption = LookupValue('LONGTABLE_CAPTIONS')) {
        AssignValue(LONGTABLE_CAPTIONS      => undef,    'global');
        AssignValue(LONGTABLE_HEAD_CAPTIONS => $caption, 'global'); } }
    elsif (($name eq 'LASTFOOT') || (($name eq 'FOOT') && !LookupValue('LONGTABLE_FOOT'))) {
      AssignValue(LONGTABLE_FOOT => [@rows], 'global');
      if (my $caption = LookupValue('LONGTABLE_CAPTIONS')) {
        AssignValue(LONGTABLE_CAPTIONS      => undef,    'global');
        AssignValue(LONGTABLE_FOOT_CAPTIONS => $caption, 'global'); } }
    return; });

DefConstructor('\lx@longtable@kill@marker', '', reversion => '\kill',
  afterDigest => sub { LookupValue('Alignment')->removeRow; return; });

#======================================================================
# Caption gets redefined.  We'll need to grab it and make it part
# of the table, rather than the tabular.
DefMacro('\lx@longtable@caption[]{}',
  '\lx@longtable@caption@{\lx@format@toctitle@@{table}{\ifx.#1.#2\else#1\fi}}'
    . '{\lx@format@title@@{table}{#2}}');
DefPrimitive('\lx@longtable@caption@{}{}', sub {
    AssignValue(LONGTABLE_CAPTIONS => [DigestText($_[1]), DigestText($_[2])], 'global');
    return; });
DefPrimitive('\lx@longtable@label Semiverbatim', sub {
    AssignValue(LONGTABLE_LABEL => CleanLabel(ToString($_[1])), 'global');
    return; });

#======================================================================
# Not used, but must be defined.
DefRegister('\LTleft'      => Glue('0pt plus 1fill'));
DefRegister('\LTright'     => Glue('0pt plus 1fill'));
DefRegister('\LTpre'       => Glue('12pt plus 4pt minus 4pt'));
DefRegister('\LTpost'      => Glue('12pt plus 4pt minus 4pt'));
DefRegister('\LTcapwidth'  => Dimension('4in'));
DefRegister('\LTchunksize' => Number(200));
DefRegister('\LT@cols'     => Number(0));
DefRegister('\LT@rows'     => Number(0));
Let('\c@LTchunksize', '\LTchunksize');
RawTeX(<<'EOL');
\newbox\LT@head
\newbox\LT@firsthead
\newbox\LT@foot
\newbox\LT@lastfoot
\newbox\LT@gbox
EOL
Let('\setlongtables', '\relax');
#======================================================================
1;