%  __________________________________________________
% |                                                  |
% |                                                  |
% |                tabularcalc v0.1                  |
% |                                                  |
% |                  March 19 2009                   |
% |                                                  |
% |__________________________________________________|
%
% This is tabularcalc.sty
%
% "tabularcalc" package consists of the 6 following files:
%   tabularcalc.sty (this file)
%   README
%   tabularcalc_doc_fr.tex, tabularcalc_doc_fr.pdf (manual in french)
%   tabularcalc_doc_en.tex, tabularcalc_doc_en.pdf (manual in english)
%
% Christian Tellechea 2009
% email : unbonpetit@gmail.com
% -------------------------------------------------------------------
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%
%     http://www.latex-project.org/lppl.txt
%
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
% -------------------------------------------------------------------
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Christian Tellechea
% -------------------------------------------------------------------

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{tabularcalc}%
	[2009/02/15 v0.1 Compute formulas in tables]
\RequirePackage{xstring}
\RequirePackage{numprint}
\RequirePackage{pgf,pgfmath}

\newcommand\tabularcalcversion     {0.1}
\newcommand\tabularcalcdate        {2009/03/19}
\newcommand\tabularcalcfrenchdate  {19 mars 2009}
\newcommand\tabularcalcenglishdate {March $19^{\mathrm{th}}$ 2009}
\newcount\tccol\newcount\tclin
\newif\iftc@showval

