<?xml version="1.0" encoding="utf-8"?>
<!--
Tabellio - software suite for deliberative assemblies
         - suite logicielle pour assemblées délibératives
         - http://www.tabellio.org/
Copyright (C) 2006 Parlement de la Communauté française de Belgique

This file is part of Tabellio.

Tabellio 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 of the License, or
(at your option) any later version.

Tabellio 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 program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
    
<!--  FileName: table.xsl                    --> 
<!-- 
     Purpose: Customize Db2Latex product for table; the major differences are:
     o Generate a table across the two columns or inside one column 
       depending on the total width of the table columns.
     o Adapt the width of the table columns depending on the width of 
       the page column (two columns style) or the width of the entire page.
     o Generate a floating element 
     o Generate a threeparttable 
--> 

<!-- Sum the width of table columns --> 
<!-- Hypothesis: the width is given using 'pt' metric --> 

<xsl:param name="bqr"/>

<xsl:template name="table.sum-width">
    <xsl:param name="list"/>
    <xsl:choose>
        <xsl:when test="$list">
            <xsl:variable name="width" select="substring-before($list[1], 'pt')"/>
            <xsl:variable name="otherWidth">
                <!-- Recursive for next column -->
                <xsl:call-template name="table.sum-width">
                    <xsl:with-param name="list" select="$list[position() != 1]"/>
                </xsl:call-template>
            </xsl:variable>
            <xsl:value-of select="$otherWidth + $width"/>
        </xsl:when>
        <!-- Out of the recursive iteration -->
        <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template name="table.get-type">
    <xsl:param name="table" value="."/>

    <xsl:variable name="total-width">
        <xsl:call-template name="table.sum-width">
            <xsl:with-param name="list" select="$table/tgroup[1]/colspec/@colwidth"/>
        </xsl:call-template>
    </xsl:variable>
    <xsl:choose>
        <!-- xsl:when test="$total-width &lt; $table-width-threshold">0</xsl:when -->
    <xsl:when test="$bqr">0</xsl:when>
    <xsl:when test="($total-width &gt; $table-width-threshold) and ($table/@role = 'long')">2</xsl:when>
    <xsl:when test="$total-width &gt; $table-width-threshold">1</xsl:when>
        <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
</xsl:template>

<!-- Generate the latex specification of the table column p{width-specification}... --> 
<xsl:template name="table.format.tabular">
    <xsl:variable name="cols">
        <xsl:choose>
            <xsl:when test="@cols">
                <xsl:value-of select="@cols"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="count(tbody/row[1]/entry)"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>

    <xsl:variable name="total-width">
        <xsl:call-template name="table.sum-width">
            <xsl:with-param name="list" select="./colspec/@colwidth"/>
        </xsl:call-template>
    </xsl:variable>

    <xsl:call-template name="table.generate.format.tabular">
        <xsl:with-param name="cols" select="$cols"/>
        <xsl:with-param name="colsep" select="0"/>
        <xsl:with-param name="total-width" select="$total-width"/>
    </xsl:call-template>
</xsl:template>

