%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%
%% Macros d�finies dans le livre %%
%% � Apprendre � programmer en TeX � %%
%% et n�cessaires � sa compilation %%
%% %%
%% Encodage ISO 8859-1 %%
%% _____ %%
%% %%
%% � 2014 Christian Tellechea %%
%% %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%
%% Ce fichier contient celles des macros d�finies dans le livre qui sont %%
%% n�cessaires � sa compilation. %%
%% %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Les codes et les macros donn�s dans ce fichier sont diffus�s sous licence
% libre � Creative Commons "BY-SA" �.
%
%
https://creativecommons.org/licenses/by-sa/4.0/
%
https://creativecommons.org/licenses/by-sa/4.0/legalcode
%
% Vous �tes autoris� �
%
% * partager : copier, distribuer et communiquer le mat�riel par tous moyens
% et sous tous formats ;
% * adapter : remixer, transformer et cr�er � partir du mat�riel pour toute
% utilisation, y compris commerciale
%
% selon les conditions suivantes
%
% * paternit� : vous devez citer le nom de l'auteur de fa�on appropri�e,
% fournir un lien vers la licence, et indiquer si des modifications ont
% �t� apport�es. Vous pouvez le faire de mani�re raisonnable, mais pas
% d'une fa�on qui sugg�re le donneur de licence vous approuve ou approuve
% l'utilisation que vous en faites ;
% * partage dans les m�mes conditions : dans le cas o� vous effectuez un
% remix, que vous transformez, ou cr�ez � partir du mat�riel composant
% l'Oeuvre originale, vous devez diffuser l'Oeuvre modifi�e dans les m�mes
% conditions, c'est-�-dire avec la m�me licence avec laquelle l'Oeuvre
% originale a �t� diffus�e.
%
%
% Les commentaires dont sont assorties les macros dans le livre ne sont pas
% sous licence libre et ne sont pas reproduits dans ce fichier.
\edef\restoreatcoatcode{\catcode`\noexpand\@=\the\catcode`\@}
\catcode`\@11
{\def\:{\let\sptoken= }\expandafter}\: %
\long\def\gobone#1{}
\long\def\identity#1{#1}
\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}
\def\gobtwo#1#2{}%
\def\defactive#1{%
\catcode`#1=13
\begingroup
\lccode`~=`#1
\lowercase{\endgroup\def~}}
\def\letactive#1{%
\catcode`#1=13
\begingroup
\lccode`~=`#1
\lowercase{\endgroup\let~}}
\def\litterate#1{% #1=lit le token fronti�re choisi
\begingroup% ouvre un groupe pour y faire les modifications
\def\do##1{\catcode`##1=12 }%
\dospecials% rend inoffensifs tous les tokens sp�ciaux
\defactive\^^M{\leavevmode\par}%
\defactive\ {\space}%
\defactive<{\string<{}}\defactive>{\string>{}}%
\defactive-{\string-{}}\defactive`{\string`{}}%
\defactive,{\string,{}}\defactive'{\string'{}}%
\defactive#1{\endgroup}% #1 sera un \endgroup
\tt% passe en police � chasse fixe
}
\long\def\firstto@nil#1#2\@nil{#1}
\long\def\remainto@nil#1#2\@nil{#2}
\def\rightofsc#1#2{%
\exparg\ifin{#1}{#2}%
{% si #1 contient le #2
\def\right@of##1#2##2\@nil{\def#1{##2}}% d�finit la macro auxiliaire
\expandafter\right@of#1\@nil% appelle la macro auxiliaire
}%
{\let#1=\empty}% sinon, ne rien faire
}
\def\defname#1{\expandafter\def\csname#1\endcsname}
\def\letname#1{\expandafter\let\csname#1\endcsname}
\long\def\addtomacro#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\long\def\eaddtomacro#1#2{\expandafter\addtomacro\expandafter#1\expandafter{#2}}
\long\def\addtotoks#1#2{#1\expandafter{\the#1#2}}
\long\def\eaddtotoks#1#2{\expandafter\addtotoks\expandafter#1\expandafter{#2}}
\long\def\swaparg#1#2{#2{#1}}
\long\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}
\let\exparg\expsecond
\def\exptwoargs#1#2{\expsecond{\expsecond{#1}{#2}}}
\def\sgn#1{\ifnum#1<0 -\fi}
\def\abs#1{\sgn{#1}#1 }
\def\truncdiv#1#2{%
\exptwoargs\truncdiv@i{\number\numexpr#1\relax}{\number\numexpr#2\relax}%
}
\def\truncdiv@i#1#2{%
\numexpr(2*\sgn{#1}#1-\sgn{#2}#2+1)/(\sgn{#1}2*#2)\relax
}
\def\ifinside#1[#2,#3]{%
\ifnum\sgn{\dimexpr#1pt-#2pt\relax}\sgn{\dimexpr#1pt-#3pt}1=1
\expandafter\secondoftwo
\else
\expandafter\firstoftwo
\fi
}
\def\absval#1{\expandafter\absval@i\expandafter{\number\numexpr#1\relax}}
\def\absval@i#1{\number\ifnum#1<\z@-\fi#1 }
\edef\saved@catcode{\number\catcode`\:}% sauvegarde du catcode de ":"
\catcode`\:12 % ":" est d�sormais un caract�re non actif normal
\def\hdif{%
\begingroup% ouvrir un groupe semi-simple
\catcode`\:12 % modifier le catcode de ":"
\hdif@i% aller lire les deux arguments
}
\def\hdif@i#1#2{% lit les 2 arguments
\hdif@ii#1-#2\@nil% et les transmet � la macro � argument d�limit�s
}
\def\hdif@ii#1:#2:#3-#4:#5:#6\@nil{%
%%%%%% calcul des nombres � afficher %%%%%%
\edef\nb@hrs{\number\numexpr#1-#4\relax}% diff�rence des heures
\edef\nb@min{\number\numexpr#2-#5\relax}% diff�rence des minutes
\edef\nb@sec{\number\numexpr#3-#6\relax}% diff�rence des secondes
\ifnum\nb@sec<\z@ % si la diff�rence des secondes est <0
\edef\nb@sec{\number\numexpr\nb@sec+60\relax}% ajouter 60 sec
\edef\nb@min{\number\numexpr\nb@min-1\relax}% enlever 1 aux minutes
\fi
\ifnum\nb@min<\z@ % si les minutes sont <0
\edef\nb@min{\number\numexpr\nb@min+60\relax}% ajouter 60 min
\edef\nb@hrs{\number\numexpr\nb@hrs-1\relax}% enlever 1 aux heures
\fi
%%%%%% affichage du r�sultat %%%%%%
\let\inter@space\empty% pas d'espace avant un nombre pour l'instant
\ifnum\nb@hrs>\z@ % si les heures sont >0
\nb@hrs h% afficher les heures et "h"
\let\inter@space\space% espace pour plus tard
\fi
\ifnum\nb@min>\z@ % si les minutes sont >0
\inter@space% afficher une espace �ventuelle
\nb@min min% afficher les minutes et "min"
\let\inter@space\space
\fi
\ifnum\nb@sec>\z@ % si les secondes sont >0
\inter@space% afficher une espace �ventuelle
\nb@sec s% afficher les secondes et "s"
\fi
\endgroup% fermer le groupe ouvert au d�but
}
\catcode`\:=\saved@catcode\relax% restaure le code de cat�gorie de ":"
\long\def\afterfi#1#2\fi{#2\fi#1}
\long\def\antefi#1\fi{\fi#1}
\def\for#1=#2to#3\do#4#{%
\edef\temp@increment{\number\numexpr0#4}% lit et normalise l'argument optionnel
\ifnum\temp@increment=\z@% s'il est nul,
\edef\temp@increment{% le red�finir � -1 (si #3<#2) et 1 sinon
\ifnum\numexpr#3-#2\relax<\z@ -1\else 1\fi
}% \temp@increment vaut donc 1 ou -1
\fi
\ifnum\numexpr\temp@increment*(#3-#2)\relax<\z@
\expandafter\gobone% si argument optionnel incompatible, manger le {<code>}
\else
\edef#1{\number\numexpr#2}% initialise la variable
\edef\macro@args{% d�finit et d�veloppe les arguments de la macro
%#1=nom de la macro � d�finir :
\expandafter\noexpand\csname for@ii@\string#1\endcsname
\ifnum\temp@increment<\z@ <\else >\fi% #2=signe de comparaison
{\temp@increment}% #3=incr�ment
\noexpand#1% #4=variable
{\number\numexpr#3\relax}% #5=entier max
}%
\antefi
\expandafter\for@i\macro@args
\fi
}
% #1=nom de la macro r�cursive de type "\for@ii@<variable>"
% #2=signe de comparaison % #3=incr�ment
% #4=variable % #5=entier max % #6=code � ex�cuter
\long\def\for@i#1#2#3#4#5#6{%
\def#1{% dfinit la sous macro r�cursive
\unless\ifnum#4#2#5\relax% tant que la variable n'a pas d�pass� l'entier max
\afterfi{% rendre la r�cursivit� terminale
#6% ex�cute le code
\edef#4{\number\numexpr#4+#3\relax}% incr�mente la variable #1
#1% recommence
}%
\fi
}%
#1% appelle la sous-macro r�cursive
}
\def\exitfor#1{% #1=variable correspondant � la boucle de laquelle on veut sortir
\expandafter\let\csname for@ii@\string#1\endcsname\empty
}
\def\quark{\quark}
\long\def\ifempty#1{%
\expandafter\ifx\expandafter\relax\detokenize{#1}\relax
\expandafter\firstoftwo
\else
\expandafter\secondoftwo
\fi}
\def\reverse#1{%
\ifempty{#1}
{}% s'il n'y a rien � inverse, ne rien faire
{\reverse@i#1\@nil\@nil}% initialisation des r�servoirs et appeler \reverse@i
}
\def\reverse@i#1#2\@nil#3\@nil{% #1 est le 1er caract�re du r�servoir A
\ifempty{#2}% si ce qui reste apr�s ce 1er caract�re est vide
{#1#3}% renvoyer #1#3 qui est le r�sultat final
{\reverse@i#2\@nil#1#3\@nil}% sinon, recommencer en d�pla�ant #1
% en 1re position du r�servoir B
}
\long\def\ifin#1#2{%
\long\def\ifin@i##1#2##2\@nil{% d�finit la macro auxiliaire
\ifempty{##2}% si ce qu'il y a derri�re le motif est vide
\secondoftwo% aller � "faux"
\firstoftwo% sinon � "vrai"
}%
\ifin@i#1#2\@nil% appel de la macro auxiliaire
}
\def\ifstart#1#2{%
\def\if@start##1#2##2\@nil{\ifempty{##1}}%
\ifempty{#2}\firstoftwo{\if@start#1\relax#2\@nil}}
\def\substin#1#2#3{%
\def\substin@i##1{%
\ifempty{##1}% si le code est vide
\relax% ne rien faire -> fin du processus
{\ifin{##1}{#2}% sinon, si le code contient motif1
{\substin@ii##1\@nil}% appeler la macro � argument d�limit�s
{##1}% sinon, afficher le code
}%
}%
\def\substin@ii##1#2##2\@nil{%
##1#3% afficher ##1 et #3 (qui est <motif2>)
\substin@i{##2}% et recommencer avec ce qui reste
}%
\substin@i{#1}%
}
\def\substtocs#1#2#3#4{%
\def\substtocs@i##1{%
\ifempty{##1}% si le code est vide
\relax% ne rien faire -> fin du processus
{\ifin{##1}{#3}% sinon, si le code contient motif1
{\substtocs@ii##1\@nil}% appeler la macro � argument d�limit�s
{\addtomacro#1{##1}}% sinon, ajouter le code
}%
}%
\def\substtocs@ii##1#3##2\@nil{%
\addtomacro#1{##1#4}% ajouter ##1#4
\substtocs@i{##2}% et recommencer avec ce qui reste
}%
\let#1=\empty% initialise la macro � vide
\substtocs@i{#2}%
}
\long\def\cnttimestocs#1#2#3{% #3=macro recevant le r�sultat
\long\def\cnttimestocs@i##1\@nil##2#2##3\@nil{%
% ##1=nb d'occurrences rencontr�es jusqu'alors
% ##2 et ##3=ce qui est avant/apr�s le <motif>
\ifin{##3}{#2}% si le <motif> est dans ce qui reste
{\expandafter\cnttimestocs@i% appeler la macro r�cursive
\number\numexpr##1+1\relax\@nil% avec une occurrence de plus
##3\@nil% et ce qui reste
}%
{\edef#3{\number\numexpr##1+1\relax}}% sinon, stocker 1 occurrence de plus dans #3
}%
\ifin{#1}{#2}% si le <motif> est dans le <code>
{\cnttimestocs@i 0\@nil#1\@nil}% appeler la macro r�cursive avec 0 occurrence
{\def#3{0}}% sinon, mettre 0 dans #3
}
\def\ifcs#1{%
\begingroup
\escapechar=`\@ % prend "@" comme caract�re d'�chappement
\if% les premiers caract�res de
\expandafter\firstto@nil\string#1a\@nil% "#1a"
\expandafter\firstto@nil\string\relax\@nil% et "\relax" sont-ils �gaux ?
\endgroup\expandafter\firstoftwo% si oui, fermer le groupe et renvoyer "vrai"
\else% sinon, fermer le groupe et renvoyer "faux"
\endgroup\expandafter\secondoftwo
\fi
}
\def\endif{\endif}\def\elseif{\elseif}
\def\idto@endif#1\endif{#1}
\def\firstto@endif#1#2\endif{#1}
\def\ifxcase#1#2{% #1=<token> #2=prochain argument
\ifx\elseif#2% si #2 est \elseif
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
\idto@endif% aller � \idto@endif, sinon :
{\ifx\endif#2% si #2 est \endif
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{}% ne rien faire, sinon :
{\ifx#1#2% s'il y a �galit�
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
\firstto@endif% aller � \firstto@endif
{\ifxcase@i{#1}}% sinon aller � \ifxcase@i
}%
}%
}
\def\ifxcase@i#1#2{% #1=<nombre> #2=<code>
\ifxcase{#1}% manger le <code> et aller � \ifxcase en transmettant #1
}
\newcount\cnt@nest \cnt@nest=0 % d�finit et initialise le compteur d'imbrication
\def\end@foreach{\end@foreach}
\long\def\save@macro#1#2{\expandafter\let\csname saved@var@\number\cnt@nest#1\endcsname#2}
\long\def\save@macro@i#1/#2{\save@macro{a}#1\save@macro{b}#2}
\long\def\restore@macro#1#2{%
\expandafter\let\expandafter#2\csname saved@var@\number\cnt@nest#1\endcsname
}
\long\def\restore@macro@i#1/#2{\restore@macro{a}#1\restore@macro{b}#2}
\def\defseplist#1{%
\long\def\doforeach##1\in##2##3{%
\global\advance\cnt@nest1 % entr�e de boucle : incr�menter le compteur d'imbrication
\ifin{##1}{/}% si ##1 contient "/"
{\save@macro@i##1% sauvegarde les macros
\doforeach@ii% appeler la macro r�cursive apr�s avoir
{##3}%\csname loop@code@\number\cnt@nest\endcsname% form� la macro contenant le code
##1% mettre les variables ##1 en 2e position
##2#1\end@foreach/\end@foreach#1% puis la liste ##2 suivie de ",\end@foreach,"
\restore@macro@i##1% une fois sorti de toutes les boucles, restaurer les macros
}% si ##1 ne contient pas "/"
{\save@macro{}##1% sauvegarde la macro
\doforeach@i% appeler la macro r�cursive
{##3}% mettre en premier le <code>
##1% puis la variable ##1 en 2e position
##2#1\end@foreach#1% enfin la liste ##2 suivie de ",\end@foreach,"
\restore@macro{}##1% une fois sorti de toutes les boucles, restaurer la macro
}%
\global\advance\cnt@nest-1 % d�cr�mente le compteur d'imbrications
}%
% ##1 = code � ex�cuter, ##2= variable, ##3=valeur courante
\long\def\doforeach@i##1##2##3#1{%
\def##2{##3}% fait l'assignation � la variable
\global\let\allow@recurse\identity% permet l'appel r�cursif plus bas
\ifx\end@foreach##2% si la fin est atteinte
\expandafter\gobone\else\expandafter\identity\fi% manger sinon ex�cuter:
{##1% le code puis
\allow@recurse{\doforeach@i{##1}##2}% recommencer
}%
}%
% ##1 = code � ex�cuter, ##2/##3= variables, ##4/##5=valeurs courantes
\long\def\doforeach@ii##1##2/##3##4/##5#1{%
\def##2{##4}\def##3{##5}% fait l'assignation des deux variables
\global\let\allow@recurse\identity% permet l'appel r�cursif plus bas
\ifx\end@foreach##2% si la fin est atteinte
\expandafter\gobone\else\expandafter\identity\fi% manger sinon ex�cuter:
{##1% le code puis
\allow@recurse{\doforeach@ii{##1}##2/##3}% recommencer
}%
}%
% macro qui, si elle remplace \allow@recurse, annule l'appel r�cursif
\long\def\forbid@recurse##1\end@foreach#1{}% tout manger jusqu'� "\end@foreach,"
}
% macro pour annuler le prochain appel r�cursif
\def\doforeachexit{\global\let\allow@recurse\forbid@recurse}
\defseplist{,}
\begingroup% ouvrir un groupe
\edef\temp{\endgroup\def\noexpand\removept##1.##2\string p\string t}%
\temp{#1\ifnum#2>0 .#2\fi}% et le fermer avant de d�finir \removept
\def\dimtodec{\expandafter\removept\the}
\def\FOR#1=#2to#3\do#4#{%
\ifempty{#4}
{\let\FOR@increment\z@}
{\edef\FOR@increment{\the\dimexpr#4pt\relax}}% lit et normalise l'argument optionnel
\ifdim\FOR@increment=\z@% s'il est nul,
\edef\FOR@increment{% le red�finir � -1pt (si #3<#2) et 1pt sinon
\ifdim\dimexpr#3pt-#2pt\relax<\z@ -1\else 1\fi pt
}% \FOR@increment vaut donc 1 ou -1
\fi
\ifdim\dimtodec\dimexpr#3pt-#2pt\relax\dimexpr\FOR@increment\relax<\z@
\expandafter\gobone% si argument optionnel incompatible, manger le {<code>}
\else
\edef#1{\dimtodec\dimexpr#2pt\relax}% initialise la \<macro>
\edef\macro@args{% d�finit et d�veloppe les arguments � passer � \FOR@i
%#1=nom de la macro r�cursive :
\expandafter\noexpand\csname FOR@ii@\string#1\endcsname
\ifdim\FOR@increment<\z@ <\else >\fi% #2=signe de comparaison
{\FOR@increment}% #3=incr�ment
\noexpand#1% #4=\<macro>
{\the\dimexpr#3pt\relax}% #5=dimension n2
}%
\antefi% externalise la ligne ci-dessous de la port�e du test
\expandafter\FOR@i\macro@args% appelle \FOR@i avec les arguments d�finis ci-dessus
\fi
}
% #1=nom de la macro r�cursive de type "\FOR@ii@\<macro>"
% #2=signe de comparaison % #3=incr�ment
% #4=\<macro> % #5=dimension n2 % #6=<code> � ex�cuter
\long\def\FOR@i#1#2#3#4#5#6{%
\def#1{% dfinit la sous macro r�cursive
\unless\ifdim#4pt#2#5\relax% tant que la \<macro> variable n'a pas d�pass� n2
\afterfi{% rendre la r�cursivit� terminale
#6% ex�cute le code
\edef#4{\dimtodec\dimexpr#4pt+#3\relax}% incr�mente la \<macro>
#1% recommence
}%
\fi
}%
#1% appelle la sous-macro r�cursive
}%
\def\exitFOR#1{% #1=\<macro> correspondant � la boucle de laquelle on veut sortir
\defname{FOR@ii@\string#1}{}%
}
\def\ifexitFOR#1{% envoie vrai si on est pr�matur�ment sorti de la boucle de \<macro> #1
% si la macro r�cursive est \empty
\expandafter\ifx\csname FOR@ii@\string#1\endcsname\empty
\expandafter\firstoftwo% c'est qu'on est sortir pr�matur�ment, renvoyer "vrai"
\else
\expandafter\secondoftwo% sinon, renvoyer "faux"
\fi
}
\def\decmul#1#2{\dimtodec\dimexpr#1\dimexpr#2pt\relax\relax}
\def\decdiv#1#2{% divise le d�cimal #1 par le d�cimal #2
\dimtodec\dimexpr 1pt*\dimexpr#1pt\relax/\dimexpr#2pt\relax\relax
}
\def\convertunit#1#2{%
\dimtodec
\dimexpr
\numexpr
\dimexpr #1 \relax * 65536 / \dimexpr 1#2 \relax
\relax
sp
\relax
}
\def\vdim#1{\dimexpr\ht#1+\dp#1\relax}% hauteur totale de la boite #1
\def\cbox#1{\setbox0\vbox{#1}\lower\dimexpr(\ht0-\dp0)/2\relax\box0 }
\def\clap#1{\hbox to\z@{\hss#1\hss}}
\def\ifzerodimbox#1{% #1=registre de boite
% revoie vrai si le registre est vide ou contient une boite vide
\csname% former le nom "\firstoftwo" ou "secondoftwo"
\ifvoid#1first%% si le registre est vide "first"
\else% sinon
\ifnum\wd#1=\z@% si la largeur
\ifnum\ht#1=\z@% la hauteur
\ifnum\dp#1=\z@ first% et la profondeur=0pt, "first"
\else second% dans les autres cas "second"
\fi
\else second%
\fi
\else second%
\fi
\fi
oftwo% compl�ter avec "oftwo"
\endcsname
}
\def\ifvoidorempty#1{% teste si le registre de boite #1 est vide ou contient une boite vide
\ifvoid#1\relax
\expandafter\firstoftwo
\else
\begingroup% dans un groupe
\setbox0=% affecter � la boite 0
\ifhbox#1\hbox\bgroup\unhcopy% un boite horizontale
\else \vbox\bgroup\unvcopy% ou verticale
\fi% dans laquelle on compose
#1\relax% composer #1 en dimensions naturelles
\expandafter\egroup% sauter la fin de la boite
\expandafter% et le \endgroup
\endgroup
\ifnum\lastnodetype<0 % pour tester si le dernier noeud est vide
\expandafter\expandafter\expandafter\firstoftwo
\else
\expandafter\expandafter\expandafter\secondoftwo
\fi
\fi
}
\def\showdim#1{%
\vrule width0.2pt height 1ex depth 0pt
\vrule width#1 height0.4pt depth 0pt
\vrule width0.2pt height 1ex depth 0pt \relax}
\newdimen\frboxrule \frboxrule0.4pt
\newdimen\frboxsep \frboxsep5pt
\def\FRbox#1{% ne pas changer le mode H ou V en cours
\hbox{% mettre � la suite horizontalement
\vrule width\frboxrule% 1) r�glure gauche
\vbox{% 2) un empilement vertical comprenant
\hrule height\frboxrule% a) r�glure sup�rieure
\kern\frboxsep% b) espace verticale haute
\hbox{% c) contenu + espaces en mode H
\kern\frboxsep#1\kern\frboxsep
}%
\kern\frboxsep% d) espace verticale basse
\hrule height\frboxrule% e)r�glure inf�rieure
}%
\vrule width\frboxrule% 3) r�glure droite
}%
}
\def\frbox#1{% ne pas changer le mode H ou V en cours
\hbox{% enferme dans une \hbox
\vrule width\frboxrule% r�glure gauche
\vtop{%
\vbox{% 1er �l�ment de la \vtop
\hrule height\frboxrule% r�glure sup�rieure
\kern\frboxsep% espace haut
\hbox{%
\kern\frboxsep% espace gauche
#1% contenu
\kern\frboxsep% espace droite
}%
}% puis autres �l�ments de la \vtop, sous la ligne de base
\kern\frboxsep% espace bas
\hrule height\frboxrule% r�glure inf�rieure
}%
\vrule width\frboxrule% r�glure droite
}%
}
\def\souligne#1{%
\setbox0=\hbox{#1}% stocke le contenu dans le registre no 0
\setbox0=\hbox{% puis, dans une \hbox, construit une r�glure
\vrule width\wd0 % de la longueur du contenu
depth\dimexpr\dp0 + 1.4pt\relax % dp = profondeur texte + 1.4pt
height\dimexpr-\dp0 - 1pt\relax % ht = -profondeux texte - 1pt
}%
\wd0=0pt \dp0=0pt \ht0=0pt % annule toutes les dimensions
\leavevmode \box0 % affiche la r�glure
#1% puis le contenu
}
\def\Souligne#1{%
\setbox0=\hbox{#1}%
\setbox0=\hbox{\vrule width\wd0 depth1.4pt height-1pt }%
\wd0=0pt \dp0=0pt \ht0=0pt
\leavevmode \box0 #1%
}
\newdimen\stackwd \stackwd=3em
\catcode`\@11
\def\stackbox#1{%
\par% termine le paragraphe en cours
\begingroup% dans un groupe semi-simple
\parindent=0pt% pas d'indentation
\parskip=0pt% annuler le \parskip
\setbox0\hbox{�gjp}% boite pour le strut
\edef\stack@strut{\vrule width\z@ height\the\ht0 depth\the\dp0 }% d�finit le strut
\stackbox@i#1\\\quark\\% ajoute "\\\quark\\" � la fin et appelle \stackbox@i
\unkern% annule la derni�re compensation verticale
\par
\endgroup
}
\def\stackbox@i#1\\{% #1=ligne courante
\def\temp@{#1}% stocke la ligne courante
\unless\ifx\quark\temp@% si ce n'est pas la fin
\hfill % ressort infini de centrage (passe en mode horizontal)
\doforeach\current@item\in{#1}% pour chaque �l�ment dans la ligne courante...
{\frbox{% ...encadrer
\hbox to\stackwd{% une \hbox de largeur \stackwd contenant
\hss% 1) ressort de centrage
\stack@strut% 2) strut de dimension verticale
\current@item%3) l'�lement courant
\hss}% 4)ressort de centrage
}% fin de la \fbox
\kern-\frboxrule% revenir en arri�re pour superposer les r�glures verticales
}% fin de \doforeach
\unkern% annuler la derni�re compensation horizontale
\hfill% ressort infini de centrage
\null% fait prendre en compte le dernier ressort
\par% termine le paragraphe
\nobreak% interdit une coupure de page
\nointerlineskip% sinon, ne pas ajouter le ressort interligne
\kern-\frboxrule% superposer les r�glures horizontales
\expandafter\stackbox@i% et recommencer
\fi
}
\def\vlap#1{\vbox to\z@{\vss#1\vss}}
\newdimen\xunit \newdimen\yunit
\newdimen\mainrule \newdimen\subrule
\xunit=1cm \yunit=1cm \mainrule=0.8pt \subrule=0.2pt
\def\grid#1#2#3#4{% #1=nb xunit #2=nb xsubunit #3=nb yunit #4=nb ysubunit
\vbox{%
\offinterlineskip
\edef\total@wd{\the\dimexpr\xunit*#1\relax}%
\edef\sub@unit{\the\dimexpr\yunit/#4\relax}%
\for\iii=1to#3\do
{\ifnum#4>1
\vbox to\z@{%
\for\jjj=2to#4\do
{\kern\sub@unit
\vlap{\hrule width\total@wd height\subrule}%
}%
\vss
}%
\fi
\vlap{\hrule width\total@wd height\mainrule}%
\kern\yunit
}%
\vlap{\hrule width\total@wd height\mainrule}%
\vbox to\z@{%
\vss
\hbox to\total@wd{%
\edef\total@ht{\the\dimexpr\yunit*#3\relax}%
\edef\sub@unit{\the\dimexpr\xunit/#2\relax}%
\for\iii=1to#1\do
{\ifnum#2>1
\rlap{%
\for\jjj=2to#2\do
{\kern\sub@unit
\clap{\vrule width\subrule height\total@ht}%
}%
}%
\fi
\clap{\vrule width\dimexpr\mainrule height\total@ht}%
\kern\xunit
}%
\clap{\vrule width\mainrule height\total@ht}%
}%
}%
}%
}
\def\iffileexists#1#2{% #1=canal de lecture #2=nom du fichier
\openin#1=#2 %
\ifeof#1% le fichier n'existe pas
\closein#1%
\expandafter\secondoftwo% renvoyer faux
\else
\closein#1
\expandafter\firstoftwo% sinon renvoyer vrai
\fi
}
\def\xread{% doit �tre suivie de "<nombre> to \<macro>"
\edef\restoreendlinechar{\endlinechar=\the\endlinechar}%
\endlinechar=-1 % neutralise \endlinechar
\afterassignment\restoreendlinechar% apr�s l'assignation restaurer \endlinechar
\read% attend <nombre> to \<macro>
}
\def\showfilecontent#1#2{% #1=canal de lecture #2=nom de fichier
\begingroup
\tt% s�lectionner la fonte � chasse fixe
\openin#1=#2\relax
\ifeof#1% si la fin du fichier est d�j� atteinte, il n'existe pas et
Le fichier n'existe pas% afficher le message
\else% le fichier existe
\def\do##1{\catcode`##1=12 }%
\dospecials% neutraliser tous les tokens sp�ciaux
\obeyspaces% rendre l'espace actif
\def\magicpar{\let\magicpar=\par}%
\loop
\xread#1 to \currline% lire une ligne
\unless\ifeof#1% si la fin du fichier n'est pas atteinte
\leavevmode\magicpar% former le paragraphe (sauf � la 1er it�ration)
\currline% afficher la ligne
\repeat% recommencer
\fi
\closein#1\relax%
\endgroup
}
\def\exactwrite#1#2{% #1=num�ro de canal #2=caract�re d�limiteur
\begingroup
\def\canal@write{#1}% sauvegarde le num�ro de canal
\for\xx=0 to 255\do{\catcode\xx=12 }% donne � tous les octets le catcode 12
\expandafter\exactwrite@i\expandafter{\string#2}% rend #2 de catcode 12
}
\def\exactwrite@i#1{% #1=caract�re fronti�re (de catcode 12)
% la macro \exactwrite@ii lit tout jusqu'au caract�re #2 et passe
% ce qu'elle a lu � la macro \exactwrite@iii en mettant un \@nil � la fin
\def\exactwrite@ii##1#1{\exactwrite@iii##1\@nil}%
\exactwrite@ii% va lire tout ce qui se trouve jusqu'au prochain #2
}
{\catcode`\^^M 12 \gdef\EOL@char{^^M}}% d�finit le caract�re <EOL> de catcode 12
\def\exactwrite@iii#1\@nil{% #1 = contenu � �crire
\expsecond{\ifin{#1}}\EOL@char% si #1 contient "retour chariot"
{\write@line#1\@nil}% �crire la premi�re ligne de #1
{\immediate\write\canal@write{#1}% sinon : derni�re ligne atteinte, l'�crire
\endgroup% puis sortir du groupe
}%
}
% les \expandafter provoquent le 1-d�veloppement de \EOL@char :
\expandafter\def\expandafter\write@line\expandafter#\expandafter1\EOL@char#2\@nil{%
\immediate\write\canal@write{#1}% �crit la ligne (ce qui se trouve avant ^^M)
\exactwrite@iii#2\@nil% continue avec ce qui se trouve apr�s ^^M
}
\def\quark@list{\quark@list}% quark de fin de liste
\def\finditemtocs#1#2#3{% #1 = \<macro> #2=position #3=macro � d�finir
\def\finditemtocs@iii##1##2\quark@list,{% renvoyer #1 et manger le reste de la liste
\expandafter\def\expandafter#3\expandafter{\gobone##1}%
}%
\let#3=\empty%
\exparg\finditemtocs@i{#1}{#2}% 1-d�veloppe la \<macro>
}
\def\finditemtocs@i#1#2{% #1 = liste #2=position cherch�e
\ifnum#2>\z@% ne faire quelque chose que si la position est >0
\antefi\finditemtocs@ii{1}{#2}\relax#1,\quark@list,% appelle la macro r�cursive
\fi
}
\def\finditemtocs@ii#1#2#3,{%
% #1=position courante #2=position cherch� #3=\relax + �l�ment courant
\expandafter\ifx\expandafter\quark@list\gobone#3%
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{}% si fin de liste ne rien faire. Sinon, si position bonne
{\ifnum#1=#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\finditemtocs@iii{#3}% renvoyer #3 et manger les �l�ments restants
}% si la position n'est pas la bonne, recommencer en incr�mentant #1
{\exparg\finditemtocs@ii{\number\numexpr#1+1}{#2}\relax%
}%
}%
}
\def\insitem#1#2#3{% #1 = macro #2=position cherch�e #3=�l�ment � ins�rer
\let\item@list=\empty
\ifnum#2<1 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
% si position < 1
{\addtomacro\item@list{#3,}% ajouter l'�lement � ins�rer en premier
\eaddtomacro\item@list#1% puis la liste enti�re
}
% si la position > 1
{% d�finir la macro r�cursive
\def\insitem@i##1##2,{% ##1 = position courante ##2=\relax + �l�ment courant
\expandafter\ifx\expandafter\quark@list\gobone##2%
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\addtomacro\item@list{#3}}% si fin de liste, ajouter l'�l�ment en dernier
{% sinon, si la position cherch�e est atteinte
\ifnum##1=#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\addtomacro\item@list{#3,}% ajouter l'�lement
\add@remainlist##2,% et ##2 (en supprimant le \relax) et le reste
}% si la position n'est pas atteinte
{\eaddtomacro\item@list{\gobone##2,}% ajouter l'�l�ment
\exparg\insitem@i{\number\numexpr##1+1}\relax% et recommencer
}%
}%
}%
% appel de la macro r�cursive
\expandafter\insitem@i\expandafter1\expandafter\relax#1,\quark@list,%
}%
\let#1=\item@list% rendre #1 �gal au r�sultat
}
\def\add@remainlist#1,\quark@list,{%
\eaddtomacro\item@list{\gobone#1}% ajouter #1 ainsi que les autres
}
\def\delitem#1#2{% #1 = macro #2=position cherch�e
\ifnum#2>0 % ne faire quelque chose que si la position est >0
\def\delitem@i##1##2,{% ##1 = position courante ##2=\relax + �l�ment courant
\expandafter\ifx\expandafter\quark@list\gobone##2%
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{}% si fin de liste, ne rien faire
{% sinon, si la position cherch�e est atteinte
\ifnum##1=#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\add@reaminingitems% et ##2 (en supprimant le \relax) et le reste
}% si la position n'est pas la bonne
{\eaddtomacro\item@list{\gobone##2,}% ajouter l'�l�ment
\exparg\delitem@i{\number\numexpr##1+1}\relax% et recommencer
}%
}%
}%
\let\item@list=\empty% initialiser la macro tempporaire
% appel de la macro r�cursive
\expandafter\delitem@i\expandafter1\expandafter\relax#1,\quark@list,%
\expandafter\remove@lastcomma\item@list\@nil
\let#1=\item@list% rendre #1 �gal au r�sultat
\fi
}
\def\add@reaminingitems#1\quark@list,{%
\eaddtomacro\item@list{#1}% ajouter tout jusqu'au quark
}
\def\remove@lastcomma#1,\@nil{\def\item@list{#1}}
\def\runlist#1\with#2{% #1=liste #2=macro
\def\runlist@i##1,##2\@nil{%
\addtomacro\collect@run{#2{##1}}% ajouter "\<macro>{<�l�ment>}""
\ifempty{##2}% plus d'�l�ment ?
\relax% ne rien faire (donc terminer le processus)
{\runlist@i##2\@nil}% sinon, recommencer avec les �l�ments restants
}%
\begingroup% fait la collecte dans un groupe
\let\collect@run=\empty% initialiser la macro
\ifcs{#1}% si #1 est une s�quence de contr�le
{\expandafter\runlist@i#1,\@nil%% aller � \runlist@i
}% sinon, former la sc
{\expandafter\expandafter\expandafter\runlist@i\csname#1\endcsname,\@nil
}%
\expandafter\endgroup% ferme le groupe et d�truit \collect@run
\collect@run% apr�s l'avoir d�velopp� !
}
\def\ifspacefirst#1{%
\expandafter\ifspacefirst@i\detokenize{#1W} \@nil% "W" se pr�munit d'un argument vide
}
\def\ifspacefirst@i#1 #2\@nil{\ifempty{#1}}
\expandafter\def\expandafter\gobspace\space{}
\def\removefirstspaces{%
\romannumeral% lance le d�veloppement maximal
\removefirstspaces@i% et passe la main � la macro r�cursive
}
\def\removefirstspaces@i#1{%
\ifspacefirst{#1}% si #1 commence par un espace
{\expandafter\removefirstspaces@i\expandafter% recommencer
{\gobspace#1}% apr�s avoir supprim� cet espace
}
{\z@#1}% sinon, renvoyer l'argument o� \z@ stoppe l'action de \romannumeral
}
\edef\catcodezero@saved{\number\catcode0 }% stocke le catcode de ^^00
\catcode0=12 % le modifie � 12
\def\removelastspaces#1{%
\romannumeral% lance le d�veloppement maximal
\removelastspaces@i#1^^00 ^^00\@nil% et passe la main � \removelastspaces@i
}
\def\removelastspaces@i#1 ^^00{%
\removelastspaces@ii#1^^00%
}
\def\removelastspaces@ii#1^^00#2\@nil{%
\ifspacefirst{#2}% si le reliquat commence par un espace
{\removelastspaces@i#1^^00 ^^00\@nil}% recommencer sans passer par \removelastspaces
{\z@#1}% sinon "\z@" stoppe l'action de \romannumeral
}
\catcode0=\catcodezero@saved\relax% restaure le catcode de ^^00
\def\removetrailspaces#1{%
\romannumeral% lance le d�veloppement maximal
\expandafter\expandafter\expandafter% le pont d'\expandafter
\removelastspaces
\expandafter\expandafter\expandafter% fait agir \removefirstspaces en premier
{%
\expandafter\expandafter\expandafter
\z@% stoppe le d�veloppement initi� par \romannumeral
\removefirstspaces{#1}%
}%
}
\newcount\test@cnt
\def\ifinteger#1{%
\ifstart{#1}{-}% si "-" est au d�but de #1
{\expandafter\ifinteger\expandafter{\gobone#1}% l'enlever et recommencer
}
{\ifempty{#1}% sinon, si #1 est vide, lire l'argument <faux>
\secondoftwo% lire l'argument <faux>
{\afterassignment\after@number% sinon, apr�s l'assignation, aller � \after@number
\test@cnt=0#1\relax% faire l'assignation (\relax termine le nombre et n'est pas mang�)
}%
}%
}
\def\after@number#1\relax{% #1 est ce qui reste apr�s l'assignation
\ifempty{#1}% teste si #1 est vide et lit l'argument <vrai> ou <faux> qui suit
}
\newif\iftestspace \testspacefalse
\def\deftok#1#2{\let#1= #2\empty}
\def\ifnexttok#1#2#3{% #1=token #2=code vrai #3=code faux
\let\test@tok= #1% stocke le token � tester
\def\true@code{#2}\def\false@code{#3}% et les codes � ex�cuter
\iftestspace \def\ifnexttok@i{\futurelet\nxttok\ifnexttok@ii}%
\else \def\ifnexttok@i{\futurelet\nxttok\ifnexttok@iii}%
\fi% apr�s avoir d�fini la macro r�cursive selon le bool�en
\ifnexttok@i% l'ex�cuter
}
\def\ifnexttok@ii{% macro qui teste aussi les espaces
\ifx\nxttok\test@tok \expandafter\true@code% ex�cuter le code vrai
\else \expandafter\false@code% sinon code faux
\fi
}
\def\ifnexttok@iii{%
\ifx\nxttok\sptoken% si le prochain token est un espace
\def\donext{%
\afterassignment\ifnexttok@i% aller "sentir" le token d'apr�s
\let\nxttok= }% apr�s avoir absorb� l'espace
\else \let\donext\ifnexttok@ii% sinon, faire le test
\fi
\donext% faire l'action d�cid�e ci-dessus
}
\def\ifstarred#1{\ifnexttok*{\firstoftwo{#1}}}
\def\parsestop{\parsestop}% d�finit le quark se trouvant en fin de code
\newtoks\code@toks% alloue le registre contenant le code lu
\def\parseadd#1{\code@toks\expandafter{\the\code@toks#1}}
\newif\ifparse@group
\def\parse{%
\code@toks{}% initialise le collecteur de tokens
\ifstarred
{\parse@grouptrue
\ifnexttok{ }% si un espace suit l'�toile
{\afterassignment\parse@i \let\nxttok= }% le manger et aller � \parse@i
{\parse@i}% sinon, aller � \parse@i
}
{\parse@groupfalse
\parse@i
}%
}
\def\parse@i{\futurelet\nxttok\parse@ii}% lit le prochain token et va � \parse@ii
\def\parse@ii{%
\ifx\nxttok\parsestop% si la fin va �tre atteinte, aller � \parsestop@i
\let\next@action\parsestop@i
\else
\ifx\nxttok\@sptoken% si un espace va �tre lu, aller � \read@space
\let\next@action\read@space
\else
\ifx\nxttok\bgroup% si une accolade ouvrante va �tre lue
\let\next@action\read@bracearg% aller � \read@bracearg
\else
\let\next@action\testtoken% dans les autres cas, aller � \testtoken
\fi
\fi
\fi
\next@action% faire l'action d�cid�e ci-dessus
}
\def\parsestop@i{% la fin est atteinte
\expandafter\the\expandafter\code@toks% afficher le registre de tokens
\gobone% apr�s avoir mang� \parsestop
}
\expandafter\def\expandafter\read@space\space{% \read@space mange un espace dans le code
\testtoken{ }% et va � \testtoken
}
\def\read@bracearg{%
\read@bracearg@i\relax% ajoute un \relax avant de passer la main � \read@bracearg@i
}
\def\read@bracearg@i#1\parsestop{% l'argument tout jusqu'� \parsestop
\expsecond\ifbracefirst{\gobone#1}% retire le \relax et teste si #1 commence par "{"
{\expandafter\read@bracearg@ii\gobone#1\parsestop}% lire l'argument entre accolades
{\expandafter\testtoken\gobone#1\parsestop}% sinon, tester le token
}
\def\read@bracearg@ii#1{% l'argument entre accolades est lu
\ifparse@group\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\begingroup% ouvre un groupe pour parser l'int�rieur de l'accolade
\def\parsestop@i{% red�finir localement \parsestop@i pour
\expandafter% retarde \endgroup
\endgroup% pour ajouter le contenu local de \code@toks entre accolades
\expandafter% au contenu de ce m�me registre avant le groupe
\parseadd
\expandafter
{\expandafter{\the\code@toks}}%
\expandafter\parse@i% puis va lire le token suivant
\gobone% apr�s avoir mang� le \parsestop
}%
\parse*#1\parsestop% <- le \parsestop@i fermera le groupe semi simple
}
{\parseadd{{#1}}% macro non �toil�e, on ajoute #1 tel quel entre accolades
\parse@i% puis va lire le token suivant
}%
}
\def\testtoken#1{% macro qui teste le token
\parseadd{#1}% ici, ne rien faire � part ajouter le token
\parse@i% aller lire le token suivant
}
\def\ifbracefirst#1{% teste si #1 commence par un token de catcode 1
\ifspacefirst{#1}% si #1 commence par un espace
{\secondoftwo}% renvoyer faux
{\ifnum
\catcode
\expandafter\expandafter\expandafter
`%
\expandafter
\firstto@nil\detokenize{#1W}\@nil=1
\expandafter\firstoftwo
\else
\expandafter\secondoftwo
\fi
}%
}
\def\grab@first#1#2{%
\ifx#1\empty\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\let#2\empty% si #1 est vide, ne rien faire et assigner <vide> � #2
}% si #1 n'est pas vide
{\def\arg@b{#2}% stocke la macro #2 dans \arg@b
\exparg\ifbracefirst#1% si le 1er token de #1 est "{"
{\expandafter\grab@arg#1\@nil#1% aller lire l'argument avec \grab@arg
}
{% sinon, d�velopper #1 avant de le regarder avec \futurelet :
\expandafter\futurelet\expandafter\nxttok\expandafter\test@nxttok#1\@nil#1%
% puis aller � \test@nxttok
}%
}%
}
\def\test@nxttok{% si le premier token de l'arg #1 de \grab@first est
\ifx\nxttok\sptoken% un espace
\expandafter\grab@spc% aller le lire avec \grab@spc
\else
\expandafter\grab@tok% sinon, lire le token avec \grab@tok
\fi
}
\def\grab@arg#1{% assigne l'argument de \grab@first (mis entre accolades)
\expandafter\def\arg@b{{#1}}% � #2
\assign@tonil\relax% puis, assigne le reste � #1 de \grab@first
}
\expandafter\def\expandafter\grab@spc\space{%
\expandafter\def\arg@b{ }% assigne un espace � #2 de \grab@first
\assign@tonil\relax% puis, assigne le reste � #1 de \grab@first
}
\def\grab@tok#1{%% assigne le premier token de l'arg #1 de \grab@first
\expandafter\def\arg@b{#1}% � la macro #2 de \grab@first
\assign@tonil\relax% puis, assigne le reste � #1 de \grab@first
}
% assigne tout ce qui reste � lire (moins le "\relax") � la macro
% #1 de \grab@first
\def\assign@tonil#1\@nil#2{\expsecond{\def#2}{\gobone#1}}
\def\ifstartwith#1#2{%
\def\startwith@code{#1}\def\startwith@pattern{#2}%
\ifempty{#2}
\firstoftwo% renvoyer vrai si #2 est vide
{\ifempty{#1}
\secondoftwo% renvoyer faux si #1 est vide et pas #2
\ifstartwith@i% dans les autres cas, aller � \ifstartwith@i
}%
}
\def\ifstartwith@i{%
\grab@first\startwith@code\first@code% extrait le premier "argument" de <code>
\grab@first\startwith@pattern\first@pattern% et celui de <motif>
\ifx\first@code\first@pattern% s'il sont �gaux
\expandafter\ifempty\expandafter{\startwith@pattern}
{\expandafter\firstoftwo}% et que <motif> ne contient plus rien => vrai
{\expandafter\ifempty\expandafter{\startwith@code}
{\expandafter\secondoftwo}% si <code> ne contient plus rien => faux
{\expandafter\ifstartwith@i}% sinon poursuivre les tests
}%
\else% s'ils ne sont pas �gaux
\expandafter\secondoftwo% renvoyer faux
\fi
}
\newif\ifin@group
\def\ifcontain{%
\ifstarred
{\in@groupfalse\ifcontain@i\ifcontain@star}%
{\ifcontain@i\ifcontain@nostar}%
}
\def\ifcontain@i#1#2#3{% #1 = macro � appeler selon �toile ou pas. #2 = code. #3 = motif
\def\main@arg{#2}\def\pattern@arg{#3}%
\ifempty{#3}%
\firstoftwo
{\ifempty{#2}
\secondoftwo
#1% aller � \ifcontain@star ou \ifcontain@nostar
}%
}
\def\ifcontain@nostar{%
\exptwoargs\ifstartwith\main@arg\pattern@arg
\firstoftwo% si motif est au d�but de code => vrai
{\expandafter\ifempty\expandafter{\main@arg}
\secondoftwo% sinon, si code est vide => faux
{\grab@first\main@arg\aux@arg% autrement, manger le 1er "argument" de code
\ifcontain@nostar% et recommencer
}%
}%
}
\def\ifcontain@star{%
\expandafter\ifbracefirst\expandafter{\main@arg}% si code commence par "{"
{\grab@first\main@arg\aux@arg% enlever {<sous code>} de main@arg
\begingroup% ouvrir un groupe
\in@grouptrue% mettre le bool�en � vrai
\expandafter\assign@main@arg\aux@arg\@nil% assigner "sous code" � \main@arg
\ifcontain@star% et recommencer avec ce nouveau \main@arg
}% si code ne commence pas par "{"
{\exptwoargs\ifstartwith\main@arg\pattern@arg% si motif est au d�but de code
\return@true% renvoyer vrai
{\expandafter\ifempty\expandafter{\main@arg}% si code est vide
{\ifin@group% et que l'on est dans un groupe
\endgroup \expandafter\ifcontain@star% en sortir et recommencer
\else% si on n'est pas dans un groupe, le code a �t� parcouru
\expandafter\secondoftwo% sans trouver <motif> => renvoyer faux
\fi
}% si code n'est pas vide
{\grab@first\main@arg\arg@code% manger le 1er "argument" de code
\ifcontain@star% et recommencer
}%
}%
}%
}
\def\return@true{%
\ifin@group% tant qu'on est dans un groupe
\endgroup \expandafter\return@true% en sortir et recommencer
\else
\expandafter\firstoftwo% sinon, renvoyer vrai
\fi
}
\def\forcemath#1{% compose #1 en mode math, quel que soit le mode en cours
\ifmmode\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{#1}{$#1$}%
}
\newcount\macro@cnt% num�ro � mettre dans le nom des sous macros
\newcount\arg@cnt% compte le nombre d'arguments
\newtoks\param@text% texte de param�tre des macros sous forme #x et/ou [#x]
\newtoks\arg@text% arguments sous forme {#x} et/ou [#x]
\def\newmacro#1{%
% stocke le nom de la macro et �ventuellement "@[<chiffre romain>]"
\def\macro@name##1{\expandafter\gobone\string#1\ifnum##1>0 @[\romannumeral##1]\fi}%
\macro@cnt=0 \arg@cnt=0 % initialise les compteurs
\param@text{}\arg@text{}% vide les registres de texte de param�tre et d'argument
\newmacro@i% va voir le prochain token
}
\def\newmacro@i{\futurelet\nxttok\newmacro@ii}% met le prochain token dans \nxttok...
% ...puis va � la macro :
\def\newmacro@ii{%
\ifx\nxttok[% si le prochain token est un crochet
\let\donext\newmacro@optarg% aller � \newmacro@optarg
\else
\ifx\nxttok\bgroup% si c'est un accolade ouvrante
% le texte de param�tre est fini et il faut d�finir la macro
\def\donext{%
\expandafter\def
\csname\macro@name\macro@cnt\expandafter\endcsname
\the\param@text}% <- code juste apr�s non encore lu
\else% sinon, c'est donc un chiffre
\let\donext\newmacro@arg% aller � \newmacro@arg
\fi
\fi
\donext% faire l'action d�cid�e ci-dessus
}
\def\newmacro@optarg[#1]{% lit la valeur par d�faut de l'argument optionnel
% d�finit la macro \<nom>@<nbre> qui lit tous les arguments (optionnels ou pas) jusqu'alors d�finis
% � l'aide de \param@text. Puis, elle testera si le prochain token est un crochet
\expandafter\edef\csname\macro@name\macro@cnt\expandafter\endcsname\the\param@text{%
\noexpand\ifnexttok[%
% si oui : la macro \<nom>@<nbr+1> le lira
{\expandafter\noexpand\csname\macro@name{\numexpr\macro@cnt+1}\expandafter\endcsname
\the\arg@text}%
% si non : transmettre � \<nom>@<nbr+1> l'argument optionnel par d�faut lu
{\expandafter\noexpand\csname\macro@name{\numexpr\macro@cnt+1}\expandafter\endcsname
\the\arg@text[\unexpanded{#1}]}%
}%
\advance\arg@cnt 1 % incr�menter le num�ro d'argument
% pour ajouter "[#<x>]" � \param@text et � \arg@text
\eaddtotoks\param@text{\expandafter[\expandafter##\number\arg@cnt]}%
\eaddtotoks\arg@text{\expandafter[\expandafter##\number\arg@cnt]}%
\advance\macro@cnt 1 % incr�menter le num�ro de nom de macro
\newmacro@i% va voir le token suivant
}
\def\newmacro@arg#1{% #1=nb arguments obligatoires � ajouter
% boucle qui ajoute "#<x>#<x+1>etc" dans \param@text
% et "{#<x>}{#<x+1>}etc" dans \arg@text
\ifnum#1>0 % tant qu'on n'a pas ajout� le nombre de #x n�cessaire
\advance\arg@cnt 1 % incr�menter le num�ro d'argument
% pour ajouter #x � \param@text et {#x} � \arg@text
\eaddtotoks\param@text{\expandafter##\number\arg@cnt}%
\eaddtotoks\arg@text{\expandafter{\expandafter##\number\arg@cnt}}%
\expandafter\newmacro@arg\expandafter{\number\numexpr#1-1\expandafter}% reboucler
\else% apr�s avoir rajout� e qu'il fallait � \param@text et � \arg@text
\expandafter\newmacro@i% lire le token suivant
\fi
}
% encadrement avec les r�glures o� l'on veut
\newmacro\framebox[ULRD]1{% #1 = ULRD (Up, Down, Right, Left)
% ne pas changer le mode H ou V en cours
\hbox{% enferme dans une \hbox
\uppercase{\ifin{#1}L}{\vrule width\frboxrule}{}% r�glure gauche
\vtop{%
\vbox{% 1er �l�ment de la \vtop
\uppercase{\ifin{#1}U}{% si la r�glure sup doit �tre trac�e
\hrule height\frboxrule% r�glure sup�rieure
\kern\frboxsep% espace haut
}
{}%
\hbox{%
\uppercase{\ifin{#1}L}{\kern\frboxsep}{}% espace gauche
#2% contenu
\uppercase{\ifin{#1}R}{\kern\frboxsep}{}% espace droite
}%
}% puis autres �l�ments de la \vtop, sous la ligne de base
\uppercase{\ifin{#1}D}{%
\kern\frboxsep% espace bas
\hrule height\frboxrule% r�glure inf�rieure
}%
{}%
}%
\uppercase{\ifin{#1}R}{\vrule width\frboxrule}{}% r�glure droite
}%
}
\def\retokenize#1{%
\immediate\openout\wtest=retokenize.tex % ouvre le fichier
\immediate\write\wtest{\unexpanded{#1}}% y �crit l'argument
\immediate\closeout\wtest% ferme le fichier
\input retokenize.tex % lit le fichier selon les catcodes en vigueur
\unskip% mange l'espace pr�c�demment ajout� qui provient de la fin du fichier
}
\newtoks\alter@toks% collecteur de tokens
\def\alter#1#2{% #1= d�limiteur #2 = macro alt�r�e
\let\alter@macro#2% sauvegarde la macro
\edef\alter@restorecatcode{% restaurera le catcode de #1
\catcode`\noexpand#1=\the\catcode`#1 }%
\edef\alter@tmp{\let\noexpand\alter@markertoks= \string#1}%
\alter@tmp% et sauvegarder le d�limiteur apr�s avoir mis son catcode � 12
\edef\alter@tmp{\def\noexpand\alter@readlitterate@i\string#1####1\string#1}%
% d�veloppe les \string#1 pour que les arguments d�limit�s aient
% des d�limiteurs de catcode 12
\alter@tmp{% <- comme si on �crivait "\def\alter@readlitterate@i#1##1#1"
\endgroup% apr�s avoir lu ##1 (tokens rendus inoffensifs), fermer le groupe
\addtotoks\alter@toks{{\tt##1}}% ajouter ces tokens
\alter@i% et aller lire le prochain token
}%
\alter@toks{}% initialise le collecteur de tokens
\afterassignment\alter@i% aller lire le premier token apr�s avoir
\let\alter@tmptok= % mang� l'accolade ouvrante de l'argument qui suit
}
\def\alter@i{% lit le prochain token et va � \alter@ii
\futurelet\alter@nxttok\alter@ii}
\def\alter@ii{%
% teste le token qui doit �tre lu (car \futurelet ne l'a pas mang�)
\ifx\alter@nxttok\egroup% si la fin va �tre atteinte
\let\alter@next\alter@stop% aller � \alterstop@i
\else
\ifx\alter@nxttok\@sptoken% si un espace va �tre lu
\let\alter@next\alter@readspc% aller � \alter@readspc
\else
\ifx\alter@nxttok\bgroup% si une accolade ouvrante av �tre lue
\let\alter@next\alter@readarg% aller � \alter@readarg
\else
\ifx\alter@nxttok\alter@markertoks% si le d�limiteur va �tre lu
\let\alter@next\alter@readlitterate% aller � \alter@readlitterate
\else
\let\alter@next\alter@readtok% dans les autres cas, aller � \alter@readtok
\fi
\fi
\fi
\fi
\alter@next% faire l'action d�cid�e ci-dessus
}
\def\alter@readlitterate{%
% le prochain token est le d�limiteur
\begingroup% ouvrir un groupe
\for\alter@tmp=0to255\do{\catcode\alter@tmp=12 }%
% mettre tous les catcodes � 12
\defactive{ }{\ }% sauf l'espace
\doforeach\alter@tmp\in{<,>,-,`,{,},'}% pour chaque motif de ligature
{\unless\if\alter@tmp\alter@markertoks% s'il est diff�rent du d�limiteur
% le d�finir pour �viter la ligature
\expandafter\alter@defligchar\alter@tmp
\fi
}%
\alter@readlitterate@i% puis aller � \alter@readlitterate@i...
% ...qui a �t� d�finie dans \alter
}
\def\alter@defligchar#1{% d�finit le caract�re pour ne pas provoquer de ligature
\defactive#1{\string#1{}}%
}
\expandafter\def\expandafter\alter@readspc\space{% \alter@readspc mange un espace dans le code
\addtotoks\alter@toks{ }% ajoute l'espace
\alter@i% puis lire le token suivant
}
\def\alter@readarg{%
% le token qui suit est "{"
\begingroup% ouvrir un groupe
\def\alterstop@ii{% et modifier localement la macro appel�e � la toute fin,
% apr�s que l'accolade fermante ait �t� mang�e (par \alterstop@i)
\expandafter\endgroup% retarder la fermeture de groupe ouvert ci-dessus
\expandafter\addtotoks\expandafter\alter@toks\expandafter
{\expandafter{\the\alter@toks}}%
% pour ajouter hors du groupe ce qui a �t� collect� � l'int�rieur,
% le tout mis entre accolades
\alter@i% puis, lire le token suivant
}%
\alter@toks{}% au d�but du groupe, initialiser le collecteur
\afterassignment\alter@i% aller lire le prochain token apr�s
\let\alter@tmptok= % avoir mang� l'accolade ouvrante
}
\def\alter@readtok#1{%
% le prochain token n'est pas un token demandant une action sp�ciale
\addtotoks\alter@toks{#1}% l'ajouter au collecteur
\alter@i% et aller lire le token suivant
}
\def\alter@stop{%
% le token � lire est "}"
\afterassignment\alterstop@ii% aller � \alterstop@ii apr�s
\let\alter@tmptok= % avoir mang� l'accolade fermante
}
\def\alterstop@ii{%
% donner � la macro #2 de \alter tout ce qui a �t� r�colt�
\expandafter\alter@macro\expandafter{\the\alter@toks}%
\alter@restorecatcode% puis restaure le catcode du d�limiteur
}
\newdimen\pixelsize
\newdimen\pixelsep
\pixelsize=.9pt \pixelsep=0pt
\def\pixel{\vrule height\pixelsize width\pixelsize}
\def\blankpixel{\vrule height\pixelsize width0pt \vrule height0pt width\pixelsize}
\def\vblankpixel{\vrule height\pixelsize width0pt}
\def\gap{\kern\pixelsep}
\newskip\letter@skip
\begingroup% dans ce groupe :
\expandafter\gdef\csname impact@" "\endcsname{\hskip4\pixelsize plus0.5\pixelsize minus0.5\pixelsize\relax}%
\catcode`\^^M=13\relax% le retour � la ligne est actif
\edef^^M{\string,}% et se d�veloppe en une virgule (de catcode 12)
\catcode`\ =12\relax% l'espace devient un "caract�re autre"
\global\deftok\otherspc{ }% d�finit un espace de catcode 12
\gdef\impact@alphabet{
a/
***
*
***
* *
****,
a`/
*
*
***
*
***
* *
****,
b/
*
*
***
* *
* *
* *
***,
c/
***
*
*
*
***,
d/
*
*
***
* *
* *
* *
***,
e/
**
* *
***
*
***,
e'/
*
*
**
* *
***
*
***,
e^/
*
* *
**
* *
***
*
***,
e`/
*
*
**
* *
***
*
***,
f/
**
*
***
*
*
*
*,
g/
***
* *
* *
* *
***_
*
**,
h/
*
*
*
***
* *
* *
* *
* *,
i/
*
*
*
*
*
*,
j/
*
*
*
*
*
*_
*
**,
k/
*
*
* *
* *
**
* *
* *,
l/
*
*
*
*
*
*
*,
m/
** *
* * *
* * *
* * *
* * *,
n/
***
* *
* *
* *
* *,
o/
**
* *
* *
* *
**,
o^/
*
* *
**
* *
* *
* *
**,
p/
***
* *
* *
* *
***_
*
*,
q/
***
* *
* *
* *
***_
*
*,
r/
* **
**
*
*
*,
s/
***
*
**
*
***,
t/
*
*
**
*
*
*
**,
u/
* *
* *
* *
* *
***,
u`/
*
*
* *
* *
* *
* *
***,
v/
* *
* *
* *
* *
*,
w/
* *
* *
* * *
* * *
* *,
x/
* *
* *
*
* *
* *,
y/
* *
* *
* *
**
*_
*
**,
z/
****
*
*
*
****,
TEX/
***** * *
* * *
* * *
* ***** *
* * * *
* * * *
* *** * *_
*
*
*****,
A/
***
* *
* *
* *
*****
* *
* *,
B/
***
* *
* *
****
* *
* *
****,
C/
****
*
*
*
*
*
****,
D/
****
* *
* *
* *
* *
* *
****,
E/
*****
*
*
***
*
*
*****,
F/
*****
*
*
***
*
*
*,
G/
***
* *
*
* **
* *
* *
***,
H/
* *
* *
* *
*****
* *
* *
* *,
I/
*
*
*
*
*
*
*,
J/
*
*
*
*
*
* *
**,
K/
* *
* *
* *
**
* *
* *
* *,
L/
*
*
*
*
*
*
****,
M/
* *
** **
* * *
* * *
* *
* *
* *,
N/
* *
** *
** *
* * *
* **
* **
* *,
O/
***
* *
* *
* *
* *
* *
***,
P/
****
* *
* *
****
*
*
*,
Q/
***
* *
* *
* *
* * *
* **
***,
R/
****
* *
* *
****
* *
* *
* *,
S/
***
* *
*
*
*
* *
***,
T/
*****
*
*
*
*
*
*,
U/
* *
* *
* *
* *
* *
* *
***,
V/
* *
* *
* *
* *
* *
* *
*,
W/
* *
* *
* *
* *
* * *
** **
* *,
X/
* *
* *
* *
*
* *
* *
* *,
Y/
* *
* *
* *
*
*
*
*,
Z/
*****
*
*
*
*
*
*****,
?/
***
* *
*
*
*
*,
!/
*
*
*
*
*
*,
'/
*
*
,
/
*,
{,}/
*_
*,
1/
*
**
* *
*
*
*
*,
2/
***
* *
*
*
*
*
*****,
3/
***
* *
*
**
*
* *
***,
4/
*
**
* *
* *
*****
*
*,
5/
*****
*
****
*
*
*
****,
6/
***
*
*
****
* *
* *
***,
7/
*****
*
*
*
*
*
*,
8/
***
* *
* *
***
* *
* *
***,
9/
***
* *
* *
****
*
*
***,
0/
***
* *
* *
* * *
* *
* *
***,
@/
**
* *
* **
* * *
* *
* *
***,
error/
* * *
* *
* * *
* *
* * *
* *
* * *}%
\endgroup%
\def\makecar#1#2{% #1=nom recevant le code final #2=macro contenant le dessin
\let\pixabove\empty \let\pixbelow\empty \let\pix@line\empty% initialise � vide
\exparg\ifin{#2}_% si le code contient _
{\expandafter\makecar@iii#2\@nil}% aller � \makecar@iii
{\exparg\makecar@i{#2}}% sinon, � \makecar@i
\edef#1{% d�finit la macro #1 comme
\vtop{% une \vtop contenant :
\unexpanded{\offinterlineskip\lineskip\pixelsep}% r�glage d'espace inter ligne
\vbox{\unexpanded\expandafter{\pixabove}}% \vbox des pixels au-dessus
% de la ligne de base
\unless\ifx\pixbelow\empty% s'il y a des pixels au-dessous de la baseline
\unexpanded\expandafter{\pixbelow}% les ajouter dans la \vtop
\fi
}%
}%
}
\def\makecar@i#1{% #1 = dessin de la lettre avec les caract�res "," "*" et " "
\doforeach\current@line\in{#1}% pour chaque ligne dans #1 :
{\ifx\empty\current@line% si la ligne est vide
\addtomacro\pixabove{\hbox{\vblankpixel}}% ajouter une fausse ligne
\else% sinon
\let\pix@line\empty% initialiser le code de la ligne � vide
\expandafter\makecar@ii\current@line\quark% et la construire
\fi
}%
}
\def\makecar@ii#1{% #1=caract�re de dessin de la ligne en cours
\ifxcase#1% si le caract�re est
* {\addtomacro\pix@line\pixel}%
\otherspc{\addtomacro\pix@line\blankpixel}%
\endif
\ifx#1\quark% si la fin est atteinte
\addtomacro\pix@line\unkern% annuler le dernier espace interpixel
\eaddtomacro\pixabove{% et encapsuler \pix@line dans une \hbox
\expandafter\hbox\expandafter{\pix@line}}%
\else% si la fin n'est pas atteinte, ajouter l'espace interpixel
\addtomacro\pix@line\gap%
\expandafter\makecar@ii% recommencer avec le caract�re suivant
\fi
}
\def\makecar@iii#1_,#2\@nil{%
\makecar@i{#2}% construit la partie au-dessous de la baseline
\let\pixbelow\pixabove% et affecte le code � \pixbelow
\let\pixabove\empty \let\pix@line\empty% r�-initialise
\makecar@i{#1}% construit la partie au-dessus de la baseline
}
% On parcourt le texte de remplacement de \impact@alphabet
\edef\saved@crcatcode{\catcode13=\the\catcode13\relax}%
\catcode`\^^M=13\relax% le retour � la ligne est actif
\edef^^M{\string,}% et se d�veloppe en une virgule (de catcode 12)
\expsecond{\doforeach\letter@name/\letter@code\in}\impact@alphabet%
{\edef\letter@name{\letter@name}% d�veloppe la lettre (^^M devient ",")
\edef\letter@code{\letter@code}% d�veloppe le code (^^M devient ",")
\exparg\ifstart\letter@name,% si la lettre commence par ","
{\edef\letter@name{\expandafter\gobone\letter@name}}% la retirer
{}%
\exparg\ifstart\letter@code,% si le code commence par ","
{\edef\letter@code{\expandafter\gobone\letter@code}}% la retirer
{}%
\expandafter\makecar\csname impact@"\letter@name"\endcsname\letter@code%
}%
\saved@crcatcode% redonne le catcode de ^^M
\def\end@process{\end@process}%
\def\impactend{\endgroup}
\newmacro\impact[0.2ex][0pt]{%
\begingroup
\pixelsize#1 \pixelsep#2
\letter@skip=#1 plus.1pt minus.1pt
\catcode`\!12 \catcode`\?12
\impact@i
}
\def\impact@i{\futurelet\nxtletter\impact@ii}
\def\impact@ii{%
\ifx\nxtletter\impactend
\let\next\unskip
\else
\leavevmode
\ifx\nxtletter\sptoken
\let\next\impact@spc
\else
\let\next\impact@arg
\fi
\fi
\next
}
\expandafter\def\expandafter\impact@spc\space{%
\csname impact@" "\endcsname
\impact@i
}
\def\impact@arg#1{%
\ifcsname impact@"#1"\endcsname
\csname impact@"#1"\endcsname
\else
\csname impact@"error"\endcsname
\fi
\hskip\letter@skip
\impact@i
}
\newdimen\maingraddim \maingraddim=4pt
\newdimen\maingradwd \maingradwd=0.5pt
\newdimen\subgraddim \subgraddim=2.5pt
\newdimen\subgradwd \subgradwd=0.2pt
\newdimen\axiswd \axiswd=0.5pt
\newdimen\plotincrement \plotincrement=0.1pt
\newdimen\tmpdim
\def\maingradx#1{%
\lower1.5ex\clap{$\scriptscriptstyle#1$}% afficher l'argument au dessous
\clap{\vrule height\maingraddim width\maingradwd depth0pt }% et la r�glure
}
\def\subgradx{\clap{\vrule height\subgraddim width\subgradwd depth0pt }}
% #1= dim entre 2 grad principales #2=nb d�part #3=incr�ment #4=nb arriv�e #4=nb intervalles secondaires
\newmacro\xaxis[1cm]1[1]1[4]{%
\hbox{% tout mettre dans une \hbox
\setbox0=\hbox{% stocke dans une \hbox les grad secondaires entre 2 unit�s
\edef\dimsubgrad{\the\dimexpr#1/#5\relax}% dimension entre 2 subdivisions
\for\xx=1 to #5-1 \do{% ins�rer #5-1 fois
\kern\dimsubgrad% une espace secondaire
\subgradx% une graduation secondaire
}%
}%
\rlap{% en d�bordement � droite :
\FOR\xx = #2 to #4 \do #3{% pour chaque graduation principale
\maingradx{\xx}% imprimer l'abscisse
\ifdim\xx pt<#4pt % et en d�bordement � droite,
\rlap{\copy0 }% les r�glures secondaires, sauf pour la derni�re
\fi
\kern#1\relax% se d�placer vers la droite
}%
}%
\vrule% tracer l'axe des abscisses
height\axiswd% d'epaisseur \axiswd, de longueur #1*(#4-#2)/#3
width\dimexpr#1*\decdiv{\dimtodec\dimexpr#4pt-#2pt\relax}{#3}\relax
depth 0pt\relax % et de profondeur nulle
}%
}
\def\maingrady#1{% affiche...
\vlap{\llap{$\scriptscriptstyle#1$\kern2pt }}% l'ordonn�e...
\vbox to0pt{\vss\hrule height\maingradwd width\maingraddim depth0pt }% et la r�glure
}
% affiche une subdiv
\def\subgrady{\vlap{\hrule height\subgradwd width\subgraddim depth0pt }}
% #1= dim entre 2 grad principales #2=abscisse d�part #3=incr�ment
% #4=abscisse arriv�e #5=nb intervalles secondaires
\newmacro\yaxis[1cm]1[1]1[4]{%
\vbox{%
\offinterlineskip% d�sactiver le ressort interligne
\setbox0=\vbox{% stocke dans une \hbox les grad secondaires entre 2 unit�s
\edef\dimsubgrad{\the\dimexpr#1/#5\relax}% dimension entre 2 subdivisions
\for\xx=1 to #5-1 \do{% ins�rer #5-1 fois
\kern\dimsubgrad% une espace secondaire
\subgrady% une graduation secondaire
}%
}%
\edef\dimsubgrad{\the\dimexpr#1/#5\relax}% distance entre 2 subdivisions
\vbox to 0pt{% en d�bordement vers le bas
\FOR\xx = #4to#2\do-#3{%
\maingrady{\xx}% imprimer l'abscisse
\ifdim\xx pt>#2pt % et en d�bordement � droite,
\vbox to 0pt{\copy0 \vss}% les r�glures secondaires, sauf pour la derni�re
\fi
\kern#1\relax% se d�placer vers la droite
}%
\vss% assure le d�bordement vers le bas
}%
\clap{\vrule% tracer l'axe des abscisses
width\axiswd% d'�paisseur \axiwd, et de hauteur (#4-#2)/#3*#1
height\decdiv{\dimtodec\dimexpr(#4pt-#2pt)\relax}{#3}\dimexpr#1\relax
depth 0pt\relax % profondeur nulle
}
}%
}
\newdimen\xunit \xunit=1cm
\newdimen\yunit \yunit=1cm
\newmacro\graphzone1[1]1[4]1[1]1[4]{%
\quitvmode
\begingroup
\def\graphxmin{#1}\def\graphxmax{#3}%
\def\graphymin{#5}\def\graphymax{#7}%
\def\xincrement{#2}\def\yincrement{#6}%
\setbox0\hbox{\yaxis[\yunit]{#5}[#6]{#7}[#8]}%
\setbox1\hbox{\xaxis[\xunit]{#1}[#2]{#3}[#4]}%
\edef\graphboxht{\the\ht0 }%
\edef\graphboxwd{\the\wd1 }%
\rlap{\box1 \clap{\vrule height\dimexpr\graphboxht+\axiswd\relax width\axiswd depth0pt }}%
\rlap{\box0 }%
\raise\graphboxht\rlap{\kern-.5\axiswd\vrule height\axiswd width\dimexpr\graphboxwd+\axiswd}%
\begingroup
\catcode`\^^M=9\relax
\graphzone@i
}
\def\graphzone@i#1{%
\endgroup
\xunit=\decdiv1\xincrement\xunit
\yunit=\decdiv1\yincrement\yunit
\setbox0\hbox{#1}%
\wd0=\dimexpr\graphboxwd+\axiswd\relax
\ht0=\dimexpr\graphboxht+\axiswd\relax
\box0
\endgroup
\ignorespaces
}
\def\plot(#1,#2){%
\edef\x@plot{#1}\edef\y@plot{#2}%
\ifinside\x@plot[\graphxmin,\graphxmax]%
{\ifinside\y@plot[\graphymin,\graphymax]%
{\putat{\dimexpr\x@plot\xunit-\graphxmin\xunit\relax}{\dimexpr\y@plot\yunit-\graphymin\yunit\relax}\plotstuff}%
\relax
}
\relax
}
\def\showyaxis{%
\ifinside0[\graphymin,\graphymax]%
{\putat\z@{-\graphymin\yunit}{\vrule width\graphboxwd height\axiswd}}%
\relax
}
\def\showxaxis{%
\ifinside0[\graphxmin,\graphxmax]%
{\putat{-\graphxmin\xunit}\z@{\clap{\vrule width\axiswd height\graphboxht}}}%
\relax
}
\def\showaxis{\showxaxis\showyaxis}
\def\putat#1#2#3{%
\leavevmode\rlap{\kern#1\vbox to0pt{\vss\hbox{#3}\kern#2}}%
}
\newmacro\cross[2pt][0.2pt]{%
\quitvmode
\vlap{%
\clap{%
\vrule height#2 depth0pt width#1
\vrule height#1 depth#1 width#2
\vrule height#2 depth0pt width#1
}%
}%
}
\protected\def\numsep{\kern0.2em }% \numsep est le s�parateur mis tous les 3 chiffres
\def\formatdecpart#1{% #1=s�rie de chiffres
\ifempty{#1}% si la partie d�cimale est vide
{}% ne rien afficher
{{,}\formatdecpart@i1.#1..}% sinon, afficher la virgule et mettre en forme
}
% #1=compteur de caract�res #2= chiffre � d�placer
% #3= chiffres restants #4 = chiffres d�j� trait�s
\def\formatdecpart@i#1.#2#3.#4.{% #1=compteur de caract�res #2= chiffres trait� #3= chiffres trait�s
\ifempty{#3}% si #2 est le dernier chiffre � traiter
{#4#2}% le mettre en derni�re position et tout afficher, sinon
{\ifnum#1=3 \expandafter\firstoftwo
\else\expandafter\secondoftwo
\fi% si 3 chiffres sont atteint, rendre #1 �gal � 1 et
{\formatdecpart@i 1.#3.#4#2\numsep.}% mettre #2\numsep en dernier puis recommencer
% sinon, mettre #2 en derni�re position et recommencer
% tout en incr�mentant #1 de 1
{\expandafter\formatdecpart@i\number\numexpr#1+1.#3.#4#2.}%
}%
}
\def\formatintpart#1{% #1=s�rie de chiffres
\expandafter\formatintpart@i\expandafter1\expandafter.%
\romannumeral\reverse{#1\z@}..% appelle la macro r�cursive
}
% #1=compteur de caract�res #2= chiffre � d�placer
% #3= chiffres restants #4 = chiffres d�j� trait�s
\def\formatintpart@i#1.#2#3.#4.{% #1=compteur de caract�res #2= chiffres trait� #3= chiffres trait�s
\ifempty{#3}% si #2 est le dernier chiffre � traiter
{#2#4}% le mettre en premi�re position et tout afficher, sinon
{\ifnum#1=3 \expandafter\firstoftwo
\else\expandafter\secondoftwo
\fi% si 3 chiffres sont atteint, rendre #1 �gal � 1 et
{\formatintpart@i 1.#3.\numsep#2#4.}% mettre \numsep#2 en premier puis recommencer
% sinon, mettre #2 en derni�re position et recommencer
% tout en incr�mentant #1 de 1
{\expandafter\formatintpart@i\number\numexpr#1+1.#3.#2#4.}%
}%
}
\def\removefirstzeros#1{%
\removefirstzeros@i#1\removefirstzeros@i
}
\def\removefirstzeros@i#1{%
\ifx\removefirstzeros@i#1% \removefirstzeros@i est lu donc tout le nombre a �t� parcouru
\expandafter0% laisser un z�ro
\else
\ifx0#1% si le chiffre lu est un 0
\expandafter\expandafter\expandafter\removefirstzeros@i% recommencer
\else% sinon remettre le chiffre et tout afficher jusqu'� \removefirstzeros@i
\expandafter\expandafter\expandafter\removefirstzeros@ii\expandafter\expandafter\expandafter#1%
\fi
\fi
}
\def\removefirstzeros@ii#1\removefirstzeros@i{#1}
\def\ifnodecpart#1{\ifnodecpart@i#1.\@nil}
\def\ifnodecpart@i#1.#2\@nil{\ifempty{#2}}
\newbox\remainbox% boite contenant le texte total
\newbox\currentline% boite contenant le ligne en cours
\newcount\linecnt% compteur pour num�roter les lignes
\newmacro\leftline[0pt]{% d�finit ce qui se trouve � gauche de chaque ligne
\def\wd@left{#1}%
\def\stuff@left
}
\newmacro\rightline[0pt]{% d�finit ce qui se trouve � droite de chaque ligne
\def\wd@right{#1}%
\def\stuff@right
}
\let\formatline=\identity
\leftline[15pt]{$\scriptscriptstyle\number\linecnt$\kern5pt }% num�rotation � gauche
\rightline{}% rien � droite
\def\numlines{%
\par\smallskip
\begingroup% dans un groupe semi simple
\splittopskip=0pt % ne rajouter aucun espace au sommet de la boite restante
\savingvdiscards=1 % autorise la sauvagarde des �l�ments supprim�s
\linecnt=0 % initialiser le compteur de lignes
\setbox\remainbox=\vbox\bgroup% compose la boite...
\advance\hsize by% diminuer la \hsize
-\dimexpr\wd@left+\wd@right\relax% de la largeur des contenus
}
\def\endnumlines{%
\egroup
\offinterlineskip
\split@line
}
\def\split@line{%
\ifvoid\remainbox% si la boite est vide
\par% fin du processus
\endgroup% fermer le groupe ouvert au d�but
\else% sinon
\advance\linecnt 1 % incr�mente le compteur de lignes
\edef\htbefore{\the\vdim\remainbox}%
\edef\restorevfuzz{\vfuzz=\the\vfuzz\relax}% sauvegarde le \vfuzz
\vfuzz=\maxdimen% annule les avertissements pour d�bordement
\setbox\currentline=\vsplit\remainbox to 0pt % couper la boite � 0pt de hauteur
\restorevfuzz
\setbox\currentline=\vbox{\unvbox\currentline}% redonner � la boite sa hauteur
\let\savedsplitdiscards\splitdiscards
\edef\intersplitspace{% calcul de l'espace vertical perdu � la coupure
\the\dimexpr\htbefore-(\vdim\remainbox+\vdim\currentline)\relax
}%
\hbox{% en mode vertical et dans une hbox, afficher :
\hbox to\wd@left{\hss\stuff@left}% 1) ce qui est � gauche
\formatline{\box\currentline}% 2) la ligne courante
\hbox to\wd@right{\stuff@right\hss}% 3) ce qui est � droite
}%
\splitdiscards% affiche ce qui a �t� ignor� � la coupure
\expandafter\split@line% recommencer
\fi
}
\newskip\interletterskip
\newskip\interwordskip
\catcode`\@11
\newtoks\spacetxt@toks% le registre qui contient le texte final
\def\spacetxt{%
\let\spacetxt@endprocess\spacetxt@endnormal
% d�finit la macro appel�e en fin de processus -> � priori : fin normale
\ifstarred% si la macro est �toil�e
{\let\spacetxt@recurse\spacetxt@star% d�finir la macro r�cursive
\spacetxt@i% et aller � \spacetxt@i
}% sinon
{\let\spacetxt@recurse\spacetxt@nostar% d�finir la macro r�cursive
\spacetxt@i% et aller � \spacetxt@i
}%
}
\newmacro\spacetxt@i[0.3em][3\interletterskip]1{%
% arg optionnel #1 et #2 = ressorts inter-lettre et inter--mot
% #3 = texte � espacer
\interletterskip=#1\relax
\interwordskip=#2\relax
\def\spacetxt@code{#3}% met le texte � espacer dans \spacetxt@code
\spacetxt@toks{}% initialiser le registre contenant le texte final
\spacetxt@recurse% aller � la macro r�cursive pr�c�demment d�finie
}
\newif\if@indivifound% bool�en qui sera vrai si un motif sp�cial est rencontr�
\def\spacetxt@nostar{%
\expandafter\ifempty\expandafter{\spacetxt@code}% si texte restant est vide
\spacetxt@endprocess% aller � la fin du processus
{\@indivifoundfalse% sinon, � priori, les motifs non r�guliers ne sont pas trouv�s
\expandafter\doforeach\expandafter\indivi@tmp\expandafter\in\expandafter{\indivilist}
% pour chaque \indivi@tmp dans \indivilist
{\exptwoargs\ifstartwith\spacetxt@code\indivi@tmp
% si le code commence par le motif courant
{\eaddtotoks\spacetxt@toks{\indivi@tmp\hskip\interletterskip}%
% l'ajouter dans le registre ainsi que l'espace inter-lettre
\expandafter\rightofsc\expandafter\spacetxt@code\expandafter{\indivi@tmp}%
% et enlever le motif du texte restant � lire
\@indivifoundtrue
% marquer qu'un motif a �t� trouv�
\doforeachexit
% et sortir pr�matur�ment de la boucle
}%
\relax
% si le code ne commence pas le motif courant -> ne rien faire
}%
\if@indivifound
\else% si aucun motif n'a �t� trouv�
\grab@first\spacetxt@code\spacetxt@temp
% retirer le 1er caract�re du texte
% \ifcat\noexpand\spacetxt@temp\sptoken
\ifx\spacetxt@temp\space
% si le 1er caract�re est un espace
\addtotoks\spacetxt@toks{\hskip\interwordskip}%
% ajouter l'espace inter-mot au registre de token
\else
% si le 1er caract�re n'est pas un espace
\eaddtotoks\spacetxt@toks{\spacetxt@temp\hskip\interletterskip}%
% ajouter ce caract�re et l'espace inter-lettre au registre de token
\fi
\fi
\spacetxt@recurse% enfin, continuer le processus
}%
}
\def\spacetxt@star{%
\expandafter\ifempty\expandafter{\spacetxt@code}% si texte restant est vide
\spacetxt@endprocess% aller � la fin du processus
{\expandafter\ifbracefirst\expandafter{\spacetxt@code}%
% sinon, si texte commence par "{"
{\grab@first\spacetxt@code\spacetxt@temp
% mettre {<argument} dans \spacetxt@temp
\begingroup% ouvrir un groupe
\expandafter\def\expandafter\spacetxt@code\spacetxt@temp
% mettre le contenu de l'argument dans \spacetxt@code
\let\spacetxt@endprocess\spacetxt@endingroup% changer le processus de fin
\spacetxt@toks{}% initialiser
\spacetxt@recurse% ex�cuter le processus avec ce nouveau texte
}% si le code ne commence pas par "{", aller � \spacetxt@nostar mais comme
\spacetxt@nostar% \spacetxt@recurse vaut \spacetxt@star, n'y faire qu'1 boucle
}%
}
\def\spacetxt@endnormal{% fin de processus normal
\the\spacetxt@toks% afficher le registre � token
\unskip% et supprimer le dernier ressort
}
\def\spacetxt@endingroup{% fin du processus dans un groupe :
\expandafter\endgroup\expandafter% avant de fermer le groupe
\addtotoks\expandafter\spacetxt@toks\expandafter% ajouter au registre hors du groupe
{\expandafter{\the\spacetxt@toks}}% ce qui est collect� localement mis entre {}
\spacetxt@recurse% puis aller � la macro r�cursive
}
\def\indivilist{<<,>>}% liste des motifs sp�ciaux
\def\insert@blankchar{%
\ifstarred\insert@blankchar@ii\insert@blankchar@i
}
\def\insert@blankchar@i#1{% ins�re une espace de largeur #1 caract�res complets
\ifnum\numexpr#1\relax>0
\kern\numexpr#1\relax\dimexpr\ttchar@width+\brktt@interletter\relax
\fi
}
\def\insert@blankchar@ii#1{% ins�re #1-1 caract�res complets + 1 largeur de caract�re
\ifnum\numexpr#1\relax>0
\insert@blankchar@i{#1-1}\kern\ttchar@width
\fi
}
\def\restart@hbox#1{%
\egroup
\hbox\bgroup
\expsecond{\def\tt@remaintext}
{\romannumeral\removefirstspaces@i{#1}}% initialiser le code � composer
\let\previous@char\space% initialise le caract�re pr�c�dent
\line@starttrue% aucun caract�re n'a encore �t� imprim�
\brktt@cnt=0\relax% remettre le compteur � 0
}
\def\print@nchar#1{% affiche #1 caract�res pris dans \tt@remaintext
\for\xxx= 1 to #1 \do 1{%
\ifx\tt@remaintext\empty% si le code restant � composer est vide
\exitfor\xxx%sortir de la boucle pr�matur�ment
\else
\@indivifoundfalse% sinon, � priori, les motifs de ligature ne sont pas trouv�s
% pour chaque \indivi@tmp dans la liste de ligatures
\expsecond{\doforeach\indivi@tmp\in}{\liglist}%
{% si le code commence par la \idx{ligature} courante
\exptwoargs\ifstartwith\tt@remaintext\indivi@tmp%
{\let\previous@char\indivi@tmp% prendre le motif pour caract�re courant
\expsecond{\rightofsc\tt@remaintext}{\indivi@tmp}% et l'enlever du texte restant � lire%
\@indivifoundtrue% marquer qu'un motif a �t� trouv�
\doforeachexit% et sortir pr�matur�ment de la boucle
}%
{}% si le code ne commence pas le motif courant -> ne rien faire
}%
\unless\if@indivifound% si aucun motif trouv�,
\grab@first\tt@remaintext\previous@char% lire le premier caract�re
\fi
\advance\brktt@cnt by 1 % incr�menter le compteur de caract�res
\hbox to\ttchar@width{\hss\previous@char\hss}% afficher le caract�re lu
\line@startfalse% nous ne sommes plus au d�but d'une ligne
\ifnum\brktt@cnt<\maxchar@num\relax% si la ligne n'est pas encore remplie
\kern\brktt@interletter% ins�rer le ressort inter-lettre
\else
\exitfor\xxx% sinon, sortir de la boucle pr�matur�ment
\fi
\fi
}%
}
\newmacro\breakttA[0.3em][\hsize]1{%
% arg optionnel #1 et #2 = ressorts inter-lettre et dimension horizontale texte
% #3 = texte � espacer
\begingroup% ouvrir un groupe et le fermer � la toute fin
\par% commencer un nouveau paragraphe -> passage en mode vertical
\parindent=0pt% emp�che l'indentation
\tt% passer en police � chasse fixe
\setbox0 = \hbox{M}% la boite 0 contient un caract�re
\edef\ttchar@width{\the\wd0 }% largeur de chaque caract�re en police \tt
\edef\text@width{\the\dimexpr#2\relax}% largeur de composition
% les 2 lignes suivantes rendent le compteur �gal � E((L-l)/(l+Delta))
\brktt@cnt=\numexpr\dimexpr#2-\wd0 \relax\relax% largeur diminu�e du 1er caract�re
\divide\brktt@cnt by \numexpr\dimexpr\wd0 + #1 \relax\relax
% le nombre de caract�res par ligne est �gal � 1 de plus :
\edef\maxchar@num{\number\numexpr\brktt@cnt+1\relax}%
% calcul de la dimension inter-lettre
\brktt@interletter=\dimexpr(\text@width-\ttchar@width*\maxchar@num)/\brktt@cnt\relax
\expsecond{\expsecond{\def\tt@remaintext}}{\removetrailspaces{#3}}% met le texte � espacer dans \tt@remaintext
\addtomacro\tt@remaintext{ \relax}% ajouter " \relax" � la fin : le code finit donc par " \relax"
\def\tt@emptytext{ \relax}% sera le code lorsque tout est compos�
\unless\ifx\tt@remaintext\tt@emptytext% si le texte � composer n'est pas vide
\hbox\bgroup% d�marrer la boite horizontale contenant la premi�re ligne
\insert@blankchar\ttindent% ins�rer une espace d'indentation de longueur (l+Delta')*\ttindent
\brktt@cnt=\ttindent\relax% tenir compte du nombre de caract�res indent�s
\line@starttrue% il s'agit du d�but d'une ligne
\expandafter\breakttA@i% aller � la macro r�cursive
\fi
}
\def\leftofsc#1#2{% dans la sc #1, garde ce qui est � gauche de #2
\def\leftofsc@i##1#2##2\@nil{\def#1{##1}}%
\expandafter\leftofsc@i#1\@nil
}
\def\len@tonextword{% stocke dans \next@len le nombre de caract�res avant
% le prochain point de coupure dans \tt@remaintext
\let\next@word\tt@remaintext% copie \tt@remaintext dans la macro temporaire \next@word
\leftofsc\next@word{ }% ne prend que ce qui est avant le prochain espace
\exparg\ifin{\next@word}{-}% si le mot contient un tiret
{\leftofsc\next@word{-}% prendre ce qui est � gauche de ce tiret
\def\extra@char{1}% il y a un caract�re de plus � loger apr�s le mot
}
{% sinon, le caract�re apr�s le mot est un espace
\def\extra@char{0}% qu'il ne faut pas compter
}%
\setbox0=\hbox{\next@word}% enfermer le mot dans une boite
% et en calculer le nombre de caract�res
\edef\next@len{\number\numexpr\dimexpr\wd0 \relax/\dimexpr\ttchar@width\relax\relax}%
}
\newmacro\zerocompose[]2{%
% #1=code � ex�cuter avant la composition
% #2=registre de boite recevant le r�sultat
% #3= texte � composer en largeur 0pt
\setbox#2=\vbox{%
#1% code a ex�cuter (changement de fonte par exemple)
\hfuzz=\maxdimen% annule les avertissements pour d�bordement horizontaux
\hbadness=10000 % annule les avertissements pour mauvaise boite horizontale
\pretolerance=-1 % d�sactive la premi�re passe (celle sans coupures)
\tolerance=10000 % passe avec coupures accept�e
\hyphenpenalty=-10000 % favorise fortement les copures de mots
\lefthyphenmin=2 \righthyphenmin=3 % longueur mini des fragments de d�but et fin
\clubpenalty=0 % pas de \idx{p�nalit�} suppl�mentaire apr�s la premi�re ligne
\interlinepenalty=0 % pas de \idx{p�nalit�} inter-ligne
\widowpenalty=0 % pas de \idx{p�nalit�} suppl�mentaire avant la derni�re ligne
\exhyphenpenalty=0 % ne pas p�naliser une coupure explicite
\leftskip=0pt \rightskip=0pt % d�sactive les �ventuels ressorts lat�raux
\everypar={}% d�sactive l'�ventuel \everypar
\parfillskip=0pt plus1fil % r�gle le \parfillskip par d�faut
\hsize=0pt % largeur de composition = 0pt
\edef\restorehyphenchar{\hyphenchar\font=\number\hyphenchar\font}%
\hyphenchar\font=`\- % impose "-" comme caract�re de coupure
\noindent % pas d'indentation + passage en mode horizontal
\hskip0pt \relax% premier noeud horizontal pour permettre la coupure de la suite
#3\par% compose #3
\restorehyphenchar% restaure le caract�re de coupure
}%
}
\def\hyphlengths#1#2{%#2 = macro contenant les longueurs de coupures du mot #1
\begingroup
\zerocompose
[\tt% passer en police � chasse fixe
\setbox\z@\hbox{M}\xdef\ttwidth{\the\wd\z@}% mesurer la largeur des caract�res
\hyphenchar\font=`\- % choisit "-" comme caract�re de coupure
]\z@{#1}% compose en 0pt dans la boite 0
\let#2 = \empty% initialise la macro #2
\def\cumul@length{0}%
\vfuzz=\maxdimen% annule les avertissements pour d�bordement
\splittopskip=\z@ % ne rajouter aucun espace au sommet de la boite restante
\loop
\setbox1=\vsplit\z@ to \z@% couper la boite � 0pt de hauteur
{\setbox\z@=\vbox{\unvbox1 \unskip\unpenalty\global\setbox1=\lastbox}}%
\setbox1=\hbox{\unhbox1 }%
\unless\ifvoid\z@% si la boite 0 n'est pas encore vide
\edef\cumul@length{% mettre � jour \cumul@length
\number\numexpr
\cumul@length
+% ajouter le quotient "largeur syllabe/largeur d'1 caract�re"
\wd1/\dimexpr\ttwidth\relax
-1% et soustraire 1 (le caract�re "-")
\relax
}%
% ajouter � #2 la virgule et le cumul actuel +1
\edef#2{% d�finir la macro #2 :
#2% reprendre le contenu de #2
\ifx#2\empty\else,\fi% ajouter "," si #2 non vide
\number\numexpr\cumul@length+1\relax% et le cumul
}%
\repeat% et recommencer
\expsecond{% avant de fermer le groupe
\endgroup
\def#2}{#2}% d�finit #2 hors du groupe
}
\newif\ifnumalgo
\newcount\algocnt
\numalgotrue
\def\algoindent{2em}
\def\algorule{.4pt}% �paisseur des r�glures de d�but et de fin
\def\algohrulefill{% remplit avec une ligne horizontale
\leavevmode
\leaders\hrule height\algorule\hfill
\kern0pt % rajoute un noeud au cas o� la commande est en fin de ligne
}
\def\algoleftskip{10pt}
\def\algorightskip{10pt}
\newmacro\algorithm[\\,\#,\{,\}]2{%
\medbreak
\begingroup% ouvre un groupe (sera ferm� � la fin de l'algorithme)
\footnotesize
\algocnt=1 % initialise le compteur de lignes
\leftskip=\algoleftskip \rightskip=\algorightskip% initialise les ressorts lat�raux
\parindent=0pt % pas d'indentation
%%%%%%%%%%%% affichage du titre %%%%%%%
\algohrulefill% remplir avec une ligne horizontale
\ifempty{#2}% si #2 est vide
{}% ne rien ins�rer
{% sinon
\lower.5ex\hbox{ #2 }% ins�rer le titre abaiss� de 0.5ex
\algohrulefill% ins�rer une ligne horizontale
}%
\par% aller � la ligne
\nointerlineskip% ne pas ins�rer le ressort interligne
\kern7pt % et sauter 7pt verticalement
\nobreak% emp�cher une coupure de page
%%%%%%%%%%%%%% fin du titre %%%%%%%%%%
%
%%%%%%%%%%%%%% rend les caract�res actifs %%%%%%%%%%%%%%
\def~##1~{\begingroup\bf##1\endgroup}%
\defactive:{% rend ":" actif
\futurelet\nxttok\algoassign% \nxttok = token suivant
}%
\def\algoassign{% suite du code de ":"
\ifx=\nxttok% si ":" est suivi de "="
\ifmmode% si mode math
\leftarrow% afficher "\leftarrow"
\else% si mode texte
${}\leftarrow{}$% passer en mode math pour "\leftarrow"
\fi
\expandafter\gobone% manger le signe "="
\else% si ":" n'est pas suivi de "="'
\string:% afficher ":"
\fi
}%
\expandafter\def\expandafter\oldeverypar\expandafter% sauvegarder...
{\the\everypar}% ... l'action effectu�e � chaque paragraphe
\ifnumalgo% si la num�rotation est demand�e,
\everypar\expandafter{% � chaque paragraphe
\the\everypar% reprendre le contenu pr�c�dent
\llap{% et � droite du d�but de la ligne,
$\scriptstyle\number\algocnt$% afficher le num�ro
\kern\dimexpr4pt+\leftskip-\algoleftskip\relax% en tenant compte de l'indentation
}%
}%
\fi
\def\algopar{% actions effectu�s par ^^M
\advance\algocnt by 1 % incr�mente le compteur de lignes
\color{black}% repasse en couleur noire
\rm% fonte droite
\par% termine le paragraphe
\leftskip=\algoleftskip % initialise le ressort gauche
}%
\doforeach\currentchar\in{#1}{\expandafter\catcode\expandafter`\currentchar=12 }%
\defactive\^^I{\advance\leftskip by \algoindent\relax}%
\defactive\ {\hskip1.25\fontdimen2\font\relax}% espace = 25% de + que la largeur naturelle
\letactive\^^M\algopar
\defactive\%{\it\color{gray}\char`\%}% passe en italique et gris puis affiche "%"
\defactive_{\ifmmode_\else\string_\fi}%
\defactive#3{% rend le token #3 actif (il sera rencontr� � la fin de l'algorithme)
\everypar\expandafter{\oldeverypar}% restaurer l'ancien \everypar
\par% aller � la ligne
\nointerlineskip% ne pas ins�rer le ressort interligne
\kern7pt % et sauter 7pt verticalement
\nobreak% emp�cher une coupure de page
\algohrulefill% tracer la ligne de fin
\smallbreak% saute un petit espace vertical
\endgroup% ferme le groupe ouvert au d�but de l'algorithme
}%
%%%%%%%%%%%%%%%%% fin des caract�res actifs %%%%%%%%%%%%%%%%
%
\sanitizealgo% va manger les espaces et les ^^M au d�but de l'algo
}
\def\sanitizealgo{\futurelet\nxttok\checkfirsttok}% r�cup�re le prochain token
\def\checkfirsttok{% teste le prochaun token
\def\nextaction{% � priori, on consid�re que la suite est " " ou "^^M" donc
\afterassignment\sanitizealgo% aller � \sanitizealgo
\let\nexttok= % apr�s avoir mang� ce "^^M" ou cet espace
}%
\unless\ifx\nxttok\algopar% si le prochain token n'est pas un ^^M
\unless\ifx\space\nxttok% et si le prochain token n'est pas un espace
\let\nextaction\relax% ne rien faire ensuite
\fi
\fi
\nextaction% faire l'action d�cid�e ci-dessus
}
\def\true@sgn#1{\ifnum#11<\z@-\fi}
\restoreatcoatcode\relax
\endinput