# -*- 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[]{}',
  '\@longtable@bindings{#2}\@@longtable[#1]{#2}\@start@alignment');
DefMacro('\endlongtable',
  '\@finish@alignment\@end@tabular');
DefMacro('\csname longtable*\endcsname []{}',
  '\@longtable@bindings{#2}\@@longtable[#1]{#2}\@start@alignment');
DefMacro('\csname endlongtable*\endcsname',
  '\@finish@alignment\@end@tabular');

DefConstructor('\@@longtable [] Undigested DigestedBody',
  "<ltx:table xml:id='#id' refnum='#refnum' frefnum='#frefnum' rrefnum='#rrefnum' labels='#label'>"
    . "?#caption(<ltx:caption>#caption</ltx:caption>)"
    . "?#toccaption(<ltx:toccaption>#toccaption</ltx:toccaption>)"
    . "#3"
    . "</ltx:table>",
  reversion    => '\begin{longtable}[#1]{#2}#3\end{longtable}',
  beforeDigest => sub { $_[0]->bgroup; },
  afterDigest  => sub {
    my ($stomach, $whatsit) = @_;
    $whatsit->setProperties(%{ LookupValue('LONGTABLE_PROPERTIES') || {} });
    # Insert caption and toccaption, if any were encountered.
    if (my $caption = LookupValue('LONGTABLE_CAPTION')) {
      $whatsit->setProperty(caption => $caption); }
    if (my $label = LookupValue('LONGTABLE_LABEL')) {
      $whatsit->setProperty(label => $label); }
    if (my $toccaption = LookupValue('LONGTABLE_TOCCAPTION')) {
      $whatsit->setProperty(toccaption => $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('\@longtable@bindings AlignmentTemplate', sub { longtableBindings($_[1]); });

sub longtableBindings {
  my ($template) = @_;
  tabularBindings($template, guess_headers => 0);
  Let('\endfirsthead', '\@longtable@endfirsthead');
  Let('\endhead',      '\@longtable@endhead');
  Let('\endfoot',      '\@longtable@endfoot');
  Let('\endlastfoot',  '\@longtable@endlastfoot');
  Let('\caption',      '\@longtable@caption');
  Let('\label',        '\@longtable@label');
  AssignValue(LONGTABLE_LABEL      => undef, 'global');    # Clear these vars.
  AssignValue(LONGTABLE_CAPTION    => undef, 'global');
  AssignValue(LONGTABLE_TOCCAPTION => 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('\@longtable@endfirsthead',
  '\@close@inner@column\@close@column\@close@row'
    . '\@longtable@grab{FIRSTHEAD}'
    . '\@open@row\@open@column\@open@inner@column');
DefMacro('\@longtable@endhead',
  '\@close@inner@column\@close@column\@close@row'
    . '\@longtable@grab{HEAD}'
    . '\@open@row\@open@column\@open@inner@column');
DefMacro('\@longtable@endfoot',
  '\@close@inner@column\@close@column\@close@row'
    . '\@longtable@grab{FOOT}'
    . '\@open@row\@open@column\@open@inner@column');
DefMacro('\@longtable@endlastfoot',
  '\@close@inner@column\@close@column\@close@row'
    . '\@longtable@grab{LASTFOOT}'
    . '\@open@row\@open@column\@open@inner@column');
DefMacro('\@longtable@kill',
  '\@close@inner@column\@close@column\@close@row'
    . '\@longtable@kill@marker'
    . '\@open@row\@open@column\@open@inner@column');

DefPrimitive('\@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'); }
    elsif (($name eq 'LASTFOOT') || (($name eq 'FOOT') && !LookupValue('LONGTABLE_FOOT'))) {
      AssignValue(LONGTABLE_FOOT => [@rows], 'global'); }
    return; });

DefConstructor('\@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('\@longtable@caption[]{}',
  '\@longtable@@toccaption{\format@toctitle@{table}{\ifx.#1.#2\else#1\fi}}'
    . '\@longtable@@caption{\format@title@{table}{#2}}');
DefPrimitive('\@longtable@label Semiverbatim', sub {
    AssignValue(LONGTABLE_LABEL => CleanLabel(ToString($_[1])), 'global');
    return; });
DefPrimitive('\@longtable@@caption{}', sub {
    AssignValue(LONGTABLE_CAPTION => Digest($_[1]), 'global');
    return; });
DefPrimitive('\@longtable@@toccaption{}', sub {
    AssignValue(LONGTABLE_TOCCAPTION => Digest($_[1]), 'global');
    return; });

#======================================================================
# Not used, but must be defined.
DefRegister('\LTLeft'      => Glue(0));
DefRegister('\LTRight'     => Glue(0));
DefRegister('\LTPre'       => Glue(0));
DefRegister('\LTPost'      => Glue(0));
DefRegister('\LTcapwidth'  => Glue(0));
DefRegister('\LTchunksize' => Number(20));

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