From 6558da0729e1c500bec9acbfaa748066b84b02f4 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 27 Jan 2010 01:41:58 +0000 Subject: spreadtab 0.2 (25jan10) git-svn-id: svn://tug.org/texlive/trunk@16829 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/tex/latex/spreadtab/spreadtab.sty | 559 +++++++++++++++++---- 1 file changed, 474 insertions(+), 85 deletions(-) (limited to 'Master/texmf-dist/tex/latex') diff --git a/Master/texmf-dist/tex/latex/spreadtab/spreadtab.sty b/Master/texmf-dist/tex/latex/spreadtab/spreadtab.sty index c4d2f63e7f3..a35d324c957 100644 --- a/Master/texmf-dist/tex/latex/spreadtab/spreadtab.sty +++ b/Master/texmf-dist/tex/latex/spreadtab/spreadtab.sty @@ -1,23 +1,22 @@ % ____________________________________________________________________________ % | | % | | -% | spreadtab v0.1 | +% | spreadtab v0.2 | % | | -% | November 3 2009 | +% | January 24, 2010 | % | | % |___________________________________________________________________________| % % This is spreadtab.sty, the code of the spreadtab package. % -% Copyright Christian Tellechea 2009 +% Copyright Christian Tellechea 2009-2010 % email : unbonpetit@gmail.com % -% The "spreadtab" package consists of the 8 following files: +% The "spreadtab" package consists of the 6 following files: % spreadtab.sty (this file) % README % spreadtab_doc_fr.tex, spreadtab_doc_fr.pdf (manual in french) % spreadtab_doc_en.tex, spreadtab_doc_en.pdf (manual in english) -% spreadtab_doc_vn.tex, spreadtab_doc_vn.tex (manual in vietnamese) % % ------------------------------------------------------------------- % This work may be distributed and/or modified under the @@ -38,10 +37,10 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%% Définitions préalables %%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\newcommand\ST@ver {0.1} -\newcommand\ST@date {2009/11/02} -\newcommand\ST@fr@date {3 novembre 2009} -\newcommand\ST@eng@date{November $3^\text{rd}$ 2009} +\newcommand\ST@ver {0.2} +\newcommand\ST@date {2010/01/20} +\newcommand\ST@fr@date {24 janvier 2010} +\newcommand\ST@eng@date{January $24^\text{th}$ 2010} \ProvidesPackage{spreadtab}[\ST@date\space v\ST@ver\space Spreadsheet features for table environments] \NeedsTeXFormat{LaTeX2e} @@ -54,6 +53,9 @@ \newcount\ST@rowcount \newcount\ST@rowcount@i \newif\ifST@hiddencol +\newif\ifST@debugmode +\newif\ifST@colortblloaded +\AtBeginDocument{\@ifpackageloaded{colortbl}\ST@colortblloadedtrue\ST@colortblloadedfalse} % Définit le marqueur qui signale le commencement du champ numérique \newcommand\STnumericfieldmarker{:=} @@ -61,6 +63,9 @@ % définit le marqueur qui signale une cellule de texte \makeatother\newcommand\STtextcell{@}\makeatletter +% Commande qui permet à l'utilisateur de définir le caractère qui conserve une référence lors de la copie d'une formule +\AtBeginDocument{\newcommand\STtransposecar{!}} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Messages d'erreur %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -136,6 +141,12 @@ \@latex@error{\ST@errname Invalid range in cell \ST@temp@callcell.}\ST@seedoc@i\stop } +\newcommand\ST@invalidSTcopy{% + \edef\ST@temp@callcell{\ST@current@colnumber,\ST@current@rownumber}% + \ST@coord@toref\ST@temp@callcell + \@latex@error{\ST@errname Numeric field marker found, \string\STcopy\space forbidden in cell \ST@temp@callcell.}\ST@seedoc@i\stop +} + % transforme la chaine de cellules "(1,3)(4,5)(3,2)(1,3)" rencontré en référence circulaire en "A3-D5-C2-A3" \newcommand\ST@show@dependance@tree{% \ST@between\ST@dependance@tree()\ST@currentref @@ -155,6 +166,10 @@ N\or O\or P\or Q\or R\or S\or T\or U\or V\or W\or X\or Y\or Z\fi#1}% } +\newcommand\ST@illegal@copy{% + \@latex@error{\ST@errname Illegal reference in copied formula!}\ST@seedoc@i +} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%% Macros d'affectation et d'expansion %%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -169,11 +184,30 @@ \newcommand\ST@expadd@tomacro[2]{\expandafter\ST@add@tomacro\expandafter#1\expandafter{#2}} +\newcommand\ST@edefadd@tomacro[2]{% + \begingroup\edef\ST@tmpstr{#2}\expandafter\endgroup + \expandafter\ST@add@tomacro\expandafter#1\expandafter{\ST@tmpstr}% +} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%% Macros de manipulation de chaines %%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \def\ST@gobble@remain#1\relax{} +\newcommand\ST@splitatfirstcar[3]{% + \def\ST@splitatfirstcar@i##1##2\@nil{\def#2{##1}\def#3{##2}}% + \expandafter\ST@splitatfirstcar@i#1\@nil +} + +% dans la sc #1, remplace le . par le séparateur décimal +\newcommand\ST@substdecsep[1]{% + \ST@Ifinstr#1.{\expandafter\ST@substdecsep@i\expandafter#1\expandafter{\ST@decsep}}\relax +} +\newcommand\ST@substdecsep@i[2]{% + \def\ST@substdecsep@ii##1.##2\@nil{\def#1{##1#2##2}}% + \expandafter\ST@substdecsep@ii#1\@nil +} + % enlève tous les espaces de la sc #1 et assigne le résultat à #1 \newcommand\ST@remove@first@spaces[1]{% \IfBeginWith#1\space @@ -223,14 +257,14 @@ \expandafter\ST@split@i#1\@nil } -% Dans la sc #1, assigne ce qui est avant la sc #2 à la sc #3 +% Dans la sc #1, assigne ce qui est avant le développement de la sc #2 à la sc #3 \newcommand\ST@left[3]{\ST@exp@two@args\ST@left@i{#1}{#2}#3} \newcommand\ST@left@i[3]{% \def\ST@left@ii##1#2##2\@nil{\def#3{##1}}% \ST@left@ii#1\@nil } -% Dans la sc #1, assigne ce qui est après la sc #2 à la sc #3 +% Dans la sc #1, assigne ce qui est après le développement de la sc #2 à la sc #3 \newcommand\ST@right[3]{\ST@exp@two@args\ST@right@i{#1}{#2}#3} \newcommand\ST@right@i[3]{% \def\ST@right@ii##1#2##2\@nil{\def#3{##2}}% @@ -328,37 +362,71 @@ \ST@Ifinstr\ST@current@cell{\@empty\multicolumn}% tester la présence d'un \multicol {\ST@firstarg@after\ST@current@cell\multicolumn\ST@multicol@number}% {\let\ST@multicol@number\@empty}% - \IfSubStr\ST@current@cell\STnumericfieldmarker% il y a un champ numérique ? - {\StrBehind\ST@current@cell\STnumericfieldmarker[\ST@current@formula]% + \IfSubStr\ST@current@cell\STnumericfieldmarker% il y a un marqueur de champ numérique ? + {\IfSubStr\ST@current@cell{\@empty\STcopy}\ST@invalidSTcopy\relax% s'il y a un \STcopy, erreur (pas de champ numérique et de \STcopy dans une même cellule) + \StrBehind\ST@current@cell\STnumericfieldmarker[\ST@current@formula]% \noexploregroups \StrChar\ST@current@formula1[\ST@temp@a]% \ST@temp@a contient {} par \= + \StrSubstitute[1]\ST@current@cell\ST@temp@b\STnumericfieldmarker[\ST@current@cell]% on remplace \={} par ":=" \noexploregroups \ST@keep@firstcar\ST@temp@a% dans la formule, on enlève les accolades \ST@removespaces\ST@temp@a% et tous les espaces \ifx\ST@temp@a\@empty% \ST@temp@a contient la formule : si la formule est vide - \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{0}% on mettra le code à 0 - \StrDel[1]\ST@current@cell\STnumericfieldmarker[\ST@current@cell]% on supprime aussi \= - \else% la formule n'est pas vide : + \ifx\ST@copylist\@empty% pas de copylist ? + \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{0}% met le code à 0 + \StrDel[1]\ST@current@cell\STnumericfieldmarker[\ST@current@cell]% on supprime aussi ":=" + \else% si la copylist existe + \ST@lookincopylist{\number\ST@colcount}{\number\ST@rowcount}\ST@celltocopy% on cherche si la cellule en cours est dans une plage de copie + \ifx\ST@celltocopy\@empty + \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{0}% si c'est non, met le code à 0 + \else + \ST@letname{formula@\number\ST@colcount @\number\ST@rowcount}\ST@celltocopy% il y a une cellule à copier : on l'assigne au champ numérique + \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{1}% et on met le code à 1 + \fi + \fi + \else% la formule n'est pas vide \ST@letname{formula@\number\ST@colcount @\number\ST@rowcount}\ST@temp@a% et on assigne à la formule \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{1}% code 1 à priori \fi - }% + }% ci dessous, il n'y a pas de marqueur de champ numérique {\IfSubStr\ST@current@cell\STtextcell% si c'est une cellule de texte {\StrDel\ST@current@cell\STtextcell[\ST@current@cell]% on le(s) supprime les flags \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{0}% met le code à 0 - }% pas de \= ni de @ + }% ci dessous, ce n'est pas une cellule texte, c'est donc une cellule purement champ numérique sans marqueur {\StrDel\ST@current@cell\space[\ST@temp@a]% - \ifx\@empty\ST@temp@a% il n'y a que des espaces ? - \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{0}% met le code à 0 - \else + \ifx\@empty\ST@temp@a% il n'y a que des espaces, c'est donc une cellule vide + \ifx\ST@copylist\@empty% pas de copylist ? + \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{0}% met le code à 0 + \else% si la copylist existe + \ST@lookincopylist{\number\ST@colcount}{\number\ST@rowcount}\ST@celltocopy% on cherche si la cellule en cours est dans un oplage de copie + \ifx\ST@celltocopy\@empty + \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{0}% si c'est non, met le code à 0 + \else + \let\ST@current@cell\STnumericfieldmarker% il y a une cellule à copier ici + \ST@letname{formula@\number\ST@colcount @\number\ST@rowcount}\ST@celltocopy% on l'assigne au champ numérique + \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{1}% et on met le code à 1 + \fi + \fi + \else% ici, la cellule est composée d'une champ numérique sans marqueur \@namedef{code@\number\ST@colcount @\number\ST@rowcount}{1}% toute la cellule est considérée comme champ numérique \ST@remove@first@spaces\ST@current@cell - \ST@letname{formula@\number\ST@colcount @\number\ST@rowcount}\ST@current@cell% et on assigne toute la cellule - \let\ST@current@cell\STnumericfieldmarker% et on met le flag pour la formule + \ST@Ifinstr\ST@current@cell{\@empty\STcopy}% + {\ST@findcopyargs\ST@current@cell\ST@copyrange\ST@copyformula% on chope les arguments de \STcopy + \ST@seekcopyoffset\ST@copyrange% cherche les décalages + \edef\ST@copyrange{\ST@hoffest,\ST@voffest}% et affecte sous forme a,b où a et b sont des nombres ou sont vides + \expandafter\def\expandafter\ST@newtocopylist\expandafter{\expandafter{\ST@copyformula}}% \ST@newtocopylist est le nouvel élément à ajouter à la copylist + \ST@edefadd@tomacro\ST@newtocopylist{[\number\ST@colcount,\number\ST@rowcount]}% + \ST@expadd@tomacro\ST@newtocopylist{\expandafter(\ST@copyrange)}% + \ST@expadd@tomacro\ST@newtocopylist\ST@copylist% ajoute la copylist à la fin + \let\ST@copylist\ST@newtocopylist% et l'assigne à copylist + \ST@transposeformula00\ST@copyformula\ST@copyformula + \ST@letname{formula@\number\ST@colcount @\number\ST@rowcount}\ST@copyformula% affecte la formule inchangée au champ numérique courant + }% + {\ST@letname{formula@\number\ST@colcount @\number\ST@rowcount}\ST@current@cell% et on assigne toute la cellule + \let\ST@current@cell\STnumericfieldmarker}%% et on met le flag pour la formule \fi }% }% @@ -366,7 +434,7 @@ \unless\ifnum\csname code@\number\ST@colcount @\number\ST@rowcount\endcsname=\z@% si le code est <> 0 \ST@try@calc@cell(\number\ST@colcount,\number\ST@rowcount)% on essaie de calculer la cellule en cours \fi - \ST@letname{cell@\number\ST@colcount @\number\ST@rowcount}\ST@current@cell + \ST@letname{text@\number\ST@colcount @\number\ST@rowcount}\ST@current@cell \unless\ifx\@empty\ST@multicol@number% si c'est une cellule qui contient \multicolumn \loop% on met tous les codes des cellules fusionées qui suivent la cellule en cours à -1 \ifnum\ST@multicol@number>\@ne @@ -383,16 +451,216 @@ \newcommand\ST@search@hline[1]{% \unless\ifcsname endrow@\number\ST@rowcount\endcsname\ST@letname{endrow@\number\ST@rowcount}\@empty\fi \ST@remove@first@spaces#1% on enlève les espaces au début + %\let\ST@temp@a#1\ST@keep@firstcar\ST@temp@a \StrChar#11[\ST@temp@a]% \ST@temp@a est le 1er car \let\next\ST@search@hline \IfStrEqCase\ST@temp@a{% on envisage tous les cas de tracé de ligne horizontale {\@empty\hline}{\StrGobbleLeft#11[#1]\expandafter\ST@add@tomacro\csname endrow@\number\ST@rowcount\endcsname\hline}% {\@empty\cline}{\StrSplit#12\ST@temp@a#1\expandafter\ST@expadd@tomacro\csname endrow@\number\ST@rowcount\endcsname\ST@temp@a}% {\@empty\hhline}{\StrSplit#12\ST@temp@a#1\expandafter\ST@expadd@tomacro\csname endrow@\number\ST@rowcount\endcsname\ST@temp@a}% + {\@empty\noalign}{\StrSplit#12\ST@temp@a#1\expandafter\ST@expadd@tomacro\csname endrow@\number\ST@rowcount\endcsname\ST@temp@a}% + {\@empty\toprule}{% les commandes de booktabs + \StrSplit#11\ST@temp@a#1% chope le 1er lexème : la commande \toprule + \IfBeginWith#1[{\StrBefore#1][\ST@temp@b]\ST@expadd@tomacro\ST@temp@a{\ST@temp@b]}\StrBehind#1][#1]}\relax + \expandafter\ST@expadd@tomacro\csname endrow@\number\ST@rowcount\endcsname\ST@temp@a + }% + {\@empty\midrule}{% + \StrSplit#11\ST@temp@a#1% chope le 1er lexème : la commande \midrule + \IfBeginWith#1[{\StrBefore#1][\ST@temp@b]\ST@expadd@tomacro\ST@temp@a{\ST@temp@b]}\StrBehind#1][#1]}\relax + \expandafter\ST@expadd@tomacro\csname endrow@\number\ST@rowcount\endcsname\ST@temp@a + }% + {\@empty\bottomrule}{% + \StrSplit#11\ST@temp@a#1% chope le 1er lexème : la commande \bottomrule + \IfBeginWith#1[{\StrBefore#1][\ST@temp@b]\ST@expadd@tomacro\ST@temp@a{\ST@temp@b]}\StrBehind#1][#1]}\relax + \expandafter\ST@expadd@tomacro\csname endrow@\number\ST@rowcount\endcsname\ST@temp@a + }% + {\@empty\cmidrule}{% + \StrSplit#11\ST@temp@a#1% chope le 1er lexème : la commande \cmidrule + \IfBeginWith#1[{\StrBefore#1][\ST@temp@b]\ST@expadd@tomacro\ST@temp@a{\ST@temp@b]}\StrBehind#1][#1]}\relax + \IfBeginWith#1({\StrBefore#1)[\ST@temp@b]\ST@expadd@tomacro\ST@temp@a{\ST@temp@b)}\StrBehind#1)[#1]}\relax + \StrSplit#11\ST@temp@b#1% chope l'argument obligatoire : {a-b} + \ST@expadd@tomacro\ST@temp@a\ST@temp@b% l'ajoute à \ST@temp@b + \expandafter\ST@expadd@tomacro\csname endrow@\number\ST@rowcount\endcsname\ST@temp@a% et on ajoute le tout à endrow + }% + {\@empty\addlinespace}{% + \StrSplit#11\ST@temp@a#1% chope le 1er lexème : la commande \addlinespace + \IfBeginWith#1[{\StrBefore#1][\ST@temp@b]\ST@expadd@tomacro\ST@temp@a{\ST@temp@b]}\StrBehind#1][#1]}\relax + \expandafter\ST@expadd@tomacro\csname endrow@\number\ST@rowcount\endcsname\ST@temp@a + }% + {\@empty\morecmidrules}{\StrGobbleLeft#11[#1]\expandafter\ST@add@tomacro\csname endrow@\number\ST@rowcount\endcsname\morecmidrules}% + {\@empty\specialrule}{\StrSplit#14\ST@temp@a#1\expandafter\ST@expadd@tomacro\csname endrow@\number\ST@rowcount\endcsname\ST@temp@a}% }[\let\next\@gobble]% \next#1% } +% Cette macro transpose toutes les références (absolues et relatives) de la sc #3. +% Le décalage est de #1 (nombre signé) pour les colonnes et de #2 (nombre signé) pour les lignes. +% La sc #4 recoit la formule transposée. +\newcommand\ST@transposeformula[4]{% + \def\ST@addcol{#1}\def\ST@addrow{#2}\let\ST@temp@formula#3% + \let\ST@transposed@formula\@empty + \ST@transposeformula@i + \let#4\ST@transposed@formula +} + +\newcommand\ST@transposeformula@i{% + \unless\ifx\@empty\ST@temp@formula% tant que l'on n'a pas parcouru \ST@temp@formula + \ST@splitatfirstcar\ST@temp@formula\ST@firstcar\ST@temp@formula% prend le 1er car de \ST@temp@formula + \if\expandafter\noexpand\STtransposecar\expandafter\noexpand\ST@firstcar% si ce caractère est un ! + \let\ST@addcol@\z@% pas de tranposition sur la colonne + \ST@splitatfirstcar\ST@temp@formula\ST@firstcar\ST@temp@formula% on prend le premier caractère qui suit le ! + \else + \let\ST@addcol@\ST@addcol% sinon, on copie le vecteur + \fi + \expandafter\ST@ifcar@isletter\expandafter{\ST@firstcar}% est-ce que le 1er car est une lettre ? + {\if\expandafter\noexpand\STtransposecar\expandafter\expandafter\expandafter\noexpand\expandafter\@car\ST@temp@formula\@nil% le caractère suivant est un "!" ? + \let\ST@addrow@\z@% pas de tranposition sur la ligne + \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\ST@temp@formula\expandafter\expandafter\expandafter{\expandafter\@cdr\ST@temp@formula\@nil}% on prend ce qui est après le ! + \else + \let\ST@addrow@\ST@addrow% sinon, on copie le vecteur + \fi + \IfInteger\ST@temp@formula\relax\relax% on prend le nombre qui suit + \ifnum\integerpart>\z@% si ce nombre est plus grand que 0 -> référence valide + \let\ST@temp@formula\@xs@afterinteger% on prend ce qui est après le nombre + \expandafter\lowercase\expandafter{\expandafter\def\expandafter\ST@firstcar\expandafter{\ST@firstcar}}% met en minuscules + \edef\ST@firstcar{\number\numexpr\expandafter`\ST@firstcar-`a+1+\ST@addcol@}% est le numéro de la colonne + \ifnum\ST@firstcar<\@ne\ST@illegal@copy\fi% erreur de copie ? + \ST@edefadd@tomacro\ST@transposed@formula{% + \ifcase\ST@firstcar \or a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m\or + n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or x\or y\or z\fi + \number\numexpr\integerpart+\ST@addrow@}% + \ifnum\numexpr\integerpart+\ST@addrow@<\@ne\ST@illegal@copy\fi% erreur de copie ? + \else + \let\ST@temp@formula\@xs@afterinteger + \ST@expadd@tomacro\ST@transposed@formula\ST@firstcar + \fi + }% + {\if[\expandafter\noexpand\ST@firstcar% si le 1er car est [ + \ST@left\ST@temp@formula]\ST@temp@ref% on prend ce qui est entre crochet + \ST@right\ST@temp@formula]\ST@temp@formula% pour la suite, on prend ce qui après le crochet + \ST@left\ST@temp@ref,\ST@rel@num% ce qui est avant la virgule + \if\expandafter\noexpand\STtransposecar\expandafter\expandafter\expandafter\noexpand\expandafter\@car\ST@rel@num\@nil% commence par un "!" ? + \let\ST@addcol@\ST@addcol% compensation pour conserver la cellule initiale + \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\ST@rel@num\expandafter\expandafter\expandafter{\expandafter\@cdr\ST@rel@num\@nil}% on prend ce qui est après le ! + \else + \let\ST@addcol@\z@% sinon, on n'ajoute rien + \fi + \IfInteger\ST@rel@num + {\edef\ST@addcol@{\number\numexpr\ST@rel@num-\ST@addcol@}% + \ST@right\ST@temp@ref,\ST@rel@num% ce qui est après la virgule + \if\expandafter\noexpand\STtransposecar\expandafter\expandafter\expandafter\noexpand\expandafter\@car\ST@rel@num\@nil% commence par un "!"? + \let\ST@addrow@\ST@addrow% on compense pour conserver la cellule initiale + \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\ST@rel@num\expandafter\expandafter\expandafter{\expandafter\@cdr\ST@rel@num\@nil}% on prend ce qui est après le ! + \else + \let\ST@addrow@\z@% sinon, on n'ajoute rien + \fi + \IfInteger\ST@rel@num + {\ST@edefadd@tomacro\ST@transposed@formula{[\ST@addcol@,\number\numexpr\ST@rel@num-\ST@addrow@]}% + }% + \ST@illegal@relativeref + }% + \ST@illegal@relativeref + \else + \ST@expadd@tomacro\ST@transposed@formula\ST@firstcar + \fi + }% + \expandafter\ST@transposeformula@i + \fi +} + +% Cherche dans la sc #1 les 3 arguments qui se trouvent après \STcopy +% Affecte le 1er à #2, le 2è à #3 et le 3è à #4 +\newcommand\ST@findcopyargs[3]{% + \def\ST@argaftercopy##1\STcopy##2##3##4\@nil{% + \def#1{##1}\ST@expadd@tomacro#1{\STnumericfieldmarker##4}% dans #1,supprime \STcopy{}{} et le remplace par := + \def#2{##2}\def#3{##3}% + }% + \expandafter\ST@argaftercopy#1\@nil +} + +% teste si #1 est dans l'intervalle [#3,#3+#5] et si #2 est dans [#4,#4+#6] +% si #5 est vide, c'est l'intervalle [#3,+inf] et si #6 est vide, c'est [#4,+inf] +\def\ST@Ifin#1#2[#3,#4](#5,#6)% +{% + \csname @% + \ifnum#1<#3 second% + \else + \ifnum#2<#4 second% + \else + \ifx\@empty#5\@empty + \ifx\@empty#6\@empty first% + \else + \ifnum#2>\numexpr#4+#6 second% + \else first% + \fi + \fi + \else + \ifnum#1>\numexpr#3+#5 second% + \else + \ifx\@empty#6\@empty first% + \else + \ifnum#2>\numexpr#4+#6 second% + \else first% + \fi + \fi + \fi + \fi + \fi + \fi oftwo\endcsname +} + +% Regarde dans la liste de copie si la cellule de coodonnées #1 #2 est dans une plage de copie +% si oui, affecte à #3 la formule transposée +% La liste de copy est parcourue de gauche à droite avec sortie dès qu'une plage qui convient est rencontrée +\newcommand\ST@lookincopylist[3]{% + \let\ST@copylist@\ST@copylist\let\ST@returnedformula\@empty + \def\ST@copycol{#1}\def\ST@copyrow{#2}\let#3\@empty + \ST@lookincopylist@i + \let#3\ST@returnedformula +} + +\newcommand\ST@lookincopylist@i{% + \expandafter\ST@testfirstincopylist\ST@copylist@\@nil + \csname + \ifx\@empty\ST@copylist@ relax% + \else + \ifx\@empty\ST@returnedformula ST@lookincopylist@i% + \else relax% + \fi + \fi\endcsname +} + +% Teste si un élément de la copylist contient une plage qui inclus la cellule en cours. +\def\ST@testfirstincopylist#1[#2,#3](#4,#5)#6\@nil% +{% + \def\ST@copylist@{#6}% on enlève le premier élément de la copylist + \ST@Ifin\ST@copycol\ST@copyrow[#2,#3](#4,#5)% si ça correspond + {\def\ST@returnedformula{#1}% + \ST@transposeformula{\numexpr\ST@copycol-#2}{\numexpr\ST@copyrow-#3}\ST@returnedformula\ST@returnedformula + }% + \relax +} + +% Cherche dans la sc#1 du type ">4,v9" les décalages horizontaux et verticaux +% spécifiés avec > et v +% S'il trouve > ou v sans nombre derrière, le décalage correspondant est vide +% S'il ne trouve pas > ou v, le décalage correspond est égal à 0 +% Assigne les décalages trouvés dans \ST@hoffest et \ST@voffest +\newcommand\ST@seekcopyoffset[1]{% + \ST@Ifinstr#1>% + {\ST@findcopyoffest#1>\ST@hoffest}% + {\def\ST@hoffest{0}}% + \ST@Ifinstr#1v% + {\ST@findcopyoffest#1v\ST@voffest}% + {\def\ST@voffest{0}}% +} + +% Cherche dans la sc #1 ce qui est entre #2 et , +\newcommand\ST@findcopyoffest[3]{% + \def\ST@findcopyoffest@i##1#2##2,##3\@nil{\def#3{##2}}% + \expandafter\ST@findcopyoffest@i#1,\@nil +} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%% Recherche d'une référence %%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -415,16 +683,11 @@ % si on trouve, renvoie les coordonnées dans #2 sous la forme x@y % si on ne trouve pas, #2 est vide. \newcommand\ST@findref@informula[2]{% - \let\ST@temp@formula#1 + \let\ST@temp@formula#1% \ST@findref@informula@i \let#2\ST@temp@formula } -\newcommand\ST@splitatfirstcar[3]{% - \def\ST@splitatfirstcar@i##1##2\@nil{\def#2{##1}\def#3{##2}}% - \expandafter\ST@splitatfirstcar@i#1\@nil -} - \newcommand\ST@findref@informula@i{% \let\ST@next@search\ST@findref@informula@i \ifx\@empty\ST@temp@formula @@ -434,7 +697,7 @@ \expandafter\ST@ifcar@isletter\expandafter{\ST@firstcar}% est-ce que le 1er car est une lettre ? {\IfInteger\ST@temp@formula\relax\relax% on prend le nombre qui suit \ifnum\integerpart>\z@% si ce nombre est plus grand que 0 -> référence valide - \edef\ST@ref@found{\ST@firstcar\number\integerpart}% + \edef\ST@ref@found{\ST@firstcar\number\integerpart}% est la référence trouvée \edef\ST@distant@rownumber{\number\integerpart}% on chope ce nombre pour le numéro de colonne \edef\ST@distant@colnumber{\expandafter\number\expandafter\numexpr\expandafter`\ST@firstcar-`a+1}% traduction lettre->chiffre \ifnum\ST@distant@colnumber<\z@\edef\ST@distant@colnumber{\number\numexpr\ST@distant@colnumber+32}\fi% met les majuscules en minuscules @@ -508,7 +771,7 @@ \unless\ifx\ST@autouround\@empty\FPround\ST@temp@a\ST@temp@a\ST@autouround\fi% on arrondi s'il faut \FPclip\ST@temp@a\ST@temp@a% puis on supprime les 0 inutiles \ST@letname{formula@#1@#2}\ST@temp@a% assigne le résultat à la formule - \@namedef{code@#1@#2}{2}%% et met le code à 2 (cellule calculée) + \@namedef{code@#1@#2}{2}% et met le code à 2 (cellule calculée) \fi } @@ -584,7 +847,7 @@ \else \ST@Ifinstr{\ST@functions@with@textresult,}{\ST@function@namesaved,}% si la dernière fonction rend du texte {\@namedef{code@#1@#2}{0}% on met le code à 0, la cellule devient textuelle - \expandafter\let\csname cell@#1@#2\expandafter\endcsname\csname formula@#1@#2\endcsname% copie de la formule vers la zone texte (avec écrasement de ce qui s'y trouvait) + \expandafter\let\csname text@#1@#2\expandafter\endcsname\csname formula@#1@#2\endcsname% copie de la formule vers la zone texte (avec écrasement de ce qui s'y trouvait) \ST@letname{formula@#1@#2}\@empty% et plus rien dansla formule }% {\ST@calc@cell(#1,#2)}% c'est une fonction qui donne un arg numérique : on calcule la cellule en cours @@ -677,7 +940,7 @@ \def\ST@nexteval{\ST@eval@cell@i(#1,#2)}% puis, on évalue à nouveau cette cellule \else% il y a une référence dans l'argument de la fontion \ifnum\csname code@\ST@temp@formula\endcsname=\z@% si la référence est une cellule texte - \expandafter\let\expandafter\ST@current@formula\csname cell@\ST@temp@formula\endcsname% alias pour la zone texte distante + \expandafter\let\expandafter\ST@current@formula\csname text@\ST@temp@formula\endcsname% alias pour la zone texte distante % on ne prend que le texte s'il y a un \multicolumn qui traine \ST@Ifinstr\ST@current@formula{\@empty\multicolumn}% {\ST@thirdarg@after\ST@current@formula\multicolumn\ST@current@formula}\relax @@ -757,7 +1020,7 @@ fact,ifeq,ifgt,iflt,numtofrshortdate,numtoengshortdate,numtofrlongdate,% numtoenglongdate,numtofrmonth,numtoengmonth,numtofrday,numtoengday} -% liste des fonctions dont l'argument est une plage +% liste des fonctions dont l'argument est une plage ou est vide \newcommand\ST@functions@with@range@arg{sum,rand,randint,sumprod} % liste des fonctions dont l'argument ne doit pas être calculé @@ -1177,44 +1440,39 @@ \ST@Ifinstr\ST@row@skiplist{\number\ST@rowcount,}% la ligne fait partie de la skiplist ? {\advance\ST@rowcount\@ne}% on passe à la ligne suivante {% - \ifcsname code@\number\ST@colcount @\number\ST@rowcount\endcsname% le code existe ? (tenir compte d'une ligne complètement vide du genre ////) - \ST@Ifinstr\ST@col@skiplist{\number\ST@colcount,}% la colonne fait partie de la skiplist ? - \ST@hiddencoltrue - {% - \ST@hiddencolfalse - \ifcsname cell@\number\ST@colcount @\number\ST@rowcount\endcsname% si la cellule existe - \expandafter\let\expandafter\ST@temp@a\csname formula@\number\ST@colcount @\number\ST@rowcount\endcsname% la valeur - \expandafter\let\expandafter\ST@temp@b\csname cell@\number\ST@colcount @\number\ST@rowcount\endcsname% on créé un alias - \exploregroups - \StrSubstitute[1]\ST@temp@b\STnumericfieldmarker\ST@temp@a[\ST@temp@a]% on remplace le flag de formule par la valeur calculée - \noexploregroups - \ST@expadd@tomacro\ST@tab\ST@temp@a% on ajoute la cellule au tableau + \ST@Ifinstr\ST@col@skiplist{\number\ST@colcount,}% la colonne fait partie de la skiplist ? + \ST@hiddencoltrue + {% + \ST@hiddencolfalse + \ifcsname text@\number\ST@colcount @\number\ST@rowcount\endcsname% si la cellule existe + \expandafter\let\expandafter\ST@temp@a\csname formula@\number\ST@colcount @\number\ST@rowcount\endcsname% la valeur + \expandafter\let\expandafter\ST@temp@b\csname text@\number\ST@colcount @\number\ST@rowcount\endcsname% on créé un alias + \ifnum\csname code@\number\ST@colcount @\number\ST@rowcount\endcsname=\tw@% si la cellule contient un champ numérique + \unless\ifx\ST@decsep\ST@decsepfp\ST@substdecsep\ST@temp@a\fi% et si le "." doit être remplacé par "," on substitue \fi - }% - \advance\ST@colcount\@ne% on passe à la colonne suivante ! - \ifcsname code@\number\ST@colcount @\number\ST@rowcount\endcsname% y a t-il encore un code défini ensuite ? - \ifnum\csname code@\number\ST@colcount @\number\ST@rowcount\endcsname<\z@% on est dans une cellule contenant \multicol ? - \expandafter\ST@firstarg@after\csname cell@\number\numexpr\ST@colcount-1@\number\ST@rowcount\endcsname\multicolumn\ST@multicol@number% combien de cellules ? - \advance\ST@colcount\ST@multicol@number% on va voir après le multicol en sautant toutes les valeurs des colonnes intermédiaires - \advance\ST@colcount\m@ne - \ifcsname code@\number\ST@colcount @\number\ST@rowcount\endcsname% y a t-il un code défini après le multicol ? - \ST@add@tomacro\ST@tab&% on ajoute la tabulation - \fi - \else% pas de \multicolumn - \unless\ifST@hiddencol% si la cellule n'est pas masquée - \unless\ifnum\ST@colcount>\ST@lastshowcol% si ce n'est pas la dernière cellule affichée - \ST@add@tomacro\ST@tab&%on ajoute la tabulation - \fi - \fi + \exploregroups + \StrSubstitute[1]\ST@temp@b\STnumericfieldmarker\ST@temp@a[\ST@temp@a]% on remplace le flag de formule par la valeur calculée + \noexploregroups + \ST@expadd@tomacro\ST@tab\ST@temp@a% on ajoute la cellule au tableau + \fi + }% + \advance\ST@colcount\@ne% on passe à la colonne suivante ! + \ifcsname code@\number\ST@colcount @\number\ST@rowcount\endcsname% y a t-il encore un code défini ensuite ? + \ifnum\csname code@\number\ST@colcount @\number\ST@rowcount\endcsname<\z@% on est dans une cellule contenant \multicol ? + \expandafter\ST@firstarg@after\csname text@\number\numexpr\ST@colcount-1@\number\ST@rowcount\endcsname\multicolumn\ST@multicol@number% combien de cellules ? + \advance\ST@colcount\ST@multicol@number% on va voir après le multicol en sautant toutes les valeurs des colonnes intermédiaires + \advance\ST@colcount\m@ne + \ifcsname code@\number\ST@colcount @\number\ST@rowcount\endcsname% y a t-il un code défini après le multicol ? + \ST@add@tomacro\ST@tab&% on ajoute la tabulation \fi - \else% il n'y a plus de code ensuite donc c'était la dernière colonne - \ifcsname endrow@\number\ST@rowcount\endcsname - \expandafter\ST@expadd@tomacro\expandafter\ST@tab\csname endrow@\number\ST@rowcount\endcsname% ajoute la fin de la ligne + \else% pas de \multicolumn + \unless\ifST@hiddencol% si la cellule n'est pas masquée + \unless\ifnum\ST@colcount>\ST@lastshowcol% si ce n'est pas la dernière cellule affichée + \ST@add@tomacro\ST@tab&%on ajoute la tabulation + \fi \fi - \ST@colcount\@ne% on remet la colonne à 1 - \advance\ST@rowcount\@ne% on passe à la ligne suivante \fi - \else + \else% il n'y a plus de code ensuite donc c'était la dernière colonne \ifcsname endrow@\number\ST@rowcount\endcsname \expandafter\ST@expadd@tomacro\expandafter\ST@tab\csname endrow@\number\ST@rowcount\endcsname% ajoute la fin de la ligne \fi @@ -1226,9 +1484,95 @@ \ST@nextcell } +% format des lettres et nombres représentant les coordonnées (helvetica gras très petit) +\newcommand\ST@debugformat@headers{% + \usefont{T1}{phv}{b}{n}% +} + +% format utilisé pour les cellules +\newcommand\ST@debug@format@cells{% + \usefont{T1}{lmtt}{m}{n}% +} + +\newcommand\ST@colorcell{% + \ifST@colortblloaded\noexpand\cellcolor[gray]{.6}\fi +} + +\newcommand\STdebug{% + \begingroup\ifmmode\scriptscriptstyle\else\scriptsize\fi + \def\ST@temp@a{formula}% pour n'afficher les fins de ligne que dans ce cas + \IfStrEqCase\ST@debuginfo{% + {formula}\relax{text}\relax{code}\relax + }[\ST@illegaldebugcommand]% + \ST@debug@format@cells + \tabcolsep0.3em + \ST@rowcount\@ne\ST@colcount\@ne + \edef\ST@debugtab{% + \noexpand\begin{tabular}{r|*{\number\numexpr\ST@lastshowcol+1}{c|}}% + \noexpand\multicolumn1{c}{\ST@colorcell}&% + }% + \loop + \ST@edefadd@tomacro\ST@debugtab{\noexpand\multicolumn1c{\ST@colorcell\noexpand\ST@debugformat@headers\@Alph\ST@colcount}}% + \ifnum\ST@colcount<\ST@lastshowcol + \advance\ST@colcount\@ne + \ST@add@tomacro\ST@debugtab&% + \repeat + \ST@colcount\@ne + \ST@edefadd@tomacro\ST@debugtab{% + &% passe à la dernière colonne de la première ligne + \noexpand\multicolumn1l{% + \ifx\ST@temp@a\ST@debuginfo + \ifcsname endrow@\number\ST@rowcount\endcsname + \detokenize\expandafter\expandafter\expandafter{\csname endrow@0\endcsname}% + \fi + \fi}% + \noexpand\\\noexpand\cline{2-\number\numexpr\ST@lastshowcol+1}% + }% + \ST@debug@tab@i +} + +\newcommand\ST@debug@tab@i{% affiche le tableau de débobage + \ifnum\ST@rowcount>\ST@total@rownumber + \ST@edefadd@tomacro\ST@debugtab{\noexpand\cline{2-\number\numexpr\ST@lastshowcol+1}\noexpand\end{tabular}}% + \ST@debugtab% affichage du tableau de débogage + \ifmmode\\[0.5ex]\else\par\smallskip\fi% retour à la ligne + \expandafter\endgroup + \else + \ifnum\ST@colcount=\@ne + \ST@edefadd@tomacro\ST@debugtab{% + \noexpand\multicolumn1{c|}{\ST@colorcell\noexpand\ST@debugformat@headers\number\ST@rowcount}&}% + \fi + \ifcsname\ST@debuginfo @\number\ST@colcount @\number\ST@rowcount\endcsname% si l'info existe pour la cellule concernée + \ST@edefadd@tomacro\ST@debugtab{\detokenize\expandafter\expandafter\expandafter{\csname\ST@debuginfo @\number\ST@colcount @\number\ST@rowcount\endcsname}}% on ajoute la cellule au tableau que l'on a detokenisée au préalable + \fi + \advance\ST@colcount\@ne% on passe à la colonne suivante ! + \ifnum\ST@colcount>\ST@lastshowcol% si c'est la dernière cellule affichée + \ST@edefadd@tomacro\ST@debugtab{% + &\noexpand\multicolumn1l{% + \ifx\ST@temp@a\ST@debuginfo + \ifcsname endrow@\number\ST@rowcount\endcsname + \detokenize\expandafter\expandafter\expandafter{\csname endrow@\number\ST@rowcount\endcsname}% + \fi + \fi}% + \noexpand\\\noexpand\cline{2-\number\numexpr\ST@lastshowcol+1}}% + \ST@colcount\@ne% on remet la colonne à 1 + \advance\ST@rowcount\@ne% on passe à la ligne suivante + \else% il reste encore des cellules dans la ligne + \ST@add@tomacro\ST@debugtab&% on ajoute la tabulation + \fi + \expandafter\ST@debug@tab@i + \fi +} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%% Environnement spreadtab et macros publiques %%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% définit le séparateur décimal +\newcommand\STsetdecimalsep[1]{\StrChar{#1}1[\ST@decsep]} +\def\ST@decsepfp{.}% le séparateur décimal donné par fp +\STsetdecimalsep.% le point par défaut + \STmessage{true}% affiche les messages par défaut \newcommand\STautoround[1]{\def\ST@autouround{#1}} @@ -1246,10 +1590,10 @@ } \newcommand\ST@find@end[1]{% - \def\@tempa{#1}% - \ifx\@tempa\ST@name@env - \def\@tempa{\end{#1}}% - \expandafter\@tempa + \def\ST@temp@a{#1}% + \ifx\ST@temp@a\ST@name@env + \def\ST@temp@a{\end{#1}}% + \expandafter\ST@temp@a \else \@addtomacro\ST@tab{\end{#1}}% \expandafter\ST@get@body @@ -1265,7 +1609,7 @@ \def\ST@tab@preamble{#2}%% préambule du tableau \StrChar{\@empty#2}1[\ST@tab@name]% \def\ST@optcode{#1}% - \let\ST@row@skiplist\@empty\let\ST@col@skiplist\@empty\def\ST@last@skipcol{0}% + \let\ST@copylist\@empty\let\ST@row@skiplist\@empty\let\ST@col@skiplist\@empty\def\ST@last@skipcol{0}% \edef\ST@previous@seed{\number\FPseed}% sauvegarde de la graine \ST@seed% graine variable \ST@emit@message{\ST@errname New spreadtab {\detokenize{#2}}^^J* reading tab:}% @@ -1276,15 +1620,32 @@ \ST@read@tab% analyse le tableau contenu dans \ST@tab \ST@emit@message{ok^^J}% \ST@search@lastshowcol% cherche la dernière colonne affichée - \ST@emit@message{* computing formulas:^^J}% - \ST@eval@tab - \ST@optcode% exécute l'argument optionnel - \expandafter\def\expandafter\ST@tab\expandafter{\expandafter\begin\ST@tab@preamble}% - \ST@emit@message{* building tab:}% - \ST@build@tab - \ST@emit@message{ok^^J}% - \ST@expadd@tomacro\ST@tab{\expandafter\end\ST@tab@name} - \ST@tab% affiche le tableau + \ST@debugmodefalse% à priori, on n'est pas en mode débogage + \loop% affiche éventuellement les tableaux de débogage + \ST@Ifinstr\ST@optcode{\@empty\STdebug}{\ST@debugmodetrue\iftrue}\iffalse% \fi + \ST@firstarg@after\ST@optcode\STdebug\ST@debuginfo + \ST@emit@message{\space\space\space\space\space Debug mode: display debug tab "\ST@debuginfo"^^J}% + \StrDel\ST@optcode{\expandafter\STdebug\expandafter{\ST@debuginfo}}[\ST@optcode]% + \STdebug + \repeat + \ifST@debugmode + \ST@Ifinstr\ST@optcode{\@empty\STdisplaytab}% + {\ST@debugmodefalse + \ST@emit@message{\space\space\space\space\space Debug mode: display final tab^^J}% + }\relax + \fi + \let\STdisplaytab\relax% on neutralise au cas où l'arg optionnel contient cette commande sans contenir \STdebug + \unless\ifST@debugmode% si on doit afficher le tableau, on fait le boulot + \ST@emit@message{* computing formulas:^^J}% + \ST@eval@tab + \ST@optcode% exécute l'argument optionnel + \expandafter\def\expandafter\ST@tab\expandafter{\expandafter\begin\ST@tab@preamble}% + \ST@emit@message{* building tab:}% + \ST@build@tab + \ST@emit@message{ok^^J}% + \ST@expadd@tomacro\ST@tab{\expandafter\end\ST@tab@name}% + \ST@tab% affiche le tableau + \fi \ST@emit@message{\ST@errname End of spreadtab^^J^^J}% \global\FPseed\ST@previous@seed% restauration de la graine } @@ -1357,4 +1718,32 @@ v0.1pre 2009/09/02 7 Améliorations et optimisations ------------------------------------------------------------------------------- v0.1 2009/11/03 Première version publique sur le CTAN -------------------------------------------------------------------------------- \ No newline at end of file +------------------------------------------------------------------------------- +v0.2 2010/01/24 + 1 On peut définir le séparateur décimal par la macro + \STsetdecimalsep{} + 2 Il est possible de copier une formule dans le tableau à l'aide de + \STcopy{>a,vb}{formule} où a et b sont les nombres de cellules + horizontaux et verticaux vers lesquels la formule sera copiée. + 3 Désormais, spreadtab est entièrement compatible avec toutes les + commandes du package booktabs + 4 La commande \noalign et son argument est prise en compte lorsqu'elle se + trouve après un \\ + 5 Suppression d'espaces indésirables + 6 Mise en place d'un mode débogage où l'on peut visualiser les champs + numériques, les champs textuels ou les codes des cellules du tableau + +############################################################################### +# TODO list # +############################################################################### + 1 Augmenter le nombre de macro-fonctions + - arithmetique : calcul de pgcd, ppcm, de reste de division + - conversion : deg-rad-gra et système métrique <-> anglo saxon + - autres... + 2 Améliorer l'algorithme pour \STcopy : enlever une formule de + \ST@copylist lorsqu'on a dépassé la dernière ligne de la plage où elle + doit être copiée + 3 Améliorer les tableaux de débogage + 4 Dans un champ textuel, créer une nouvelle fonctionnalité pour afficher + le résultat du champ numérique d'une autre cellule, sans avoir à le + sauvegarder avec \STsave pour l'afficher ensuite. \ No newline at end of file -- cgit v1.2.3