\newcommand\tc@checkdefine[2]{\@ifdefinable#1{\def#1{#2}}{}}

\newcommand\tc@addtomacro[2]{\expandafter\def\expandafter#1\expandafter{#1#2}}
\newcommand\tc@expaddtomacro[2]{%
	\expandafter\tc@addtomacro\expandafter#1\expandafter{#2}}

% choisit le moteur pour calculer l'expression contenue dans \tc@currentresult
% puis assigne le r\'esultat dans \tc@currentresult
\tc@checkdefine\tc@evalexpr{%
	\expandafter\pgfmathparse\expandafter{\tc@currentresult}%
	\let\tc@currentresult\pgfmathresult}

\tc@checkdefine\noshowmark{}
\makeatother\def\noshowmark{@}\makeatletter

\tc@checkdefine\startline{\rule[-1.2ex]{0pt}{4ex}}
\tc@checkdefine\tc@cellcode{}
\tc@checkdefine\tc@currentcellcode{}
\newcommand\resetcellcode{\let\tc@cellcode\@empty}

\tc@checkdefine\numberletter{x}
\tc@checkdefine\listsep{,}

% d\'efinit la routine d'affichage des valeurs
\tc@checkdefine\printvalue{}
\def\printvalue#1{\numprint{#1}}
% d\'efinit la routine d'affichage des r\'esultats
\tc@checkdefine\printresult{}
\def\printresult#1#2{\numprint{#1}}

\newcommand\edefcellcode[3]{%
	\ifx\@empty#1\@empty
		\ifx\@empty#2\@empty
			\tc@addtomacro\tc@cellcode{#3}%
		\else
			\tc@addtomacro\tc@cellcode{\ifnum\tccol=#2\relax#3\fi}%
		\fi
	\else
		\ifx\@empty#2\@empty
			\tc@addtomacro\tc@cellcode{\ifnum\tclin=#1\relax#3\fi}%
		\else
			\tc@addtomacro\tc@cellcode{%
				\ifnum\tclin=#1\relax\ifnum\tccol=#2\relax#3\fi\fi}%
		\fi
	\fi}

\newcommand\defcellcode[3]{\edefcellcode{#1}{#2}{\unexpanded{#3}}}

\tc@checkdefine\tc@firstrule\hline
\tc@checkdefine\tc@interrule\hline
\tc@checkdefine\tc@updwnrule\hline

% d\'efinit les 3 types de lignes
\newcommand\sethrule[3]{%
	\def\tc@updwnrule{#1}\def\tc@firstrule{#2}\def\tc@interrule{#3}}

\newcommand\resethrule{\sethrule\hline\hline\hline}

\tc@checkdefine\tc@lastvline{}
\tc@checkdefine\tc@firstcoltype{|c|}
\tc@checkdefine\tc@othercoltype{c|}

% d\'efinit les 3 types de colonnes
\newcommand\setcoltype[3][]{%
	\def\tc@firstcoltype{#2}\def\tc@othercoltype{#3}\def\tc@lastvline{#1}}

\newcommand\resetcoltype{\setcoltype{|c|}{c|}}

\newcommand\htablecalc{\def\tc@orientation{h}\tc@deftablestart}
\newcommand\vtablecalc{\def\tc@orientation{v}\tc@deftablestart}

\newcommand\tc@deftablestart[3][1]{%
	\begingroup
	\expandarg
	\def\tc@nbformulas{#1}%
	\StrCount{\listsep#3}\listsep[\tc@nbval]% \tc@nbval = nombre de valeurs
	\let\tc@coltype\@empty
	\tc@expaddtomacro\tc@coltype{\tc@firstcoltype*}% construit \tc@coltype
	\expandafter\tc@addtomacro\expandafter\tc@coltype\expandafter
		{\expandafter{\tc@nbval}}% qui contiendra par exemple |c|*{4}{c|}
	\expandafter\tc@addtomacro\expandafter\tc@coltype\expandafter
		{\expandafter{\tc@othercoltype}}%
	\tc@expaddtomacro\tc@coltype\tc@lastvline
	\let\tc@firstline\tc@updwnrule% 1ere ligne
	\tclin\z@\tccol\z@
	\edef\tc@currentcellcode{\tc@cellcode}%
	\tc@expaddtomacro\tc@firstline\tc@currentcellcode
	\tc@expaddtomacro\tc@firstline{\startline#2&}%
	\def\tc@valuelist{#3}%
	\tc@expaddtomacro\tc@valuelist\listsep
	\tclin\@ne\tccol\@ne
	\csname tc@\tc@orientation readarg\endcsname}

% lit tous les arguments {nom ligne}{formule} et les assigne dans les sc
% \tcline@i et \tc@formula@i et ainsi de suite, puis va \`a \tc@hbuildlines
\newcommand\tc@hreadarg[2]{%
	\tccol\z@
	\@namedef{tc@line@\romannumeral\tclin}{}%
	\edef\tc@currentcellcode{\tc@cellcode}%
	\tc@expaddtocurrentline\tc@currentcellcode
	\tc@expaddtocurrentline{\startline#1&}%
	\@namedef{tc@formula@\romannumeral\tclin}{#2}%
	\ifnum\tclin<\tc@nbformulas
		\advance\tclin\@ne
		\expandafter\tc@hreadarg
	\else
		\tccol\@ne
		\expandafter\tc@hbuildlines
	\fi}%

\newcommand\tc@vreadarg[2]{%
	\tclin\z@
	\edef\tc@currentcellcode{\tc@cellcode}% construit la 1\`ere ligne
	\tc@expaddtomacro\tc@firstline{\tc@currentcellcode#1}%
	\@namedef{tc@formula@\romannumeral\tccol}{#2}%
	\ifnum\tccol<\tc@nbformulas
		\tc@addtomacro\tc@firstline&%
		\advance\tccol\@ne
		\expandafter\tc@vreadarg
	\else
		\tclin\@ne\tccol\z@
		\loop% initialise les lignes \`a "\tc@currentcellcode\startline"
			\@namedef{tc@line@\romannumeral\tclin}{}%
			\edef\tc@currentcellcode{\tc@cellcode}%
			\tc@expaddtocurrentline\tc@currentcellcode
			\tc@expaddtocurrentline\startline
			\ifnum\tclin<\tc@nbval
			\advance\tclin\@ne
		\repeat
		\tclin\@ne
		\expandafter\tc@vbuildlines
	\fi}%

\newcommand\tc@findskiplist{%
	\IfBeginWith\tc@currentvalue\noshowmark
		{\tc@showvalfalse% si le signe \noshowmark est pr\'esent...
		 \StrGobbleLeft\tc@currentvalue1[\tc@currentvalue]}% ...efface-le
		{\tc@showvaltrue}%
	\IfSubStr\tc@currentvalue[% s'il y a une skiplist...
		{\let\tc@skiplist\tc@currentvalue
		 \StrBefore\tc@currentvalue[[\tc@currentvalue]% ce qui est avant "["
		 \StrBehind\tc@skiplist\tc@currentvalue[\tc@skiplist]}% d\'efinit-la
		{\let\tc@skiplist\@empty}}

\newcommand\tc@addtocurrentline[1]{%
	\expandafter\tc@addtomacro\csname tc@line@\romannumeral\tclin\endcsname
	{#1}}

\newcommand\tc@expaddtocurrentline[1]{%
	\expandafter\tc@addtocurrentline\expandafter{#1}}

% construit toutes les lignes du tableau par r\'ecursivit\'e principale sur
% le nombre de colonnes
\newcommand\tc@hbuildlines{%
	\tclin\z@
	\StrBefore\tc@valuelist\listsep[\tc@currentvalue]% prend \tc@currentvalue
	\StrBehind\tc@valuelist\listsep[\tc@valuelist]% purge \tc@valuelist
	\ifx\@empty\tc@currentvalue
	\else
		\tc@findskiplist
		\edef\tc@currentcellcode{\tc@cellcode}%
		\tc@expaddtomacro\tc@firstline\tc@currentcellcode
		\iftc@showval% pas de noshowmark : ajoute affichage valeur courante
			\expandafter\tc@expaddtomacro\expandafter\tc@firstline
				\expandafter{\expandafter\printvalue\expandafter
				{\tc@currentvalue}}%
		\fi
		\tclin\@ne
		\loop
			\edef\tc@currentcellcode{\tc@cellcode}%
			\tc@expaddtocurrentline\tc@currentcellcode
			\tc@displaycurrentresult\tclin
			\ifnum\tclin<\tc@nbformulas
			\advance\tclin\@ne
		\repeat% recommence pour toutes les lignes
	\fi
	\ifnum\tccol<\tc@nbval% s'il reste des colonnes
		\tc@addtomacro\tc@firstline&% ajoute "&" \`a la 1\`ere ligne
		\tclin\@ne
		\loop% et ajoute "&" aux autres lignes
			\tc@addtocurrentline&%
			\ifnum\tclin<\tc@nbformulas
			\advance\tclin\@ne
		\repeat
		\advance\tccol\@ne
		\expandafter\tc@hbuildlines% recommence tout le processus
	\else
		\let\tc@nblines\tc@nbformulas
		\expandafter\tc@printtabular% sinon, va afficher la table
	\fi}

% construit les lignes du tableau par r\'ecursivit\'e principale sur \tclin
\newcommand\tc@vbuildlines{%
	\StrBefore\tc@valuelist\listsep[\tc@currentvalue]% prend \tc@currentvalue
	\StrBehind\tc@valuelist\listsep[\tc@valuelist]% purge \tc@valuelist
	\ifx\@empty\tc@currentvalue
	\else
		\tc@findskiplist
		\iftc@showval% pas de noshowmark : ajoute affichage valeur courante
			\expandafter\tc@expaddtocurrentline\expandafter
				{\expandafter\printvalue\expandafter{\tc@currentvalue}}%
		\fi
		\tccol\@ne
		\loop
			\tc@addtocurrentline&% change de cellule dans la ligne en cours
			\edef\tc@currentcellcode{\tc@cellcode}%
			\tc@expaddtocurrentline\tc@currentcellcode
			\tc@displaycurrentresult\tccol% ajoute le r\'esultat courant ou pas
			\ifnum\tccol<\tc@nbformulas
			\advance\tccol\@ne
		\repeat% s'il reste des colonnes, recommence
	\fi
	\ifnum\tclin<\tc@nbval
		\advance\tclin\@ne
		\expandafter\tc@vbuildlines% s'il reste des lignes, recommence
	\else
		\let\tc@nblines\tc@nbval
		\expandafter\tc@printtabular% sinon, va afficher la table
	\fi}

\newcommand\tc@displaycurrentresult[1]{%
	\StrBetween\tc@skiplist[][\tc@nexttoskip]%
	\ifx\@empty\tc@skiplist% pas de skiplist -> ajoute l'affichage de resultat
		\tc@addcurrentresult#1
	\else
		\ifnum\tc@nexttoskip=\z@% si 0, n'affiche rien
		\else
			\ifnum\tc@nexttoskip=#1% si le numero correspond
				\StrBehind\tc@skiplist][\tc@skiplist]% purge la skiplist
			\else% sinon, ajoute l'affichage de resultat
				\tc@addcurrentresult#1%
			\fi
		\fi
	\fi}

\newcommand\tc@addcurrentresult[1]{% #1 : compteur courant
	\expandafter\StrSubstitute% remplace "x" par la valeur courante
		\csname tc@formula@\romannumeral#1\endcsname
		\numberletter\tc@currentvalue[\tc@currentresult]%
	\tc@evalexpr% \'evalue l'expression
	\edef\tc@currentresult{{\tc@currentresult}{\tc@currentvalue}}%
	\expandafter\tc@expaddtocurrentline\expandafter
		{\expandafter\printresult\tc@currentresult}}

\newcommand\tc@printcalclines{%
	\csname tc@line@\romannumeral\tclin\endcsname% affiche la ni\`eme ligne
	\ifnum\tclin<\tc@nblines% et s'il en reste encore \`a afficher
		\\\tc@interrule% va \`a la ligne, met le filet
		\global\advance\tclin\@ne
		\expandafter\tc@printcalclines% et recommence
	\fi}%

\newcommand\tc@printtabular{%
	\global\tclin\z@
	\def\tc@currentvalue{\begin{tabular}}%
	\expandafter\tc@currentvalue\expandafter{\tc@coltype}%
		\tc@firstline\\\tc@firstrule% 1\`ere ligne +  1er filet
		\global\tclin\@ne
		\tc@printcalclines% affichage des autres lignes
		\\\tc@updwnrule% filet du bas
	\end{tabular}% fin du tableau
	\endgroup}
%
% Historique
%------------------------------------------------------------------------------
%% v0.1    19/03/2009 : - Premi\`ere version
%------------------------------------------------------------------------------