<xsl:template name="table.generate.format.tabular">
    <xsl:param name="cols" select="1"/>
    <xsl:param name="i" select="1"/>
    <xsl:param name="colsep" select="0"/>
    <xsl:param name="total-width"/>
    <xsl:choose>
        <!-- Out of the recursive iteration -->
        <xsl:when test="$i > $cols"></xsl:when>

        <!-- There are still columns to count -->
        <xsl:otherwise>
            <!-- define the width of the current column: 
                   '$currentWidth div $totalWidth'\mytablewidth 
                 where 'mytablewidth' is a latex length taking into account 
                 the width available for the columns 
            -->
            <xsl:variable name="width-specification">
                <xsl:variable name="current-width">
                    <xsl:choose>
                        <xsl:when test="substring-before(./colspec[@colnum=$i], 'pt')">
                            <xsl:value-of select="./colspec[@colnum=$i]/@colwidth"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:value-of select="substring-before(./colspec[position()=$i]/@colwidth, 'pt')"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:variable>
                <xsl:variable name="cells" select="thead/row/entry[$i]|tbody/row/entry[$i]"/>
                <xsl:value-of select="concat($current-width div $total-width,'\mytablewidth')"/>
            </xsl:variable>
            <!-- Keep the @align attribute of the colspec node -->
            <xsl:variable name="useralign">
                <xsl:choose>
                    <xsl:when test="./colspec[@colnum=$i]">
                        <xsl:value-of select="./colspec[@colnum=$i]/@align"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="./colspec[position()=$i]/@align"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:choose>
                <xsl:when test="$useralign='left'"><xsl:text>&gt;{\RaggedRight}</xsl:text></xsl:when>
                <xsl:when test="$useralign='right'"><xsl:text>&gt;{\RaggedLeft}</xsl:text></xsl:when>
                <xsl:when test="$useralign='center'"><xsl:text>&gt;{\Centering}</xsl:text></xsl:when>
                <xsl:when test="$useralign='char'"><xsl:message>Table column 'char' alignment is not supported when width specified.</xsl:message></xsl:when>
                <xsl:when test="$useralign!=''"><xsl:message>Table column '<xsl:value-of select="$useralign"/>' alignment is not supported.</xsl:message></xsl:when>
            </xsl:choose>
            <xsl:text>p{</xsl:text><xsl:value-of select="$width-specification" /><xsl:text>}</xsl:text>

            <xsl:if test="$i&lt;$cols and $colsep='1'">
                <xsl:text>|</xsl:text>
            </xsl:if>
    
            <!-- Recursive for next column -->
        
            <xsl:call-template name="table.generate.format.tabular">
                <xsl:with-param name="i" select="$i+1"/>
                <xsl:with-param name="cols" select="$cols"/>
                <xsl:with-param name="colsep" select="$colsep"/>
                <xsl:with-param name="total-width" select="$total-width"/>
            </xsl:call-template>

        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<!-- Template to generate the row of the table body  
     Remark: no \hline is generated
--> 
<xsl:template match="tbody/row">
    <xsl:apply-templates/>
    <xsl:text> \tabularnewline&#10;</xsl:text>
</xsl:template>

<!-- Template to generate the row of the table header 
     Remark: \hline are generated before and after the header rows
--> 
<xsl:template match="thead/row">
    <xsl:apply-templates/>
    <xsl:text> \tabularnewline&#10;</xsl:text>
</xsl:template>


<!-- Template to generate the row of the table footer 
     Remark: \hline are generated before and after the footer rows
--> 
<xsl:template match="tfoot/row">
    <xsl:apply-templates/>
    <xsl:text> \tabularnewline&#10;</xsl:text>
</xsl:template>



<!-- Template to generate the content of the mpsupertabular table 
     Hypothesis: only one tgroup per table
--> 

<xsl:template match="tgroup" mode="mpsupertabular">

    <xsl:variable name="colspecs" select="./colspec"/>
    <xsl:variable name="align" select="@align"/>
    <xsl:variable name="colsep">0</xsl:variable>

    <!-- APPLY TEMPLATES -->
    <xsl:choose>
        <xsl:when test="thead">
            <xsl:text>\tablefirsthead{&#10;</xsl:text>
            <xsl:text>\hline&#10;</xsl:text>
            <xsl:apply-templates select="thead"/>
            <xsl:text>\hline&#10;</xsl:text>
            <xsl:text>}&#10;</xsl:text>
            <xsl:text>\tablehead{&#10;</xsl:text>
            <xsl:text>\hline&#10;</xsl:text>
            <xsl:apply-templates select="thead"/>
            <xsl:text>\hline&#10;</xsl:text>
            <xsl:text>}&#10;</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>\tablefirsthead{}&#10;</xsl:text>
            <xsl:text>\tablehead{}&#10;</xsl:text>
        </xsl:otherwise>
    </xsl:choose>

    <xsl:text>\begin{mpsupertabular}{</xsl:text>
    <xsl:call-template name="table.format.tabular"/>
    <xsl:text>}&#10;</xsl:text>

    <xsl:apply-templates select="tbody"/>

    <xsl:text>\end{mpsupertabular}&#10;</xsl:text>
</xsl:template>


<!-- Template to generate the content of the threeparttable table 
     Hypothesis: only one tgroup per table
--> 

<xsl:template match="tgroup" mode="threeparttable">

    <xsl:variable name="colspecs" select="./colspec"/>
    <xsl:variable name="align" select="@align"/>
    <xsl:variable name="colsep">0</xsl:variable>

    <!-- APPLY TEMPLATES -->

    <xsl:text>\begin{threeparttable}&#10;</xsl:text>
    <xsl:text>\begin{tabular}{</xsl:text>
    <xsl:call-template name="table.format.tabular"/>
    <xsl:text>}&#10;</xsl:text>

    <xsl:if test="thead">
        <xsl:text>\hline &#10;</xsl:text>
        <xsl:apply-templates select="thead"/>
        <xsl:text>\hline &#10;</xsl:text>
    </xsl:if>

    <xsl:apply-templates select="tbody"/>

    <xsl:text>\end{tabular}&#10;</xsl:text>

    <xsl:if test=".//footnote">
        <xsl:text>\rule{1.8cm}{1pt}&#10;</xsl:text>
        <xsl:text>\begin{tablenotes}&#10;</xsl:text>
        <xsl:call-template name="table-footnote-generation">
            <xsl:with-param name="footnotes" select=".//footnote"/>
            <xsl:with-param name="index" select="1"/>
        </xsl:call-template>
        <xsl:text>\end{tablenotes}&#10;</xsl:text>
    </xsl:if>

    <xsl:text>\end{threeparttable}&#10;</xsl:text>
</xsl:template>

<!-- Template to generate the footnotes just after the table
--> 
<xsl:template name="table-footnote-generation">
    <xsl:param name="footnotes"/>
    <xsl:param name="index" select="1"/>
    <xsl:choose>
        <xsl:when test="$index > count($footnotes)">
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>\item[</xsl:text>
            <xsl:number value="$index" format="a" />
            <xsl:text>] {</xsl:text>
            <xsl:apply-templates select="$footnotes[$index]/*"/>
            <xsl:text>}</xsl:text>
            <xsl:call-template name="table-footnote-generation">
                <xsl:with-param name="footnotes" select="$footnotes"/>
                <xsl:with-param name="index" select="$index+1"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>


<!-- Entry rule for table generation 
--> 
<xsl:template match="table">

    <xsl:variable name="placement">
        <xsl:call-template name="generate.formal.title.placement">
            <xsl:with-param name="object" select="local-name(.)" />
        </xsl:call-template>
    </xsl:variable>

    <!-- Keep the table position specification (default: htb) -->
    <xsl:variable name="position">
        <xsl:choose>
            <xsl:when test="@condition">
                <xsl:value-of select="@condition"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>htb</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>

    <xsl:variable name="table.type">
        <xsl:call-template name="table.get-type">
            <xsl:with-param name="table" select="."/>
        </xsl:call-template>
    </xsl:variable>

    <!-- Keep the caption  -->
    <xsl:variable name="table.caption.mpsupertabular">
        <xsl:choose>
            <xsl:when test="title">
                <xsl:value-of select="$latex.table.caption.style"/>
                <xsl:text>\tablecaption{</xsl:text>
                <xsl:if test="title/@id">
                    <xsl:text>\label{</xsl:text>
                    <xsl:value-of select="title/@id"/>
                    <xsl:text>}</xsl:text>
                </xsl:if>
                <xsl:call-template name="label.id"/>
                <xsl:apply-templates select="title" mode="caption.mode"/>
                <xsl:text>}</xsl:text>
            </xsl:when>
            <xsl:otherwise>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>

    <xsl:variable name="table.caption.threeparttable">
        <xsl:choose>
            <xsl:when test="title">
                <xsl:value-of select="$latex.table.caption.style"/>
                <xsl:text>\caption{</xsl:text>
                <xsl:if test="title/@id">
                    <xsl:text>\label{</xsl:text>
                    <xsl:value-of select="title/@id"/>
                    <xsl:text>}</xsl:text>
                </xsl:if>
                <xsl:call-template name="label.id"/>
                <xsl:apply-templates select="title" mode="caption.mode"/>
                <xsl:text>}</xsl:text>
            </xsl:when>
            <xsl:otherwise>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    
    <!-- Calculate the total width of the table -->
    <xsl:variable name="total-width">
        <xsl:call-template name="table.sum-width">
            <xsl:with-param name="list" select="./tgroup[1]/colspec/@colwidth"/>
        </xsl:call-template>
    </xsl:variable>

    <!-- Keep the number of columns -->
    <xsl:variable name="nbr-cols">
        <xsl:choose>
            <xsl:when test="./tgroup[1]/@cols">
                <xsl:value-of select="./tgroup[1]/@cols"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="count(./tgroup[1]/tbody/row[1]/entry)"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>

    <!-- Core part of the template: Code generation -->
    
    <xsl:text>&#10;</xsl:text>
    <xsl:text>% Begin table definition &#10;</xsl:text>
    <xsl:text>% ------------------------ &#10;&#10;</xsl:text>
    <xsl:if test='$bqr'>
        <xsl:text>\end{multicols}&#10;</xsl:text>
        <xsl:text>\begin{changemargin}{1cm}{1cm}&#10;</xsl:text>
    </xsl:if>

    <xsl:text>\setlength{\mytempvalue}{</xsl:text>
    <xsl:value-of select="concat($total-width,'pt')"/>
    <xsl:text>}&#10;</xsl:text>
    <xsl:choose>
        <xsl:when test="$table.type = '1'">  <!-- flotting type -->
            <xsl:text>% The table is floating -> threeparttable inside a floating element &#10;</xsl:text>
            <xsl:text>\setlength{\mytablewidth}{\textwidth}&#10;</xsl:text>
            <xsl:text>\addtolength{\mytablewidth}{-</xsl:text>
            <xsl:value-of select="$nbr-cols * 2"/>
            <xsl:text>\tabcolsep}&#10;</xsl:text>
            <xsl:text>\begin{table*}[htb]</xsl:text>
            <xsl:value-of select="$table.caption.threeparttable" />
            <xsl:text>&#10;%&#10;%&#10;%&#10;</xsl:text>
            <xsl:apply-templates select="tgroup[1]" mode="threeparttable"/>
            <xsl:text>\end{table*}</xsl:text>
        </xsl:when>
        <xsl:when test="$table.type = '2'">  <!-- long and broad table -->
            <xsl:text>% The table is not floating but broad and long -> mpsupertabular with page break&#10;</xsl:text>
            <xsl:text>%\balance&#10;</xsl:text>
            <xsl:text>\onecolumn&#10;</xsl:text>
            <xsl:text>\setlength{\mytablewidth}{\textwidth}&#10;</xsl:text>
            <xsl:text>\addtolength{\mytablewidth}{-</xsl:text>
            <xsl:value-of select="$nbr-cols * 2"/>
            <xsl:text>\tabcolsep}&#10;</xsl:text>
            <xsl:value-of select="$table.caption.mpsupertabular" />
            <xsl:text>&#10;%&#10;%&#10;%&#10;</xsl:text>
            <xsl:apply-templates select="tgroup[1]" mode="mpsupertabular"/>
            <xsl:text>\twocolumn</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>% The table is not floating: using mpsupertabular&#10;</xsl:text>
            <xsl:text>\setlength{\mytablewidth}{\columnwidth}&#10;</xsl:text>
            <xsl:text>\addtolength{\mytablewidth}{-</xsl:text>
            <xsl:value-of select="$nbr-cols * 2"/>
            <xsl:text>\tabcolsep}&#10;</xsl:text>
            <xsl:if test='$bqr'>
                <xsl:text>\addtolength{\mytablewidth}{-2cm}&#10;</xsl:text>
            </xsl:if>
            <xsl:value-of select="$table.caption.mpsupertabular" />
            <xsl:apply-templates select="tgroup[1]" mode="mpsupertabular"/>
        </xsl:otherwise>
    </xsl:choose>
    <xsl:if test='$bqr'>
        <xsl:text>\begin{center}&#10;&#10;</xsl:text>
        <xsl:text>\vskip 3ex&#10;</xsl:text>
        <xsl:text>* *\\[-2mm]&#10;</xsl:text>
        <xsl:text>*&#10;</xsl:text>
        <xsl:text>\end{center}&#10;</xsl:text>
        <xsl:text>\end{changemargin}&#10;</xsl:text>
        <xsl:text>\begin{multicols}{2}&#10;</xsl:text>
    </xsl:if>
    <xsl:text>% End table definition&#10;</xsl:text>
    <xsl:text>% ------------------------ &#10;</xsl:text>
</xsl:template>


</xsl:stylesheet>
