%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%
%% Codes donn�s dans le livre %%
%% � Apprendre � programmer en TeX � %%
%% %%
%% Encodage ISO 8859-1 %%
%% _____ %%
%% %%
%% � 2014-2020 Christian Tellechea %%
%% %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Les codes et les macros comment�s donn�s dans ce fichier sont diffus�s sous
% la licence LaTeX project public license (LPPL) 1.2
%
%
https://www.latex-project.org/lppl/lppl-1-2/
%
https://www.latex-project.org/lppl/lppl-1-2.txt
%
% Attention : ce fichier n'a pas vocation � �tre compil�
\endinput
****************** Code 1 ******************
Voici le code en \TeX{} du premier exemple.% ceci est un commentaire
On peut observer l'affichage qu'il produit juste au-dessous !
****************** Fin code ******************
****************** Code 2 ******************
3 tailles : $% entre en mode math�matique (espaces ignor�s)
1^{2^3}% 2 est en taille "\scriptstyle" et 3 en taille "\scriptscriptstyle"
$% fin du mode math
normal $1$, petit $\scriptstyle 2$, tr�s petit $\scriptscriptstyle 3$.
****************** Fin code ******************
****************** Code 3 ******************
%%% comportement normal %%%
a) comportement normal :
Ligne 1
Ligne 2
Ligne 3
\medbreak
b) Aucun caract�re de fin de ligne :
%%% aucune insertion en fin de ligne %%%
\endlinechar=-1
Ligne 1
Ligne 2
Ligne 3\endlinechar13
\medbreak
c) "X" comme caract�re de fin de ligne :
%%% "X" est ins�r� � chaque fin de ligne
\endlinechar=88
Ligne 1
Ligne 2
Ligne 3
****************** Fin code ******************
****************** Code 4 ******************
a) \number"1A \qquad b) \number"AB3FE \qquad c) \number"78
****************** Fin code ******************
****************** Code 5 ******************
a) \number'15 \qquad b) \number'674 \qquad c) \number'46
****************** Fin code ******************
****************** Code 6 ******************
a) \number`\a \quad %code de caract�re de "a"
b) \number`\\ \quad % code de caract�re de "\"
c) \number`\$ \quad % code de caract�re de "$"
d) \number`\ \quad % code de caract�re de l'espace
e) \number`\5 \quad % code de caract�re de "5"
f) \number`\{ \quad % code de caract�re de l'accolade ouvrante
g) \number`\} % code de caract�re de accolade fermante
****************** Fin code ******************
****************** Code 7 ******************
a) \number\catcode`\a \quad %code de cat�gorie de "a"
b) \number\catcode`\\ \quad % code de cat�gorie de "\"
c) \number\catcode`\$ \quad % code de cat�gorie de "$"
d) \number\catcode`\ \quad % code de cat�gorie de l'espace
e) \number\catcode`\5 \quad % code de cat�gorie de "5"
f) \number\catcode`\{ \quad % code de cat�gorie de l'accolade ouvrante
g) \number\catcode`\} % code de cat�gorie de accolade fermante
****************** Fin code ******************
****************** Code 8 ******************
Ici, W est une lettre...\par
\catcode`\W=3 % W devient le signe de bascule en mode math
Wx+y=3W\par
$a+b=cW\par
W2^3=8$\par
\catcode`\W=11 % W redevient une lettre
De nouveau, W est une lettre...
****************** Fin code ******************
****************** Code 9 ******************
$3+4=7$ \par % $ est la bascule math
\catcode`\$=12 % $ devient un caract�re affichable
$ s'affiche sans probl�me : $\par
\catcode`\$=3 % $ redevient la bascule math
$4+3=7$
****************** Fin code ******************
****************** Code 10 ******************
Voici les premiers mots de chaque ligne :
\catcode`\ =5 % l'espace est d�ormais de catcode 5
Cette premi�re ligne sera tronqu�e...
La deuxi�me aussi !
Et la derni�re �galement.
\catcode`\ =10 % l'espace reprend son catcode
Le comportement normal est restaur�.
****************** Fin code ******************
****************** Code 11 ******************
\def\foo{Bonjour}% d�finit le texte de remplacement de \foo
a) \foo Alice.\qquad% espace ignor�
b) {\foo} Bob.\qquad% espace non ignor�
c) \foo{} Chris.\qquad% espace non ignor�
d) \foo\space Daniel.% \space est remplac� par un espace
****************** Fin code ******************
****************** Code 12 ******************
\def\startbold{\begingroup \bf}
\def\stopbold{\endgroup}
Voici \startbold du texte en gras\stopbold{} et la suite.
****************** Fin code ******************
****************** Code 13 ******************
\def\foo{foo}
\begingroup A\aftergroup\foo B\endgroup\par
{A\aftergroup X\aftergroup\foo B}
****************** Fin code ******************
****************** Code 14 ******************
1) (un {\it cheval})\par% sans correction d'italique
2) (un {\it\aftergroup\/cheval})\par% avec correction d'italique
% on peut d�finir une macro \itacorr qui effectue automatiquement la correction
\def\itacorr{\it\aftergroup\/}
3) (un {\itacorr cheval})% avec correction d'italique
****************** Fin code ******************
****************** Code 15 ******************
\def\bar{Je suis bar.}
\let\foo\bar % \foo devient �gal � \bar
\def\bar{ABC}% \bar est red�finie
\foo\par% affiche "Je suis bar"
\bar% affiche "ABC"
****************** Fin code ******************
****************** Code 16 ******************
Initialement, c'est \TeX.\par
\let\TeXsauve\TeX% sauvegarde
\def\TeX{tEx}% red�finition
Ici, on a modifi� \TeX.\par
\let\TeX\TeXsauve% retauration
De nouveau, c'est \TeX.
****************** Fin code ******************
****************** Code 17 ******************
\let\sptoken= %2 espaces avant le "%"
La commande \sptoken compose le paragraphe
****************** Fin code ******************
****************** Code 18 ******************
{% d�but du groupe
\catcode`\W=13 \def W{wagons}
Les W constituent le train.
}% fin du groupe
****************** Fin code ******************
****************** Code 19 ******************
\begingroup \catcode`\W=13
\gdef\actiw{%
\catcode`\W=13
\def W{wagons}}
\endgroup
a) Les trains ne sont pas constitu�s de W !\par
b) \begingroup\actiw Ici, les W forment les trains.\endgroup\par
c) Ici, les W sont redevenus des lettres.
****************** Fin code ******************
****************** Code 20 ******************
\begingroup
\catcode`\ =13 % rend l'espace actif
\gdef\>{\begingroup
\catcode`\ =13
\def {\hskip5mm\relax}}
\endgroup
\let\<=\endgroup
a) Du texte normal\par
b) \>Des mots tr�s espac�s\<\par
c) Du texte normal
****************** Fin code ******************
****************** Code 21 ******************
\begingroup
\catcode`\,=13 \def,{\unskip\string,\space\ignorespaces}
La rue assourdissante autour de moi hurlait.
Longue , mince,en grand deuil , douleur majestueuse ,
Une femme passa ,d'une main fastueuse
Soulevant,balan�ant le feston et l'ourlet ;
\endgroup\medbreak\hfill Charles {\sc Baudelaire}
****************** Fin code ******************
****************** Code 22 ******************
\begingroup
\catcode`\,=13 \def,{\unskip\string, \ignorespaces}
\catcode`\^^M=13 \let ^^M\par % rend le retour charriot �gal � \par
La rue assourdissante autour de moi hurlait.
Longue , mince,en grand deuil , douleur majestueuse ,
Une femme passa , d'une main fastueuse
Soulevant,balan�ant le feston et l'ourlet ;
\endgroup\medbreak\hfill Charles {\sc Baudelaire}
****************** Fin code ******************
****************** Code 23 ******************
{% ouvre un groupe
\let\AA=a \let\EE=e \let\II=i \let\OO=o \let\UU=u \let\YY=y
% sauvegarder avant de modifier le catcode de a et e :
\let\lEt=\let \let\cAtcOdE=\catcode
\cAtcOdE`\a=13 \lEt a=\EE \cAtcOdE`\e=13 \lEt e=\II
\cAtcOdE`\i=13 \lEt i=\OO \cAtcOdE`\o=13 \lEt o=\UU
\cAtcOdE`\u=13 \lEt u=\YY \cAtcOdE`\y=13 \lEt y=\AA
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat
contient des sonorit\'es catalanes, corses ou grecques assez
inattendues.
}% ferme le groupe
****************** Fin code ******************
****************** Code 24 ******************
{%
\let\AA=a \let\lEt=\let \let~=\catcode
~`a=13 \lEt a=e ~`e=13 \lEt e=i ~`i=13 \lEt i=o
~`o=13 \lEt o=u ~`u=13 \lEt u=y ~`y=13 \lEt y=\AA
Ce texte devenu \`a peine reconnaissable...
}
****************** Fin code ******************
****************** Code 25 ******************
a) \def\foo{Bonjour}\meaning\foo\par
b) \let\bar=\foo\meaning\bar\par% \foo est "copi�e" vers \bar
c) \def\baz{\foo}\meaning\baz\par
d) \catcode`\W=13 \def W{Wagons}% W est un caract�re actif
\meaning W\par
e) \meaning\def% \def est une primitive
****************** Fin code ******************
****************** Code 26 ******************
a) \def\foo{
}Signification de \string\foo{} : \meaning\foo
b) Signification de deux retours charriots cons�cutifs : \meaning
****************** Fin code ******************
****************** Code 27 ******************
a) \meaning\relax\par% primitive
b) \meaning {\par% catcode 1
c) \meaning }\par% catcode 2
d) \meaning $\par% catcode 3
e) \meaning &\par% catcode 4
g) \meaning #\par% catcode 6
h) \meaning ^\par% catcode 7
i) \meaning _\par% catcode 8
j) \meaning a\par% catcode 11 (une lettre)
k) \meaning +\par% catcode 12 (caract�re "autre")
l) \meaning ~\par% catcode 13 (caract�re actif)
****************** Fin code ******************
****************** Code 28 ******************
\begingroup% dans un groupe
\let\*=\meaning% rendre \* �gal � \meaning
\* %<- espace pris en compte
\endgroup% fermer le groupe
****************** Fin code ******************
****************** Code 29 ******************
\begingroup
\catcode`\*0
\catcode`\\12 % \ n'est plus un caract�re d'�chappement
*def*foo{bar}
*LaTeX{} et la macro *string*foo : *foo.
L'ancien caract�re d'�chappement "\" et \TeX.
*endgroup
****************** Fin code ******************
****************** Code 30 ******************
\def\foo{\bar}
\begingroup
a) \escapechar=-1 \meaning\foo\qquad% pas de caract�re d'�chappement
b) \escapechar=`\@ \meaning\foo\qquad% "@" est le caract�re d'�chappement
\endgroup
c) \meaning\foo% caract�re d'�chappement par d�faut
****************** Fin code ******************
****************** Code 31 ******************
\begingroup
\catcode`\|=0 |catcode`|\=11 |catcode`|2=11 |catcode`|1=11
|gdef|1\2\a{foo}
|endgroup
Voici la macro : \csname 1\string\2\string\a\endcsname
****************** Fin code ******************
****************** Code 32 ******************
\newtoks\foo% allocation d'un nouveau registre
\foo={Bonjour le monde}% assignation
Contenu du registre {\tt\string\foo} : \the\foo.
\newtoks\bar% allocation d'un autre registre
\bar=\foo% assigne � \bar les tokens du registre \foo
Contenu du registre {\tt\string\bar} : \the\bar.
****************** Fin code ******************
****************** Code 33 ******************
\def\hello#1#2{Bonjour #1 et #2.\par}% d�finition
\hello ab% #1=a et #2=b
\hello a b% #1=a et #2=b
\hello{foo}{bar}% #1=foo et #2=bar
\hello foobar% #1=f et #2=o
% (le reste "obar" est lu apr�s que la macro est termin�e)
****************** Fin code ******************
****************** Code 34 ******************
\def\tenlist#1#2#3#4#5#6#7#8#9{(#1,#2,#3,#4,#5,#6,#7,#8,#9\endlist}
\def\endlist#1{,#1)}
Une liste \tenlist abcdefghij de lettres.
****************** Fin code ******************
****************** Code 35 ******************
\def\foo#1#2{Bonjour #1 et #2.\par}
\begingroup\tt% passer en fonte � chasse fixe
a) \foo{monsieur}{madame}
b) \foo{{\bf toi}}{moi}
c) \foo{}{{}}
d) \foo{ }{ }
e) \foo{$\pi$} {$\delta$}
f) \foo ab
g) \foo X Y
\endgroup% fin de la fonte � chasse fixe
****************** Fin code ******************
****************** Code 36 ******************
\def\foo{Programmer en \TeX {} est facile}
\meaning\foo\par
\def\foo{Program^^6der en \TeX{} est facile}
\meaning\foo
****************** Fin code ******************
****************** Code 37 ******************
a) \gobone XY - \secondoftwo XY\par
b) \gobone{ab}{xy} - \secondoftwo{ab}{xy}\par
c) \gobone{123}4 - \secondoftwo{123}4\par
d) \gobone A{BCD} - \secondoftwo A{BCD}
****************** Fin code ******************
****************** Code 38 ******************
\gobone {a}{\catcode`\~12 Le <<~>> est un espace ?} Et ici <<~>> ?
\secondoftwo{a}{\catcode`\~12 Le <<~>> est un espace ?} Et ici <<~>> ?
****************** Fin code ******************
****************** Code 39 ******************
\def\visible{\let\choix=\firstoftwo}
\def\cache{\let\choix=\secondoftwo}
\def\?#1{\choix{#1}{...}}%
\def\interro{J'ai �t\?{�} invit\?{�} � gout\?{er} chez Max. Apr�s s'�tre
bien amus\?{�}, nous avons rang\?{�} et il a fallu rentr\?{er}.}
Compl�ter avec << � >> ou << er >> :\par
\cache\interro\par\medskip
Correction :\par
\visible\interro
****************** Fin code ******************
****************** Code 40 ******************
\def\visible{\let\?=\identity}
\def\cache{\def\?##1{...}}
\def\interro{J'ai �t\?{�} invit\?{�} � go�t\?{er} chez Max. On s'est
bien amus\?{�} et ensuite, il a fallu rentr\?{er}.}
Compl�ter avec << � >> ou << er >> :\par
\cache\interro\par\medskip
Correction :\par
\visible\interro
****************** Fin code ******************
****************** Code 41 ******************
\def\makemacro#1#2{\def#1##1{##1 #2}}
\makemacro\LL{Lamport}
\makemacro\juin{juin 2014}
Paris, le \juin{3}.\medbreak
\LL{Cher Monsieur},\smallbreak
Vous �tes convoqu� � un examen sur \TeX{} le \juin{21} �
9h00 pr�cise dans le bureau de D. Knuth.\smallbreak
Veuillez croire, \LL{Monsieur}, en mes sentiments \TeX iens.
****************** Fin code ******************
****************** Code 42 ******************
\def\showcodes#1{\string#1 : $\number`#1 \rightarrow \number\lccode`#1$}
\showcodes A\qquad \showcodes B\qquad
\showcodes a\qquad \showcodes b\qquad \showcodes ^
****************** Fin code ******************
****************** Code 43 ******************
\lowercase{CACAO foobar}\par
\lowercase{\def\foo{Bonjour}}% d�finit une commande \foo
\foo % la commande d�finie pr�c�demment
****************** Fin code ******************
****************** Code 44 ******************
\begingroup
\lccode`A=`* % change le code minuscule de A
\lowercase{CACAO ABRACADABRA}\par
\endgroup
\lowercase{CACAO ABRACADABRA}
****************** Fin code ******************
****************** Code 45 ******************
\def\defactive#1{%
\catcode`#1=13
\begingroup
\lccode`~=`#1
\lowercase{\endgroup\def~}%
}
\begingroup% les modifications restent locales
\defactive W{wagons}% d�finit le caract�re actif "W"
Les W constituent les trains.
\endgroup %fermeture du groupe, "W" redevient une lettre
\par Les W sont des lettres
****************** Fin code ******************
****************** Code 46 ******************
\defactive W{wagon}
1) Les W constituent le train.\par
2) \catcode`W=11 Les W sont des lettres.\par
3) \catcode`\W=13 Les W constituent-ils le train ?
****************** Fin code ******************
****************** Code 47 ******************
\def\defactive#1#2{%
\catcode`#1=13 % #1 sera actif apr�s la fin du texte de remplacement
\begingroup
\lccode`~=`#1 % dans \lowercase, changer les ~ (actifs) en "#1", ceux-ci �tant actifs
\lowercase{\endgroup\def~}{#2}%
}
\defactive W{Wagon}
Un W.
****************** Fin code ******************
****************** Code 48 ******************
\def\defactive#1{%
\catcode`#1=13 % #1 sera actif apr�s la fin du texte de remplacement
\begingroup
\lccode`~=`#1 % dans \lowercase, changer les ~ (actifs) en "#1", ceux-ci �tant actifs
\lowercase{\endgroup\def~}%
}
\defactive W{Wagon}
Un W.
****************** Fin code ******************
****************** Code 49 ******************
\def\defactive#1#2{%
\catcode`#1=13 % #1 sera actif apr�s la fin du texte de remplacement
\begingroup
\uccode`~=`#1 % dans \uppercase, changer les ~ (actifs) en "#1", ceux-ci �tant actifs
\uppercase{\endgroup\def~}{#2}%
}
\defactive W{Wagon}
Un W.
****************** Fin code ******************
****************** Code 50 ******************
\def\letactive#1{%
\catcode`#1=13 % #1 sera actif apr�s la fin du texte de remplacement
\begingroup
\uccode`~=`#1 % dans \uppercase, changer les ~ (actifs) en "#1", ceux-ci �tant actifs
\uppercase{\endgroup\let~}%
}
\def\W{wagon}%
\letactive X\W
Un X.
****************** Fin code ******************
****************** Code 51 ******************
\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 }% \do change le catcode de son argument � 12
\dospecials% rend inoffensifs tous les tokens sp�ciaux
\defactive\^^M{\leavevmode\par}% d�finit le retour charriot
\letactive#1\endgroup% d�finit #1 qui sera un \endgroup
\tt% passe en fonte � chasse fixe
}
essai 1 : \litterate*\foo # #34{ } &_\ *
\medbreak
essai 2 : \litterate/une premi�re ligne ,, >>
un saut de ligne et la seconde --/
****************** Fin code ******************
****************** Code 52 ******************
\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 }% \do change le catcode de son argument � 12
\dospecials% rend inoffensifs tous les tokens sp�ciaux
\defactive\^^M{\leavevmode\par}% d�finit le retour charriot
\defactive\ {\ }% l'espace est actif et devient "\ "
\defactive<{\string<{}}\defactive>{\string>{}}% emp�che
\defactive-{\string-{}}\defactive`{\string`{}}% les
\defactive,{\string,{}}\defactive'{\string'{}}% ligatures
\letactive#1\endgroup% #1 sera un \endgroup
\tt% passe en fonte � chasse fixe
}
essai 1 : \litterate*\foo # #34{ %} &_\ *
\medbreak
essai 2 : \litterate/une premi�re ligne ,, >>
un saut de ligne et la seconde --/
****************** Fin code ******************
****************** Code 53 ******************
\def\baz#1#2#3#{"#1", puis "#2" et enfin "#3".}
\baz{abc}def{gh}ij
****************** Fin code ******************
****************** Code 54 ******************
\catcode`\@11
\long\def\firstto@nil#1#2\@nil{#1}
\long\def\remainto@nil#1#2\@nil{#2}
a) \firstto@nil foobar\@nil \qquad b) \remainto@nil foobar\@nil \par
c) \firstto@nil {foo}bar\@nil \qquad d) \remainto@nil {foo}bar\@nil
****************** Fin code ******************
****************** Code 55 ******************
\catcode`\@=11 % "@" devient une lettre
\def\rightof#1#2{%
\def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
\right@of#1\@nil% appelle la macro auxiliaire o� #1 est la <chaine>
}
\catcode`\@=12 %"@" redevient un signe
--\rightof{Programmation}{g}--\par
--\rightof{Programmation}{gram}--\par
--\rightof{Programmation}{on}--
****************** Fin code ******************
****************** Code 56 ******************
\catcode`\@=11 % "@" devient une lettre
\def\rightof#1#2{%
\def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
\right@of#1\@nil% appelle la macro auxiliaire
}
\catcode`\@=12 %"@" redevient un signe
--\rightof{Programmation}{z}--\par
--\rightof{Programmation}{Gram}
****************** Fin code ******************
****************** Code 57 ******************
\catcode`\@=11 % "@" devient une lettre
\def\rightof#1#2{%
\def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
\right@of#1#2\@nil% appelle la macro auxiliaire avec le motif #2
}
\catcode`\@=12 %"@" redevient un signe
--\rightof{Programmation}{g}--\par
--\rightof{Programmation}{ti}--\par
--\rightof{Programmation}{z}--\par
--\rightof{Programmation}{Gram}--
****************** Fin code ******************
****************** Code 58 ******************
\catcode`\@=11 % "@" devient une lettre
\def\gobto@@nil#1\@@nil{}
\def\rightof#1#2{%
\def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
\right@of#1\gobto@@nil#2\gobto@@nil\@@nil\@nil% appelle la macro auxiliaire
}
\catcode`\@=12 %"@" redevient un signe
--\rightof{Programmation}{g}--\par
--\rightof{Programmation}{ti}--\par
--\rightof{Programmation}{z}--\par
--\rightof{Programmation}{Gram}--
****************** Fin code ******************
****************** Code 59 ******************
\catcode`\@=11 % "@" devient une lettre
\def\rightof#1#2{%
\ifin{#1}{#2}%
{% si #1 contient le #2
\def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
\right@of#1\@nil% appelle la macro auxiliaire
}%
{}% sinon, ne rien faire
}
\catcode`\@=12 %"@" redevient un signe
--\rightof{Programmation}{g}--\par
--\rightof{Programmation}{z}--\par
--\rightof{Programmation}{o}--
****************** Fin code ******************
****************** Code 60 ******************
\catcode`\@=11
\def\leftof#1#2{%
\def\leftof@i##1#2##2\@nil{##1}% renvoie ce qui est � gauche de #2
\leftof@i #1#2\@nil% ajoute #2 apr�s #1
}
\catcode`\@=12
--\leftof{Programmation}{ram}--\par
--\leftof{Programmation}{zut}--
****************** Fin code ******************
****************** Code 61 ******************
\catcode`\@=11
\def\leftof#1#2{%
\def\leftof@i##1#2##2\@nil{\leftof@ii##1#1\@nil}%
\def\leftof@ii##1#1##2\@nil{##1}%
\leftof@i #1#2\@nil
}
\catcode`\@=12
--\leftof{Programmation}{ram}--\par
--\leftof{Programmation}{zut}--
****************** Fin code ******************
****************** Code 62 ******************
\catcode`\@=11
\def\rightof#1#2{%
\def\rightof@i##1#2##2\@nil{\rightof@ii##2#2\@nil}%
\def\rightof@ii##1#2##2\@nil{##1}%
\rightof@i#1#2\@nil
}
\catcode`\@=12
--\rightof{Programmation}{g}--\par
--\rightof{Programmation}{z}--
****************** Fin code ******************
****************** Code 63 ******************
\catcode`\@=11
\def\gobto@@nil#1\@@nil{}
\def\rightof#1#2{%
\def\right@of##1#2##2\@nil{##2}% d�finit la macro auxiliaire
\right@of#1\gobto@@nil#2\gobto@@nil\@@nil\@nil% appelle la macro auxiliaire
}
\catcode`\@=12
\rightof{abc{1}def}{c{1}d}% affiche ce qui est � droite de "c{1}d"
****************** Fin code ******************
****************** Code 64 ******************
\expandafter\def\csname ab1c\endcsname{Bonjour}
Texte de remplacement de la macro : \csname ab1c\endcsname
****************** Fin code ******************
****************** Code 65 ******************
\def\defname#1{\expandafter\def\csname#1\endcsname}
\defname{ab1c}{Bonjour}
Texte de remplacement de \litterate|\abc1| : \csname ab1c\endcsname\par
\def\letname#1{\expandafter\let\csname#1\endcsname}
\def\foo{abc}\letname{foo1}=\foo% rend la macro "\foo1" �gale � \foo
Texte de remplacement de \litterate|\foo1| : \csname foo1\endcsname
****************** Fin code ******************
****************** Code 66 ******************
\def\foo{Bonjour}\catcode`@=11
R�sultat : \firstto@nil\foo\@nil
\catcode`@=12
****************** Fin code ******************
****************** Code 67 ******************
\def\foo{Bonjour}\catcode`@=11
R�sultat : \expandafter\firstto@nil\foo\@nil
\catcode`@=12
****************** Fin code ******************
****************** Code 68 ******************
\newtoks\testtoks \testtoks={Bonjour}
\catcode`@=11
R�sultat : \expandafter\firstto@nil\the\testtoks\@nil
\catcode`@=12
****************** Fin code ******************
****************** Code 69 ******************
\def\foo{bonjour}
a) \>\csname foo\endcsname< \par
b) \>\foo< \par
c) \expandafter\>\foo< \par
d) \>\foo\foo< \par
e) \expandafter\>\foo\foo<
****************** Fin code ******************
****************** Code 70 ******************
\def\foo{Bonjour} \expandafter\>\expandafter\foo\foo<
****************** Fin code ******************
****************** Code 71 ******************
\def\foo{Bonjour}
\expandafter\def\expandafter\bar\expandafter{\expandafter\foo\foo}
\meaning\bar
****************** Fin code ******************
****************** Code 72 ******************
\def\foo{\foo Bonjour}% d�finition r�cursive
\foo% l'ex�cution provoque un d�passement de la capacit� de la pile
****************** Fin code ******************
****************** Code 73 ******************
\long\def\addtomacro#1#2{%
\expandafter\def\expandafter#1\expandafter{#1#2}%
}
\def\foo{Bonjour}
\addtomacro\foo{ le monde}
\meaning\foo
****************** Fin code ******************
****************** Code 74 ******************
\long\def\eaddtomacro#1#2{%
\expandafter\addtomacro\expandafter#1\expandafter{#2}%
}
\def\foo{Bonjour} \def\world{ le monde}
\eaddtomacro\foo\world
\meaning\foo
****************** Fin code ******************
****************** Code 75 ******************
\long\def\addtotoks#1#2{#1= \expandafter{\the#1#2}}
\newtoks\bar
\bar={Bonjour}% met "Bonjour" dans le registre
\addtotoks\bar{ le monde}% ajoute " le monde"
\the\bar% affiche le registre
****************** Fin code ******************
****************** Code 76 ******************
\long\def\eaddtotoks#1#2{\expandafter\addtotoks\expandafter#1\expandafter{#2}}
\bar={Bonjour}
\def\macrofoo{ le monde}
\eaddtotoks\bar\macrofoo
\the\bar
****************** Fin code ******************
****************** Code 77 ******************
\def\X{Bonjour} \def\Y{\X}
\expandafter\expandafter\expandafter\>\Y<
****************** Fin code ******************
****************** Code 78 ******************
\long\def\swaparg#1#2{#2{#1}}
\long\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}
\def\X{Bonjour}
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\>\expsecond{\X}{\X}<
****************** Fin code ******************
****************** Code 79 ******************
\expsecond{\def\foo}\secondoftwo{A}{B}
****************** Fin code ******************
****************** Code 80 ******************
\expsecond{\def\foo}{\secondoftwo{A}{B}}
\meaning\foo
****************** Fin code ******************
****************** Code 81 ******************
\def\exptwoargs#1#2{\expsecond{\expsecond{#1}{#2}}}
\def\foo{Bonjour}\def\bar{ le monde}
\def\displaytwoargs#1#2{\detokenize{#1#2}}% affiche tels quels les arguments
\exptwoargs\displaytwoargs\foo\bar
****************** Fin code ******************
****************** Code 82 ******************
\def\aa{Bonjour}\def\bb{\aa}
\def\cc{ le monde}
\edef\foo{\bb\cc}
\meaning\foo
****************** Fin code ******************
****************** Code 83 ******************
\def\aa{Bonjour } \def\bb{\aa} \def\cc{le } \def\dd{ monde}
\edef\ee#1{\bb\cc#1 !!!}
\meaning\ee\par
\expandafter\>\ee{\dd}<
****************** Fin code ******************
****************** Code 84 ******************
\def\foo{123xyz}
a) signification du 1-d�veloppement d'un \litterate-\noexpand- :
\expandafter\meaning\noexpand\foo
b) ex�cution d'un \litterate-\noexpand- : \noexpand\foo% identique � \relax
c) 1-d�veloppement de \litterate-\noexpand- dans le texte de remplacement de
\litterate-\bar- :
\expandafter\def\expandafter\bar\expandafter{\noexpand\foo}
\meaning\bar
****************** Fin code ******************
****************** Code 85 ******************
\def\aa{Bonjour}\def\bb{\aa}\def\cc{\bb}
a) \edef\foo{\aa\noexpand\bb\cc}\meaning\foo \qquad b) ex�cution : \foo\par
c) \edef\foo{\aa\noexpand{\aa\cc}}\meaning\foo\qquad d) ex�cution : \foo
****************** Fin code ******************
****************** Code 86 ******************
\def\aa{Bonjour}\def\bb{Au revoir}
a) \edef\truc{\aa\noexpand\bb\noexpand\aa\bb}\meaning\truc \par
b) \edef\truc{\aa\unexpanded{\bb\aa}\bb}\meaning\truc
****************** Fin code ******************
****************** Code 87 ******************
\def\aa{Bonjour}\def\bb{Au revoir}
\toks0={\aa\bb}
\edef\foo{\aa\the\toks0 \bb}
\meaning\foo
****************** Fin code ******************
****************** Code 88 ******************
\def\aa{Bonjour}
\protected\def\bb{ le}% \ bb est prot�g�e !
\def\cc{ monde}
\edef\foo{\aa\bb\cc}
Signification de \string\foo~: \meaning\foo \par
Ex�cution de \string\foo~: \foo
****************** Fin code ******************
****************** Code 89 ******************
\def\aa{Bonjour}
\protected\def\bb{ le}
\def\cc{ monde}
\edef\foo{\expandafter\aa\bb\cc}% le \expandafter 1-d�veloppe \bb
\meaning\foo
****************** Fin code ******************
****************** Code 90 ******************
\def\foo{Bonjour}% d�finition
\foo% ex�cution
****************** Fin code ******************
****************** Code 91 ******************
\def\foo{abc}
\edef\bar{\def\foo{Bonjour}\foo}
\meaning\bar
****************** Fin code ******************
****************** Code 92 ******************
\def\foo{abc}
\edef\bar{\def\noexpand\foo{Bonjour}\noexpand\foo}
Signification : \meaning\bar\par
Ex�cution : \bar
****************** Fin code ******************
****************** Code 93 ******************
\long\def\>#1<{\detokenize{#1}}
\expandafter\>% provoque le 1-d�veloppement de :
\csname foo\expandafter\endcsname
\csname bar\expandafter\endcsname
\csname wee\expandafter\endcsname
\csname fin\endcsname<
****************** Fin code ******************
****************** Code 94 ******************
\long\def\>#1<{\detokenize{#1}}
\def\fin{YY} \def\wee{\weeA} \def\weeA{XX}
\expandafter\>%
\csname foo\expandafter\endcsname
\csname bar\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\endcsname
\csname wee\expandafter\expandafter\expandafter\endcsname
\csname fin\endcsname<
****************** Fin code ******************
****************** Code 95 ******************
\long\def\>#1<{\detokenize{#1}}
\def\fin{YYY} \def\wee{\weeA} \def\weeA{XXX}
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\>%
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\foo
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\bar
\expandafter\wee\fin<
****************** Fin code ******************
****************** Code 96 ******************
\chardef\foo65
a) |\foo|\qquad % employ�e seule, \foo affiche un A
b) |\number\foo|\qquad % si TeX lit un nombre, \foo est le nombre 65
****************** Fin code ******************
****************** Code 97 ******************
\mathchardef\foo4944
a) |$\foo$|\qquad % en mode math, affiche le signe "somme" (uniquement en mode maths)
b) |\number\foo|\qquad % si TeX lit un nombre, \foo est 4944
****************** Fin code ******************
****************** Code 98 ******************
a) "\romannumeral 27 "\quad
b) "\romannumeral 4687 "\quad
c) "\romannumeral 0 "\quad% 0 donc d�veloppement vide
d) "\romannumeral -2014 "\quad% n�gatif donc d�veloppement vide
e) \def\foo{7}\def\bar{\foo}%
"\romannumeral \foo\foo\bar"\quad% 777
f) "\romannumeral 1\bar8\foo"\quad% 1787
g) "\romannumeral 1\bar8 \foo"% 178 (stopp� par l'espace) puis 7
****************** Fin code ******************
****************** Code 99 ******************
\long\def\>#1<{\detokenize{#1}}
\def\swaparg#1#2{#2{#1}}
\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}
\def\X{Bonjour}
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\>\expsecond\X\X<
****************** Fin code ******************
****************** Code 100 ******************
\long\def\>#1<{\detokenize{#1}}
\def\swaparg#1#2{0 #2{#1}}% le "0 " stoppe ici le d�veloppement maximal
\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}
\def\X{Bonjour}
\expandafter\>\romannumeral\expsecond\X\X<
****************** Fin code ******************
****************** Code 101 ******************
\long\def\>#1<{\detokenize{#1}}
\def\swaparg#1#2{#2{#1}}
\def\expsecond#1#2{\expandafter\swaparg\expandafter{#2}{#1}}
\def\X{Bonjour}
\expandafter\>\romannumeral\expsecond{0 \X}\X<
****************** Fin code ******************
****************** Code 102 ******************
\long\def\>#1<{\detokenize{#1}}
\def\X{Bonjour}
\catcode`\@=11
\expandafter\>\romannumeral\expsecond{\z@\X}{\X}<
\catcode`\@=12
****************** Fin code ******************
****************** Code 103 ******************
\def\newunivar#1{\def#1[##1]{\csname\string#1[##1]\endcsname}}
\def\defunivar#1[#2]{\defname{\string#1[#2]}}
\newunivar\foobar
\defunivar\foobar[0]{abcd}
\defunivar\foobar[1]{1 23}
\defunivar\foobar[3]{XY Z}
Cellule 0 : \foobar[0]\par
Cellule 1 : \foobar[1]\par
Cellule 2 : \foobar[2]\par% cellule non d�finie : \foobar[2] donne \relax
Cellule 3 : \foobar[3]\bigbreak
\newunivar\client
\defunivar\client[nom]{M. Raymond {\sc Tartempion}}
\defunivar\client[adr]{5 rue de la paix}
\defunivar\client[cod_post]{75000}
\defunivar\client[ville]{Paris}
% fin des d�finitions, affichage de l'adresse :
\client[nom]\par
\client[adr]\par
\client[cod_post] \client[ville]
****************** Fin code ******************
****************** Code 104 ******************
\newcount\foo \newcount\bar
\foo=42 \bar=\foo \string\bar\ vaut : \the\bar \par
\bar=\foo57 \string\bar\ vaut : \number\bar\par
\bar=2014 \string\bar\ vaut : \romannumeral\bar
****************** Fin code ******************
****************** Code 105 ******************
\newcount\foo
\def\fonction#1{%
\foo=#1 % assigne l'entier #1 au compteur puis
\multiply\foo3 % multiplie par 3
\advance\foo-4 % soustrait 4
\multiply\foo\foo% �l�ve au carr� (lmultiplie \foo par lui m�me)
\number\foo% enfin, afficher le r�sultat
}
a) \fonction5\qquad b) \fonction{-13}
****************** Fin code ******************
****************** Code 106 ******************
\newcount\foo
\def\fonction#1{%
\foo=#1 \multiply\foo3 \advance\foo-4 \multiply\foo\foo
\number\foo}
\edef\bar{\fonction{5}}%
a) Signification : \meaning\bar\par
b) Ex�cution : \bar
****************** Fin code ******************
****************** Code 107 ******************
a) \number\numexpr2+3*4\relax\qquad
b) \romannumeral\numexpr2*3\relax\qquad
c) \number\numexpr(6-2*4)*(1-(2-6))\relax\qquad
d) \number\numexpr7/4\relax\qquad %7/4 vaut 1,75
e) \edef\foo{\number\numexpr2+3*4\relax}\meaning\foo
****************** Fin code ******************
****************** Code 108 ******************
\number\numexpr3*\numexpr1+2*5\relax+2\relax
****************** Fin code ******************
****************** Code 109 ******************
\def\fonction#1{\number\numexpr(3*#1-4)*(3*#1-4)\relax}
a) \fonction5\qquad
b) \fonction{-13}\qquad
c) \edef\bar{\fonction5}\meaning\bar
****************** Fin code ******************
****************** Code 110 ******************
\def\fonction#1{\exparg\carre{\number\numexpr3*#1-4\relax}}
\def\carre#1{\number\numexpr#1*#1\relax}
a) \fonction{5}\qquad
b) \fonction{-13}\qquad
c) \edef\bar{\fonction5}\meaning\bar
****************** Fin code ******************
****************** Code 111 ******************
\def\truncdiv#1#2{\numexpr(#1-(#2-1)/2)/#2\relax}
8/3 :
a) \number\truncdiv83\qquad % doit donner 2
b) \number\truncdiv{-8}3\qquad % doit donner -2
c) \number\truncdiv8{-3}\qquad % doit donner -2
d) \number\truncdiv{-8}{-3}\par % doit donner 2
4/3 :
e) \number\truncdiv43\qquad % doit donner 1
f) \number\truncdiv{-4}3\qquad % doit donner -1
g) \number\truncdiv4{-3}\qquad % doit donner -1
h) \number\truncdiv{-4}{-3} % doit donner 1
****************** Fin code ******************
****************** Code 112 ******************
a) \ifnum 15=14 vrai\else faux\fi\qquad% test faux
b) \ifnum4<200 vrai\else faux\fi\qquad% test vrai
c) \newcount\foo \foo=9
\ifnum\foo>9 nombre\else chiffre\fi% test faux
****************** Fin code ******************
****************** Code 113 ******************
\long\def\>#1<{\detokenize{#1}}
\expandafter\>\ifnum5=5 vrai\else faux\fi<\par% test vrai
\expandafter\>\ifnum5=6 vrai\else faux\fi<% test faux
\fi\fi% r�tablir l'�quilibre \ifnum et \fi
****************** Fin code ******************
****************** Code 114 ******************
\def\numtest#1{%
\ifnum#1>-10
\ifnum#1<10
chiffre%
\else
nombre positif%
\fi
\else
nombre n�gatif%
\fi
}
a) \numtest{3}\qquad
b) \numtest{-67}\qquad
c) \numtest{-8}\qquad
d) \numtest{21}\qquad
e) \edef\foo{\numtest{2014}}\meaning\foo
****************** Fin code ******************
****************** Code 115 ******************
\def\normalise#1{%
\ifnum#1>-1 % ne faire quelque chose que si #1 est positif ou nul
\ifnum#1<100 % si <100
0% afficher un 0
\ifnum#1<10 % si <10
0%afficher un autre 0
\fi
\fi
\number#1 %afficher le nombre
\fi}% affiche le nombre
a) \normalise{749}\qquad
b) \normalise{0017}\qquad
c) \normalise8\qquad
d) \normalise{1789}\qquad
e) \normalise{-18}\qquad
f) \normalise{0}
****************** Fin code ******************
****************** Code 116 ******************
\def\mois#1{%
\ifcase#1\relax
\char`\#\char`\#% afficher "##" si argument = 0
\or janvier\or f\'evrier\or mars\or avril%
\or mai\or juin\or juillet\or aout%
\or septembre\or octobre\or novembre\or d\'ecembre%
\else
\char`\#\char`\#% afficher "##" sinon
\fi
}
a) \mois{-4}\qquad
b) \mois{3}\qquad
c) \mois{11}\qquad
d) \mois{20}\qquad
e) \edef\foo{\mois{\month}}\meaning\foo% mois en cours
****************** Fin code ******************
****************** Code 117 ******************
\def\ifletter#1#2#3{%
\ifnum`#1<`a% si le caract�re est avant "a"
#3% ex�cuter "<code faux>"
\else% sinon
\ifnum`#1>`z% si le caract�re est apr�s "z"
#3% ex�cuter "<code faux>"
\else% dans tous les autres cas
#2% "#1" est une lettre : ex�cuter "<code vrai>"
\fi
\fi}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}
****************** Fin code ******************
****************** Code 118 ******************
\def\ifletter#1{%
\ifnum`#1<`a
\expandafter\secondoftwo% \expandafter 1-d�veloppe "\else...\fi"
\else
\ifnum`#1>`z
\expandafter\expandafter\expandafter% 1-d�veloppe "\else...\fi" puis "\fi"
\secondoftwo
\else
\expandafter\expandafter\expandafter%1-d�veloppe "\fi" puis "\fi"
\firstoftwo
\fi
\fi}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}
****************** Fin code ******************
****************** Code 119 ******************
\def\ifletter#1#2#3{%
\romannumeral % <- initie le d�veloppement maximal
\ifnum`#1<`a
\expandafter\secondoftwo
\else
\ifnum`#1>`z
\expandafter\expandafter\expandafter\secondoftwo
\else
\expandafter\expandafter\expandafter\firstoftwo
\fi
\fi{0 #2}{0 #3}% <- "0 " stoppe le d�veloppement maximal
}
\long\def\>#1<{\detokenize{#1}}
a) \expandafter\expandafter\expandafter\>\ifletter{0}{vrai}{faux}<\qquad
b) \expandafter\expandafter\expandafter\>\ifletter{x}{vrai}{faux}<
****************** Fin code ******************
****************** Code 120 ******************
\def\ifletter#1{%
\ifnum`#1<`a
\let\donext=\secondoftwo
\else
\ifnum`#1>`z
\let\donext=\secondoftwo
\else
\let\donext=\firstoftwo
\fi
\fi
\donext% ex�cuter l'action d�cid�e ci-dessus
}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}
****************** Fin code ******************
****************** Code 121 ******************
\def\ifletter#1{%
\csname
\ifnum`#1<`a
second% <- commenter la fin de ligne pour �viter un
\else% espace parasite dans le nom de la macro cr��e
\ifnum`#1>`z
second%
\else
first%
\fi
\fi
oftwo%
\endcsname
}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}
****************** Fin code ******************
****************** Code 122 ******************
\def\ifletter#1{%
\lowercase{\csname
\ifnum`#1<`a second%
\else
\ifnum`#1>`z second\else first\fi
\fi
oftwo\endcsname
}%
}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}
****************** Fin code ******************
****************** Code 123 ******************
\edef\foo{\lowercase{AbCd}}\meaning\foo
****************** Fin code ******************
****************** Code 124 ******************
\def\ifletter#1{%
\csname
\ifnum`#1<`A second%
\else
\ifnum`#1<`Z first%
\else
\ifnum`#1>`a
\ifnum`#1<`z
first%
\else
second%
\fi
\else
second%
\fi
\fi
\fi
oftwo%
\endcsname
}
a) \ifletter{4}{vrai}{faux}\qquad
b) \ifletter{t}{vrai}{faux}\qquad
c) \ifletter{D}{vrai}{faux}\qquad
d) \edef\foo{\ifletter{x}{vrai}{faux}}\meaning\foo\qquad
e) \edef\foo{\ifletter{=}{vrai}{faux}}\meaning\foo
****************** Fin code ******************
****************** Code 125 ******************
\def\ifinside#1[#2,#3]{%
\csname
\ifnum#1<#2 second% si n<a, <code faux>
\else
\ifnum#1>#3 second% si n>b, <code faux>
\else first% sinon, <code vrai>
\fi
\fi
oftwo%
\endcsname
}
a) \ifinside 3[1,8]{oui}{non}\qquad
b) \ifinside -7[-20,-11]{oui}{non}\qquad
c) \ifinside 9[0,6]{oui}{non}\qquad
d) \ifinside -1[-5,1]{oui}{non}
****************** Fin code ******************
****************** Code 126 ******************
\def\ifinside#1[#2,#3]{%
\ifnum\numexpr(#1-#2)*(#1-#3)\relax>0
\expandafter\secondoftwo
\else
\expandafter\firstoftwo
\fi
}
a) \ifinside 3[1,8]{oui}{non}\qquad
b) \ifinside -7[-20,-11]{oui}{non}\qquad
c) \ifinside 9[0,6]{oui}{non}\qquad
d) \ifinside -1[-5,1]{oui}{non}
****************** Fin code ******************
****************** Code 127 ******************
\def\absval#1{%
\ifnum#1<0 \number-#1
\else \number#1
\fi}
a) \absval{-87}\qquad b) \absval{75}\qquad c) \absval{0}
****************** Fin code ******************
****************** Code 128 ******************
\def\absval#1{\number\ifnum#1<0 -\fi#1 }
a) \absval{-87}\qquad b) \absval{75}\qquad c) \absval{0}
****************** Fin code ******************
****************** Code 129 ******************
\def\absval#1{\number\ifnum\numexpr#1\relax<0 -\fi\numexpr#1\relax}
a) \absval{-87}\qquad
b) \absval{75}\qquad
c) \absval{0}\qquad
d) \absval{-20+13}\qquad% -7 affich� 7
e) \absval{5-3*(-4)+10-50}% -23 affich� 23
****************** Fin code ******************
****************** Code 130 ******************
\catcode`\@11
\def\absval#1{\exparg\absval@i{\number\numexpr#1\relax}}
\def\absval@i#1{\number\ifnum#1<\z@-\fi#1 }
\catcode`\@12
a) \absval{-87}\qquad
b) \absval{75}\qquad
c) \absval{0}\qquad
d) \absval{-20+13}\qquad% r�sultat -7 qui est affich� 7
e) \absval{5-3*(-4)+10-50}% r�sultat -23 qui est affich� 23
****************** Fin code ******************
****************** Code 131 ******************
\def\sgn#1{\ifnum#1<0 -\fi}
\def\truncdiv#1#2{%
\numexpr
\sgn{#1}\sgn{#2}1*% multiplie le quotient ci-dessous par +1 ou -1
(2*\absval{#1}-\absval{#2}+1)/(2*\absval{#2})
\relax
}
a) \number\truncdiv{-8}3\qquad
b) \number\truncdiv{-8}{-3}\qquad
c) \number\truncdiv8{-3}\qquad
d) \number\truncdiv{0}{-5}
****************** Fin code ******************
****************** Code 132 ******************
\catcode`\@11
\def\sgn#1{\ifnum#1<\z@-\fi}
\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
}
\catcode`\@12
a) \number\truncdiv{-8}3\qquad
b) \number\truncdiv{-8}{-3}\qquad
c) \number\truncdiv8{-3}\qquad
d) \number\truncdiv{0}{-5}\qquad
e) \number\truncdiv{20+2*3}{4-5*2}% 26/(-6) doit donner -4
****************** Fin code ******************
****************** Code 133 ******************
\def\siecle#1{%
\unless\ifnum#1=0 % ne faire quelque chose que si #1 diff�rent de 0
\uppercase\expandafter{\romannumeral\absval{#1}}% chiffres romains majuscules
\raise 1ex \hbox{e\ifnum\absval{#1}=1 r\fi} si�cle% affiche l'exposant puis "si�cle"
\ifnum#1<0 {} av. J.-C.\fi% affiche si besoin "av. J.-C."
\fi
}
a) \siecle{19}\qquad
b) \siecle{-3}\qquad
c) \siecle{1}\qquad
d) \siecle{0}\qquad
e) \siecle{-1}
****************** Fin code ******************
****************** Code 134 ******************
\catcode`\@11
\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 ":"
\catcode`\@12
a) \hdif{10:51:20}{9:20:10}\par
b) \hdif{14:20:0}{13:50:0}\par
c) \hdif{7:50:20}{5:50:20}\par
d) \hdif{7:50:10}{6:50:20}\par
e) \hdif{20:00:00}{19:59:15}\par
f) \hdif{17:13:15}{14:12:45}
****************** Fin code ******************
****************** Code 135 ******************
\newcount\ii
\catcode`\@=11
\def\ncar#1#2{%
\ii=0 % initialise le compteur � 0
\def\val@max{#1}% stocke la valeur maximale
\def\car@save{#2}% stocke le caract�re � afficher
\ncar@i% appelle la macro r�cursive
}
\def\ncar@i{%
\ifnum\ii<\val@max% si la valeur maxi n'est pas atteinte
\car@save% afficher le caract�re
\advance\ii 1 % incr�menter le compteur
\ncar@i% recommencer
\fi
}
\catcode`\@=12
\ncar{7}{*}\par
\ncar{13}W\par
\ncar{10}{foobar }
****************** Fin code ******************
****************** Code 136 ******************
\newcount\ii
\catcode`\@=11
\def\ncar#1#2{%
\ii=0 % initialise le compteur � 0
\def\val@max{#1}% stocke la valeur maximale
\def\car@save{#2}% stocke le caract�re � afficher
\ncar@i% appelle la macro r�cursive
}
\def\ncar@i{%
\ifnum\ii<\val@max% si la valeur maxi n'est pas atteinte
\car@save% afficher le caract�re
\advance\ii 1 % incr�menter le compteur
\ncar@i% recommencer
\fi
}
\catcode`\@=12
\ncar{2}{3a}
****************** Fin code ******************
****************** Code 137 ******************
a) \romannumeral 9600 \qquad b) \romannumeral 12000
****************** Fin code ******************
****************** Code 138 ******************
\def\ncar#1#2{%
\begingroup
\lccode`\m=`#2 % dans \lowercase, les "m" deviennent des "#2"
\lowercase\expandafter{\expandafter\endgroup\romannumeral#1000 }%
}
a) \ncar{7}{*}\qquad
b) \ncar{15}{\%}\qquad
c) \ncar{10}{4}
****************** Fin code ******************
****************** Code 139 ******************
\def\ncar#1#2{%
\ifnum#1>0 % <- espace apr�s le "0"
#2% affiche le caract�re
\exparg\ncar{\number\numexpr#1-1}{#2}% appel r�cursif
\fi
}
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \edef\foo{\ncar{5}{7}}\meaning\foo
****************** Fin code ******************
****************** Code 140 ******************
\def\ncar#1#2{%
\ifnum#1>0 \expandafter\identity% si #1>0 ex�cuter...
\else \expandafter\gobone% ...sinon manger
\fi% ce qui est entre ces accolades :
{#2% afficher le caract�re
\exparg\ncar{\number\numexpr#1-1}{#2}% appel r�cursif
}%
}
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \edef\foo{\ncar{5}X}\meaning\foo
****************** Fin code ******************
****************** Code 141 ******************
\long\def\antefi#1\fi{\fi#1}
\def\ncar#1#2{%
\ifnum#1>0
\antefi% comme si le \fi �tait "d�plac�" ici
#2% affiche le caract�re
\exparg\ncar{\number\numexpr#1-1}{#2}% appel r�cursif
\fi
}
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \edef\foo{\ncar{5}X}\meaning\foo
****************** Fin code ******************
****************** Code 142 ******************
\long\def\afterfi#1#2\fi{#2\fi#1}
\def\ncar#1#2{%
\ifnum#1>0
\afterfi{\exparg\ncar{\number\numexpr#1-1}{#2}}% <- argument renvoy� apr�s le \fi
#2% <- ceci reste avant le \fi
\fi
}
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \edef\foo{\ncar{5}X}\meaning\foo
****************** Fin code ******************
****************** Code 143 ******************
\def\ncar#1#2{%
\ifnum#1>0
#2% afficher le caract�re
\expandafter\ncar\expandafter% le pont d'\expandafter lance \number et \numexpr
{\number\numexpr#1-1\expandafter}% le dernier \expandafter mange "\else...\fi"
\else
\expandafter\gobone% si le test est faux, manger {#2} ci-dessous
\fi{#2}%
}
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \edef\foo{\ncar{5}X}\meaning\foo
****************** Fin code ******************
****************** Code 144 ******************
\catcode`\@11
\def\ncar#1#2{%
\def\ncar@i##1{%
\ifnum##1<#1 % si i < valeur maxi
#2% afficher le caract�re
\exparg\ncar@i{\number\numexpr##1+1\expandafter}% puis recommencer avec i+1
\fi% \fi mang� par le \expandafter en fin de zone de \numexpr
}%
\ncar@i{0}% commence avec la valeur "compteur" 0
}
\catcode`\@12
a) \ncar{7}{*}\qquad
b) \ncar{13}{W}\qquad
c) \ncar{5}{X}
****************** Fin code ******************
****************** Code 145 ******************
\catcode`\@11 \newcount\compte@cnt
\def\compte#1{%
\def\val@max{#1}\compte@cnt=0 % effectue les initialisations
\compte@i% appelle la macro principale
}
\def\compte@i{%
\ifnum\compte@cnt<\val@max% si compteur < valeur maxi
\advance\compte@cnt1 % incr�menter le compteur
\number\compte@cnt, % afficher le nombre, la virgule et l'espace
\expandafter\compte@i %recommencer
\fi
}
\catcode`\@12
a) \compte{9}\qquad
b) \compte{-4}\qquad
c) \compte{2}
****************** Fin code ******************
****************** Code 146 ******************
\catcode`\@11 \newcount\compte@cnt
\def\compte#1{\def\val@max{#1}\compte@cnt=0 \compte@i}
\def\compte@i{%
\ifnum\compte@cnt<\val@max\relax
\advance\compte@cnt1
\number\compte@cnt
\ifnum\compte@cnt<\val@max , \fi% afficher ", " si le maxi n'est pas atteint
\expandafter\compte@i
\fi
}
\catcode`\@12
a) \compte{9}\qquad
b)\compte{-4}\qquad
c) \compte{2}
****************** Fin code ******************
****************** Code 147 ******************
\catcode`\@11 \newcount\compte@cnt
\def\compte#1{%
\ifnum#1>0 % ne faire quelque chose que si l'argument est positif
\def\val@max{#1}\compte@cnt=1 % faire les initialisations
\expandafter\compte@i% appeller la macro r�crusive
\fi
}
\def\compte@i{%
\number\compte@cnt\relax % afficher le nombre
\ifnum\compte@cnt<\val@max\relax % si valeur maxi n'est pas atteinte
, % afficher la virgule et l'espace
\advance\compte@cnt1 % incr�menter le compteur
\expandafter\compte@i % recommencer
\fi
}
\catcode`\@12
a) \compte{9}\qquad
b) \compte{-4}\qquad
c) \compte{2}
****************** Fin code ******************
****************** Code 148 ******************
\catcode`\@11
\def\compte#1{%
\ifnum#1>\z@% ne faire quelque chose que si #1 > 0
\antefi\compte@i{1}{#1}%
\fi
}
\def\compte@i#1#2{%
#1% afficher le nombre
\ifnum#1<#2 % si le maxi n'est pas atteint
\expandafter\identity% ex�cuter...
\else
\expandafter\gobone% sinon, manger...
\fi% le code entre accolades ci-dessous
{, % afficher la virgule et l'espace
\exparg\compte@i{\number\numexpr#1+1}{#2}% appel r�cursif
}%
}
\catcode`\@12
a) \compte{9}\qquad
b) \compte{-4}\qquad
c) \edef\foo{\compte{2}}\meaning\foo
****************** Fin code ******************
****************** Code 149 ******************
\catcode`\@11
\def\compte#1{%
\ifnum#1>\z@% ne faire quelque chose que si #1 > 0
\antefi\compte@i{1}{#1}%
\fi
}
\def\compte@i#1#2{%
#1% afficher le nombre
\ifnum#1<#2 % si le maxi n'est pas atteint
\antefi% d�place le \fi ici
, % affiche la virgule et l'espace
\exparg\compte@i{\number\numexpr#1+1}{#2}% appel r�cursif
\fi
}
\catcode`\@12
a) \compte{9}\qquad
b) \compte{-4}\qquad
c) \edef\foo{\compte{2}}\meaning\foo
****************** Fin code ******************
****************** Code 150 ******************
\catcode`\@11
\def\for#1=#2to#3\do#4{% #1=\<macro> #2=n1 #3=n2 #4=<code>
\def#1{#2}% initialise la \<macro> � l'entier n1
\def\val@max{#3}% stocke n2
\def\loop@code{#4}% stocke le <code>
\for@i#1% appelle la macro r�cursive et passe la \<macro> en argument
}
\def\for@i#1{%
\unless\ifnum#1>\val@max\relax% tant que la \<macro> est <= n2
\loop@code% effectue le code pr�c�demment sauvegard�
\edef#1{\number\numexpr#1+1}% incr�menter la \<macro>
\expandafter\for@i\expandafter#1% et recommencer apr�s avoir mang� le \fi
\fi
}
\catcode`\@=12
\for\ii=1to5\do{Maintenant \string\ii\ vaut : \ii.\endgraf}\medbreak
"\for\ii=1to0\do{A}"\medbreak% boucle parcourue 0 fois
"\for\ii=1to1\do{A}"\medbreak% boucle parcourue 1 fois
\for\ii = 0 to 10 \do {[\ii]}.
****************** Fin code ******************
****************** Code 151 ******************
\catcode`\@11
\long\def\for#1=#2to#3\do#4{%
\def\for@i{%
\unless\ifnum#1>\val@max\relax% tant que la \<macro> <= n2
#4% code � ex�cuter
\edef#1{\number\numexpr#1+1}% incr�menter \<macro>
\expandafter\for@i% et recommencer apr�s avoir mang� le \fi
\fi
}%
\edef#1{\number\numexpr#2\relax}% initialise la variable � n1
\edef\val@max{\number\numexpr#3\relax}% stocke n2
\for@i% appelle la sous-macro r�cursive
}
\catcode`\@=12
\for\ii = 1 to 5 \do {Maintenant \string\ii\ vaut : \ii.\par}\medbreak
"\for\ii=1to0\do{A}"\medbreak% boucle parcourue 0 fois
"\for\ii=1to1\do{A}"\medbreak% boucle parcourue 1 fois
\for\ii = 0 to 10 \do {[\ii]}.
****************** Fin code ******************
****************** Code 152 ******************
\catcode`\@11
\def\for#1=#2to#3\do#4#{%
\edef\for@increment{\number\numexpr0#4}% lit et normalise l'argument optionnel
\ifnum\for@increment=\z@% s'il est nul,
\edef\for@increment{% le red�finir :
\ifnum\numexpr#3\relax<\numexpr#2\relax
-% ajoute un signe - si #3<#2
\fi
1% devant "1"
}% \for@increment vaut donc 1 ou -1
\fi
\ifnum\numexpr\for@increment*(#3-#2)\relax<\z@% si l'argument est incompatible
\expandafter\firstoftwo% ex�cuter le 1er argument qui suit
\else
\expandafter\secondoftwo% sinon le second
\fi
{Incr�ment incompatible !\gobone %\gobone mangera le <code> qui � lire
}%
{\edef#1{\number\numexpr#2\relax}% initialise la \<macro>
\edef\cmp@sgn{\ifnum\for@increment<\z@<\else>\fi}% stocke "<" ou ">" pour plus tard
\expandafter\for@i\expandafter#1\expandafter% appelle la macro r�cursive
{\number\numexpr#3\relax}% et lui lui passe la \<macro> (#1) et n2 (#3)
}%
}
% #1 = \<macro> #2 = n2
\long\def\for@i#1#2#3{% l'argument #3 (le <code>) est lu � ce moment-l�
\def\for@ii{%
\unless\ifnum#1\cmp@sgn#2\relax% tant que la \<macro> n'a pas d�pass� n2
#3% ex�cute le <code>
\edef#1{\number\numexpr#1+\for@increment}% incr�mente la \<macro>
\expandafter\for@ii% recommence apr�s avoir mang� le \fi
\fi
}%
\for@ii% appelle la sous-macro r�cursive
}%
\catcode`\@=12
a) \for\ii = -4 to 7 \do{(\ii)}\par
b) \for\jj = 20 to -50\do-10 {(\jj)}\par
c) \for\xx = 8 to 185\do 20 {[\xx]}\par
d) \for\yy = 0 to 10\do -2{(\yy)}\par
e) "\for\ii = 1 to 0 \do1{XX}"\par
f) "\for\ii = 1 to 1 \do{A}"\par% boucle parcourue 1 fois
g) \for\ii=1to4\do{\for\jj=0to2\do{(\ii,\jj)}\par}% imbrication de boucles
****************** Fin code ******************
****************** Code 153 ******************
\catcode`\@11
\def\for#1=#2to#3\do#4#{%
\edef\for@increment{\number\numexpr0#4}% lit et normalise l'argument optionnel
\ifnum\for@increment=\z@% s'il est nul,
\edef\for@increment{% le red�finir � -1 (si #3<#2) et 1 sinon
\ifnum\numexpr#3-#2\relax<\z@ -1\else 1\fi
}% \for@increment vaut donc 1 ou -1
\fi
\ifnum\numexpr\for@increment*(#3-#2)\relax<\z@
\expandafter\gobone% si argument optionnel incompatible, manger le {<code>}
\else
\edef#1{\number\numexpr#2}% 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
\ifnum\for@increment<\z@ <\else >\fi% #2=signe de comparaison
{\for@increment}% #3=incr�ment
\noexpand#1% #4=\<macro>
{\number\numexpr#3\relax}% #5=entier 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=entier n2 % #6=<code> � ex�cuter
\long\def\for@i#1#2#3#4#5#6{%
\def#1{% d�finit la sous macro r�cursive
\unless\ifnum#4#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{\number\numexpr#4+#3\relax}% incr�mente la \<macro>
#1% recommence
}%
\fi
}%
#1% appelle la sous-macro r�cursive
}%
\catcode`\@=12
\for\ii=1to4\do{\for\jj=0to2\do{(\ii,\jj)}\par}\medbreak
\for\carA= `\A to `\E \do{\for\carB= `w to `z \do{\char\carA\char\carB}\quad}
****************** Fin code ******************
****************** Code 154 ******************
\catcode`\@11
\long\def\for@i#1#2#3#4#5#6{%
\def\exitfor{\def#1{}}%
\def#1{% d�finit 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
}%
\catcode`\@=12
\for\ii= 1 to 9 \do{\string\ii{} vaut \ii.\ifnum\ii=5 \exitfor\fi\par}
****************** Fin code ******************
****************** Code 155 ******************
\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 �gale � la macro "\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
}
% on ne sort QUE de la boucle int�rieure quand \ii=3 donc
% les boucles sont normalement ex�cut�es pour \ii=4 et \ii=5
a. \for\ii=1 to 5\do1{%
\for\jj=1 to 3\do1{(\ii,\jj) \ifnum\ii=3 \exitfor\jj\fi}%
\qquad
}
% on sort de la boucle ext�rieure lorsque \ii=3 donc la boucle
% int�rieure est faite enti�rement m�me lorsque \ii=3
b. \for\ii=1 to 5\do1{%
\for\jj=1 to 3\do1{(\ii,\jj) \ifnum\ii=3 \exitfor\ii\fi}%
\qquad
}
% on sort de la boucle int�rieure lorsque \ii=3
% et aussi de la boucle ext�rieure � l'aide de \ifexitfor
c. \for\ii=1 to 5\do1{%
\for\jj=1 to 3\do1{(\ii,\jj) \ifnum\ii=3 \exitfor\jj\fi}%
\ifexitfor\jj{\exitfor\ii}{}% si on est sorti de \jj, sortir aussi de \ii
\qquad
}
****************** Fin code ******************
****************** Code 156 ******************
\def\foo{a}\ifx a\foo vrai\else faux\fi
****************** Fin code ******************
****************** Code 157 ******************
1) \meaning9\par% un caract�re de catcode 12
2) \meaning a\par% une lettre
3) \def\foo{a}\meaning\foo\par% une macro
4) \long\def\foo{a}\meaning\foo\par% une macro d�clar�e \long
5) \meaning\sdlkfj\par% une macro ind�finie
6) \edef\foo{\string a}\meaning\foo\par%\foo contient un "a" de catcode 12
7) \def\foo{a}\meaning\foo\par%\foo contient un "a" de catcode 11
****************** Fin code ******************
****************** Code 158 ******************
a) \ifx abvrai\else faux\fi\quad% a est n'est pas �gal � b
b) \ifx++vrai\else faux\fi\quad% le caract�re "+" est �gal � "+"
c) \ifx\relax\par vrai\else faux\fi\quad% \relax n'est pas la m�me primitive que \par
d) \ifx\par\par vrai\else faux\fi\quad% \par et \par sont les m�mes primitives
e) \ifx\sdfk\qlms vrai\else faux\fi\quad% 2 macros non d�finies sont �gales
f) \def\foo{abcd}\def\bar{abc}% \foo et \bar ont des textes de remplacement diff�rents
\ifx\foo\bar vrai\else faux\fi\quad
g) \def\foo{abcd}\def\bar{abcd }% \foo et \bar ont des textes de remplacement diff�rents
\ifx\foo\bar vrai\else faux\fi\quad
h) \def\foo{abcd}\def\bar{abcd}
\ifx\foo\bar vrai\else faux\fi\quad% \foo et \bar ont les m�mes textes de remplacement
i) \long\def\foo{a}\def\bar{a}
\ifx\foo\bar vrai\else faux\fi\quad% \foo est \long, \bar ne l'est pas
j) \edef\foo{\string a}% \foo contient un "a" de catcode 12
\def\bar{a}% \bar contient un "a" de catcode 11
\ifx\foo\bar vrai\else faux\fi
****************** Fin code ******************
****************** Code 159 ******************
\def\cmpmacro#1#2{%
\begingroup
\edef\tempa{\detokenize\expandafter{#1}}\edef\tempb{\detokenize\expandafter{#2}}%
\ifx\tempa\tempb% si �galit�
\endgroup\expandafter\firstoftwo% ferme le groupe et lit 1er argument
\else
\endgroup\expandafter\secondoftwo% sinon, ferme le groupe et lit le 2e argument
\fi
}
a) \edef\foo{\string a}\def\bar{a}
\cmpmacro\foo\bar{vrai}{faux}\qquad
b) \edef\foo{\detokenize{$i^2=-1$\relax}}\def\bar{$i^2=-1$\relax}
\cmpmacro\foo\bar{vrai}{faux}
****************** Fin code ******************
****************** Code 160 ******************
a) \let\rien\relax \ifx\rien\relax vrai\else faux\fi\qquad
b) \let\AA=a \ifx a\AA vrai\else faux\fi\qquad
c) \let\foo=_\let\bar=_ \ifx\foo\bar vrai\else faux\fi
****************** Fin code ******************
****************** Code 161 ******************
\def\quark{\quark}% d�finit un quark
1) \def\test{\quark} \ifx\quark\test vrai\else faux\fi
\qquad
2) \let\test=\quark \ifx\quark\test vrai\else faux\fi
****************** Fin code ******************
****************** Code 162 ******************
\def\ifempty#1{%
\def\tempa{#1}% stocke l'argument #1 dans \tempa
\ifx\tempa\empty% si \tempa = \empty
\expandafter\firstoftwo% 1er argument
\else
\expandafter\secondoftwo% sinon, second
\fi
}
a) \ifempty{abc}{vide}{pas vide}\qquad
b) \ifempty{}{vide}{pas vide}\qquad
c) \ifempty{ }{vide}{pas vide}\qquad
d) \ifempty{\empty}{vide}{pas vide}
****************** Fin code ******************
****************** Code 163 ******************
\def\empty{}
\long\def\ifempty#1{%
\ifx_#1_\expandafter\firstoftwo
\else\expandafter\secondoftwo
\fi}
a) \ifempty{abc}{vide}{pas vide}\qquad
b) \ifempty{}{vide}{pas vide}\qquad
c) \ifempty{ }{vide}{pas vide}\qquad
d) \ifempty{\empty}{vide}{pas vide}\qquad
e) \edef\foo{\ifempty{abc}{vide}{pas vide}}\meaning\foo
****************** Fin code ******************
****************** Code 164 ******************
\long\def\ifempty#1{%
\ifx W#1W\expandafter\firstoftwo
\else \expandafter\secondoftwo
\fi}
1) \ifempty{foobar}{vide}{pas vide}\qquad
2) \ifempty{}{vide}{pas vide}\qquad
2) \ifempty{\empty}{vide}{pas vide}\qquad
4) \ifempty{Wagons}{vide}{pas vide}
****************** Fin code ******************
****************** Code 165 ******************
\long\def\ifempty#1{%
\expandafter\ifx\expandafter\relax\detokenize{#1}\relax
\expandafter\firstoftwo
\else
\expandafter\secondoftwo
\fi
}
a) \ifempty{abc}{vide}{pas vide}\qquad
b) \ifempty{}{vide}{pas vide}\qquad
c) \ifempty{ }{vide}{pas vide}\qquad
d) \ifempty{\relax}{vide}{pas vide}\qquad
e) \edef\foo{\ifempty{abc}{vide}{pas vide}}\meaning\foo
****************** Fin code ******************
****************** Code 166 ******************
\catcode`\@11
\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
}
\catcode`\@12
a) \reverse{foobar}\qquad
b) \edef\foo{\reverse{Bonjour}}\meaning\foo\qquad
c) \reverse{Bonjour le monde}\qquad
d) \reverse{Bonjour{ }le{ }monde}
****************** Fin code ******************
****************** Code 167 ******************
\catcode`\@11
\def\ifin#1#2{%
\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
}
\catcode`\@12
a) \ifin{abc\relax1}{bc}{vrai}{faux}\qquad
b) \ifin{abc \relax1}{c\relax}{vrai}{faux}\qquad
c) \ifin{abc \relax1}{ }{vrai}{faux}\qquad
d) \ifin{abc \relax1}{}{vrai}{faux}\qquad
e) \ifin{}{a}{vrai}{faux}
****************** Fin code ******************
****************** Code 168 ******************
\catcode`\@11
\def\ifstart#1#2{%
\def\ifstart@i##1#2##2\@nil{\ifempty{##1}}%
\ifstart@i#1#2\@nil
}
\catcode`\@12
a) \ifstart{abc}{bc}{vrai}{faux}\qquad
b) \ifstart{abc}{ab}{vrai}{faux}\qquad
c) \ifstart{ abc}{ }{vrai}{faux}\qquad
d) \ifstart{abc}{}{vrai}{faux}\qquad
e) \ifstart{}{a}{vrai}{faux}
****************** Fin code ******************
****************** Code 169 ******************
\catcode`\@11
\def\ifstart#1#2{%
\def\ifstart@i##1#2##2\@nil{\ifempty{##1}}%
\ifempty{#2}% si motif vide
\firstoftwo% ex�cuter code "vrai"
{\ifstart@i#1\relax#2\@nil}% sinon, aller � la macro auxiliaire
}
\catcode`\@12
a) \ifstart{abc}{bc}{vrai}{faux}\qquad
b) \ifstart{abc}{ab}{vrai}{faux}\qquad
c) \ifstart{ abc}{ }{vrai}{faux}\qquad
d) \ifstart{abc}{}{vrai}{faux}\qquad
e) \ifstart{}{a}{vrai}{faux}
****************** Fin code ******************
****************** Code 170 ******************
\catcode`\@11
\def\ifend#1#2{%
\def\ifend@i##1#2##2\@nil{% ##2 = ce qui reste apr�s le motif
\ifempty{##2}% si ##2 est vide
\firstoftwo% ex�cuter l'argument "vrai"
{\ifin{##2}{#2}% sinon, si ##2 contient le <motif>
{\ifend@i##2\@nil}% appeler \ifend@i avec ce qui reste
\secondoftwo% sinon, ex�cuter l'argument "faux"
}%
}%
\ifend@i#2#1\@nil% appelle la macro r�cursive
}
\catcode`\@12
1) \ifend{abc de}{de}{vrai}{faux}\qquad
2) \ifend{abd de }{de}{vrai}{faux}\qquad
3) \ifend{abc de }{ }{vrai}{faux}\qquad
4) \ifend{}{a}{vrai}{faux}\qquad
5) \ifend{abc de}{}{vrai}{faux}
****************** Fin code ******************
****************** Code 171 ******************
\catcode`\@11
\def\ifend#1#2{%
\def\ifend@i##1#2##2\@nil{% ##2 = ce qui reste apr�s le motif
\ifempty{##2}% si ##2 est vide
\firstoftwo% ex�cuter l'argument "vrai"
{\ifin{##2}{#2}% sinon, si ##2 contient le <motif>
{\ifend@i##2\@nil}% appeler \ifend@i avec ce qui reste
\secondoftwo% sinon, ex�cuter l'argument "faux"
}%
}%
\ifempty{#2}% si le motif est vide
\firstoftwo% ex�cuter "vrai"
{\ifend@i#2\relax#1\@nil}% sinon, appelle la macro r�cursive
}
\catcode`\@12
1) \ifend{abc de}{de}{vrai}{faux}\qquad
2) \ifend{abd de }{de}{vrai}{faux}\qquad
3) \ifend{abc de }{ }{vrai}{faux}\qquad
4) \ifend{}{a}{vrai}{faux}\qquad
5) \ifend{abc de}{}{vrai}{faux}
****************** Fin code ******************
****************** Code 172 ******************
\catcode`\@11
\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}%
}
\catcode`\@12
a) \substin{abracadabra}{a}{A}\qquad
b) \substin{abracadabra}{x}{W}\qquad
c) \substin{abracadabra}{br}{}\qquad
d) \substin{1\relax3}\relax{222}\qquad
****************** Fin code ******************
****************** Code 173 ******************
\catcode`\@11
\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}%
}
\catcode`\@12
\substtocs\foo{abracadabra}{a}{A}\meaning\foo\par
\substtocs\foo{abracadabra}{x}{W}\meaning\foo\par
\substtocs\foo{abracadabra}{br}{}\meaning\foo\par
\substtocs\foo{1\relax3}\relax{222}\meaning\foo\par
\substtocs\foo{\ifnum1=2 test vrai\fi}{2}{1}\meaning\foo
****************** Fin code ******************
****************** Code 174 ******************
\def\majuscule#1{\uppercase{#1}}
\def\majmot#1{\substin{\majuscule#1}{ }{ \majuscule}}
\majmot{un petit texte}\par
\majmot{Un grand texte sans importance}
****************** Fin code ******************
****************** Code 175 ******************
\def\majuscule#1{\uppercase{#1}}
\def\majmot#1{%
\begingroup
\substtocs\temp{\majuscule#1}{ }{ \majuscule}%
\temp% ex�cute la macro temporaire
\endgroup
}
\majmot{un petit texte}\par
\majmot{Un grand texte Sans importance}
****************** Fin code ******************
****************** Code 176 ******************
\catcode`\@11
\newcount\cnt@occ
\def\cnttimes#1#2{%
\def\cnttimes@i##1{%
\ifempty{##1}% si le <code> est vide
{\number\cnt@occ}% afficher le nombre d'occurrences
{\ifin{##1}{#2}% sinon, si le <code> contient <motif1>
{\cnttimes@ii##1\@nil}% appeler la macro � argument d�limit�s
{\number\cnt@occ}% sinon, afficher le nombre d'occurrences
}%
}%
\def\cnttimes@ii##1#2##2\@nil{%
\advance\cnt@occ1
\cnttimes@i{##2}% et recommencer avec ce qui reste
}%
\cnt@occ=0 % initialise le compteur
\cnttimes@i{#1}%
}
\catcode`\@12
a) \cnttimes{abracadabra}{a}\qquad
b) \cnttimes{abracadabra}{ra}\qquad
c) \cnttimes{abracadabra}{w}\qquad
d) \cnttimes{abc def ghijk l }{ }\qquad
e) \cnttimes{\ifnum1=2 vrai\else faux\fi}{\ifnum}
****************** Fin code ******************
****************** Code 177 ******************
\catcode`\@11
\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
}
\catcode`\@12
a) \cnttimestocs{abracadabra}{a}\foo \meaning\foo\qquad
b) \cnttimestocs{abracadabra}{ra}\foo \meaning\foo\qquad
c) \cnttimestocs{abracadabra}{w}\foo \meaning\foo\qquad
d) \cnttimestocs{abc def ghijk l }{ }\foo \meaning\foo\qquad
e) \cnttimestocs{\ifnum1=2 vrai\else faux\fi}{\ifnum}\foo \meaning\foo
****************** Fin code ******************
****************** Code 178 ******************
\catcode`\@11
\def\multisubst#1#2{%
\def\subst@code{#1}% stocke le <code>
\multisubst@i#2\@nil% appelle la macro r�cursive avec la liste de motifs
}
\def\multisubst@i#1#2#3\@nil{% #1 et #2=paire de motifs #3=motifs restants
\expandafter\substtocs\expandafter\subst@code\expandafter% 1-d�veloppe
{\subst@code}{#1}{#2}% le <code> et effectue la substitution en cours
\ifempty{#3}% si la liste des motifs est vide
\subst@code% ex�cuter le <code> obtenu
{\multisubst@i#3\@nil}% recommencer avec les motifs qui restent
}
\catcode`\@12
1) \multisubst{abracadabra}{aA rR}\par
2) \multisubst{Ce texte devenu \`a peine reconnaissable montre que le
r\'esultat contient des sonorit\'es catalanes, corses ou grecques
assez inattendues.}{a{AA} ya uy ou io ei {AA}e}
****************** Fin code ******************
****************** Code 179 ******************
\catcode`\@11
\def\quark{\quark}
\def\multisubst#1#2{% #1 = <code> #2 = <liste des paires>
\def\subst@code{#1}% stocke le <code>
\multisubst@i#2\quark\quark% appelle la macro r�cursive avec
% 2 arguments sp�ciaux en fin de liste
}
\def\multisubst@i#1#2{% #1#2 = paire de motifs en cours
\def\arg@a{#1}% stocke le <motif1> dans une macro
\ifx\arg@a\quark% si le motif sp�cial est atteint
\expandafter\subst@code% ex�cuter le code obtenu
\else
\expandafter\substtocs\expandafter\subst@code\expandafter% 1-d�veloppe
{\subst@code}{#1}{#2}% le <code> et effectue la substitution en cours
\expandafter\multisubst@i% puis lis la paire de motifs suivants
\fi
}
\catcode`\@12
\multisubst{abracadabra}{aA rR}\par
\multisubst{Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des
sonorit\'es catalanes, corses ou grecques assez inattendues.}{a{AA} ya uy ou io ei {AA}e}
****************** Fin code ******************
****************** Code 180 ******************
\iftrue foobar\else ceci n'est jamais lu par \TeX\fi\par
\iffalse ceci n'est jamais lu par \TeX\else foobar\fi
****************** Fin code ******************
****************** Code 181 ******************
\newif\ifhomme
\def\debutlettre{Ch\ifhomme er Monsieur\else �re Madame\fi}%
\hommetrue
\debutlettre
\medbreak
\hommefalse
\debutlettre
****************** Fin code ******************
****************** Code 182 ******************
\catcode`\*=13 \catcode`\+=13 % "*" et "+" sont actifs
1) \def*{xyz}\def+{abc}% d�finit les caract�res actifs
\ifcat *+vrai\else faux\fi\qquad
2) \ifcat \noexpand *\noexpand +vrai\else faux\fi\qquad
3) \def\foo{foobar}%
\ifcat \noexpand\foo\relax vrai\else faux\fi\qquad% \foo et \relax sont vus �gaux
4) \ifcat = vrai\else faux\fi\qquad% "=" et " " n'ont pas le m�me catcode
5) \ifcat _^vrai\else faux\fi\qquad% "_" et "^" n'ont pas le m�me catcode
6) \let\foo=&
\ifcat &\foo vrai\else faux\fi% "&" et \foo (let-�gal � "&") sont vus �gaux
****************** Fin code ******************
****************** Code 183 ******************
\catcode`\@11
\def\ifcs#1{%
\ifcat\noexpand#1\relax\expandafter\firstoftwo
\else \expandafter\secondoftwo
\fi
}
\catcode`\@12
1) \def\foo{bar}\ifcs\foo{vrai}{faux}\qquad
2) \ifcs\def{vrai}{faux}\qquad
3) \ifcs A{vrai}{faux}\qquad
\catcode`\*=13
4) \let*=W \ifcs*{vrai}{faux}\qquad
5) \let*=\relax \ifcs*{vrai}{faux}\qquad
6) \let\foo=A \ifcs\foo{vrai}{faux}\qquad
7) \ifcs\bgroup{vrai}{faux}
****************** Fin code ******************
****************** Code 184 ******************
1) \def\foo{xxy}\def\bar{aab}
\if\foo\bar vrai\else faux\fi\qquad
2) \if aA vrai\else faux\fi\qquad% "a" et "A" n'ont pas les m�mes charcode
3) \if\relax\noexpand\foo vrai\else faux\fi\qquad% \relax et \foo ont un charcode=256
4) \let\foo=&\if\foo &vrai\else faux\fi\qquad% \foo est vue comme "&"
5) \if\string~\noexpand~vrai\else faux\fi
****************** Fin code ******************
****************** Code 185 ******************
\catcode`\@11
\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
}
\catcode`\@12
1) \def\foo{bar}\ifcs\foo{vrai}{faux}\qquad
2) \ifcs\def{vrai}{faux}\qquad
3) \ifcs A{vrai}{faux}\qquad
\catcode`\*=13
4) \let*=W \ifcs*{vrai}{faux}\qquad
5) \let*=\relax \ifcs*{vrai}{faux}\qquad
6) \let\foo=A \ifcs\foo{vrai}{faux}\qquad
7) \ifcs\bgroup{vrai}{faux}
****************** Fin code ******************
****************** Code 186 ******************
\edef\specialrelax{\ifnum1=1\fi}
\meaning\specialrelax
****************** Fin code ******************
****************** Code 187 ******************
\edef\specialrelax{\ifnum1=1\fi}% texte de remplacement = \relax sp�cial
\edef\normalrelax{\relax}% texte de remplacement = \relax normal
\meaning\specialrelax\par
\meaning\normalrelax\par
Les 2 \string\relax{} sont \ifx\specialrelax\normalrelax identiques\else diff�rents\fi.
****************** Fin code ******************
****************** Code 188 ******************
\edef\specialrelax{\ifnum1=1\fi}
\expandafter\def\specialrelax{foobar}% red�finition un \relax sp�cial
****************** Fin code ******************
****************** Code 189 ******************
\catcode`\@11
\def\ifnumcase#1{%
\begingroup
\def\elseif{\elseif}\def\endif{\endif}% d�finir deux "quarks" locaux
\def\nombre@{#1}% stocker le nombre � comparer dans \nombre@
\ifnumcase@i% appeller la macro r�cursive
}
\def\ifnumcase@i#1{%
\def\nxt@arg{#1}% stocker l'argument suivant
\ifx\nxt@arg\elseif% si c'est \elseif
\def\next@todo{\endgroup\idto@endif}% fermer le groupe et aller � \idto@endif
\else
\ifx\nxt@arg\endif% si c'est \endif
\let\next@todo\endgroup% fermer le groupe
\else
\ifnum\nombre@=\nxt@arg% s'il y a �galit�
\def\next@todo{\endgroup\firstto@endif}% fermer le groupe puis \firstto@endif
\else% sinon
\let\next@todo=\ifnumcase@ii% aller � \ifnumcase@ii
\fi
\fi
\fi
\next@todo% ex�cuter l'action d�cid�e ci-dessus
}
\def\ifnumcase@ii#1{\ifnumcase@i}
\def\idto@endif#1\endif{#1}
\def\firstto@endif#1#2\endif{#1}
\catcode`\@12
\def\swaptwo#1#2{#2#1}
\def\testenombre#1{%
\ifnumcase{#1}
{1}{C'est "un" et je prends le premier argument: \firstoftwo}
{3}{J'ai vu un "trois" et je mange les deux arguments : \gobtwo}
{15}{L'argument est "15" et je prends le second argument : \secondoftwo}
\elseif
ni 1, ni 3, ni 5 et j'inverse les deux arguments : \swaptwo
\endif
}
\testenombre{3}{foo}{bar}\par
\testenombre{16}{foo}{bar}\par
\testenombre{15}{foo}{bar}\par
\testenombre{1}{foo}{bar}
****************** Fin code ******************
****************** Code 190 ******************
\catcode`\@11
\def\endif{\endif}\def\elseif{\elseif}% d�finit les quarks
\def\ifnumcase#1#2{% #1=<nombre> #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 #2 est une <valeur i>:
{\ifnum#1=#2 % s'il y a �galit� entre <nombre> et <valeur i>
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
\firstto@endif% aller � \firstto@endif
{\ifnumcase@i{#1}}% sinon aller � \ifnumcase@i
}%
}%
}
\def\ifnumcase@i#1#2{% #1=<nombre> #2=<code i> � suivre qui est mang�
\ifnumcase{#1}% retourner � \ifnumcase en transmettant #1
}
\def\idto@endif#1\endif{#1}
\def\firstto@endif#1#2\endif{#1}
\catcode`\@12
\def\swaptwo#1#2{#2#1}
\def\testenombre#1{%
\ifnumcase{#1}
{1}{C'est "un" et je prends le premier argument: \firstoftwo}
{3}{J'ai vu un "trois" et je mange les deux arguments : \gobtwo}
{15}{L'argument est "15" et je prends le second argument : \secondoftwo}
\elseif
ni 1, ni 3, ni 5 et j'inverse les deux arguments : \swaptwo
\endif
}
\testenombre{3}{foo}{bar}\par
\testenombre{16}{foo}{bar}\par
\testenombre{15}{foo}{bar}\par
\edef\macro{\testenombre{1}{foo}{bar}}\meaning\macro
****************** Fin code ******************
****************** Code 191 ******************
\catcode`\@11
\def\endif{\endif}\def\elseif{\elseif}%
\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 #2 est un <token i>:
{\ifx#1#2% s'il y a �galit� entre <token> et <token i>
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
\firstto@endif% aller � \firstto@endif
{\ifxcase@i{#1}}% sinon aller � \ifnumcase@i
}%
}%
}
\def\ifxcase@i#1#2{% #1=<token> #2=<code i> � suivre (qui est mang�)
\ifxcase{#1}% retourner � \ifxcase en transmettant #1
}
\def\idto@endif#1\endif{#1}
\def\firstto@endif#1#2\endif{#1}
\catcode`\@12
\def\testtoken#1{%
\ifxcase{#1}
a{Le token est "a"}
+{J'ai vu un "+"}
\relax{L'argument est "\string\relax"}
\elseif
Tous les tests sont n�gatifs%
\endif
}
1) \testtoken a\par
2) \let\foo=a\testtoken\foo\par
3) \testtoken+\par
4) \testtoken\relax\par
5) \edef\foo{\testtoken\relax}\meaning\foo\par
6) \edef\foo{\testtoken W}\meaning\foo
****************** Fin code ******************
****************** Code 192 ******************
\newcount\xx % d�finit un compteur utilis� dans la boucle
\def\compte#1{%
\xx=0 % initialise le compteur
\loop% d�but de la boucle
\advance\xx1 % incr�mente le compteur
\ifnum\xx<#1 % s'il est inf�rieur � la borne
\number\xx , % affiche le nombre et la virgule
\repeat% et recommence
\ifnum#1>0 \number\xx\relax\fi% si le nombre #1 est >0, afficher le dernier nombre
}
a) \compte{1}.\qquad b) \compte{-3}.\qquad c) \compte{7}.
****************** Fin code ******************
****************** Code 193 ******************
\catcode`\@11
\newcount\cnt@repeat % d�finit le compteur de \xrepeat
\def\xloop{%
\def\xiterate{}% initialiser \xiterate � vide
\cnt@repeat\z@% initialiser le compteur de \xrepeat
\xloop@i% aller � la macro r�cursive
}
\long\def\xloop@i#1\xrepeat{%
\addtomacro\xiterate{#1}% ajoute ce qui est avant le premier \xrepeat
\exparg\cnttimestocs{\xiterate}\xloop\cnt@loop
% combien de \xloop dans \xiterate
\ifnum\cnt@loop=\cnt@repeat\relax
\expandafter\firstoftwo\else\expandafter\secondoftwo
\fi
{% autant que de \xrepeat -> \detokenize pour afficher
"\detokenize\expandafter{\xiterate}"%
}
{\addtomacro\xiterate\xrepeat% sinon, ajouter ce \xrepeat
\advance\cnt@repeat by 1% incr�menter le compteutr de \xrepeat
\xloop@i% et chercher le prochain \xrepeat
}%
}
\let\xrepeat\fi
\catcode`\@12
\xloop a\xloop b\xloop 12\xrepeat c\xrepeat \xloop X\xrepeat\xrepeat
****************** Fin code ******************
****************** Code 194 ******************
\catcode`\@11
\newcount\cnt@repeat
\newcount\cnt@nested
\cnt@nested=0 % compteur d'imbrications
\def\xloop{%
\global\advance\cnt@nested by 1 % augmente le compteur d'imbrications
\expandafter\def\csname xiterate@\number\cnt@nested\endcsname{}%
\cnt@repeat\z@% initialise le compteur de \xrepeat � 0
\xloop@i% aller � la macro \xloop@i
}
\long\def\xloop@i#1\xrepeat{%
\expandafter\addtomacro\csname xiterate@\number\cnt@nested\endcsname{#1}%
\expandafter\expandafter\expandafter\cnttimestocs\expandafter\expandafter\expandafter
{\csname xiterate@\number\cnt@nested\endcsname}\xloop\cnt@loop
\ifnum\cnt@loop=\cnt@repeat\relax
\expandafter\firstoftwo\else\expandafter\secondoftwo
\fi
{\expandafter\eaddtomacro\csname xiterate@\number\cnt@nested\expandafter\endcsname
{\expandafter\expandafter\csname xiterate@\number\cnt@nested\endcsname\fi}%
%\expandafter\show\csname xiterate@\number\cnt@nested\endcsname
\csname xiterate@\number\cnt@nested\endcsname
\letname{xiterate@\number\cnt@nested}\relax
\global\advance\cnt@nested by -1
}
{\expandafter\addtomacro\csname xiterate@\number\cnt@nested\endcsname\xrepeat
\advance\cnt@repeat by 1
\xloop@i
}%
}%
\let\xrepeat\fi
\catcode`\@12
\newcount\cntxx \cntxx=1 % compteur des lignes
\newcount\cntyy
\xloop
\cntyy=1 % compteur des colonnes
\xloop
(\number\cntxx,\number\cntyy)% affiche "(ligne,colonne)"
\ifnum\cntyy<5 % tant que colonne<5
\advance\cntyy1 % incr�mente colonne
, % <- affiche ", "
\xrepeat% et recommence
\ifnum\cntxx<3 % tant que ligne<3
\advance\cntxx1 % incr�mente ligne
\par % va � la ligne
\xrepeat% et recommence
****************** Fin code ******************
****************** Code 195 ******************
\catcode`\@11
\def\end@foreach{\end@foreach}% d�finit un quark
\long\def\doforeach#1\in#2#3{%
\def\loop@code{#3}% assigne le <code> � \loop@code
% appel � \doforeach@i : mettre la macro #1 en premier, puis la liste de valeurs #2
\doforeach@i#1#2,\end@foreach,% ajouter � la fin ",\end@foreach,"
% une fois les boucles finies, neutraliser les macros d�j� d�finies
\let#1\relax \let\loop@code\relax
}
\long\def\doforeach@i#1#2,{% #1=\<macro> #2=valeur courante
\def#1{#2}% stocke la valeur en cours dans la \<macro>
\unless\ifx\end@foreach#1% si \end@foreach n'est pas atteint
\antefi% am�ne le \fi ici
\loop@code% ex�cute le code
\doforeach@i#1% et recommencer
\fi
}
\catcode`@12
\doforeach\x\in{a,bcd,{efg},hi}{\meaning\x.\par}
****************** Fin code ******************
****************** Code 196 ******************
\catcode`\@11
\def\end@foreach{\end@foreach}
\def\defseplist#1{%
\long\def\doforeach##1\in##2##3{%
\def\loop@code{##3}% assigne le <code> � \loop@code
\doforeach@i##1##2#1\end@foreach#1% ajouter ",\end@foreach," et aller � \doforeach@i
% apr�s �tre sorti des boucles, neutraliser les macros d�j� d�finies
\let\loop@code\relax \let##1\relax
}%
\long\def\doforeach@i##1##2#1{%
\def##1{##2}% stocke la valeur en cours dans la \<macro>
\unless\ifx\end@foreach##1% si la fin n'est pas atteinte
\antefi% am�ne le \fi ici
\loop@code% ex�cute le code
\doforeach@i##1% et recommencer
\fi
}%
}
\defseplist{,}% d�finit les macros avec le s�parateur par d�faut
\catcode`@12
\doforeach\x\in{a,bcd,efg}{Argument courant : "\x".\par}\medbreak
\defseplist{--}% s�parateur "--"
\doforeach\nn\in{4,19--0,5--8,575}{Nombre lu : "\nn"\par}
****************** Fin code ******************
****************** Code 197 ******************
\catcode`\@11
\newcount\cnt@nest \cnt@nest=0 % d�finit et initialise le compteur d'imbrication
\def\end@foreach{\end@foreach}
\def\defseplist#1{%
\long\def\doforeach##1\in##2##3{%
\global\advance\cnt@nest1 % entr�e de boucle : incr�menter le compteur d'imbrication
\defname{loop@code@\number\cnt@nest}{##3}% assigne le <code> � \loop@code@<n>
\doforeach@i##1##2#1\end@foreach#1% ajouter ",\end@foreach," et aller � \doforeach@i
% une fois fini :
\let##1\empty% dans ce cas, neutraliser les macros d�j� d�finies
\letname{loop@code@\number\cnt@nest}\empty%
\global\advance\cnt@nest-1 %sortie de boucle : d�cr�menter le compteur d'imbrication
}%
\long\def\doforeach@i##1##2#1{%
\def##1{##2}% stocke la valeur en cours dans la \<macro>
\unless\ifx\end@foreach##1% tant que la fin n'est pas atteinte
\antefi% am�ne le \fi ici
\csname loop@code@\number\cnt@nest\endcsname% ex�cute le code
\doforeach@i##1% et recommencer
\fi
}%
}
\catcode`@12
\defseplist{,}
\doforeach\xxx\in{1,2,3}{%
Ligne \xxx{} : \doforeach\yyy\in{a,b,c,d,e}{(\xxx,\yyy)}.\par
}
****************** Fin code ******************
****************** Code 198 ******************
\catcode`\@11
\newcount\cnt@nest \cnt@nest=0 % d�finit et initialise le compteur d'imbrication
\def\end@foreach{\end@foreach}
\long\def\save@macro#1{% sauvegarde la macro #1
\ifdefined#1% si la macro #1 est d�j� d�finie...
\letname{saved@var@\number\cnt@nest}#1% ...la sauvegarder
\fi
}
\long\def\restore@macro#1{% restaure la macro #1
% le \csname donne \relax si la sauvegarde n'a pas �t� faite
\expandafter\let\expandafter#1\csname saved@var@\number\cnt@nest\endcsname
}
\def\defseplist#1{%
\long\def\doforeach##1\in##2##3{%
\global\advance\cnt@nest1 % entr�e de boucle : incr�menter le compteur d'imbrication
\save@macro##1% sauvegarde la macro ##1
\defname{loop@code@\number\cnt@nest}{##3}% assigne le <code> � \loop@code@<n>
\doforeach@i##1##2#1\end@foreach#1% ajouter ",\end@foreach," et aller � \doforeach@i
% une fois fini, neutraliser la macro contenant le <code>
\letname{loop@code@\number\cnt@nest}\empty
\restore@macro##1% restaurer la \<macro>
\global\advance\cnt@nest-1 % et d�cr�menter le compteur d'imbrication
}%
\long\def\doforeach@i##1##2#1{%
\def##1{##2}% stocke la valeur en cours dans la \<macro>
\unless\ifx\end@foreach##1% si la fin n'est pas atteinte
\antefi% am�ne le \fi ici
\csname loop@code@\number\cnt@nest\endcsname% ex�cute le code
\doforeach@i##1% et recommencer
\fi%
}%
}
\catcode`@12
\defseplist{,}
\doforeach\par\in{a,b,c,y,z}{$\par_i$}
\meaning\par% \par doit �tre redevenu une primitive
\doforeach\xxx\in{1,2,3}{%
Ligne \xxx{} : \doforeach\yyy\in{a,b,c,d,e}{(\xxx,\yyy)}.\par
}
****************** Fin code ******************
****************** Code 199 ******************
\let\foo=\djfhdsldv% \foo est rendue \let-�gale � une macro ind�finie
a) \meaning\foo\par
% puis \djfhdsldv est rendue \let-�gale � \foo (ou \foo est construit avec \csname)
\expandafter\let\expandafter\djfhdsldv\csname foo\endcsname
b) \meaning\djfhdsldv
****************** Fin code ******************
****************** Code 200 ******************
\catcode`\@11
\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{\letname{saved@var@\number\cnt@nest#1}#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
\global\let\allow@recurse\identity% permet l'appel r�cursif plus bas
\ifin{##1}{/}% si ##1 contient "/"
{\save@macro@i##1% sauvegarde les macros
\doforeach@ii% appeler la macro r�cursive avec les arguments
{##3}% 1) code � ex�cuter
##1% 2) variables sous la forme \<macro1>/\<macro2>
##2#1\end@foreach/\end@foreach#1% puis la liste ##2 suivie de
% ",\end@foreach/\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{%
\ifx\end@foreach##3% si la fin est atteinte
\expandafter\gobone\else\expandafter\identity\fi% manger sinon ex�cuter:
{\def##2{##3}% fait l'assignation � la variable
##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{%
\ifx\end@foreach##4% si la fin est atteinte
\expandafter\gobone\else\expandafter\identity\fi% manger sinon ex�cuter:
{\def##2{##4}\def##3{##5}% fait l'assignation des deux variables
##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,"
}
\def\doforeachexit{\global\let\allow@recurse\forbid@recurse}
\catcode`\@12
\defseplist{,}
\doforeach\par\in{a,b,c,y,z}{$\par_i$}\medskip
\doforeach\sujet/\terminaison\in{Je/e,Tu/es,Il/e,Nous/ons,Vous/ez,Ils/ent}
{\sujet\ programm\terminaison{} en \TeX\par}\medskip
Les voyelles lues sont :
\doforeach\ii\in{a,e,i,o,u,y}{\ii\if o\ii\doforeachexit\fi}.\medskip
\doforeach\xx\in{a,b,c,d,e,f}
{\doforeach\ii\in{1,2,3,4}{\xx\ii{} \ifnum\ii=3 \doforeachexit\fi}\par}
****************** Fin code ******************
****************** Code 201 ******************
\newdimen\dimA \newdimen\dimB% alloue deux registres de dimension
a) \dimA=59.5pt
\the\dimA\qquad% doit afficher 59.5pt
b) \dimA=1.5cm
\the\dimA\qquad% convertit � l'affichage 1.5cm en pt
c) \dimB=7pt % assigne 7pt � \dimB
\dimA\dimB% rend \dimA �gal � dimB
\the\dimA\qquad
d) \dimA=6\dimB% rend \dimA �gal � 6 fois \dimB
\the\dimA
****************** Fin code ******************
****************** Code 202 ******************
\newdimen\foo
\foo=25pt % assigne 25pt au registre \foo
\divide\foo 4 % le multiplie par 4
\advance\foo1.72pt % lui ajoute 1.72pt
\multiply\foo3 % le multiplie par 3
\the\foo% affiche la dimension obtenue
****************** Fin code ******************
****************** Code 203 ******************
\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
\newdimen\foo
a) \foo=15pt \expandafter\removept\the\foo\qquad
b) \foo=3.14pt \expandafter\removept\the\foo
****************** Fin code ******************
****************** Code 204 ******************
\def\dimtodec{\expandafter\removept\the}
\newdimen\foo
a) \foo=15pt \dimtodec\foo \qquad
b) \foo=3.14pt \dimtodec\foo
****************** Fin code ******************
****************** Code 205 ******************
a) \the\dimexpr 1cm + 0.5cm\relax \qquad
b) \the\dimexpr 1pt + 1pt\relax \qquad
c) \the\dimexpr 1pt + 2pt * 3\relax\qquad
d) \the\dimexpr (1pt + 2pt) * 3\relax\qquad
e) \the\dimexpr (1.2pt + 0.8pt) * 5\relax\qquad
f) \newdimen\foo \foo=15pt
\the\dimexpr\foo-(\foo + 1pt) / 4\relax
****************** Fin code ******************
****************** Code 206 ******************
\the\dimexpr0,7pt + 0.4pt\relax
****************** Fin code ******************
****************** Code 207 ******************
a) \newdimen\foodim \foodim=1cm \number\foodim\relax\qquad
b) \number\dimexpr 0.7pt + 0.4pt\relax\qquad
c) \number\dimexpr 1.1pt\relax
****************** Fin code ******************
****************** Code 208 ******************
\catcode`\@11
\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{% d�finit 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
}
\catcode`\@=12
a) \FOR\xx=1.5 to -5\do-1{"\xx" }\par
b) \FOR\ii=1 to 2.742\do.25{"\ii" }\par
c) \FOR\ii=0 to 1\do0.1{"\ii" \ifdim\ii pt>0.5pt \exitFOR\ii\fi}
****************** Fin code ******************
****************** Code 209 ******************
\newdimen\foo
\foo=15.2pt \foo=1.5\foo \the\foo% vaut 15.2*1.5
****************** Fin code ******************
****************** Code 210 ******************
\catcode`\@11
\newdimen\dim@a
\def\decmul#1#2{%
\dim@a=#2pt % range la dimension #2pt dans le registre de dimension
\dim@a=#1\dim@a% multiplier le registre par le d�cimal #1
\dimtodec\dim@a% convertir la dimension en d�cimal
}
\catcode`\@12
a) \decmul{15.2}{1.5}\qquad
b) \decmul{48.2}{.375}
****************** Fin code ******************
****************** Code 211 ******************
\def\decmul#1#2{\dimtodec\dimexpr#1\dimexpr#2pt\relax\relax}
a) \decmul{15.2}{1.5}\qquad
b) \edef\foo{\decmul{48.2}{.375}}\meaning\foo
****************** Fin code ******************
****************** Code 212 ******************
\def\decdiv#1#2{% divise le d�cimal #1 par le d�cimal #2
\dimtodec
\dimexpr
\numexpr
\dimexpr #1pt \relax * 65536 / \dimexpr #2pt \relax
\relax
sp
\relax
}
1) \decdiv{4.5}{0.075}\qquad% doit donner 60
2) \decdiv{8}{0.1}\qquad% doit donner 80
3) \decdiv{3.14}{1.6}\qquad% doit donner 1.9625
4) \decdiv{687.59829}{5.29871}\qquad% doit donner 129.76706
4) \edef\foo{\decdiv{0.37}{2.5}}\foo% doit donner 0.148
****************** Fin code ******************
****************** Code 213 ******************
\def\convertunit#1#2{%
\dimtodec
\dimexpr
\numexpr
\dimexpr #1 \relax * 65536 / \dimexpr 1#2 \relax
\relax
sp
\relax
}
a) \convertunit{15cm}{mm}\qquad
b) \convertunit{9,14in}{cm}\qquad
c) \convertunit{100000sp}{mm}\qquad
d) \convertunit{160.5pt}{cm}\qquad
e) \edef\foo{\convertunit{2,5cm}{cc}}\meaning\foo
****************** Fin code ******************
****************** Code 214 ******************
\the\glueexpr 5pt plus 2pt minus 1.5pt + 7pt plus0.5pt minus 3pt\relax \par
\the\glueexpr 25pt plus2fil + 35pt plus 0.1fill\relax
****************** Fin code ******************
****************** Code 215 ******************
foo% les caract�res font entrer TeX en mode horizontal
\kern0.5cm % espace ins�r�e en mode horizontal
bar\par% \par fait passer en mode vertical
\kern0.5cm % espace ins�r�e en mode vertical
boo
****************** Fin code ******************
****************** Code 216 ******************
Une premi�re ligne\par
\nointerlineskip% n'ins�re pas de ressort d'interligne ici
Un second paragraphe constitu� de plusieurs lignes.
Un second paragraphe constitu� de plusieurs lignes.
Un second paragraphe constitu� de plusieurs lignes.
\par% le ressort d'interligne sera ins�r� ici
Une derni�re ligne
****************** Fin code ******************
****************** Code 217 ******************
\begingroup
\offinterlineskip
La macro \litterate-\offinterlineskip-, en modifiant de fa�on appropri�e les trois
primitives \litterate-\baselineskip-, \litterate-\lineskip- et
\litterate-\lineskiplimit-, rend les boites cons�cutives jointives.
On peut constater dans ces deux paragraphes o� \litterate-\offinterlineskip- a �t�
appel�e, que les lignes sont plac�es verticalement au plus pr�s les unes des autres ce
qui rend la lecture tr�s p�nible et d�montre que le ressort d'interligne est une
n�cessit� typographique !\par
\endgroup
D�sactiver le ressort d'interligne ne se justifie que lorsque l'on doit composer
des boites contenant autre chose que du texte, sauf � vouloir des effets
typographiques sp�ciaux.
****************** Fin code ******************
****************** Code 218 ******************
\baselineskip=12pt
d�but \vtop{\hbox{ligne du haut ligne du haut ligne du haut}
\hbox{ligne du bas ligne du bas ligne du bas}
}
\par
Et la suite du texte suite du texte suite du texte
****************** Fin code ******************
****************** Code 219 ******************
\baselineskip=12pt
d�but \vtop{\hbox{ligne du haut ligne du haut ligne du haut}
\hbox{ligne du bas ligne du bas ligne du bas}
\xdef\sprevdepth{\the\prevdepth}% sauvegarde la valeur de \prevdepth
}
\par\prevdepth=\sprevdepth\relax% ment sur la boite pr�c�dente
Et la suite du texte suite du texte suite du texte
****************** Fin code ******************
****************** Code 220 ******************
\def\dummytext{Voici un texte qui ne rev�t aucune importance
et dont le seul but est de meubler artificiellement un paragraphe. }
\begingroup% � l'int�rieur d'un groupe,
\leftskip=0pt plus 0.5\hsize\relax
\rightskip=\leftskip\relax % modifier les ressort d'extr�mit�s
\spaceskip=0.3em plus 0.05em\relax% dimension de l'espace intermot
\parfillskip=0pt \relax% annuler le ressort de fin de paragraphe
\dummytext\dummytext\dummytext% corps du paragraphe
\par% compose la paragraphe courant
Juste une phrase%
\par% compose la paragraphe courant
\endgroup% avant de sortir du groupe
****************** Fin code ******************
****************** Code 221 ******************
\def\narrowtext{%
\par
\begingroup
\advance\leftskip 0.1\hsize
\advance\rightskip 0.1\hsize
}
\def\endnarrowtext{\par\endgroup}
\def\dummytext{Ceci est un texte sans
importance destin� � meubler un paragraphe. }
\dummytext\dummytext\dummytext
\narrowtext
\dummytext\dummytext\dummytext
\narrowtext
\dummytext\dummytext\dummytext
\endnarrowtext
\dummytext\dummytext\dummytext
\endnarrowtext
****************** Fin code ******************
****************** Code 222 ******************
a) \hfill Composition au fer � droite\par
b) Composition au fer � gauche\hfill\kern0pt\par
c) \hfill Centrage\hfill\kern0pt\par
d) Des \hfill mots\hfill r�guli�rement\hfill espac�s
****************** Fin code ******************
****************** Code 223 ******************
a% le caract�re "a" fait passer en mode horizontal
\hbox{b}c\hbox{d}% les \hbox sont ajout�es en mode horizontal
\medbreak
..� comparer avec...
\medbreak
a \par% \par fait passer en mode vertical
\hbox{b}% \hbox est ajout�e � la liste verticale
c% "c" fait passer en mode horizontal
\hbox{d}% la \hbox est ajout�e en mode horizontal
****************** Fin code ******************
****************** Code 224 ******************
Ligne de base : .........%
\vbox{\hbox{ligne du haut}\hbox{ligne du milieu}\hbox{ligne du bas}}%
........%
\vtop{\hbox{ligne du haut}\hbox{ligne du milieu}\hbox{ligne du bas}}.........
****************** Fin code ******************
****************** Code 225 ******************
\def\dummytext{Bla, bla, bla, un texte sans importance. }
Ligne de base.........%
\vbox{\hsize=4cm \dummytext\dummytext}%
........%
\vtop{\hsize=4cm \dummytext\dummytext}.........
****************** Fin code ******************
****************** Code 226 ******************
\newbox\foobox
a) \setbox\foobox=\hbox{foobar}% registre non vide
Le registre est \ifvoid\foobox vide\else non vide\fi\par
b) \setbox\foobox=\hbox{foobar}
"\box\foobox" et le registre est \ifvoid\foobox vide\else non vide\fi\par
c) \setbox\foobox=\hbox{foobar}
"\copy\foobox" et le registre est \ifvoid\foobox vide\else non vide\fi\par
d) \setbox\foobox=\hbox{}
Le registre est \ifvoid\foobox vide\else non vide\fi
****************** Fin code ******************
****************** Code 227 ******************
\newbox\foobox
\setbox\foobox=\hbox{Programmer est facile.}
<<\copy\foobox>>
mesure \the\wd\foobox\ de long, \the\dp\foobox\ de profondeur et \the\ht\foobox\ de haut.
\medbreak
\setbox\foobox=\vbox{\hbox{Programmer}\hbox{est}\hbox{facile.}}
<<\copy\foobox>>
mesure \the\wd\foobox\ de long, \the\dp\foobox\ de profondeur et \the\ht\foobox\ de haut.
\medbreak
\setbox\foobox=\vtop{\hbox{Programmer}\hbox{est}\hbox{facile.}}
<<\copy\foobox>>
mesure \the\wd\foobox\ de long, \the\dp\foobox\ de profondeur et \the\ht\foobox\ de haut.
****************** Fin code ******************
****************** Code 228 ******************
\def\vdim#1{\dimexpr\ht#1+\dp#1\relax}
a) \setbox\foobox=\vbox{\hbox{Programmer}\hbox{est}\hbox{facile.}}
Verticalit� de la \litterate-\vbox- = \the\vdim\foobox\par
b) \setbox\foobox=\vtop{\hbox{Programmer}\hbox{est}\hbox{facile.}}
Verticalit� de la \litterate-\vtop- = \the\vdim\foobox
****************** Fin code ******************
****************** Code 229 ******************
\def\countallchar#1{%
Il y a %
\setbox0=\hbox{\tt#1}% met #1 dans la boite
\edef\arglength{\number\wd0 }% stocke la largeur de la boite en sp
\setbox0=\hbox{\tt A}% met "A" dans la boite
\edef\charlength{\number\wd0 }% stocke la largeur d'un caract�re
$\number\arglength/\charlength % affiche la division
=\number\numexpr\arglength/\charlength\relax$ % affiche le quotient
caract�res%
}
\countallchar{abcd efgh}\par
\countallchar{A5 xW5 64 a1}\par
\countallchar{affligeant}
****************** Fin code ******************
****************** Code 230 ******************
\catcode`@11
\def\countchar#1#2{%
\setbox\z@\hbox{\tt#2}% met #2 dans boite 0
\edef\len@a{\number\wd\z@}% mesure la boite
\setbox\z@\hbox{\tt\substin{#2}{#1}{}}% recommencer sans "#1"
\edef\len@b{\number\wd\z@}% mesure la boite
\setbox\z@\hbox{\tt A}% met "A" dans la boite
\edef\charlength{\number\wd\z@}% stocke la largeur du caract�re
\number\numexpr(\len@a-\len@b)/\charlength% et affiche le quotient
}
\catcode`@12
a) \countchar{a}{abracadabra}\qquad
b) \countchar{b}{zigzag}\qquad
c) \countchar{ }{a bc de f ghi j k }
****************** Fin code ******************
****************** Code 231 ******************
Programmer \raise1ex\hbox{en} \lower1ex\hbox{\TeX} \lower2ex\hbox{est} facile.
****************** Fin code ******************
****************** Code 232 ******************
\def\cbox#1{%
\setbox0\vbox{#1}% met le contenu dans une \vbox
\lower\dimexpr(\ht0-\dp0)/2\relax\box0 % l'abaisse
}
.....\cbox{\hbox{$x^2$}}......\cbox{\hbox{foo}\hbox{et bar}}......%
\cbox{\hbox{Programmer}\hbox{en \TeX}\hbox{est facile}}.......
****************** Fin code ******************
****************** Code 233 ******************
.....\cbox{\hbox{foo}\hbox{et bar}}......$\vcenter{\hbox{foo}\hbox{et bar}}$......
****************** Fin code ******************
****************** Code 234 ******************
\def\htmath{\begingroup
\setbox0=\hbox{$\vcenter{}$}\the\ht0
\endgroup
}
L'axe math�matique se trouve � \htmath{} de la ligne de base.
****************** Fin code ******************
****************** Code 235 ******************
1) \hbox{foobar}\par
2) \hbox spread 5pt{foo\hfil bar}\par
3) \hbox spread10pt{foo\hfil bar}
****************** Fin code ******************
****************** Code 236 ******************
foobar|\rlap{/////}123456\qquad foobar|\llap{/////}123456
****************** Fin code ******************
****************** Code 237 ******************
\def\clap#1{\hbox to0pt{\hss#1\hss}}
a) avant la macro|\clap{SURIMPRESSION}apr�s la macro\medbreak
b) avant la macro|\raise2.5ex\clap{Au-dessus}\lower2.5ex\clap{Au-dessous}%
apr�s la macro\medbreak
c) avant la macro|\raise2.5ex\llap{Au-dessus avant}\lower2.5ex\rlap{Au-dessous apr�s}%
apr�s la macro
****************** Fin code ******************
****************** Code 238 ******************
\setbox0=\hbox{\tt//////////}
\wd0=0pt % fait croire � TeX que la larguer de la boite est nulle
Voici \copy0 du texte partiellement barr�...
****************** Fin code ******************
****************** Code 239 ******************
\def\printdim{largeur=\the\wd0 \qquad hauteur=\the\ht0 \qquad profondeur = \the\dp0 }
\setbox0=\hbox{Programmer en \TeX{} est facile}
a) \printdim\par
b) \wd0=0pt \ht0=0pt \dp0=0pt% rend toutes le dimensions nulles
\printdim\par
c) \setbox0=\hbox{\unhbox0 }% reprend les dimensions d'origine
\printdim
****************** Fin code ******************
****************** Code 240 ******************
\setbox0=\hbox{}% le registre 0 contient une boite vide
Le registre \ifvoid0 est vide\else n'est pas vide\fi
****************** Fin code ******************
****************** Code 241 ******************
\catcode`\@11
\def\ifzerodimbox#1{% #1=registre de boite
% revoie vrai si le registre est vide ou contient une boite de dimensions nulles
\csname% former la macro "\firstoftwo" ou "\secondoftwo"
\ifvoid#1first%% si le registre est vide "first"
\else% sinon
\ifdim\wd#1=\z@% si la largeur
\ifdim\ht#1=\z@% la hauteur
\ifdim\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
}
\catcode`\@12
a) \setbox0=\hbox{}\ifzerodimbox0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par
b) \box0 % affiche la boite vide, le registre est maintenant "void"
\ifzerodimbox0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par
c) \setbox0=\hbox{x}\ifzerodimbox0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par
d) \wd0=0pt \ht0=0pt \dp0=0pt % rend toutes les dimensions nulles
\ifzerodimbox0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par
e) \setbox0=\vbox{}\ifzerodimbox0{vrai}{faux} (et \ifvoid0 void\else non void\fi)
****************** Fin code ******************
****************** Code 242 ******************
\def\ifvoidorempty#1{% teste si le registre #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% #1 en dimensions naturelles
\expandafter\egroup% sauter la fin de la boite
\expandafter% et le \endgroup
\endgroup
\ifnum\lastnodetype=-1 % et tester si le dernier noeud est vide
\expandafter\expandafter\expandafter\firstoftwo
\else
\expandafter\expandafter\expandafter\secondoftwo
\fi
\fi
}
a) \setbox0=\hbox{}\ifvoidorempty0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par
b) \box0 % affiche la boite vide, le registre est maintenant "void"
\ifvoidorempty0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par
c) \setbox0=\hbox{x}\ifvoidorempty0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par
d) \wd0=0pt \ht0=0pt \dp0=0pt % rend toutes les dimensions nulles
\ifvoidorempty0{vrai}{faux} (et \ifvoid0 void\else non void\fi)\par
e) \setbox0=\vbox{}\ifvoidorempty0{vrai}{faux} (et \ifvoid0 void\else non void\fi)
****************** Fin code ******************
****************** Code 243 ******************
\newdimen\hmaxsize
\def\cvtop#1{%
\hmaxsize=-\maxdimen% initialise � la plus petite longueur
\doforeach\htext\in{#1}% pour chaque �l�ment :
{\setbox0=\hbox{\htext}% stocker l'�l�ment "\htext" dans une \hbox
\ifdim\wd0 >\hmaxsize% si sa longueur est sup�rieure � \hmaxsize
\hmaxsize=\wd0 % mettre � jour \hmaxsize
\fi
}%
\vtop{% dans une \vtop...
\doforeach\htext\in{#1}% pour chaque �l�ment :
{\hbox to\hmaxsize{\hss\htext\hss}% le centrer dans une \hbox de longueur \hmaxsize
}%
}%
}
texte avant...\cvtop{Ligne du haut,Tr�s grande ligne du milieu,Ligne du bas pour finir}%
..texte apr�s
****************** Fin code ******************
****************** Code 244 ******************
\newdimen\hmaxsize
\def\cvtop#1{%
\hmaxsize=-\maxdimen% initialise � la plus petite longueur
\doforeach\htext\in{#1}% pour chaque �l�ment :
{\setbox0=\hbox{\htext}% stocker l'�l�ment "\htext" dans une \hbox
\ifdim\wd0 >\hmaxsize% si sa longueur est sup�rieure � \hmaxsize
\hmaxsize=\wd0 % mettre � jour \hmaxsize
\fi
}%
\vtop{% dans une \vtop...
\hsize\hmaxsize % longueur de la \vtop = \maxhsize
\parindent=0pt % pas d'indentation
\leftskip=0pt plus1fil minus0pt \rightskip=\leftskip% ressorts de centrage
\doforeach\htext\in{#1}% pour chaque �l�ment :
{\htext\par}% le composer et finir le paragraphe
}%
}
texte avant...\cvtop{Ligne du haut,Tr�s grande ligne du milieu,Ligne du bas pour finir}%
..texte apr�s
****************** Fin code ******************
****************** Code 245 ******************
\halign{X#**\ignorespaces&#&\hfil #\cr % pr�ambule
foo &foo bar&123 456\cr % premi�re ligne
deuxi�me ligne &1 &12\cr % deuxi�me ligne
a &\TeX &1 2 3 4 5 6\cr % troisi�me ligne
\crcr}
****************** Fin code ******************
****************** Code 246 ******************
\def\cvtop#1{%
\vtop{% \vtop assure que l'on est en mode vertical
\substtocs\temp{#1}{,}{\cr}% dans \temp, remplacer les "," par "\cr"
\halign{%
\hfil##\hfil\cr% pr�ambule : centrer le contenu
\temp\crcr}% mettre \temp dans l'alignement
}% \temp est d�truite en sortant de la boite
}
texte avant...\cvtop{Ligne du haut,Tr�s grande ligne du milieu,Ligne du bas pour finir}%
..texte apr�s
****************** Fin code ******************
****************** Code 247 ******************
\def\calcmaxdim#1#2{%
\setbox0=\vtop{% \vtop assure que l'on est en mode vertical (interne)
\substtocs\temp{#2}{,}{\cr}% dans \temp, remplacer les "," par "\cr"
\halign{##\hfil\cr% pr�ambule : composer au fer � gauche
\temp\crcr}% mettre \temp dans l'alignement
}% \temp est d�truite en sortant de la boite
\edef#1{\the\wd0 }%
}
a) La plus grande longueur vaut
\calcmaxdim\foo{Ligne du haut,Tr�s grande ligne du milieu,Ligne du bas pour finir}\foo
b) V�rification : \setbox0=\hbox{Tr�s grande ligne du milieu}\the\wd0
****************** Fin code ******************
****************** Code 248 ******************
a) .......\vbox{\hrule\hbox{foo}\hbox{ligne du bas}\hrule}.......\medbreak
b) .......\vrule\vtop{\hbox{foo}\hbox{ligne du bas}}\vrule.......
****************** Fin code ******************
****************** Code 249 ******************
Une r�glure de 1.5cm :\hrule width1.5cm
foo\vrule width 2pt height .5cm depth .2cm bar
****************** Fin code ******************
****************** Code 250 ******************
\def\showdim#1{%
\vrule width 0.4pt height 1ex depth 0pt % trait vertical gauche
\vrule width #1 height0.4pt depth 0pt % r�glure horizontale de longueur #1
\vrule width 0.4pt height 1ex depth 0pt % trait vertical droit
\relax% stoppe la lecture de la pr�c�dente dimension
}
a) une longueur de 1 cm : \showdim{1cm}\par
b) une longueur de 137,4 pt : \showdim{137,4pt}\par
c) une longueur de 2 mm : \showdim{2mm}
****************** Fin code ******************
****************** Code 251 ******************
\frboxsep=5pt \frboxrule=1pt
\leavevmode
..%
\vbox{%
\hrule height\frboxrule% r�glure sup�rieure
\kern\frboxsep% espace verticale haute
\hbox{\kern\frboxsep Programmation\kern\frboxsep}% contenu + espaces horizontales
\kern\frboxsep% espace verticale basse
\hrule height\frboxrule% r�glure inf�rieure
}%
..
****************** Fin code ******************
****************** Code 252 ******************
\frboxsep=5pt \frboxrule=0.6pt
\def\FRbox#1{% /!\ ne change pas le mode H ou V en cours
\hbox{% mettre � la suite horizontalement les 3 choses suivantes :
\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
}%
}
Ligne de base : ...\FRbox{Programmation}...%
\frboxrule=2pt \FRbox{Programmation}...%
\frboxsep=0pt \FRbox{Programmation}...%
\frboxrule0.4pt \FRbox{Programmation}...
****************** Fin code ******************
****************** Code 253 ******************
Persuadez-vous que :
\vtop{
\vbox{
\hbox{Programmer}
\hbox{en}
\hbox{\TeX}
\hbox{est}% <- ligne de base de la \vtop
}
\hbox{\it tout sauf}
\hbox{facile.}
}
****************** Fin code ******************
****************** Code 254 ******************
%\newdimen\frboxrule \newdimen\frboxsep
\frboxrule=0.4pt \frboxsep=2pt
\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
}%
}
Ligne de base : ......\frbox{Programmation}......%
\frboxrule=2pt \frbox{Programmation}......%
\frboxsep=0pt \frbox{Programmation}......%
\frboxrule0.4pt \frbox{Programmation}......
****************** Fin code ******************
****************** Code 255 ******************
\def\centretitre#1{%
\medbreak% passe en mode v puis saute une espace verticale
\noindent% pas d'indentation et passe en mode horizontal
\frbox{% encadre
\vbox{% une boite verticale
\hsize=\dimexpr\hsize-2\frboxrule-2\frboxsep\relax
\parindent=0pt % pas d'indentation
\leftskip=0pt plus1fil \rightskip=\leftskip% ressorts de centrage
\parfillskip=0pt % annule le ressort de fin de paragraphe
#1% ins�re le titre
\endgraf% et le compose
}%
}%
\medbreak% passe en mode v puis saute une espace verticale
\ignorespaces% mange les espaces situ�s apr�s la macro \centretitre
}
\frboxrule=0.8pt \frboxsep=5pt
Voici un
\centretitre{Titre}
puis un
\centretitre{Texte tr�s long pour composer un titre qui va prendre plusieurs
lignes et pour s'assurer que la composition s'effectue correctement}
****************** Fin code ******************
****************** Code 256 ******************
Une r�glure en hauteur : \vrule width 1cm height 10.4pt depth -10pt
****************** Fin code ******************
****************** Code 257 ******************
Une r�glure en dessous: \vrule width 1cm depth 2.4pt height -2pt
****************** Fin code ******************
****************** Code 258 ******************
\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
}
Voici \souligne{du texte normal}.\par
Voici \souligne{du texte profond}.
****************** Fin code ******************
****************** Code 259 ******************
\def\Souligne#1{%
\setbox0=\hbox{#1}%
\setbox0=\hbox{\vrule width\wd0 depth1.4pt height-1pt }%
\wd0=0pt \dp0=0pt \ht0=0pt
\leavevmode \box0 #1%
}
Voici \Souligne{du texte normal}.\par
Voici \Souligne{du texte profond}.
****************** Fin code ******************
****************** Code 260 ******************
\def\Souligne#1{%
\setbox0=\hbox{#1}%
\lower 1pt % abaisser � 1pt sous la ligne de base
\rlap{% une \hbox en surimpression vers la droite
\vrule width\wd0 height0pt depth0.4pt % contenant le soulignement
}%
#1% puis afficher le <texte>
}
Voici \Souligne{du texte normal}.\par
Voici \Souligne{du texte profond}.
****************** Fin code ******************
****************** Code 261 ******************
\newdimen\stackwd \stackwd=3em % dimension horizontale interne des cadres
\catcode`@11
\def\stackbox#1{%
\par% termine le paragraphe en cours
\noindent
\stackbox@i#1\\\quark\\% ajoute "\\\quark\\" � la fin et appelle \stackbox@i
\par
}
\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 (et fait passer en mode horizontal)
\noindent
\doforeach\current@item\in{#1}% pour chaque �l�ment dans la ligne courante...
{\frbox{% ...encadrer
\hbox to\stackwd{% une \hbox de largeur \stackwd
\hss% ressort de centrage
\current@item% l'�l�ment courant
\hss% ressort de centrage
}
}% fin de la \frbox
}% fin \doforeach
\hfill% ressort infini de centrage
\null% assure que le dernier ressort est pris en compte
\par% finir le paragraphe
\nobreak% interdire une coupure de page
\nointerlineskip% ne pas ins�rer le ressort d'interligne
\expandafter\stackbox@i% et recommencer
\fi
}
\catcode`@12
\frboxrule=0.5pt \frboxsep=3pt
\stackbox{a,bc,,d\\e,foobar,g\\123,456,$\alpha$,$x+y$,}
****************** Fin code ******************
****************** Code 262 ******************
a\vrule width0.2pt height15pt depth0pt \quad
a\vrule width0.2pt height0pt depth5pt \quad
a\vrule width0.2pt height10pt depth10pt \quad
a\vrule width1cm height0.2pt depth0pt
****************** Fin code ******************
****************** Code 263 ******************
\frboxsep0pt %encadrement au plus proche
\leavevmode
\frbox{a\vrule width0pt height15pt depth0pt }\quad
\frbox{a\vrule width0pt height0pt depth5pt }\quad
\frbox{a\vrule width0pt height10pt depth10pt }\quad
\frbox{a\vrule width1cm height0pt depth0pt }
****************** Fin code ******************
****************** Code 264 ******************
\def\rectangle#1#2{%
\begingroup% dans un groupe
\frboxsep = 0pt % encadrer au plus proche
\frboxrule= 0.4pt % en traits assez fins
\frbox{%
\vrule width#1 height0pt depth0pt %strut horizontal
\vrule width0pt height#2 depth0pt %strut vertical
}%
\endgroup% fermer le groupe
}
Carr� de 0.5 cm : \rectangle{0.5cm}{0.5cm}\smallskip
Rectangle de 2.5cm par 3pt : \rectangle{2.5cm}{3pt}
****************** Fin code ******************
****************** Code 265 ******************
\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 d'interligne
\kern-\frboxrule% superposer les r�glures horizontales
\expandafter\stackbox@i% et recommencer
\fi
}
\frboxrule=0.5pt
\frboxsep=3pt
\stackbox{a,bc,,d\\e,foobar,g\\123,456,$\alpha$,$x+y$,}
****************** Fin code ******************
****************** Code 266 ******************
\catcode`\@11
\def\lineboxed#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
\lineboxed@i#1\\\quark\\% ajoute "\\\quark\\" � la fin et appelle la macro r�cursive
\unkern% annule la derni�re compensation verticale
\par
\endgroup
}
\def\lineboxed@i#1\\{% #1=ligne courante
\def\temp@{#1}% stocke la ligne courante
\unless\ifx\quark\temp@% si ce n'est pas la fin
\cnttimestocs{#1,}{,}\nb@args% re�oit le nombre d'arguments dans la ligne courante
\edef\dim@box{\the\dimexpr(\hsize-\frboxrule*(\nb@args+1)-
\frboxsep*2*\nb@args)/\nb@args}%
\hbox{%
\doforeach\current@item\in{#1}% pour chaque �l�ment dans la ligne courante...
{\frbox{% ...encadrer
\hbox to\dim@box{% une \hbox de largeur \dim@box 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
}%
\par% termine le paragraphe
\nobreak% interdit une coupure de page
\nointerlineskip% sinon, ne pas ajouter le ressort d'interligne
\kern-\frboxrule% superposer les r�glures horizontales
\expandafter\lineboxed@i% et recommencer
\fi
}
\catcode`\@12
\lineboxed{a,bc,,d\\e,foobar,g\\123,456,$\alpha$,$x+y$,}\medbreak
\frboxrule=1.5pt
\frboxsep=3pt
\lineboxed{,,,,,,,\\,,\\,,,,,,}
****************** Fin code ******************
****************** Code 267 ******************
\xunit=0.5cm \yunit=0.5cm \mainrule=0.8pt \subrule=0.2pt
\def\vlap#1{\vbox to0pt{\vss#1\vss}}
\catcode`@11
\def\grid#1#2#3#4{%
\vbox{% empiler les �l�ments verticalement
\offinterlineskip% pas de ressort d'interligne
\edef\total@wd{\the\dimexpr\xunit*#1\relax}% largeur totale ds r�glures
\for\ii = 1 to #3 \do1% pour chaque carreau vertical (\ii=variable muette)
{\vlap{\hrule width\total@wd height\mainrule}% tracer la r�glure horizontale
\kern\yunit% ins�rer l'espace vertical
}%
\vlap{\hrule width\total@wd height\mainrule}% derni�re r�glure horizontale
}%
}
\catcode`@12
\setbox0\hbox{\grid{4}{}{3}{}}% range la quadrillage dans le registre no 0
Essai \copy0{} qui a pour
largeur=\convertunit{\wd0}{cm} cm et pour hauteur=\convertunit{\ht0}{cm} cm
****************** Fin code ******************
****************** Code 268 ******************
D�but\vbox to0pt{\hbox{sous}\hbox{la ligne de base}\vss}suite
****************** Fin code ******************
****************** Code 269 ******************
\xunit=0.5cm \yunit=0.5cm \mainrule=0.8pt \subrule=0.2pt
\def\vlap#1{\vbox to0pt{\vss#1\vss}}
\catcode`@11
\def\grid#1#2#3#4{%
\vbox{% empiler les �l�ments verticalement
\offinterlineskip% pas de ressort d'interligne
\edef\total@wd{\the\dimexpr\xunit*#1\relax}% largeur totale de la boite
\edef\sub@unit{\the\dimexpr\yunit/#4\relax}% hauteur verticale de la subdivision
\for\ii = 1 to #3 \do% pour chaque unit� verticale en partant du haut, tracer :
{\vlap{\hrule width\total@wd height\mainrule}% la r�glure horizontale principale
% et dessous, les r�glures horizontales secondaires :
\vbox to\z@{% dans une \vbox de hauteur nulle,
\for\jj = 2 to #4 \do 1% ins�rer #4-1 fois sous la position courante :
{\kern\sub@unit % l'espace verticale
\vlap{\hrule width\total@wd height\subrule}% et la r�glure secondaire
}%
\vss% ressort qui se comprime pour satisfaire la hauteur nulle
}%
\kern\yunit% ins�rer l'espace vertical entre r�glures principales
}%
\vlap{\hrule width\total@wd height\mainrule}% derni�re r�glure principale du bas
}%
}
\catcode`@12
\setbox0=\hbox{\grid{4}{}{3}{5}}
Essai \copy0{} qui a pour
largeur=\convertunit{\wd0}{cm} cm et pour hauteur=\convertunit{\ht0}{cm} cm
****************** Fin code ******************
****************** Code 270 ******************
\mainrule=0.8pt \subrule=0.2pt
\def\vlap#1{\vbox to0pt{\vss#1\vss}}
\catcode`@11
\def\grid#1#2#3#4{%
\vbox{% empiler les �l�ments verticalement
\offinterlineskip% pas de ressort d'interligne
% #################### Trac� des r�glures verticales ####################
\vbox to\z@{% dans une \vbox de hauteur nulle
\edef\total@ht{\the\dimexpr\yunit*#3\relax}% hauteur totale
\edef\sub@unit{\the\dimexpr\xunit/#2\relax}% espace entre 2 subdivisions
\rlap{% mettre � droite de la position sans bouger
\for\ii = 1 to #1 \do 1% pour chaque unit� horizontale
{\clap{\vrule width\dimexpr\mainrule height\total@ht}% r�glure principale
\rlap{% mettre � droite de la position sans bouger
\for\jj = 2 to #2 \do 1% ins�rer #2-1 fois
{\kern\sub@unit % l'espace horizontal
\clap{\vrule width\subrule height\total@ht}% et la r�glure verticale
}%
}%
\kern\xunit % ins�rer l'espace entre r�glures horizontales
}%
\clap{\vrule width\mainrule height\total@ht}% derni�re r�glure principale
}%
\vss% compense la hauteur=0pt de la \vbox
}%
% #################### Trac� des r�glures horizontales ####################
\edef\total@wd{\the\dimexpr\xunit*#1\relax}% largeur totale de la boite
\edef\sub@unit{\the\dimexpr\yunit/#4\relax}% espace entre 2 subdivisions
\for\ii = 1 to #3 \do 1% pour chaque carreau vertical en partant du haut :
{\vlap{\hrule width\total@wd height\mainrule}% r�glure horizontale principale
% et dessous, les r�glures secondaires :
\vbox to\z@{% dans une \vbox de hauteur nulle,
\for\jj = 2 to #4 \do 1% ins�rer #4-1 fois sous la position courante :
{\kern\sub@unit % l'espace vertical
\vlap{\hrule width\total@wd height\subrule}% et la r�glure secondaire
}%
\vss% ressort qui se comprime pour satisfaire la hauteur nulle
}%
\kern\yunit% ins�rer l'espace vertical entre r�glures principales
}%
\vlap{\hrule width\total@wd height\mainrule}% derni�re r�glure horizontale
}%
}
\catcode`@12
Grille 1 : \xunit=1cm \yunit=1cm \grid{5}{10}{2}{10}\smallskip
Grille 2 : \xunit=0.5cm \yunit=0.5cm \grid{7}{1}{3}{1}\smallskip
Grille 3 : \xunit=1.5cm \yunit=0.5cm \grid{4}{3}{3}{2}
****************** Fin code ******************
****************** Code 271 ******************
\vrule\hbox to10cm{\leaders\hbox to1.5cm{\hss A\hss}\hfill}\vrule
****************** Fin code ******************
****************** Code 272 ******************
\frboxsep=-\frboxrule \def~{\leavevmode\raise.75ex\hbox{\vrule height.2pt width1em}}
~\hbox to10cm{\leaders\hbox{\frbox{\hbox to1.5cm{\hss A\hss}}}\hfill}~
~\hbox to10cm{\cleaders\hbox{\frbox{\hbox to1.5cm{\hss A\hss}}}\hfill}~
~\hbox to10cm{\xleaders\hbox{\frbox{\hbox to1.5cm{\hss A\hss}}}\hfill}~
****************** Fin code ******************
****************** Code 273 ******************
a) \leavevmode\hbox to10cm{\leaders\hrule\hfill}\smallskip
b) \hbox to10cm{\leaders\hbox{\vrule height0.2pt width2.5mm \kern1.5mm}\hfill}
c) \vrule width0.2pt height1ex depth0pt % premi�re r�glure verticale
\hbox to10cm{% puis r�p�tition de "_|"
\leaders\hbox{\vrule width2em height0.2pt \vrule width0.2pt height1ex}\hfill}
d) \hbox to10cm{\leaders\hbox{%
\vrule height.2pt width.5em% 1/2 palier bas
\vrule height5pt width0.2pt% mont�e au palier haut
\vrule height5pt depth-4.8pt width1em% palier haut
\vrule height5pt width0.2pt% descente au palier bas
\vrule height.2pt width.5em% 1/2 palier bas
}\hfill}
****************** Fin code ******************
****************** Code 274 ******************
\mainrule=0.8pt \subrule=0.2pt
\def\carreau#1#2{% #1=nb subdiv H #2=nb subdiv V
\vbox to\yunit{% dans un \vbox de hauteur \yunit
\offinterlineskip% pas de ressort d'interligne
\vlap{\hrule height\mainrule width\xunit}% r�glure principale du haut
\leaders% r�p�ter (ici ce sera donc #2-1 fois)
\vbox to\dimexpr\yunit/#2\relax% une \vbox de hauteur \yunit/#2
{\vss% ressort qui va s'�tirer � \yunit/#2
\vlap{\hrule height\subrule width\xunit}% r�glure de subdiv de dim 0pt
}\vfill
\kern\dimexpr\yunit/#2\relax% derni�re espace verticale
\vlap{\hrule height\mainrule width\xunit}% r�glure principale du bas
}%
}
\yunit=1cm
\leavevmode \carreau{}{4} puis \carreau{}{10}
****************** Fin code ******************
****************** Code 275 ******************
\mainrule=0.8pt \subrule=0.2pt
\def\carreau#1#2{% #1=nb subdiv H #2=nb subdiv V
% ######## r�glures horizontales ########
\rlap{% mettre � droite de la position sans bouger
\vbox to\yunit{% dans un \vbox de hauteur \yunit
\offinterlineskip% pas de ressort d'interligne
\vlap{\hrule height\mainrule width\xunit}% r�glure principale du haut
\leaders% r�p�ter (ici ce sera #2-1 fois)
\vbox to\dimexpr\yunit/#2\relax% une \vbox de hauteur \yunit/#2
{\vss% ressort qui va s'�tirer � \yunit/#2
\vlap{\hrule height\subrule width\xunit}% r�glure de subdiv de dim 0pt
}\vfill% ressort de \leaders
\kern\dimexpr\yunit/#2\relax% derniere espace verticale
\vlap{\hrule height\mainrule width\xunit}% r�glure principale du bas
}%
}%
% ######## r�glures verticales ########
\hbox to\xunit{% dans une \hbox de longueur \xunit
\clap{\vrule height\yunit width\mainrule}% r�glure principale de gauche
\leaders% r�p�ter (ici ce sera #1-1 fois)
\hbox to\dimexpr\xunit/#1\relax
{\hss% ressort qui va s'�tirer � \xunit/#1
\clap{\vrule height\yunit width\subrule}% r�glure H de dimension 0
}\hfill% ressort de \leaders
\kern\dimexpr\xunit/#1\relax% derni�re espace H
\clap{\vrule height\yunit width\mainrule}% r�glure principale de droite
}%
}
\yunit=1cm \xunit=2cm
\leavevmode \carreau{3}{4} puis \carreau{8}{10}
****************** Fin code ******************
****************** Code 276 ******************
\mainrule=0.8pt \subrule=0.2pt
\def\grid#1#2#3#4{%
\vbox to#3\yunit{% dans une boite verticale de hauteur #3*\yunit
\leaders% r�p�ter verticalement
\hbox to#1\xunit{% une boite de longueur #1*\xunit
\leaders% dans laquelle se r�p�te horizontalement
\hbox{\carreau{#2}{#4}}% le carreau de largeur \xunit
\hfill}%
\vfill
}%
}
Grille 1 : \xunit=1cm \yunit=1cm \grid{5}{10}{2}{10}\smallskip
Grille 2 : \xunit=0.5cm \yunit=0.5cm \grid{7}{1}{3}{1}\smallskip
Grille 3 : \xunit=1.5cm \yunit=0.5cm \grid{4}{3}{3}{2}
****************** Fin code ******************
****************** Code 277 ******************
\outer\def\foo{Bonjour}
\def\bar{\foo}
****************** Fin code ******************
****************** Code 278 ******************
\outer\def\foo{Bonjour}
\expandafter\def\expandafter\bar\expandafter{\noexpand\foo}
\meaning\bar
\edef\baz{\noexpand\foo}
\meaning\baz
****************** Fin code ******************
****************** Code 279 ******************
\catcode`\@11
\long\def\filedef#1#2{%
\begingroup
\let\input\@@input% <- utilisateurs de latex uniquement
\everyeof{\eof@nil\noexpand}% ins�re "\eof@nil\noexpand" � la fin du fichier
\expandafter\filedef@i\expandafter#1% d�veloppe \input #2
\expandafter\relax\input #2
}
\long\def\filedef@i#1#2\eof@nil{%
\endgroup
\expandafter\def\expandafter#1\expandafter{\gobone#2}% mange le \relax
}
\catcode`\@12
\filedef\foo{test.txt}
\meaning\foo
****************** Fin code ******************
****************** Code 280 ******************
% canal de lecture employ� dans tout ce chapitre
\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
}
a) \iffileexists\rtest{test.txt}{vrai}{faux}\qquad
b) \iffileexists\rtest{foobar.txt}{vrai}{faux}
****************** Fin code ******************
****************** Code 281 ******************
\openin\rtest =filetest.txt
\read\rtest to \foo% lit la premi�re ligne
1) Signification : \meaning\foo.\par% signification de ce qui a �t� lu
1) Ex�cution : \foo\par
\read\rtest to \foo% lit la deuxi�me ligne
2) Signification : \meaning\foo.\par
2) Ex�cution : \foo\par
\read\rtest to \foo% lit la derni�re ligne
3) Signification : \meaning\foo.\par
3) Ex�cution : \foo
\closein\rtest
****************** Fin code ******************
****************** Code 282 ******************
\openin\rtest =filetest.txt
\readline\rtest to \foo% lit la premi�re ligne
1) Signification : \meaning\foo.\par% signification de ce qui a �t� lu
1) Ex�cution : \foo\par
\readline\rtest to \foo% lit la deuxi�me ligne
2) Signification : \meaning\foo.\par
2) Ex�cution : \foo\par
\readline\rtest to \foo% lit la derni�re ligne
3) Signification : \meaning\foo.\par
3) Ex�cution : \foo
\closein\rtest
****************** Fin code ******************
****************** Code 283 ******************
Valeur de \string\endlinechar = \number\endlinechar\par
Caract�re correspondant : << \char\endlinechar{} >>
****************** Fin code ******************
****************** Code 284 ******************
\openin\rtest =filetest.txt
Ligne 1 : {\endlinechar=-1 \global\read\rtest to \foo}% lit la premi�re ligne
\meaning\foo.\par% donne ce qui a �t� lu
Ligne 2 : {\endlinechar=-1 \global\read\rtest to \foo}% lit la deuxi�me ligne
\meaning\foo.\par
Ligne 3 : {\endlinechar=-1 \global\read\rtest to \foo}% lit la derni�re ligne
\meaning\foo.
\closein\rtest
****************** Fin code ******************
****************** Code 285 ******************
\def\xread#1to#2{%
\ifcs{#2}% si #2 est une s�quence de contr�le
{\edef\restoreendlinechar{\endlinechar=\the\endlinechar}%
\endlinechar=-1 % supprime le caract�re mis en fin de ligne
\read#1to#2% lit la ligne et l'assigne � la macro #2
\restoreendlinechar\relax% restaure le \endlinechar
}% si #2 n'est pas une s�quence de contr�le,
{\xread#1to}% ignorer #2, et recommencer
}
\openin\rtest =filetest.txt
Ligne 1 : \xread\rtest to \foo% lit la premi�re ligne
\meaning\foo.\par% donne ce qui a �t� lu
Ligne 2 : \xread\rtest to \foo% lit la deuxi�me ligne
\meaning\foo.\par
Ligne 3 : \xread\rtest to \foo% lit la derni�re ligne
\meaning\foo.
\closein\rtest
****************** Fin code ******************
****************** Code 286 ******************
\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> pour effectuer l'assignation
}
\catcode`\@12
\openin\rtest =filetest.txt
Ligne 1 : \xread\rtest to \foo% lit la premi�re ligne
\meaning\foo.\par% donne ce qui a �t� lu
Ligne 2 : \xread\rtest to \foo% lit la deuxi�me ligne
\meaning\foo.\par
Ligne 3 : \xread\rtest to \foo% lit la derni�re ligne
\meaning\foo.
\closein\rtest
****************** Fin code ******************
****************** Code 287 ******************
\def\macroname{% se d�veloppe en le nom de la macro qui suit sans
% le caract�re d'�chappement
\ifnum\escapechar>-1 % si le caract�re d'�chappement est positif
\ifnum\escapechar<256 % et inf�rieur � 256, d�velopper les 2 "\fi"
\expandafter\expandafter\expandafter\expandafter% et le "\string", puis
\expandafter\expandafter\expandafter\gobone% manger le "\" avec \gobone
\fi
\fi
\string% doit �tre suivi d'une macro
}
\catcode`\@11
\newcount\field@cnt
\def\searchitem#1#2#3#4{% #1= canal #2=nom fichier #3=r�f�rence #4=macro � d�finir
\let#4\gobone% pour l'instant, #4=\gobone
\openin#1=#2\relax
\unless\ifeof#1% si le fichier existe
\lowercase{\def\sought@firstfield{#3}}% stocke le 1er champ � chercher
\edef\macro@name{\macroname#4}% nom de la macro sans "\"
\xread#1 to \current@line% lire la premi�re ligne
\field@cnt=0 % initialiser le compteur de champs
% ################ sauvegarde du nom des champs ################
\expsecond{\doforeach\current@field\in}\current@line% pour chaque champ
{\advance\field@cnt1 % incr�menter le compteur de champs
\lowercase\expandafter{% e texte de remplacement de \current@field en minuscule
\expandafter\def\expandafter\current@field\expandafter{\current@field}%
}%
% sauvegarder chaque champ de la 1re ligne (qui sont les intitul�s) dans une macro
\letname{fieldname\number\field@cnt}=\current@field
}%
\edef\field@num{\number\field@cnt}% nombre de champs
% ################ lecture des lignes de donn�es ################
\loop% tant que...
\unless\ifeof#1\relax% ...la fin du fichier n'est pas atteinte
\xread#1 to \current@line% lire une ligne
\unless\ifx\current@line\empty% si elle n'est pas vide
% examniner les champs qu'elle contient (aller � \test@field)
\expsecond{\expandafter\test@field\current@line\@nil}\macro@name%
\fi
\repeat
\fi
\closein#1\relax
}
\def\test@field#1,#2\@nil#3{% #1=champ no 1 #2=autres champs #3=nom de la macro sans "\"
\def\current@firstfield{#1}% stocke le premier champ de la ligne en cours
\ifx\current@firstfield\sought@firstfield% s'il est �gal � celui cherch�
\defname{#3.\csname fieldname1\endcsname}{#1}% d�finir la macros \<#3."champ 1">
\field@cnt=1 % initialiser le compteur de champ
\doforeach\current@field\in{#2}% puis, pour i>2, d�finir les macros \<#3."champ i">
{\advance\field@cnt1 % incr�menter le compteur de champ
\letname{#3.\csname fieldname\number\field@cnt\endcsname}=\current@field
}%
\defname{#3}##1{% et d�finir la macro \<#3>
\ifcsname#3.##1\endcsname% si la macro \<#3."argument"> existe d�j�
\csname#3.##1\expandafter\endcsname% l'ex�cuter apr�s avoir mang� le \fi
\fi
}%
\fi
}
\catcode`\@12
\searchitem\rtest{fournitures.txt}{4562u}\monarticle
r�f = \monarticle{ref},
d�nomination = \monarticle{item},
prix = \monarticle{prix},
fournisseur = \monarticle{fournisseur},
champ non existant = \monarticle{foobar}.
\searchitem\rtest{fournitures.txt}{truc}\essai% r�f�rence "truc" n'existe pas
r�f = \essai{ref},
d�nomination = \essai{item},
prix = \essai{prix},
fournisseur = \essai{fournisseur}.
****************** Fin code ******************
****************** Code 288 ******************
\def\macroname{% se d�veloppe en le nom de la macro qui suit sans
% le caract�re d'�chappement
\ifnum\escapechar>-1 % si le caract�re d'�chappement est positif
\ifnum\escapechar<256 % et inf�rieur � 256, d�velopper les 2 "\fi"
\expandafter\expandafter\expandafter\expandafter% et le "\string", puis
\expandafter\expandafter\expandafter\gobone% manger le "\" avec \gobone
\fi
\fi
\string% doit �tre suivi d'une macro
}
\catcode`\@11
\newcount\field@cnt
\newif\ifsearch@repeat
\def\assign@arg#1=#2\@nil{%
\def\sought@fieldnumber{#1}% no du champ � chercher
\def\sought@fielvalue{#2}% et sa valeur
}
\def\searchitem#1#2#3#4{% #1= canal #2=nom fichier #3=champ cherch� #4=macro � d�finir
\let#4\gobone% pour l'instant, #4=\gobone
\openin#1=#2\relax%
\unless\ifeof#1% si le fichier existe
\edef\macro@name{\macroname#4}% nom de la macro sans "\"
\xread#1 to \current@line% lire et ignorer la premi�re ligne
\ifin{#3}{=}% si #3 contient =
{\assign@arg#3\@nil}% trouver le no de champ et sa valeur
{\def\sought@fieldnumber{1}% sinon, no du champ = 1
\def\sought@fielvalue{#3}% et sa valeur = #3
}%
% ################ lecture des lignes de donn�es ################
\search@repeattrue% poursuite de la boucle loop : vraie
\loop% tant que...
\ifeof#1\relax% ...la fin du fichier n'est pas atteinte
\search@repeatfalse% sortir de la boucle loop
\else
\xread#1 to \current@line% lire une ligne
\unless\ifx\current@line\empty% si elle n'est pas vide
% examniner les champs qu'elle contient (aller � \test@field)
\expsecond{\expandafter\test@field\current@line\@nil}\macro@name%
\fi
\fi
\ifsearch@repeat% ne poursuivre que si le bool�en en vrai
\repeat
\fi
\closein#1\relax
}
\def\test@field#1\@nil#2{% #1=champs #2=nom de la macro sans "\"
\field@cnt=0 % initialiser le compteur de champ
\doforeach\current@field\in{#1}% parcourir les champs de la ligne en cours
{\advance\field@cnt1 % incr�menter le compteur de champ
\ifnum\field@cnt=\sought@fieldnumber\relax% si c'est le bon num�ro de champ
\ifx\current@field\sought@fielvalue% et si le champ correspond � celui cherch�
\search@repeatfalse% sortir de la boucle loop
\doforeachexit% sortir de la boucle \doforeach en cours
\fi
\fi
}%
\unless\ifsearch@repeat% si la ligne a �t� trouv�e
\field@cnt=0 % initialiser le compteur de champ
\doforeach\current@field\in{#1}% parcourir � nouveau les champs de la ligne
{\advance\field@cnt1 % incr�menter le compteur de champ
\letname{#2.\number\field@cnt}=\current@field% faire l'assignation
}%
\defname{#2}##1{% et d�finir la macro \<#2>
\ifcsname#2.##1\endcsname% si la macro \<#2."argument"> existe d�j�
\csname#2.##1\expandafter\endcsname% l'ex�cuter apr�s avoir mang� le \fi
\fi
}%
\fi
}
\catcode`\@12
a) \searchitem\rtest{basecourse.txt}{3=283}\foo
"\foo1", "\foo2", "\foo3", "\foo4", "\foo5", "\foo6", "\foo7"
b) \searchitem\rtest{basecourse.txt}{Valet}\bar
"\bar1", "\bar2", "\bar3", "\bar4", "\bar5", "\bar6", "\bar{abcd}"
****************** Fin code ******************
****************** Code 289 ******************
\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
\loop
\xread#1 to \currline% lire une ligne
\unless\ifeof#1% si la fin du fichier n'est pas atteinte
\leavevmode\par% aller � la ligne
\currline% afficher la ligne lue
\repeat% recommencer
\fi
\closein#1\relax
\endgroup
}
Contenu du fichier : "\showfilecontent\rtest{readtest.txt}", affich� tel quel
****************** Fin code ******************
****************** Code 290 ******************
\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
}
Contenu du fichier : "\showfilecontent\rtest{readtest.txt}", affich� tel quel
****************** Fin code ******************
****************** Code 291 ******************
% sera le canal d'�criture dans tout ce chapitre
\immediate\openout\wtest=writetest.txt % lie \wtest au fichier
\immediate\write\wtest{Programmer en \noexpand\TeX{} est facile.}% �crit une ligne
\immediate\write\wtest{Et utile...}% puis une autre
\immediate\closeout\wtest% d�fait la liaison
a) Contenu du fichier :\par
"\showfilecontent\rtest{writetest.txt}"% affiche le contenu du fichier
\medbreak
% 2e tentative :
b) Contenu du fichier :\par
\immediate\openout\wtest=writetest.txt % lie \wtest au fichier
\immediate\write\wtest{Essai d'�criture}% �crit une ligne
\immediate\closeout\wtest% d�fait la liaison
"\showfilecontent\rtest{writetest.txt}"% affiche le contenu du fichier
****************** Fin code ******************
****************** Code 292 ******************
\def\noexpwrite#1#2{% #1=num�ro de canal #2=texte � �crire
\write#1{\unexpanded{#2}}%
}
\immediate\openout\wtest=writetest.txt
\immediate\noexpwrite\wtest{Programmer en \TeX{} est facile.}%
\immediate\noexpwrite\wtest{Et utile...}%
\immediate\closeout\wtest
Contenu du fichier :\par
\showfilecontent\rtest{writetest.txt}% affiche le contenu du fichier
****************** Fin code ******************
****************** Code 293 ******************
\catcode`\@11
\def\exactwrite#1{% #1=num�ro de canal
\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
\exactwrite@i% aller lire le <car>
}
\def\exactwrite@i#1{% #1 est le <car> de catcode 12
\def\exactwrite@ii##1#1{% ##1 est le <texte> � envoyer vers le fichier
\exactwrite@iii##1\@nil% envoyer <texte> � \exactwrite@iii
}%
\exactwrite@ii% va lire tout ce qui se trouve jusqu'au prochain <car>
}
{\catcode`\^^M 12 \gdef\EOL@char{^^M}}% d�finit le caract�re <EOL> de catcode 12
\def\exactwrite@iii#1\@nil{% #1 = <texte> � �crire dans le fichier
\expsecond{\ifin{#1}}\EOL@char% si #1 contient "retour charriot"
{\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% recommencer avec ce qui se trouve apr�s "^^M"
}
\catcode`\@12
\immediate\openout\wtest=writetest.txt % lie le canal \wtest au fichier
\exactwrite\wtest|Programmer en \TeX{} est facile !
Et tr�s utile.|
\immediate\closeout\wtest% et fermer le fichier
Le contenu du fichier "writetest.txt" est :\par
"\showfilecontent\rtest{writetest.txt}"
****************** Fin code ******************
****************** Code 294 ******************
\catcode`\@11
\newcount\exo@number% compteur pour le num�ro d'exercice
\def\exocalctotal#1\endtotal{\edef\total@points{\dimtodec\dimexpr#1}}
\def\initexo#1{%
\def\exo@canal{#1}% sauvegarde le canal d'�criture
\exo@number=0 % initialiser le compteur d'exo
\iffileexists\exo@canal{\jobname.pts}% si le fichier .pts existe
{\input \jobname.pts }% le lire et ex�cuter son contenu
{\def\total@points{\char`\#\char`\#}}% sinon, d�finir un total alternatif
\immediate\openout\exo@canal=\jobname.pts % ouvrir le fichier .pts
\immediate\write\exo@canal{\noexpand\exocalctotal}% et commencer � y �crire dedans
}
\def\exo#1{% d�finti la macro qui affiche l'exercice
\bigbreak% sauter une grande espace verticale
\immediate\write\exo@canal{+#1}% �crire "+#1" dans le fichier .pts
\advance\exo@number by 1 % incr�menter le num�ro de l'exercice
\noindent\vrule height1ex width1ex depth0pt % trace le carr�
\kern1ex% ins�rer une espace horizontale
{\bf Exercice \number\exo@number}% afficher "Exercice <nombre>"
\leaders\hbox to.5em{\hss.\hss}\hfill% afficher les pointill�s
#1/\total@points% puis #1/<total>
\smallbreak% composer la ligne pr�c�dente et sauter une espace verticale
}
\def\stopexo{%
\immediate\write\exo@canal{\relax\noexpand\endtotal}%
\immediate\closeout\exo@canal
}
\catcode`\@12
\initexo\wtest
\hfill{\bf Interrogation �crite. Sujet : \TeX{}}\hfill\null
\par
\leavevmode\hfill\vrule height.4pt width 2cm depth0pt\hfill\null
\exo{3pt}
�laborer un test \litterate/\ifonebyte{<texte>}{<vrai>}{<faux>}/ qui teste, pour une
compilation avec un moteur 8 bits, si le \litterate/<texte>/ est cod� sur un seul
octet. Ce test pourrait �tre utilis� pour d�terminer si l'encodage d'un document
est � plusieurs octets (comme l'est UTF8) en prenant comme \litterate/<texte>/
les caract�res <<~�~>>, <<~�~>>, etc.
\exo{5,5pt}
Si \verb-#1- est un nombre entier, quel est le test fait par ce code ?
\smallbreak
\hfill
\litterate/\if\string l\expandafter\firstto@nil\romannumeral#1\relax\@nil/
\hfill\null
\exo{4,5pt}
On a vu que pour provoquer un $n$-d�veloppement, les \litterate/\expandafter/se pla�aient
en nombre �gal � $2^n-1$ devant chaque token pr�c�dant celui que l'on veut d�velopper.
Or, ce nombre est {\it impair\/}. Trouver un exemple ou un cas particulier o� il faut
placer un nombre {\it pair\/} d'\litterate/\expandafter/ devant un token (on pourra
envisager le cas de 2 \litterate/\expandafter/).
\stopexo
****************** Fin code ******************
****************** Code 295 ******************
\def\identite{Foo Bar}% Pr�nom Nom
\def\beforespace#1 #2\nil{#1}
\def\afterspace#1 #2\nil{#2}
\def\prenom{\beforespace\identite\nil}
\def\nom{\afterspace\identite\nil}
Mon pr�nom : \expandafter\expandafter\prenom
Mon nom : \expandafter\expandafter\nom
****************** Fin code ******************
****************** Code 296 ******************
\newlinechar`\^^J
\immediate\openout\wtest=test1.txt
\immediate\write\wtest{Une premi�re ligne^^JEt une seconde.}
\immediate\closeout\wtest
\showfilecontent\rtest{test1.txt}
****************** Fin code ******************
****************** Code 297 ******************
\newlinechar`\^^J
\immediate\openout\wtest=test2.txt
\immediate\write\wtest{Une premi�re ligne^^JEt une seconde.}
\immediate\write\wtest{Et la derni�re.}
\immediate\closeout\wtest
{\endlinechar`\X % ins�re "X" � chaque fin de ligne
\openin\rtest=test2.txt % les fins de lignes sont comment�es
\loop% pour �viter que \endlinechar
\read\rtest to \foo% ne soit ins�r� � chaque fin de
\unless\ifeof\rtest% ligne du code source
\meaning\foo\par% affiche le texte de remplacement de \foo
\repeat%
\closein\rtest}%
****************** Fin code ******************
****************** Code 298 ******************
\catcode`\@11
\def\exactwrite#1{% #1=num�ro de canal
\begingroup
\for\xx=0 to 255\do{\catcode\xx=12 }% donne � tous les octets le catcode 12
\newlinechar=`\^^M % caract�re de fin de ligne = retour charriot
\exactwrite@i{#1}% donne le <canal> d'�criture comme premier argument
}
\def\exactwrite@i#1#2{% #2 est le caract�re d�limiteur de catcode 12
\def\exactwrite@ii##1#2{% ##1 est le <texte> � envoyer vers le fichier
\immediate\write#1{##1}% �crire le <texte> dans le fichier
\endgroup% puis, sortir du groupe
}%
\exactwrite@ii% traiter tout ce qui se trouve jusqu'au prochain #2
}
\catcode`\@12
\immediate\openout\wtest=writetest.txt % lie le canal \wtest au fichier
\exactwrite\wtest|Programmer en \TeX{} est facile !
Et tr�s utile.|
\immediate\closeout\wtest% et fermer le fichier
Le contenu du fichier "writetest.txt" est :\par
"\showfilecontent\rtest{writetest.txt}"
****************** Fin code ******************
****************** Code 299 ******************
\newlinechar`\^^J
\message{^^JQuel est votre nom ? }
\xread-1 to \username
\message{Bonjour \username.^^J%
Depuis combien d'ann�es pratiquez-vous TeX ? }
\read-1 to \yeartex
\message{%
\ifnum\yeartex<5 Cher \username, vous �tes encore un d�butant !
\else\ifnum\yeartex<10 Bravo \username, vous �tes un TeXpert !
\else\ifnum\yeartex<15 F�licitations \username, vous �tes un TeXgourou.
\else Passez � autre chose, par exemple � Metafont et Metapost !
\fi\fi\fi^^J}
****************** Fin code ******************
****************** Code 300 ******************
\catcode`\@11
\def\answer@plus{+}\def\answer@minus{-}\def\answer@equal{=}%
\def\nb@found#1{% macro appel�e lorsque le nombre (argument #1) est trouv�
\message{^^JVotre nombre est #1.^^JMerci d'avoir jou� avec moi.^^J}%
}
\def\nbguess#1#2{%
\message{Choisissez un nombre entre #1 et #2.^^J
Tapez entr�e lorsque c'est fait.}%
\read-1 to \tex@guess% attend que l'on tape sur "entr�e"
\nbguess@i{#1}{#2}%
}
\def\nbguess@i#1#2{%
\ifnum#1<#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
% si #1<#2 (donc le nombre n'est pas trouv�),
% mettre dans \tex@guess la troncature de la moyenne de #1 et #2
{\edef\tex@guess{\number\truncdiv{\numexpr#1+#2\relax}2}%
\message{Je propose \tex@guess.^^J% afficher sur le terminal
Votre nombre est-il plus grand (+), plus petit (-) ou �gal (=) : }%
\read -1 to \user@answer% lire la r�ponse de l'utilisateur
\edef\user@answer{%
\expandafter\firstto@nil\user@answer\relax\@nil% ne garder que le 1er caract�re
}%
\ifxcase\user@answer% envisager les cas "+", "-" et "="
\answer@plus{\exparg\nbguess@i{\number\numexpr\tex@guess+1\relax}{#2}}%
\answer@minus{\expsecond{\nbguess@i{#1}}{\number\numexpr\tex@guess-1\relax}}%
\answer@equal{\nb@found\tex@guess}%
\elseif% si la r�ponse ne commence pas par "+", "-" ou "="
\message{Je n'ai pas compris votre r�ponse}% afficher message erreur
\nbguess@i{#1}{#2}% et recommencer avec les m�mes nombres
\endif
}
% si #1>=#2, le nombre est trouv�
{\nb@found{#1}}%
}
\catcode`\@12
\nbguess{1}{100}
****************** Fin code ******************
****************** Code 301 ******************
\def\syracuse#1{%
#1% affiche le nombre
\ifnum#1>1 % si le nombre est >1
, % afficher une virgule+espace
\ifodd#1 % s'il est pair
\exparg\syracuse% appeler la macro \syracuse
{\number\numexpr3*#1+1% avec 3*n+1
\expandafter\expandafter\expandafter}% apr�s avoir rendu la macro terminale
\else % s'il est pair
\expandafter\syracuse\expandafter% appeler la macro \syracuse
{\number\numexpr#1/2% avec n/2
\expandafter\expandafter\expandafter}% apr�s avoir rendu la macro terminale
\fi
\else% si le nombre est 1
.% afficher un point
\fi
}
a) \syracuse{20}\par
b) \syracuse{14}\par
c) \syracuse{99}\par
d) \edef\foo{\syracuse{15}}\meaning\foo
****************** Fin code ******************
****************** Code 302 ******************
\def\syracuse#1{%
#1% afficher le nombre
\ifnum#1>1 % si le nombre est >1
, % afficher une virgule+espace
\exparg\syracuse{% appeler la macro \syracuse
\number\numexpr% avec le nombre :
\ifodd#1 3*#1+1% 3n+1 si #1 est impair
\else #1/2% n/2 sinon
\fi%
\expandafter}% avant de rendre la r�cursivit� terminale
\else
.% si #1=1, afficher un point
\fi
}
a) \syracuse{20}\par
b) \syracuse{14}\par
c) \syracuse{99}\par
d) \edef\foo{\syracuse{15}}\meaning\foo
****************** Fin code ******************
****************** Code 303 ******************
\def\factorielle#1{%
\ifnum#1=0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{1}% "1" si #1=0}
{#1*\exparg\factorielle{\number\numexpr#1-1}}%
}
a) \factorielle{0}\qquad
b) \factorielle{3}\qquad
c) \edef\foo{\factorielle{8}}\meaning\foo
****************** Fin code ******************
****************** Code 304 ******************
\catcode`\@11
\def\factorielle#1{%
\number\numexpr\factorielle@i{#1}\relax% appelle \factorielle@i
% en lan�ant le d�veloppement maximal
}
\def\factorielle@i#1{%
\ifnum#1=0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{1}% "1" si #1=
{#1*\exparg\factorielle@i{\number\numexpr#1-1}}%
}
\catcode`\@12
a) \factorielle{0}\qquad
b) \factorielle{3}\qquad
c) \edef\foo{\factorielle{8}}\meaning\foo
****************** Fin code ******************
****************** Code 305 ******************
\catcode`\@11
\def\PGCD#1#2{%
\ifnum#1<#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\PGCD@i{#2}{#1}}% si #1<#2, mettre #2 (le grand) dans le premier argument
{\PGCD@i{#1}{#2}}%
}
\def\PGCD@i#1#2{% #1=a #2=b avec a>b
\exptwoargs\PGCD@ii% appeler la macro r�cursive avec
{\number\numexpr#1-#2*\truncdiv{#1}{#2}}% le reste de a/b
{#2}% et le divisieur b
}
\def\PGCD@ii#1#2{% #1=reste r #2=diviseur b
\ifnum#1=\z@\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{#2}% si le reste est nul, renvoyer b
{\PGCD@i{#2}{#1}}% sinon, recommencer avec b et r
}
\catcode`\@12
a) \PGCD{120}{75}\qquad
b) \PGCD{64}{180}\qquad
c) \PGCD{145}{64}\qquad
d) \edef\foo{\PGCD{1612}{299}}\meaning\foo
****************** Fin code ******************
****************** Code 306 ******************
\catcode`\@11
\def\calcPGCD#1#2{%
\ifhmode\par\fi% si en mode horizontal, former le paragraphe
\ifnum#1<#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\calcPGCD@i{#2}{#1}}% si #1<#2, mettre #2 (le grand) dans le premier argument
{\calcPGCD@i{#1}{#2}}%
}
\def\calcPGCD@i#1#2{% #1=a #2=b avec a>b
\edef\calcPGCD@quotient{\number\truncdiv{#1}{#2}}% stocke le quotient
$#1=\calcPGCD@quotient\times#2% en mode maths, afficher "a=q*b" (� suivre)
\exptwoargs\calcPGCD@ii% appeler la macro r�cursive avec
{\number\numexpr#1-#2*\calcPGCD@quotient}% le reste de a/b
{#2}% et le divisieur b
}
\def\calcPGCD@ii#1#2{% #1=reste r #2=diviseur b
+#1$\par% (suite du mode math) afficher "+r", fermer le mode math et \par
\ifnum#1=\z@\expandafter\firstoftwo\else\expandafter\secondoftwo\fi%
{}% si le reste est nul, ne rien faire
{\calcPGCD@i{#2}{#1}}% sinon, recommencer avec b et r
}
\catcode`\@12
\calcPGCD{39}{15}\medbreak
\calcPGCD{1612}{299}
****************** Fin code ******************
****************** Code 307 ******************
\frboxsep=0pt % encadrer au plus proche
\leavevmode\frbox{$=$} n'est pas identique � \frbox{${}={}$}
****************** Fin code ******************
****************** Code 308 ******************
\catcode`\@11
\def\calcPGCD#1#2{%
\vtop{% mettre l'alignement dans une \vtop
\halign{% les "#" doivent �tre doubl�s puisqu'� l'int�rieur d'une macro
$\hfil##$&${}=\hfil##$&${}\times##\hfil$&${}+##\hfil$% pr�ambule
\cr% fin du pr�ambule et d�but de la premi�re cellule
\ifnum#1<#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\calcPGCD@i{#2}{#1}}% si #1<#2, mettre #2 (le grand) dans le premier argument
{\calcPGCD@i{#1}{#2}}%
\crcr% fin de l'alignement
}%
}%
}
\def\calcPGCD@i#1#2{% #1=a #2=b avec a>b
\xdef\calcPGCD@quotient{\number\truncdiv{#1}{#2}}% stocke le quotient
#1 & \calcPGCD@quotient & #2 &% afficher "a=q*b" (� suivre)
\exptwoargs\calcPGCD@ii% appeler la macro r�cursive avec
{\number\numexpr#1-#2*\calcPGCD@quotient}% le reste de a/b
{#2}% et le divisieur b
}
\def\calcPGCD@ii#1#2{% #1=reste r #2=diviseur b
#1% (suite de l'alignement) afficher "+r"
\cr% et terminer la ligne en cours
\ifnum#1=\z@\expandafter\firstoftwo\else\expandafter\secondoftwo\fi%
{}% si le reste est nul, ne rien faire
{\calcPGCD@i{#2}{#1}}% sinon, recommencer avec b et r
}
\catcode`\@12
a) \calcPGCD{39}{15}\medbreak
b) \calcPGCD{1612}{299}
****************** Fin code ******************
****************** Code 309 ******************
\catcode`\@11
\def\baseconv#1{%
\unless\ifnum#1=\z@ % si #1 est diff�rent de 0
\number\numexpr#1-2*\truncdiv{#1}2\relax% �crire le reste
\exparg\baseconv{\number\truncdiv{#1}2\expandafter}% recommencer avec #1/2
\fi% apr�s que le \fi ait �t� lu
}
\catcode`\@12
a) \baseconv{43}\qquad
b) \baseconv{32}\qquad
c) \edef\foo{\baseconv{159}}\meaning\foo
****************** Fin code ******************
****************** Code 310 ******************
\catcode`\@11
\def\baseconv#1{%
\baseconv@i{}{#1}%
}
\def\baseconv@i#1#2{% #1=restes #2=n
\ifnum#2=\z@\expandafter\firstoftwo\else\expandafter\secondoftwo\fi% si n=0
{#1}% si <n>=0, afficher tous les restes
{% sinon, recommencer en
\exptwoargs\baseconv@i% ajoutant le reste courant avant #1
{\number\numexpr#2-2*\truncdiv{#2}2\relax #1}
{\number\truncdiv{#2}2}% et en prenant n:=n/2
}%
}
\catcode`\@12
a) \baseconv{43}\qquad
b) \baseconv{32}\qquad
c) \edef\foo{\baseconv{159}}\meaning\foo
****************** Fin code ******************
****************** Code 311 ******************
\catcode`\@11
\def\z@@{\expandafter\z@\expandafter}
\def\basedigit#1{%
\ifcase#1
\z@@ 0%
\or\z@@ 1\or\z@@ 2\or\z@@ 3\or\z@@ 4\or\z@@ 5\or\z@@ 6\or\z@@ 7%
\or\z@@ 8\or\z@@ 9\or\z@@ A\or\z@@ B\or\z@@ C\or\z@@ D\or\z@@ E%
\or\z@@ F\or\z@@ G\or\z@@ H\or\z@@ I\or\z@@ J\or\z@@ K\or\z@@ L%
\or\z@@ M\or\z@@ N\or\z@@ O\or\z@@ P\or\z@@ Q\or\z@@ R\or\z@@ S%
\or\z@@ T\or\z@@ U\or\z@@ V\or\z@@ W\or\z@@ X\or\z@@ Y\or\z@@ Z%
\fi
}
\long\def\>#1<{\detokenize{#1}}
a) \expandafter\>\romannumeral\basedigit{23}<\quad
b) \expandafter\>\romannumeral\basedigit{6}<
\catcode`@12
****************** Fin code ******************
****************** Code 312 ******************
\catcode`\@11
\def\baseconv#1#2{% #1=base #2=nombre � convertir
\ifnum#1<37 % base maxi = 36 (10 signes chiffres + 26 signes lettres)
\antefi
\baseconv@i{}{#2}{#1}%
\fi
}
\def\baseconv@i#1#2#3{% #1=restes #2=n #3=base
\ifnum#2=\z@ \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{#1}% si n=0, afficher tous les restes
{% si non, transmettre en dernier argument
\expsecond{\baseconv@ii{#1}{#2}{#3}}%
{\number\truncdiv{#2}{#3}}% le quotient
}%
}
\def\baseconv@ii#1#2#3#4{% #1=restes #2=n #3=base #4=q
\exparg\baseconv@i% recommencer, en ajoutant le <chiffre> avant les restes
{\romannumeral\basedigit{\number\numexpr#2-#4*#3\relax}#1}%
{#4}% et en rempla�ant n par q
{#3}%
}
\def\z@@{\expandafter\z@\expandafter}%
\def\basedigit#1{%
\ifcase#1
\z@@ 0%
\or\z@@ 1\or\z@@ 2\or\z@@ 3\or\z@@ 4\or\z@@ 5\or\z@@ 6\or\z@@ 7%
\or\z@@ 8\or\z@@ 9\or\z@@ A\or\z@@ B\or\z@@ C\or\z@@ D\or\z@@ E%
\or\z@@ F\or\z@@ G\or\z@@ H\or\z@@ I\or\z@@ J\or\z@@ K\or\z@@ L%
\or\z@@ M\or\z@@ N\or\z@@ O\or\z@@ P\or\z@@ Q\or\z@@ R\or\z@@ S%
\or\z@@ T\or\z@@ U\or\z@@ V\or\z@@ W\or\z@@ X\or\z@@ Y\or\z@@ Z%
\fi
}
\catcode`\@12
a) "\baseconv{20}{21587}"\qquad
b) "\baseconv{16}{32}"\qquad
c) \edef\foo{\baseconv{16}{159}}%
"\meaning\foo"\qquad
d) "\baseconv{2}{43}"
****************** Fin code ******************
****************** Code 313 ******************
\catcode`\@11
\def\quark@list{\quark@list}% quark de fin de liste
\def\finditem#1{% #1 = \<macrolist>, la position est lue plus tard par \finditem@i
\exparg\finditem@i{#1}% 1-d�veloppe la \<macrolist>
}
\def\finditem@i#1#2{% #1 = liste #2=position cherch�e
\finditem@ii{1}{#2}#1,\quark@list,% appelle la macro r�cursive
}
\def\finditem@ii#1#2#3,{% #1=position courante #2=position cherch�e #3=�l�ment courant
\ifx\quark@list#3\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{}% si la fin de liste est atteinte, ne rien renvoyer
{% sinon
\ifnum#1=#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{% si la position est la bonne
\finditem@iii{#3}% renvoyer #3 et manger les �l�ments restants
}
{% si la position n'est pas la bonne, recommencer en incr�mentant #1
\exparg\finditem@ii{\number\numexpr#1+1}{#2}%
}%
}%
}
\def\finditem@iii#1#2\quark@list,{% renvoyer #1 et manger le reste de la liste
#1%
}
\catcode`\@12
\def\liste{a,bcd,{ef},g,hij,kl}
a) \edef\foo{\finditem\liste5}\meaning\foo\qquad
b) \edef\bar{\finditem\liste3}\meaning\bar
****************** Fin code ******************
****************** Code 314 ******************
\catcode`\@11
\def\quark@list{\quark@list}% quark de fin de liste
\def\finditem#1{% #1 = \<macro>, la position est lue plus tard par \finditem@i
\exparg\finditem@i{#1}% 1-d�veloppe la \<macro>
}
\def\finditem@i#1#2{% #1 = liste #2=position cherch�e
\ifnum#2>\z@% ne faire quelque chose que si la position est >0
\antefi
\finditem@ii{1}{#2}\relax#1,\quark@list,% appelle la macro r�cursive
\fi
}
\def\finditem@ii#1#2#3,{% #1=position courante #2=position cherch� #3=�l�ment courant
\expandafter\ifx\expandafter\quark@list\gobone#3%
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{}% si la fin de liste est atteinte, ne rien renvoyer
{% sinon
\ifnum#1=#2 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{% si la position est la bonne
\finditem@iii{#3}% renvoyer #3 et manger les �l�ments restants
}
{% si la position n'est pas la bonne, recommencer en incr�mentant #1
\exparg\finditem@ii{\number\numexpr#1+1}{#2}\relax
}%
}%
}
\def\finditem@iii#1#2\quark@list,{% renvoyer #1 et manger le reste de la liste
\gobone#1%
}
\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%
}%
}%
}
\catcode`\@12
\def\liste{a,bcd,{ef},g,hij,kl}
a) "\finditem\liste5"\qquad
b) \edef\bar{\finditem\liste3}\meaning\bar\qquad
c) \finditemtocs\liste{3}\foo\meaning\foo
****************** Fin code ******************
****************** Code 315 ******************
\catcode`\@11
\def\quark@list{\quark@list}% quark de fin de liste
\def\positem#1{% #1 = \<macrolist>, la position est lue plus tard par \positem@i
\def\positem@endprocess{\pos@item}% hook : afficher la position
\exparg\positem@i{#1}% 1-d�veloppe la \<macrolist>
}
\def\positem@i#1#2{% #1 = liste #2=�l�ment cherch�
\def\sought@item{#2}% d�finir l'�l�ment cherch�
\positem@ii{1}\relax#1,\quark@list,% appelle la macro r�cursive
}
\def\positem@ii#1#2,{% #1=position courante #2=\relax + �l�ment courant
\expandafter\def\expandafter\current@item\expandafter{\gobone#2}%
\ifx\current@item\quark@list\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\def\pos@item{0}% si la fin de liste est atteinte, renvoyer 0
\positem@endprocess% et aller au hook
}% sinon
{\ifx\current@item\sought@item\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\def\pos@item{#1}% si la position est la bonne, d�finir la position
\positem@goblist% et manger les �l�ments restants
}% si la position n'est pas la bonne, recommencer en incr�mentant #1
{\exparg\positem@ii{\number\numexpr#1+1}\relax
}%
}%
}
\def\positem@goblist#1\quark@list,{\positem@endprocess}% manger la liste et aller au hook
\def\positemtocs#1#2#3{% #1=\<macrolist> #2=�l�ment � chercher #3=macro � d�finir
\def\positem@endprocess{\let#3=\pos@item}% hook : mettre le r�sultat dans #3
\exparg\positem@i{#1}{#2}% 1-d�veloppe la \<macrolist>
}
\catcode`\@12
\def\liste{a,bcd,{ef},g,hij,,kl}
a) \positem\liste{g}\qquad
b) \positem\liste{ef}\qquad
c) \positem\liste{{ef}}\qquad
d) \positem\liste{}\medbreak
\def\liste{a,bcd,{ef},g,hij,,kl}
a) \positemtocs\liste{g}\foo\meaning\foo\qquad
b) \positemtocs\liste{ef}\foo\meaning\foo\qquad
c) \positemtocs\liste{{ef}}\foo\meaning\foo\qquad
d) \positemtocs\liste{}\foo\meaning\foo\qquad
****************** Fin code ******************
****************** Code 316 ******************
\catcode`\@11
\def\quark@list{\quark@list}% quark de fin de liste
\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
}
\catcode`\@12
\def\liste{a,bra,{cA},da,brA}\insitem\liste3{XX}\meaning\liste\par
\def\liste{a,bra,{cA},da,brA}\insitem\liste0{XX}\meaning\liste\par
\def\liste{a,bra,{cA},da,brA}\insitem\liste9{XX}\meaning\liste
****************** Fin code ******************
****************** Code 317 ******************
\catcode`\@11
\def\quark@list{\quark@list}% quark de fin de liste
\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,%
\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
}
\catcode`\@12
\for\xx=0 to 8 \do{%
\def\liste{a,bcd,{ef},g,hij,kl}
position \xx{} : \expandafter\delitem\expandafter\liste\xx\meaning\liste.\par
}
****************** Fin code ******************
****************** Code 318 ******************
\catcode`\@11
\def\moveitem#1#2#3{% #1 = liste, #2=position d�part, #3=position arriv�e
\ifnum#2>0 % ne faire quemque chose que si #2>0
\finditemtocs#1{#2}\temp@item% sauvegarder l'�l�ment
\delitem#1{#2}% supprimer l'�l�ment
\expsecond{\insitem#1{#3}}\temp@item% ins�rer l'�l�ment
\fi
}
\catcode`\@12
% d�place "b" en 5e position
a) \def\liste{a,b,c,d,e,f} \moveitem\liste25 "\liste"\par
% d�place "d" en 1e position
b) \def\liste{a,b,c,d,e,f} \moveitem\liste41 "\liste"\par
% d�place "c" en 9e position
c) \def\liste{a,b,c,d,e,f} \moveitem\liste39 \liste"\par
% position d�part=0 -> sans effet
d) \def\liste{a,b,c,d,e,f} \moveitem\liste02 "\liste"
****************** Fin code ******************
****************** Code 319 ******************
\catcode`\@11
\def\runlist#1\with#2{% #1=liste #2=macro
\def\runlist@i##1,{%
\ifx\quark@list##1\relax\else% si la fin n'est pas atteinte
\addtomacro\collect@run{#2{##1}}% ajouter "\<macro>{<�l�ment>}""
\expandafter\runlist@i% et recommencer en lisant l'�l�ment suivant
\fi
}%
\begingroup% fait la collecte dans un groupe
\let\collect@run=\empty% initialiser la macro
\expandafter\runlist@i#1,\quark@list,% appeler \runlist@i
\expandafter\endgroup% ferme le groupe et d�truit \collect@run
\collect@run% apr�s l'avoir d�velopp� !
}
\catcode`\@12
\newcount\foocnt
\foocnt=0 % compteur utilis� pour num�roter les �l�ments dans la macro \foo
\def\foo#1{% la macro qui va ex�cuter chaque �l�ment de la liste. #1 = l'�l�ment
\advance\foocnt1 % incr�mente le compteur
L'argument \number\foocnt\ est : {\bf #1}\par%
}
\def\liste{a,bra,ca,da,BRA}%
\runlist\liste\with\foo%
****************** Fin code ******************
****************** Code 320 ******************
\catcode`\@11
\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}}% renvoyer vrai s'il n'y a rien avant " "
\catcode`\@12
a) \ifspacefirst{a bc d}{vrai}{faux}\qquad
b) \ifspacefirst{ a bc d}{vrai}{faux}\qquad
c) \ifspacefirst{ }{vrai}{faux}\qquad
d) \ifspacefirst{}{vrai}{faux}\qquad
e) \ifspacefirst{{ } }{vrai}{faux}\qquad
f) \ifspacefirst{ {x} }{vrai}{faux}
****************** Fin code ******************
****************** Code 321 ******************
\catcode`\@11
\expandafter\def\expandafter\gobspace\space{}
\def\removefirstspaces#1{%
\ifspacefirst{#1}% si #1 commence par un espace
{\exparg\removefirstspaces{\gobspace#1}}% recommencer sans le 1er espace
{#1}% sinon, renvoyer l'argument
}
\catcode`\@12
a) "\removefirstspaces{12 {\bf3}4 567}"\qquad
b) "\removefirstspaces{ 12 {\bf3}4 567}"\qquad
c) \edef\foo{\space\space\space 12 34 567}
"\exparg\removefirstspaces\foo"
****************** Fin code ******************
****************** Code 322 ******************
\catcode`\@11
\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
{\exparg\removefirstspaces@i{\gobspace#1}}% recommencer sans le 1er espace
{\z@#1}% sinon, renvoyer l'argument o� \z@ stoppe l'action de \romannumeral
}
\catcode`\@12
\long\def\>#1<{"\detokenize{#1}"}
a) \expandafter\expandafter\expandafter\>\removefirstspaces{12 {\bf3}4 567}<\qquad
b) \expandafter\expandafter\expandafter\>\removefirstspaces{ 12 {\bf3}4 567}<\qquad
c) "\removefirstspaces{ 12 {\bf3}4 }"
****************** Fin code ******************
****************** Code 323 ******************
\catcode`\@11
\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\relax#1^^00 ^^00\@nil% mettre un \relax au d�but
% et passer la main � \removelastspaces@i
}
\def\removelastspaces@i#1 ^^00{% prendre ce qui est avant " W"
\removelastspaces@ii#1^^00% ajouter "W"
}
\def\removelastspaces@ii#1^^00#2\@nil{% #1=ce qui est avant "W" #2=reliquat
\ifspacefirst{#2}% si le reliquat commence par un espace
{\removelastspaces@i#1^^00 ^^00\@nil}% recommencer sans passer par \removelastspaces
{\expandafter\z@\gobone#1}% sinon supprimer le \relax ajout� au d�but
% et stopper l'action de \romannumeral avec \z@
}
\catcode0=\catcodezero@saved\relax% restaure le catcode de ^^00
\catcode`\@12
\long\def\>#1<{"\detokenize{#1}"}
a) \expandafter\expandafter\expandafter\>\removelastspaces{ 12 {\bf3}4 }<\qquad
b) \expandafter\expandafter\expandafter\>\removelastspaces{12 {\bf3}4}<\qquad
c) "\removelastspaces{ 12 {\bf3}4 }"
****************** Fin code ******************
****************** Code 324 ******************
\catcode`\@11
\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}%
}%
}
\catcode`\@12
\long\def\>#1<{"\detokenize{#1}"}
a) \expandafter\expandafter\expandafter\>\removetrailspaces{ 12 {\bf3}4 }<\qquad
b) \expandafter\expandafter\expandafter\>\removetrailspaces{12 {\bf3}4}<\par
c) \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter
\foo\expandafter\expandafter\expandafter{\removetrailspaces{ 12 {\bf3}4 }}%
signification : \meaning\foo.\par
c) ex�cution : "\foo"\par
d) "\removetrailspaces{ 12 {\bf3}4 }"
****************** Fin code ******************
****************** Code 325 ******************
\catcode`\@11
\def\sanitizelist#1{% #1 = liste
\let\item@list\empty% initialise le r�ceptacle de la liste assainie
\def\sanitizelist@endprocess{% d�finit le hook de fin
\expandafter\remove@lastcomma\item@list\@nil% supprimer derni�re virgule
\let#1=\item@list% et assigner le r�sultat � #1
}%
\expandafter\sanitizelist@i\expandafter\relax#1,\quark@list,% aller � la macro r�cursive
}
\def\sanitizelist@i#1,{% #1="\relax" + �l�ment courant
\expandafter\ifx\expandafter\quark@list\gobone#1%
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\sanitizelist@endprocess% si fin de liste, hook de fin
}% si la fin de la liste n'est pas atteinte :
{\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
\addtomacro% 1-d�velopper \gobone pour retirer \relax
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
\item@list% puis 2-d�velopper \removetrailspaces
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
{\expandafter\removetrailspaces\expandafter{\gobone#1},}% "#1"
\sanitizelist@i\relax% et continuer avec l'�l�ment suivant
}%
}
\catcode`\@12
\frboxsep=0pt % encadrer au plus proche
\def\foo#1{\frbox{\tt\strut#1} }% boite avec un strut et en fonte "tt" puis espace
\def\liste{ Programmer, en \TeX{} ,est ,{\bf facile}, et utile }
a) \runlist\liste\with\foo% encadrer les items
b) \sanitizelist\liste% supprimer les espaces inutiles des items
\runlist\liste\with\foo
****************** Fin code ******************
****************** Code 326 ******************
\catcode`\@11
\def\boxsentence#1{%
\leavevmode% se mettre en mode horizontal
\boxsentence@i#1\quark% transmet "#1+\quark" � boxsentence@i
}
\def\boxsentence@i#1{% #1= argument lu
\def\current@arg{#1}% stocke l'argument dans une macro temporaire
\unless\ifx\quark\current@arg% si la fin n'est pas atteinte
\frbox{#1}% encadrer cet argument
\expandafter\boxsentence@i% lire l'argument suivant
\fi
}
\catcode`@12
\frboxsep=1pt \frboxrule=0.2pt
\boxsentence{Programmer en \TeX\ est facile}
****************** Fin code ******************
****************** Code 327 ******************
\catcode`\@11
\edef\star@macro{\string *}% stocke une �toile de catcode 12
\def\expo#1{%
\def\temp@arg{#1}% stocke l'argument lu
\ifx\star@macro\temp@arg\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{% si l'argument est une �toile de catcode 12
$^\dag$% affiche une dague
}% sinon
{$^\ddag$% affiche une double dague
{#1}% puis r�-�crit l'argument {#1}
}%
}
A\expo B\expo*C
****************** Fin code ******************
****************** Code 328 ******************
\def\boxsentence#1{%
\readtok#1\quark% met le token d'arr�t \quark � la fin de #1
}
\def\readtok{\afterassignment\cmptok\let\nxttok= }
\def\cmptok{%
\unless\ifx\nxttok\quark% si la fin n'est pas atteinte
\frbox{\nxttok}% encadrer le token lu
\expandafter\readtok% puis aller lire le suivant
\fi
}
\frboxsep=1pt \frboxrule=0.2pt
\leavevmode\boxsentence{Programmer en \TeX\ est facile}
****************** Fin code ******************
****************** Code 329 ******************
\def\permutstart{\afterassignment\cmptok\let\nxttok= }
\def\permutend{\permutend}%
\def\cmptok{%
\unless\ifx\permutend\nxttok% tant que la fin n'est pas atteinte :
\ifxcase\nxttok
ae% si le token lu est "a", afficher un "e"
ei io ou uy ya% etc pour les autres lettres
\elseif
\nxttok% si ce n'est aucune voyelle, afficher le token
\endif
\expandafter\permutstart% aller lire le token suivant
\fi
}
\permutstart Un "a" puis "e puis "i" ensuite, un "o", un "u" et "y".\permutend
****************** Fin code ******************
****************** Code 330 ******************
\def\boxsentence#1{\readtok#1\boxsentence}
\def\readtok{\afterassignment\cmptok\let\nxttok= }
\def\cmptok{%
%\show\nxttok% � d�commenter pour d�bogage
\unless\ifx\nxttok\boxsentence
\frbox{\nxttok}%
\expandafter\readtok
\fi
}
\frboxsep=1pt \frboxrule=0.2pt
\leavevmode\boxsentence{Pro{gra}mmer en \TeX\ est facile}
****************** Fin code ******************
****************** Code 331 ******************
\catcode`\@11
\def\Litterate{%
\begingroup% ouvrir un groupe
\tt% et adopter une fonte � chasse fixe
\afterassignment\Litterate@i% apr�s l'assignation, aller � \Litterate@i
\expandafter\let\expandafter\lim@tok\expandafter=\string% \lim@tok = token d�limiteur
}
\def\Litterate@i{%
\afterassignment\Litterate@ii%apr�s avoir lu le prochain token, aller � \Litterate@ii
\expandafter\let\expandafter\nxttok\expandafter=\string% lit le token suivant
}
\def\Litterate@ii{%
\ifx\nxttok\lim@tok% si le token suivant="token d�limiteur"
\endgroup% fermer le groupe et finir
\else
\nxttok% sinon, afficher ce token
\expandafter\Litterate@i% et lire le token suivant
\fi
}
\catcode`\@12
\Litterate|Programmer en \TeX {} est << facile >> !|
****************** Fin code ******************
****************** Code 332 ******************
\catcode`\@11
\def\Litterate{%
\begingroup% ouvrir un groupe
\tt% et adopter une fonte � chasse fixe
\afterassignment\Litterate@i% apr�s l'assignation, aller � \Litterate@i
\expandafter\let\expandafter\lim@tok\expandafter=\string% \lim@tok = token d�limiteur
}
\def\Litterate@i{%
\afterassignment\Litterate@ii% apr�s avoir lu un token, aller � \Litterate@ii
\expandafter\expandafter\expandafter% 1-d�velopper \string
\let
\expandafter\expandafter\expandafter% puis 1-d�velopper \space en " "
\nxttok
\expandafter\expandafter\expandafter
=\expandafter\space\string% et lire le token obtenu
}
\def\Litterate@ii{%
\ifx\nxttok\lim@tok% si le token suivant="token d�limiteur"
\endgroup% fermer le groupe et finir
\else
\nxttok% sinon, afficher ce token
\expandafter\Litterate@i% et lire le token suivant
\fi
}
\catcode`\@12
\Litterate|Programmer en \TeX {} est << facile >> : $~$^_#|
****************** Fin code ******************
****************** Code 333 ******************
\catcode`@11
\newskip\ltr@spc
\def\letterspace#1#2{%
\ltr@spc=#1\relax % assigne le ressort
\letterspace@i#2\letterspace@i% appelle la macro \letterspace@i
}
\def\letterspace@i{%
\afterassignment\letterspace@ii
\let\nxttok=
}
\def\letterspace@ii{%
\ifx\nxttok\letterspace@i% si la fin est atteinte
\unskip% supprimer le dernier ressort qui est de trop
\else
\nxttok% afficher le token
\hskip\ltr@spc\relax% ins�re le ressort
\expandafter\letterspace@i% va lire le token suivant
\fi
}
\catcode`@12
Voici "\letterspace{0.3em}{des lettres espac�es}"
et voici "\letterspace{-0.075em}{de la compression}".
****************** Fin code ******************
****************** Code 334 ******************
\catcode`@11
\newcount\test@cnt
\def\ifinteger#1{%
\ifstart{#1}{-}% si "-" est au d�but de #1
{\exparg\ifinteger{\gobone#1}% l'enlever et recommencer
}
{\ifempty{#1}% sinon, si #1 est vide
\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
}
\catcode`@12
1) \ifinteger{5644}{oui}{non}\qquad
2) \ifinteger{-987}{oui}{non}\qquad
3) \ifinteger{6a87}{oui}{non}\qquad
4) \ifinteger{abcd}{oui}{non}\qquad
5) \ifinteger{-a}{oui}{non}\qquad
6) \ifinteger{-}{oui}{non}\qquad
7) \ifinteger{3.14}{oui}{non}
****************** Fin code ******************
****************** Code 335 ******************
\catcode`\@11
\def\teststar{%
\futurelet\nxttok\teststar@i% % pioche le token suivant puis aller � \teststar@i
}
\def\teststar@i{%
\ifx *\nxttok\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{% si le token suivant est une �toile
\afterassignment\teststar@bf% apr�s avoir lu "*", aller � \teststar@bf
\let\nxttok= % lire l'�toile
}% si le token n'est pas une �toile
{\teststar@it% aller � \teststar@it
}%
}
\def\teststar@bf#1{{\bf#1}}% lit l'argument et le compose en gras dans un groupe
\def\teststar@it#1{{\it#1\/}}% lit l'argument et le compose en italique
\catcode`\@12
Un essai \teststar{r�ussi} et un essai \teststar*{�toil�} r�ussi aussi.
****************** Fin code ******************
****************** Code 336 ******************
\catcode`@11
\def\deftok#1#2{\let#1= #2\empty}% d�finit le token #1 (\empty au cas o� #2 est vide)
\deftok\sptoken{ }
\def\ifnexttok#1#2#3{% lit les 3 arguments : #1=token #2=code vrai #3=code faux
\deftok\test@tok{#1}% stocke le token cherch�
\def\true@code{#2}\def\false@code{#3}% et les codes � ex�cuter
\ifnexttok@i% aller � la macro r�cursive
}
\def\ifnexttok@i{%
\futurelet\nxttok\ifnexttok@ii% piocher le token d'apr�s et aller � \ifnexttok@ii
}
\def\ifnexttok@ii{%
\ifx\nxttok\sptoken% si le prochain token est un espace
\def\donext{%
\afterassignment\ifnexttok@i% recommencer apr�s
\let\nxttok= % apr�s avoir absorb� cet espace
}%
\else
\ifx\nxttok\test@tok% si le prochain token est celui cherch�
\let\donext\true@code% ex�cuter le code vrai
\else
\let\donext\false@code% sinon code faux
\fi
\fi
\donext% faire l'action d�cid�e ci-dessus
}
\catcode`@12
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : }W.\par
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : }a.\par
\ifnexttok *{je vais lire une �toile : }{je ne vais pas lire une �toile : } *.\par
\ifnexttok *{je vais lire une �toile : }{je ne vais pas lire une �toile : }a.
****************** Fin code ******************
****************** Code 337 ******************
\catcode`@11
\newif\iftestspace \testspacefalse
\def\deftok#1#2{\let#1= #2}\deftok\sptoken{ }
\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 "normale" qui ne teste pas 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{% macro qui ignore les espaces
\ifx\nxttok\sptoken% si le prochain token est un espace
\def\donext{%
\afterassignment\ifnexttok@i% lire le token d'apr�s
\let\nxttok= % apr�s avoir absorb� l'espace
}%
\else
\let\donext\ifnexttok@ii% sinon, faire le test "normal"
\fi
\donext% faire l'action d�cid�e ci-dessus
}
\catcode`@12
\testspacefalse
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : }W.\par
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : } W.\medbreak
\testspacetrue
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : }W.\par
\ifnexttok W{je vais lire un W : }{je ne vais pas lire un W : } W.
****************** Fin code ******************
****************** Code 338 ******************
\def\ifstarred#1{\ifnexttok*{\firstoftwo{#1}}}
\catcode`\@11
\def\teststar{\ifstarred{\teststar@bf}{\teststar@it}}
\def\teststar@bf#1{{\bf#1}}
\def\teststar@it#1{{\it#1\/}}
\catcode`\@12
Un essai \teststar{r�ussi} et un essai \teststar*{�toil�} r�ussi aussi.
****************** Fin code ******************
****************** Code 339 ******************
\catcode`\@11
\def\parsestop{\parsestop}% d�finit la macro-quark se trouvant en fin de code
\newtoks\code@toks% registre contenant le code lu
\def\parseadd{\addtotoks\code@toks}
\def\parse{%
\code@toks={}% initialise \code@toks � vide
\parse@i% et passe la main � \parse@i
}
\def\parse@i{\futurelet\nxttok\parse@ii}% lit le prochain token et va � \parse@ii
\def\parse@ii{%
\ifxcase\nxttok
\parsestop\parsestop@i% si la fin va �tre atteinte, aller � \parsestop@i
\sptoken\read@space% si un espace va �tre lu, aller � \read@space
\bgroup\read@bracearg% si une accolade ouvrante aller � \read@bracearg
\elseif
\testtoken% dans les autres cas, aller � \testtoken
\endif
}
\def\parsestop@i\parsestop{% la fin est atteinte : manger \parsestop
\the\code@toks% afficher le registre de tokens
}
\expandafter\def\expandafter\read@space\space{% manger un espace dans le code
\testtoken{ }% et aller � \testtoken
}
\def\read@bracearg#1{% l'argument entre accolades est lu
\parseadd{{#1}}% puis ajout� (entre accolades) tel quel � \code@toks
\parse@i% ensuite, lire le prochain token
}
\catcode`@12
{\bf Exemple 1 :}
\catcode`@11
\def\testtoken#1{% macro qui teste le token
\ifxcase{#1}
a{\parseadd{e}}% remplacer a par e
e{\parseadd{i}}% e par i
i{\parseadd{o}}% i par o
o{\parseadd{u}}% o par u
u{\parseadd{y}}% u par y
y{\parseadd{a}}% y par a
\elseif
\parseadd{#1}% sinon, ajouter le token tel quel
\endif
\parse@i% aller lire le token suivant
}%
\catcode`@12
\parse
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des sonorit\'es
{\bf catalanes, corses ou grecques} assez inattendues.
\parsestop\medbreak
{\bf Exemple 2 :}
\leavevmode \frboxsep=1pt
\catcode`@11
\def\testtoken#1{%
\ifxcase{#1}% si #1 est un espace
{ }{\parseadd{\hskip 0.75em }}% ajouter un espace
\ {\parseadd{\hskip 0.75em }}
\elseif
\parseadd{\frbox{#1}}% sinon, l'encadrer
\endif
\parse@i}%
\catcode`@12
\parse Programmer en \TeX\ est facile\parsestop\medbreak
{\bf Exemple 3 :}
\catcode`@11
\def\testtoken#1{%
\ifx a#1\parseadd{X}\else\parseadd{#1}\fi% remplace les "a" par des "X"
\parse@i
}
\catcode`@12
\parse a\bgroup\bf braca\egroup dabra\parsestop
****************** Fin code ******************
****************** Code 340 ******************
\catcode`\@11
\def\ifbracefirst#1{%
\ifnum\catcode\expandafter\expandafter\expandafter
`\expandafter\firstto@nil\detokenize{#1W}\@nil=1 % tester si son catcode est 1
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
}
\catcode`\@12
a) \ifbracefirst{123 456}{vrai}{faux}\qquad
b) \ifbracefirst{\bgroup12\egroup3 456}{vrai}{faux}\qquad
c) \ifbracefirst{{12}3 456}{vrai}{faux}\qquad
d) \ifbracefirst{1{2}3 456}{vrai}{faux}\qquad
\begingroup
\catcode`[=1 \catcode`]=2 % les crochets deviennent des accolades
e) \ifbracefirst[[]123 456][vrai][faux]
\endgroup
****************** Fin code ******************
****************** Code 341 ******************
\catcode`\@11
\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 % tester si son catcode est 1
\expandafter\firstoftwo
\else
\expandafter\secondoftwo
\fi
}%
}
\catcode`\@12
a) \ifbracefirst{}{vrai}{faux}\qquad b) \ifbracefirst{ }{vrai}{faux}\qquad
c) \ifbracefirst{ {}}{vrai}{faux}
****************** Fin code ******************
****************** Code 342 ******************
\catcode`\@11
\def\parsestop@i\parsestop{% la fin va �tre atteinte
\detokenize\expandafter{\the\code@toks}% afficher le contenu du registre
}
\def\read@bracearg{%
\read@bracearg@i\relax% ajoute un \relax avant de passer la main � \read@bracearg@i
}
\def\read@bracearg@i#1\parsestop{% #1 = tout jusqu'� \parsestop
\exparg\ifbracefirst{\gobone#1}% retire le \relax et teste si #1 commence par "{"
{\expandafter\read@bracearg@ii\gobone#1\parsestop}% si oui, aller � \readbrace@ii
{\expandafter\testtoken\gobone#1\parsestop}% sinon, aller � \testtoken
}
\def\read@bracearg@ii#1{% lit l'argument entre accolades
\parseadd{{#1}}% ajoute cet argument entre accolades
\parse@i% aller lire le token suivant
}
\def\testtoken#1{%
\parseadd{#1}% ajouter le token tel quel
\parse@i% aller lire le token suivant
}
\catcode`\@12
\parse a\hbox\bgroup\bf braca\egroup {da}{}b{ra}\parsestop
****************** Fin code ******************
****************** Code 343 ******************
\catcode`\@11
\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% teste si la macro est �toil�e
{\parse@grouptrue\parse@i}% mettre le bool�en � vrai
{\parse@groupfalse\parse@i}% sinon � faux
}
\def\parse@i{\futurelet\nxttok\parse@ii}% lit le prochain token
% et va � \parse@ii
\def\parse@ii{%
\ifxcase\nxttok
\parsestop\parsestop@i% si la fin va �tre atteinte, aller � \parsestop@i
\sptoken\read@space% si un espace va �tre lu, aller � \read@space
\bgroup\read@bracearg% si une accolade ouvrante aller � \read@bracearg
\elseif
\testtoken% dans les autres cas, aller � \testtoken
\endif
}
\def\parsestop@i\parsestop{% la fin est atteinte
\the\code@toks% afficher le registre de tokens
}
\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% si macro �toil�e
{\begingroup% ouvre un groupe pour parser l'int�rieur de l'accolade
\def\parsestop@i\parsestop{% red�finir localement \parsestop@i pour
\expandafter\endgroup% ne fermer le groupe qu'apr�s avoir
\expandafter\parseadd% 1-d�velopp� � l'ext�rieur du groupe
\expandafter{\expandafter{\the\code@toks}}%
\parse@i% puis va lire le token suivant
}%
\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
\ifxcase{#1}
a{\parseadd{e}}
e{\parseadd{i}}
i{\parseadd{o}}
o{\parseadd{u}}
u{\parseadd{y}}
y{\parseadd{a}}
\elseif
\parseadd{#1}%
\endif
\parse@i% aller lire le token suivant
}
\catcode`@12
\frboxsep=1pt
a) \parse
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des sonorit\'es
{\bf catalanes, \frbox{corses} ou grecques} assez inattendues.
\parsestop\medbreak
b) \parse*
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des sonorit\'es
{\bf catalanes, \frbox{corses} ou grecques} assez inattendues.
\parsestop
****************** Fin code ******************
****************** Code 344 ******************
\catcode`\@11
\def\parse{%
\code@toks{}% initialise le collecteur de tokens
\ifstarred
{\parse@grouptrue
\ifnexttok{ }% si un espace suit l'�toile
{\afterassignment\parse@i% aller � \parse@i
\let\nxttok= }% apr�s l'avoir mang�
{\parse@i}% sinon, aller � \parse@i
}
{\parse@groupfalse
\parse@i
}%
}
\def\testtoken#1{% macro qui teste le token
\ifxcase{#1}
a{\parseadd{e}}e{\parseadd{i}}i{\parseadd{o}}o{\parseadd{u}}
u{\parseadd{y}}y{\parseadd{a}}
\elseif
\parseadd{#1}%
\endif
\parse@i% aller lire le token suivant
}
\catcode`@12
\frboxsep=1pt
a) \parse
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des sonorit\'es
{\bf catalanes, \frbox{corses} ou grecques} assez inattendues.
\parsestop\medbreak
b) \parse*
Ce texte devenu \`a peine reconnaissable montre que le r\'esultat contient des sonorit\'es
{\bf catalanes, \frbox{corses} ou grecques} assez inattendues.
\parsestop
****************** Fin code ******************
****************** Code 345 ******************
\catcode`\@11
\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}}
\tt
a) \def\foo{1 {2 3} 4}\grab@first\foo\bar
"\meaning\bar"\qquad"\meaning\foo"
b) \def\foo{ 1 {2 3} 4}\grab@first\foo\bar
"\meaning\bar"\qquad"\meaning\foo""
c) \def\foo{{1 2} 3 4}\grab@first\foo\bar
"\meaning\bar"\qquad"\meaning\foo"
****************** Fin code ******************
****************** Code 346 ******************
\catcode`\@11
\def\ifstartwith#1#2{% #1=<texte> #2=<motif>
\ifempty{#2}
\firstoftwo% si <motif> est vide, renvoyer vrai
{\ifempty{#1}% si <code> est vide et <motif> non vide
\secondoftwo% renvoyer faux
{\def\startwith@code{#1}\def\startwith@pattern{#2}%
\ifstartwith@i% dans les autres cas, aller � \ifstartwith@i
}%
}%
}
\def\ifstartwith@i{%
\grab@first\startwith@code\first@code% extrait le premier "argument" de <texte>
\grab@first\startwith@pattern\first@pattern% et celui de <motif>
\ifx\first@code\first@pattern\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{% si les deux arguments �largis sont �gaux
\exparg\ifempty\startwith@pattern
\firstoftwo% et que <motif> ne contient plus rien => vrai
{\exparg\ifempty\startwith@code
\secondoftwo% si <texte> ne contient plus rien => faux
\ifstartwith@i% sinon poursuivre les tests
}%
}
\secondoftwo% si les deux argument �largis sont diff�rents, renvoyer faux
}
\catcode`\@12
1) \ifstartwith{a b c}{a b}{oui}{non}\quad 2) \ifstartwith{a b}{a b c}{oui}{non}\quad
3) \ifstartwith{ 123 }{ }{oui}{non}\quad 4) \ifstartwith{ 123 }{1}{oui}{non}\quad
5) \ifstartwith{1{2} 3}{12}{oui}{non}\quad 6) \ifstartwith{1{2} 3}{1{2} }{oui}{non}\quad
7) \ifstartwith{{} {}}{ }{oui}{non}\quad 8) \ifstartwith{{} {}}{{} }{oui}{non}\quad
9) \ifstartwith{ {12} a}{ }{oui}{non}\quad10) \ifstartwith{ {12} a}{ {1}}{oui}{non}
****************** Fin code ******************
****************** Code 347 ******************
\catcode`\@11
\def\ifcontain#1#2{% #1 contient-il #2?
\def\main@arg{#1}\def\pattern@arg{#2}% stocke le <code> et le <motif>
\ifempty{#2}
\firstoftwo% si #2 est vide => vrai
{\ifempty{#1}
\secondoftwo% si #1 est vide et pas #2 => faux
\ifcontain@i% sinon, aller faire les tests
}%
}
\def\ifcontain@i{%
\exptwoargs\ifstartwith\main@arg\pattern@arg
\firstoftwo% si motif est au d�but de code => vrai
{\exparg\ifempty\main@arg
\secondoftwo% sinon, si code est vide => faux
{\grab@first\main@arg\aux@arg% autrement, manger le 1er "argument" de code
\ifcontain@i% et recommencer
}%
}%
}
\catcode`\@12
1) \ifcontain{abc def}{c }{oui}{non}\quad 2) \ifcontain{abc def}{cd}{oui}{non}\quad
3) \ifcontain{12 34 5}{1 }{oui}{non}\quad 4) \ifcontain{12 34 5}{ }{oui}{non}\quad
5) \ifcontain{a{b c}d}{b c}{oui}{non}\quad 6) \ifcontain{a{b c}d}{{b c}}{oui}{non}\quad
7) \ifcontain{{} {}}{ }{oui}{non}\quad 8) \ifcontain{{} {}}{{}}{oui}{non}
****************** Fin code ******************
****************** Code 348 ******************
\catcode`@11
\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
{\exparg\ifempty\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 {<argument>} de main@arg
\begingroup% ouvrir un groupe
\in@grouptrue% mettre le bool�en � vrai
\expandafter\def\expandafter\main@arg\aux@arg% assigner "argument" � \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\startwith@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
}
\catcode`@12
1) \ifcontain{ab {c d}ef}{c}{oui}{non}\quad 2) \ifcontain*{ab {c d}ef}{c}{oui}{non}
****************** Fin code ******************
****************** Code 349 ******************
\catcode`@11
\newtoks\subst@toks% registre de tokens pour stocker le <texte> modifi�
\def\substitute{%
\def\substitute@end{\the\subst@toks}% macro ex�cut�e � la fin
\ifstarred
{\let\recurse@macro\substitute@star \substitute@i}%
{\let\recurse@macro\substitute@nostar\substitute@i}%
}
\def\substitute@i#1#2#3#4{% #1=macro � appeler selon �toile ou pas.
% #2=<texte> #3=<motif> #4=<motif de substi>
\def\code@arg{#2}\def\pattern@arg{#3}\def\subst@arg{#4}%
\subst@toks={}% initialiser le collecteur � vide
#1% aller � \substitute@star ou \substitute@nostar
}
\def\substitute@nostar{%
\exptwoargs\ifstartwith\code@arg\pattern@arg% si le <texte> commence par <motif>
{\eaddtotoks\subst@toks\subst@arg% ajouter <motif subst>
\grab@first\code@arg\aux@code% manger le 1er "argument" de <texte>
\substitute@nostar% et recommencer
}
{\expandafter\ifempty\expandafter{\code@arg}%
{\substitute@end% sinon, si <texte> est vide => afficher le registre de tokens
}
{\grab@first\code@arg\aux@arg% autrement, manger le 1er "argument" de <texte>
\eaddtotoks\subst@toks\aux@arg% et l'ajouter au registre de tokens
\substitute@nostar% et recommencer
}%
}%
}
\def\substitute@star{%
\expandafter\ifbracefirst\expandafter{\code@arg}% si <texte> commence par "{"
{\grab@first\code@arg\aux@arg% enlever {<argument>} de \code@arg
\begingroup% ouvrir un groupe
\def\substitute@end{% modifier localement la macro ex�cut�e � la fin
\expandafter\endgroup\expandafter% avant de fermer le groupe
\addtotoks\expandafter\subst@toks\expandafter% ajouter au registre hors du groupe
{\expandafter{\the\subst@toks}}% ce qui est collect� localement, mis entre {}
\substitute@star% puis recommencer
}%
\subst@toks{}% initialiser � vide
\expandafter\def\expandafter\code@arg\aux@arg% % assigner "argument" au <texte>
\substitute@star% et recommencer avec ce nouveau \code@arg
}% si code ne commence pas par "{"
{\exptwoargs\ifstartwith\code@arg\pattern@arg% si <motif> est au d�but de <texte>
{\eaddtotoks\subst@toks\subst@arg% ajouter <motif subst>
\grab@first\code@arg\aux@code% manger le 1er "argument" de <texte>
\substitute@star% et recommencer
}
{\expandafter\ifempty\expandafter{\code@arg}% si <texte> est vide
{\substitute@end% aller � la macro de fin
}% si <texte> n'est pas vide
{\grab@first\code@arg\aux@code% manger le 1er "argument" de <texte>
\eaddtotoks\subst@toks\aux@code% et l'ajouter au registre
\substitute@star% et recommencer
}%
}%
}%
}
\catcode`@12
1) \substitute{ab{\bf racada}bra}{a}{W}\qquad
2) \substitute*{ab{\bf racada}bra}{a}{W}\qquad
3) \substitute{12\frbox{\bf 34}56}{\bf}{\it}\qquad
4) \substitute*{12\frbox{\bf 34}56}{\bf}{\it}
****************** Fin code ******************
****************** Code 350 ******************
\catcode`@11
\newtoks\subst@toks% registre de tokens pour stocker le <texte> modifi�
\def\substitute{%
\def\substitute@end{\the\subst@toks}% macro ex�cut�e � la fin
\ifstarred
{\let\recurse@macro\substitute@star \substitute@i}%
{\let\recurse@macro\substitute@nostar\substitute@i}%
}
\def\substitute@i#1#2#3{% #1=<texte> #2=<motif> #3=<motif de substi>
\def\code@arg{#1}\def\pattern@arg{#2}\def\subst@arg{#3}%
\subst@toks={}% initialiser � vide
\recurse@macro% aller � \substitute@star ou \substitute@nostar
}
\def\substitute@nostar{%
\exptwoargs\ifstartwith\code@arg\pattern@arg% si le <texte> commence par <motif>
{\eaddtotoks\subst@toks\subst@arg% ajouter <motif subst>
\grab@first\code@arg\aux@code% manger le 1er "argument" de <texte>
\recurse@macro% et recommencer
}
{\expandafter\ifempty\expandafter{\code@arg}%
\substitute@end% sinon, si <texte> est vide => afficher le registre de tokens
{\grab@first\code@arg\aux@arg% autrement, manger le 1er "argument" de <texte>
\eaddtotoks\subst@toks\aux@arg% et l'ajouter au registre de tokens
\recurse@macro% et recommencer
}%
}%
}
\def\substitute@star{%
\expandafter\ifbracefirst\expandafter{\code@arg}% si <texte> commence par "{"
{\grab@first\code@arg\aux@arg% enlever {<argument>} de \code@arg
\begingroup% ouvrir un groupe
\def\substitute@end{% modifier localement la macro ex�cut�e � la fin
\expandafter\endgroup\expandafter% avant de fermer le groupe
\addtotoks\expandafter\subst@toks\expandafter% ajouter au registre hors du groupe
{\expandafter{\the\subst@toks}}% ce qui est collect� localement, mis entre {}
\recurse@macro% puis recommencer
}%
\subst@toks{}% initialiser � vide
\expandafter\def\expandafter\code@arg\aux@arg% % assigner "argument" au <texte>
\recurse@macro% et recommencer avec ce nouveau \code@arg
}% si <texte> ne commence pas par "{" :
\substitute@nostar% ex�cuter macro non �toil�e pour une seule it�ration
}
\def\substitutetocs{%
\ifstarred
{\let\recurse@macro\substitute@star \substitutetocs@i}%
{\let\recurse@macro\substitute@nostar\substitutetocs@i}%
}
\def\substitutetocs@i#1#2#3#4{% #1=<texte> #2=<motif> #3=<motif de substi> #4=\<macro>
\def\substitute@end{\edef#4{\the\subst@toks}}% macro ex�cut�e � la fin
\substitute@i{#1}{#2}{#3}% continuer comme avec \substitute
}
\catcode`@12
\frboxsep=1pt
1) \substitute{ab{\bf racada}bra}{a}{W}\qquad
2) \substitute*{ab{\bf racada}bra}{a}{W}\qquad
3) \substitute{12\frbox{\bf 34}56}{\bf}{\it}\qquad
4) \substitute*{12\frbox{\bf 34}56}{\bf}{\it}
\medbreak
1) \substitutetocs{ab{\bf racada}bra}{a}{W}\foo \meaning\foo\par
2) \substitutetocs*{ab{\bf racada}bra}{a}{W}\foo \meaning\foo\par
3) \substitutetocs{12\frbox{\bf 34}56}{\bf}{\it}\foo \meaning\foo\par
4) \substitutetocs*{12\frbox{\bf 34}56}{\bf}{\it}\foo \meaning\foo
****************** Fin code ******************
****************** Code 351 ******************
\catcode`@11
\def\vecteur{%
\ifnexttok[% si la macro est suivie d'un crochet
\vecteur@i% aller � la macro � arguments d�limit�s
{\vecteur@i[1]}% sinon, ajouter l'argument optionnel par d�faut entre crochets
}
\def\vecteur@i[#1]#2{% #1=arg optionnel #2=arg obligatoire
$(x_{#1},\ldots,x_{#2})$
}
\catcode`@12
1) \vecteur{n}\qquad 2) \vecteur[0]{k}\qquad 3) \vecteur[i]j \qquad4) \vecteur[]n
****************** Fin code ******************
****************** Code 352 ******************
\catcode`@11
\def\forcemath#1{% compose #1 en mode math, quel que soit le mode en cours
\ifmmode\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{#1}{$#1$}%
}
\def\vecteur{%
\ifnexttok[% si la macro est suivie d'un crochet
\vecteur@i% aller � la macro � arguments d�limit�s
{\vecteur@i[1]}% sinon, ajouter l'argument optionnel par d�faut entre crochets
}
\def\vecteur@i[#1]{%
\ifnexttok(% si une parenth�se vient ensuite
{\vecteur@ii[#1]}% aller � la macro � argument d�limit�s
{\vecteur@ii[#1](x)}% sinon, rajouter "x" comme argument optionnel
}
\def\vecteur@ii[#1](#2)#3{% #1 et #2=arg optionnel #3=arg obligatoire
\forcemath{({#2}_{#1},\ldots,{#2}_{#3})}%
}
\catcode`@12
1) \vecteur{n}\qquad 2) \vecteur[0]{k}\qquad
3) \vecteur[i](y)j \qquad4) \vecteur[](\alpha)n
****************** Fin code ******************
****************** Code 353 ******************
\catcode`@11
\def\vecteur{%
\ifnexttok[% si la macro est suivie d'un crochet
\vecteur@bracket% lire cet argument entre crochet
{\ifnexttok(% sinon, si elle est suivie d'une parenth�se
\vecteur@paren % lire cet argument entre parenth�ses
{\vecteur@i[1](x)}% sinon, transmettre les arguments par d�faut
}%
}
\def\vecteur@bracket[#1]{%
\ifnexttok(% s'il y a une parenth�se apr�s
{\vecteur@i[#1]}% lire la parenth�se
{\vecteur@i[#1](x)}% sinon, donne "x" comme argument par d�faut
}
\def\vecteur@paren(#1){%
\ifnexttok[% si le caract�re suivant est un crochet
{\vecteur@ii(#1)}% lire l'argument entre crochets
{\vecteur@ii(#1)[1]}% sinon, donner "1" comme argument par d�faut
}
\def\vecteur@i[#1](#2)#3{\forcemath{({#2}_{#1},\ldots,{#2}_{#3})}}
\def\vecteur@ii(#1)[#2]{\vecteur@i[#2](#1)}% met les arg optionnels dans l'ordre
\catcode`@12
1) \vecteur{n}\qquad 2) \vecteur[i](y){j}\qquad 3) \vecteur(y)[i]{j}\qquad
4) \vecteur[0]{k}\qquad 5) \vecteur(\alpha){n}
****************** Fin code ******************
****************** Code 354 ******************
\catcode`\@11
\def\foo#1{% #1 -> lit le premier argument obligatoire
\ifnexttok[% si le token suivant est un crochet
{\foo@i{#1}}% aller � \foo@i qui va lire cet argument
{\foo@i{#1}[xxx]}% sinon, transmettre [xxx] � foo@i
}
\def\foo@i#1[#2]#3#4{% lit l'arg obligatoire + arg optionnel + 2 arg obligatoires
\ifnexttok[
{\foo@ii{#1}[#2]{#3}{#4}}%
{\foo@ii{#1}[#2]{#3}{#4}[y]}%
}
\def\foo@ii#1[#2]#3#4[#5]#6{% lit tous les arguments
1="#1" 2="#2" 3="#3" 4="#4" 5="#5" 6="#6"%
}
\catcode`\@12
1) \foo{arg1}{arg2}{arg3}{arg4}\par
2) \foo{arg1}[OPT\_A]{arg2}{arg3}{arg4}\par
3) \foo{arg1}{arg2}{arg3}[OPT\_B]{arg4}\par
4) \foo{arg1}[OPT\_A]{arg2}{arg3}[OPT\_B]{arg4}\medbreak
****************** Fin code ******************
****************** Code 355 ******************
\catcode`\@11
\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{%
% \macro@name construit 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{%
\ifxcase\nxttok
[\newmacro@optarg% si le prochain token est un crochet aller � \newmacro@optarg
\bgroup% si c'est un accolade ouvrante
% le texte de param�tre est fini et il faut d�finir la macro
{\defname{\macro@name\macro@cnt\expandafter}%
\the\param@text}% <- le {<code>} est juste apr�s, il n'est pas encore lu
\elseif% sinon, c'est donc un chiffre
\newmacro@arg% aller � \newmacro@arg
\endif
}
\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, cette macro 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=nombre d'arguments obligatoires � ajouter
% boucle qui ajoute "#<x>#<x+1>etc" dans \param@text
% et "{#<x>}{#<x+1>}etc" dans \arg@text
\ifnum#1>\z@ % 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}% boucler
\else% si les arguments sont tous ajout�s
\expandafter\newmacro@i% lire le token suivant
\fi
}
\catcode`\@12
\newmacro\foo 1[xxx]2[y]1{1="#1" 2="#2" 3="#3" 4="#4" 5="#5" 6="#6"}
a) \foo{arg1}{arg2}{arg3}{arg4}\par
b) \foo{arg1}[OPT\_A]{arg2}{arg3}{arg4}\par
c) \foo{arg1}{arg2}{arg3}[OPT\_B]{arg4}\par
d) \foo{arg1}[OPT\_A]{arg2}{arg3}[OPT\_B]{arg4}\medbreak
\meaning\foo\par
\expandafter\meaning\csname foo@[i]\endcsname\par
\expandafter\meaning\csname foo@[ii]\endcsname
****************** Fin code ******************
****************** Code 356 ******************
\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
}%
}
\frboxsep=1pt
Boite \framebox{enti�re}, \framebox[ud]{Up down}, \framebox[LR]{Left Right},
\framebox[LU]{Left Up} et \framebox[rd]{Right Down}.
****************** Fin code ******************
****************** Code 357 ******************
\catcode`\@11
\newtoks\eargs@toks
\newtoks\eargs@temptoks
\def\eargs[#1]#2{% #1=liste des d�veloppements #2=macro
\eargs@toks{#2}% mettre la macro dans le collecteur de tokens
\expandafter\eargs@i\detokenize{#1}\@nil% appeler \eargs@i avec
% la liste des developpements
}
\def\eargs@i#1\@nil{% #1=liste des n-d�veloppements restant
\ifempty{#1}% s'il n' y plus de n-d�veloppements
{\the\eargs@toks}% ex�cuter la macro et ses arguments d�velopp�s
{\eargs@ii#1\@nil}% sinon appeller la macro qui lit un argument
}
% #1=n-d�veloppement actuel #2=liste des n-d�veloppements restants #3=argument lu
\def\eargs@ii#1#2\@nil#3{%
\if+#1% si #1="+", un \edef est demand� pour cet argument
\edef\eargs@tempmacro{{#3}}% le stocker dans une macro temporaire
\else% sinon
\eargs@temptoks={#3}% stocker l'argument dans un registre temporaire
\for\eargs@loop = 1 to #1\do 1 % faire #1 fois :
{\eargs@temptoks=% 1-d�velopper le 1er token du registre temporaire
\expandafter\expandafter\expandafter{\the\eargs@temptoks}%
}% puis le stocker dans la macro temporaire
\edef\eargs@tempmacro{{\the\eargs@temptoks}}%
\fi
\eaddtotoks\eargs@toks\eargs@tempmacro% ajouter le contenu de la macro au collecteur
\eargs@i#2\@nil% appeler \eargs@i avec les n-d�veloppements restants
}
\catcode`\@12
\def\foo#1#2#3#4#5{\detokenize{1="#1" 2="#2" 3="#3" 4="#4" 5="#5"}}
\def\aaa{\bbb}\def\bbb{\ccc}\def\ccc{Bonjour}
\eargs[0123+]\foo{\aaa\bbb}{\aaa\bbb}{\aaa\bbb}{\aaa\bbb}{\aaa\bbb}.
****************** Fin code ******************
****************** Code 358 ******************
\catcode`\@11
\def\detectmark#1{% #1 est le marqueur
\begingroup
\catcode`#1=13 % rendra #1 actif apr�s la macro
\begingroup% pour les besoins du \lccode
\lccode`\~=`#1 % transforme "~" en " #1 actif"
\lowercase{\endgroup\def~##1~}{\markeffect{##1}}%
\detectmark@i
}
\def\detectmark@i#1{%
#1% ex�cute le code
\endgroup% ferme le groupe, le marqueur perd son catcode actif
}
\catcode`\@12
a) \def\markeffect#1{{\bf #1}}% met en gras
\detectmark+{Un +argument+ o� les +marqueurs+ sont d�tect�s}
\medskip
b) \def\markeffect#1{% met dans une boite
\begingroup
\frboxsep=1pt % modifie l'espacement entre texte et encadrement
\frbox{\strut#1}% encadre
\endgroup
}
\detectmark|{Un |argument| o� les |marqueurs| sont d�tect�s}
\medskip
c) \def\markeffect#1{$\vcenter{\hbox{#1}\hbox{#1}}$}% superpose 2 fois
\detectmark`{Un `argument` o� les `marqueurs` sont d�tect�s}
****************** Fin code ******************
****************** Code 359 ******************
\catcode`\@11
\def\detectmark#1{%
\begingroup
\catcode`#1=13 % rendra #1 actif apr�s la macro
\begingroup% pour les besoins du \lccode
\lccode`\~=`#1 % transforme "~" en " #1 actif"
\lowercase{\endgroup\def~##1~}{\markeffect{##1}}%%
\detectmark@i
}
\def\detectmark@i#1{%
#1% lit le code
\endgroup% ferme le groupe, le marqueur perd son catcode actif
}
\catcode`\@12
\def\markeffect#1{{\bf #1}}% met en gras
\frbox{\detectmark+{Un +argument+ o� les +marqueurs+ sont d�tect�s}}
****************** Fin code ******************
****************** Code 360 ******************
\catcode`\@11
\newtoks\alter@toks% collecteur de tokens
\def\alter#1#2{% #1= d�limiteur #2 = macro � alt�rer
\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
\ifxcase\alter@nxttok% si le token � lire est
\egroup \alter@stop% "}" : aller � \alterstop@i
\sptoken \alter@readspc% " " : aller � \alter@readspc
\bgroup \alter@readarg% "{" : aller � \alter@readarg
\alter@markertoks \alter@readlitterate% "<delimiteur>" : aller � \alter@readlitterate
\elseif
\alter@readtok% dans les autres cas, aller � \alter@readtok
\endif
}
\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 rendu actif
\doforeach\alter@tmp\in{<,>,-,`,{,},'}% pour chaque motif de ligature
{\unless\if\alter@tmp\alter@markertoks% s'il est diff�rent du d�limiteur
% le rendre actif 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{% 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\alter@stop@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 ne demande pas 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\alter@stop@ii% aller � \alter@stop@ii apr�s
\let\alter@tmptok= % avoir mang� l'accolade fermante
}
\def\alter@stop@ii{% donner � la \<macro> tout ce qui a �t� r�colt�
\expandafter\alter@macro\expandafter{\the\alter@toks}%
\alter@restorecatcode% puis restaure le catcode du d�limiteur
}
\catcode`@12
\frboxsep=1pt
\alter|\frbox{Texte normal - |#& }| - texte normal - |_^ ##| - texte normal}
\alter=\frbox{La macro =\alter= autorise du verbatim dans
des commandes imbriqu�es \frbox{comme ici =\alter=}.}
****************** Fin code ******************
****************** Code 361 ******************
\def\hello#1#2{Bonjour #1 et #2 !}
\hello{foo}{bar}\par
\alter|\identity{\hello{macro |{{{\foo|}{macro |\bar}|}}
****************** Fin code ******************
****************** Code 362 ******************
\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
}
\frboxsep=1pt
1) \frbox{Programmer en \catcode`\~=12 \TeX{} est~facile et~utile.}\par
2) \frbox{Programmer en \retokenize{\catcode`\~=12 \TeX{} est~facile} et~utile.}\par
3) \frbox{Programmer en \catcode`\~=12 \retokenize{\TeX{} est~facile} et~utile.}
****************** Fin code ******************
****************** Code 363 ******************
\frboxsep=1pt
1) \frbox{Programmer \retokenize{\litterate|en \TeX {} est |}facile et utile.}\par
2) \frbox{Programmer \retokenize{\litterate|en \TeX{} est |}facile et utile.}
****************** Fin code ******************
****************** Code 364 ******************
\frboxsep=1pt
1) \frbox{Programmer en \catcode`\~=12 \TeX{} est~facile et~utile.}\par
2) \frbox{Programmer en \scantokens{\catcode`\~=12 \TeX{} est~facile} et~utile.}\par
3) \frbox{Programmer en \catcode`\~=12 \scantokens{\TeX{} est~facile} et~utile.}\par
4) \frbox{Programmer \scantokens{\litterate|en \TeX {} est facile|} et utile.}\par
5) \frbox{Programmer \scantokens{\litterate|en \TeX{} est facile|} et utile.}
****************** Fin code ******************
****************** Code 365 ******************
\scantokens{a}b
****************** Fin code ******************
****************** Code 366 ******************
\begingroup\endlinechar=-1 \scantokens{a}b\endgroup
****************** Fin code ******************
****************** Code 367 ******************
\edef\foo{\scantokens{Bonjour le monde}}% produit une erreur
****************** Fin code ******************
****************** Code 368 ******************
\expandafter\def\expandafter\foo\expandafter
{\scantokens{Bonjour le monde}}% produit une erreur
****************** Fin code ******************
****************** Code 369 ******************
Voici la macro \string\foo\ : \foo.
****************** Fin code ******************
****************** Code 370 ******************
\catcode`\@11
\def\scandef#1#2{% #1=\<macro> #2=<texte>
\begingroup
\endlinechar=-1 % pas de caract�re de fin de ligne
\everyeof{\@nil#1\noexpand}% ajoute "\@nil\<macro>\noexpand" avant la fin du fichier
\expandafter\scandef@i\expandafter\relax\scantokens{#2}%
}
\def\scandef@i#1\@nil#2{% "\@nil#2" ont �t� ajout� par \everyeof
\endgroup% ferme le groupe
\expandafter\def\expandafter#2\expandafter{\gobone#1}% et d�finit la \<macro>
}
\catcode`@12
\def\foo{%
Dans tout l'argument de \string\foo, <<~>> est actif
sauf
\catcode`\~12
\scandef\bar{dans celui de \string\bar : <<~>>}%
\catcode`~13
\bar
}
\foo
****************** Fin code ******************
****************** Code 371 ******************
{%
\endlinechar=`\d% ins�re la lettre "d" � chaque fin de ligne
% le \noexpan(d) est incomplet
Voici la macro \string\foo\ : \foo.% fins de ligne...
}% ...comment�es pour �viter le "d"
****************** Fin code ******************
****************** Code 372 ******************
\catcode`\@11
\def\cprotect#1{% #1 est la \<macro>
\def\cprotect@i##1{% ##1 est l'<argument>
\endgroup% ferme le groupe pr�c�demment ouvert
#1{\scantokens{##1\noexpand}}%
}%
\begingroup% rend tous les octets de catcode12
\for\cprotect@temp=0to255\do{\catcode\cprotect@temp=12 }%
\catcode`\{=1 \catcode`\}=2 % sauf "{" et "}"
\cprotect@i% puis, lit l'argument
}
\catcode`@12
\frboxsep=1.5pt
1) \cprotect\frbox{foo \litterate-&# #^ ^_%- bar}\par
2) \cprotect\frbox{\catcode`\~=12 a~b~c~d}\par
3) \cprotect\frbox{foo \litterate-\bar- \cprotect\frbox{\litterate-&# #-} fin}
****************** Fin code ******************
****************** Code 373 ******************
\catcode`@11
\def\Cprotect#1{% #1 est la \<macro>
\def\Cprotect@i##1{% ##1 est la liste des arguments
\endgroup% ferme le groupe pr�c�demment ouvert
\toks0={#1}% met la \<macro> dans le registre de tokens
\Cprotect@ii##1\quark% \quark est mis � la fin des arguments
\the\toks0 % ex�cute le registre
}%
\begingroup% rend tous les octets de catcode12
\for\temp@arg= 0 to 255 \do{% changer � 12 tous les catcodes
\unless\ifnum\catcode\temp@arg=1 % sauf si catcode=1
\unless\ifnum\catcode\temp@arg=2 % ou 2
\catcode\temp@arg=12
\fi
\fi}%
\Cprotect@i% puis, lit l'argument
}
\def\Cprotect@ii#1{% #1 est l'argument courant (d�pouill� de ses accolades)
\def\temp@arg{#1}% stocke l'argument pour le tester ci dessous :
\unless\ifx\quark\temp@arg% si la fin n'est pas atteinte
% ajouter "{\scantokens{#1\noexpand}}" au registre
\addtotoks{\toks0}{{\scantokens{#1\noexpand}}}%
\expandafter\Cprotect@ii% et recommencer
\fi
}
\catcode`@12
\def\test#1#2{Bonjour #1 et #2}
\Cprotect\test{{argument 1 : \litterate-\foo-}{argument 2 : \litterate-\bar-}}
****************** Fin code ******************
****************** Code 374 ******************
\newdimen\pixelsize \newdimen\pixelsep
\def\pixel{\vrule height\pixelsize width\pixelsize depth0pt }
\def\vblankpixel{\vrule height\pixelsize width0pt depth0pt }
\def\blankpixel{\vblankpixel \vrule height0pt width\pixelsize depth0pt }
\def\gap{\kern\pixelsep}
\pixelsize=3pt \pixelsep=1pt
Essai :
\vbox{% aligne verticalement
\offinterlineskip% annule le ressort d'interligne
\lineskip=\pixelsep\relax% pour le mettre � \pixelsep
\hbox{\pixel\gap\blankpixel\gap\blankpixel\gap\blankpixel\gap\pixel}% 1re ligne
\hbox{\pixel\gap\pixel \gap\blankpixel\gap\pixel \gap\pixel}% 2e ligne
}
****************** Fin code ******************
****************** Code 375 ******************
\pixelsize=3pt \pixelsep=1pt
Essai :
\vtop{%
\offinterlineskip \lineskip=\pixelsep\relax
\vbox{%
\hbox{\blankpixel\gap\pixel \gap\pixel \gap\pixel}% ***
\hbox{\pixel \gap\blankpixel\gap\blankpixel\gap\pixel}% * *
\hbox{\pixel \gap\blankpixel\gap\blankpixel\gap\pixel}% * *
\hbox{\pixel \gap\blankpixel\gap\blankpixel\gap\pixel}% * *
\hbox{\blankpixel\gap\pixel \gap\pixel \gap\pixel}% ***
}% ----ligne de base
\hbox {\blankpixel\gap\blankpixel\gap\blankpixel\gap\pixel}% *
\hbox {\blankpixel\gap\pixel \gap\pixel }% **
}
****************** Fin code ******************
****************** Code 376 ******************
\catcode`\@11
\begingroup% dans ce groupe :
\catcode`\ =12\relax% l'espace devient un "caract�re autre"
\catcode`\^^M=13\relax% le retour � la ligne est actif
\edef^^M{\string,}% et se d�veloppe en une virgule (de catcode 12)
\global\deftok\otherspc{ }% d�finit un espace de catcode 12
\xdef\letter@code{% macro contenant le dessin de la lettre "e"
**
* *
***
*
***}%
\endgroup
\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
}
\pixelsize=3pt \pixelsep=1pt
\let\pixabove\empty% initialisation de la macro finale � vide
\exparg\makecar@i\letter@code% appelle la macro qui construit \pixabove
La lettre
\vtop{% enferme le tout dans une \vtop :
\offinterlineskip\lineskip=\pixelsep% ajuste l'espace interligne
\vbox{\pixabove}% affiche le caract�re cr��
}.
****************** Fin code ******************
****************** Code 377 ******************
\catcode`\@11
\begingroup% dans ce groupe :
\catcode`\ =12\relax% l'espace devient un "caract�re autre"
\catcode`\^^M=13\relax% le retour � la ligne est actif
\edef^^M{\string,}% et se d�veloppe en une virgule (de catcode 12)
\global\deftok\otherspc{ }% d�finit un espace de catcode 12
\xdef\letter@code{% macro contenant le dessin de la lettre "g"
***
* *
* *
* *
***_
*
**}%
\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@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
}
\makecar\lettreg\letter@code
\catcode`\@12
\pixelsize=3pt \pixelsep=1pt
Essai : \lettreg
****************** Fin code ******************
****************** Code 378 ******************
\catcode`\@11
\begingroup
\expandafter\gdef\csname impact@" "\endcsname{% d�finit la lettre "espace"
\hskip 4\pixelsize plus.5\pixelsize minus.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"
\gdef\impact@alphabet{
a/
***
*
***
* *
****,
b/
*
*
***
* *
* *
* *
***,
% beaucoup de caract�res omis
9/
***
* *
* *
****
*
*
***,
0/
***
* *
* *
* * *
* *
* *
***,
error/
* * *
* *
* * *
* *
* * *
* *
* * *}% <- commenter la fin de ligne
\endgroup%
% 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
% % d�finit l'espace
\pixelsize=3pt \pixelsep=1pt
% puis, on affiche ce qui a �t� d�fini :
a = \csname impact@"a"\endcsname\qquad b = \csname impact@"b"\endcsname\qquad
9 = \csname impact@"9"\endcsname \qquad 0 = \csname impact@"0"\endcsname\qquad
error = \csname impact@"error"\endcsname
****************** Fin code ******************
****************** Code 379 ******************
\catcode`\@11
\newskip\letter@skip% ressort mis entre chaque lettre
\def\impactend{\impactend}% d�finit le quark de fin
\newmacro\impact[0.2ex][0pt]{% d�finit la macro � arguments optionnels
\leavevmode% passer en mode horizontal
\begingroup% dans un groupe semi-simple :
\pixelsize=#1\relax \pixelsep=#2\relax% d�finir ces deux dimensions
\letter@skip=#1 plus.1\pixelsize minus.1\pixelsize\relax% d�finir espace inter-lettre
\baselineskip=% d�finir la distance entre les lignes de base
\dimexpr12\pixelsize+7\pixelsep\relax% � 12\pixelsize+7\pixelsep
\lineskiplimit=0pt % si lignes trop serr�es
\lineskip=2\pixelsize\relax% les espacer de 2\pixelsize
\impact@i% puis aller voir le prochain token
}
% va voir le prochain token puis va le tester � \impact@ii
\def\impact@i{\futurelet\nxtletter\impact@ii}
\def\impact@ii{%
\ifx\nxtletter\impactend% si le token est \let �gal � \impactend
\let\donext\impact@endprocess% aller � al macro de fin
\else
\ifx\nxtletter\sptoken% si c'est un espace
\let\donext\impact@spc% aller � \impact@spc
\else
\let\donext\impact@arg% sinon, aller � \impact@arg
\fi
\fi
\donext% faire l'action d�cid�e ci-dessus
}
% mange un espace (argument d�limit�) et affiche "\letter@<spc>"
\expandafter\def\expandafter\impact@spc\space{%
\csname impact@" "\endcsname
\impact@i% puis va voir le prochain token
}
%
% lit l'argument suivant
\def\impact@arg#1{%
\csname impact@% affiche
\ifcsname impact@"#1"\endcsname
"#1"% le caract�re \impact@"#1" s'il est d�fini
\else
"error"% sinon \impact@"error"
\fi
\endcsname
\hskip\letter@skip% ins�rer le ressort inter-lettre
\impact@i% puis, aller voir le prochain token
}
\def\impact@endprocess\impactend{% macro ex�cut� lorsqque le quark \impactend va �tre lu
\unskip% annuler le dernier ressort
\par% composer le paragraphe pour prendre en compte
% \baselineskip, \lineskip et \lineskiplimit
\endgroup% et fermer le groupe
}
\catcode`\!=12 % rend le point d'exclamation "gentil"
\impact Programmer en {TEX} est facile et tr{e`}s utile !\impactend\par
\impact[2pt][0.5pt]Programmer en {TEX} est facile et tr{e`}s utile !\impactend
****************** Fin code ******************
****************** Code 380 ******************
\newdimen\maingraddim \maingraddim=4pt % hauteur des graduations principales
\newdimen\maingradwd \maingradwd=0.5pt % �paisseur des graduations principales
\def\maingradx#1{%
\lower1.5ex\clap{$\scriptscriptstyle#1$}% afficher l'argument au dessous
\clap{\vrule height\maingraddim width\maingradwd depth0pt }% et la r�glure
}
D�but\maingradx{1}suite\maingradx{2}conclusion\maingradx{3}fin.
****************** Fin code ******************
****************** Code 381 ******************
\maingraddim=4pt \maingradwd=0.5pt
\newdimen\axiswd \axiswd=0.5pt
\newmacro\xaxis[1cm]1[1]1[4]{%% #1= dist #2=xmin #3=inc #4=xmax #5=subdiv
\hbox{% mettre le tout dans une \hbox
\rlap{% en d�bordement � droite :
\FOR\xx = #2 to #4 \do #3{% pour chaque graduation principale
\maingradx{\xx}% tracer la graduation et �crire l'abscisse
\kern#1\relax% puis 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
}%
}
a) \xaxis{-2}{5}suite
b) \frboxsep=0pt\frbox{\xaxis[1.25cm]{-1}[0.25]{1}}suite
****************** Fin code ******************
****************** Code 382 ******************
\maingraddim=4pt \maingradwd=0.5pt \axiswd=0.5pt
\newdimen\subgraddim \subgraddim=2.5pt
\newdimen\subgradwd \subgradwd=0.2pt
% trace un trait de subdivision
\def\subgradx{\clap{\vrule height\subgraddim width\subgradwd depth0pt }}
\newmacro\xaxis[1cm]1[1]1[4]{% #1= dist #2=xmin #3=inc #4=xmax #5=subdiv
\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
}%
}
a) \xaxis{-2}{5}[2]
)b \xaxis[1.25cm]{-1}[0.25]{1}[5]
****************** Fin code ******************
****************** Code 383 ******************
\maingraddim=4pt \maingradwd=0.5pt \axiswd=0.5pt
\subgraddim=2.5pt \subgradwd=0.2pt
\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 }}
\newmacro\yaxis[1cm]1[1]1[4]{%
% #1= dist #2=ymin #3=inc #4=ymax #5=subdiv
\vbox{%
\offinterlineskip% d�sactiver le ressort d'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 ordonn�es
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
}%
}%
}
Essai : \yaxis{-2}{5}[2]\qquad \frboxsep=0pt \frbox{\yaxis[0.75cm]{-1}[0.5]{3}[5]}
****************** Fin code ******************
****************** Code 384 ******************
\newdimen\xunit \xunit=1cm
\newdimen\yunit \yunit=0.75cm
\maingraddim=4pt \maingradwd=0.5pt \axiswd=0.5pt
\subgraddim=2.5pt \subgradwd=0.2pt
\catcode`@11
\newmacro\graphzone1[1]1[4]1[1]1[4]{%
\leavevmode% quitter le mode vertical
\begingroup% travailler dans un groupe semi-simple
\def\graphxmin{#1}\def\graphxmax{#3}% sauvegarder
\def\graphymin{#5}\def\graphymax{#7}% les
\def\xincrement{#2}\def\yincrement{#6}% arguments
\setbox0\hbox{\yaxis[\yunit]{#5}[#6]{#7}[#8]}% axe "y" dans boite 0
\setbox1\hbox{\xaxis[\xunit]{#1}[#2]{#3}[#4]}% axe "x" dans boite 1
\edef\graphboxht{\the\ht0 }% \graphboxh est la hauteur de la zone
\edef\graphboxwd{\the\wd1 }% \graphboxw est la largeur de la zone
\rlap{% annuler la dimension horizontale, et...
\box1 % ...afficher l'axe (Ox) puis
% le trait vertical � l'extr�me droite de la zone
\clap{\vrule height\dimexpr\graphboxht+\axiswd\relax width\axiswd depth0pt }%
}%
\rlap{\box0 }% afficher l'axe (Oy) en annulant sa dimension horizontale
\raise\graphboxht% puis monter tout en haut de la zone
% pour tracer le trait horizontal en annulant sa longueur
\rlap{\kern-0.5\axiswd% et en rattrapant le centrage de l'axe des ordonn�es
\vrule height\axiswd width\dimexpr\graphboxwd+\axiswd}%
\begingroup% pour lire l'argument "<code>" :
\catcode`\^^M=9\relax % ignorer les retours � la ligne
\graphzone@i% appeler \graphzone@i
}
\def\graphzone@i#1{% lire le <code>...
\endgroup% et fermer le groupe pr�c�demment ouvert
\setbox0\hbox{#1}% mettre les instructions graphique dans la boite 0
\wd0=\dimexpr\graphboxwd+\axiswd\relax% forcer sa dim horizontale
\ht0=\dimexpr\graphboxht+\axiswd\relax% et verticale
% pour correspondre aux dimension de la zone graphique
\box0 % l'afficher
\endgroup% sortir du groupe initial
}
\catcode`@12
essai\graphzone{-1}[0.5]{1.5}[5]{-20}[10]{10}[2]{\relax}fin
****************** Fin code ******************
****************** Code 385 ******************
\def\putat#1#2#3{%
\leavevmode\rlap{\kern#1\vbox to0pt{\vss\hbox{#3}\kern#2}}%
}
Essai\putat{0.5cm}{0.3cm}{A}\putat{-0.2cm}{-0.1cm}{B}\putat{0pt}{0.2cm}{C}suite
****************** Fin code ******************
****************** Code 386 ******************
\def\ifinside#1[#2,#3]{%
\ifnum\sgn{\dimexpr#1pt-#2pt\relax}\sgn{\dimexpr#1pt-#3pt}1=1
\expandafter\secondoftwo
\else
\expandafter\firstoftwo
\fi
}
1) \ifinside3.5[0.5,4]{vrai}{faux}\qquad
2) \ifinside-0.2[-0.4,-0.3]{vrai}{faux}\qquad
3) \ifinside-0.999[-1,-0.5]{vrai}{faux}
****************** Fin code ******************
****************** Code 387 ******************
\def\fonction#1{\dimtodec\dimexpr
\decmul{#1}{\decmul{#1}{#1}}pt% x^3
-\decmul{#1}{#1}pt% -x^2
-#1pt*3% -3x
+2pt\relax}% +2
1) \fonction{-4}\qquad% doit afficher -66
2) \fonction{-1.7}\qquad % doit afficher -0.703
3) \fonction{1}\qquad% doit afficher -1
4) \fonction{1.35}% doit afficher -1.412125
****************** Fin code ******************
****************** Code 388 ******************
\newmacro\cross[2pt][0.2pt]{%
% #1=dimensions de traits depuis le centre de la croix
% #2=�paisseur des traits
\leavevmode
\vlap{%
\clap{%
\vrule height#2 depth0pt width#1 % 1/2 trait horizontal gauche
\vrule height#1 depth#1 width#2 % trait vertical
\vrule height#2 depth0pt width#1 % 1/2 trait horizontal droit
}%
}%
}
Une croix : \cross{}puis une autre\cross[8pt][0.8pt]
****************** Fin code ******************
****************** Code 389 ******************
\maingraddim=4pt \maingradwd=0.5pt \axiswd=0.5pt
\subgraddim=2.5pt \subgradwd=0.2pt
\xunit=1.25cm \yunit=0.75cm
\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 }}
\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 d'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 ordonn�es
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
}%
}%
}
\catcode`@11
\newmacro\graphzone1[1]1[4]1[1]1[4]{%
\leavevmode% quitter le mode vertical
\begingroup% travailler dans un groupe semi-simple
\def\graphxmin{#1}\def\graphxmax{#3}% sauvegarder
\def\graphymin{#5}\def\graphymax{#7}% les
\def\xincrement{#2}\def\yincrement{#6}% arguments
\setbox0\hbox{\yaxis[\yunit]{#5}[#6]{#7}[#8]}% axe "y" dans boite 0
\setbox1\hbox{\xaxis[\xunit]{#1}[#2]{#3}[#4]}% axe "x" dans boite 1
\edef\graphboxht{\the\ht0 }% \graphboxh est la hauteur de la zone
\edef\graphboxwd{\the\wd1 }% \graphboxw est la largeur de la zone
\rlap{% annuler la dimension horizontale, et...
\box1 % ...afficher l'axe (Ox) puis
% le trait vertical � l'extr�me droite de la zone
\clap{\vrule height\dimexpr\graphboxht+\axiswd\relax width\axiswd depth0pt }%
}%
\rlap{\box0 }% afficher l'axe (Oy) en annulant sa dimension horizontale
\raise\graphboxht% puis monter tout en haut de la zone
% pour tracer le trait horizontal en annulant sa longueur
\rlap{\kern-0.5\axiswd% et en rattrapant le centrage de l'axe des ordonn�es
\vrule height\axiswd width\dimexpr\graphboxwd+\axiswd}%
\begingroup% pour lire l'argument "<code>" :
\catcode`\^^M=9\relax % ignorer les retours � la ligne
\graphzone@i% appeler \graphzone@i
}
\def\graphzone@i#1{% lire le <code>...
\endgroup% et fermer le groupe pr�c�demment ouvert
\xunit=\decdiv1\xincrement\xunit% divise les unit�s par l'incr�ment
\yunit=\decdiv1\yincrement\yunit
\setbox0\hbox{#1}% mettre les instructions graphique dans la boite 0
\wd0=\dimexpr\graphboxwd+\axiswd\relax% forcer sa dim horizontale
\ht0=\dimexpr\graphboxht+\axiswd\relax% et verticale
% pour correspondre aux dimension de la zone graphique
\box0 % l'afficher
\endgroup% sortir du groupe initial
}
\def\putat#1#2#3{%
\leavevmode\rlap{\kern#1\vbox to0pt{\vss\hbox{#3}\kern#2}}%
}
\newmacro\cross[2pt][0.2pt]{%
\leavevmode
\vlap{%
\clap{%
\vrule height#2 depth0pt width#1 % 1/2 terait horizontal gauche
\vrule height#1 depth#1 width#2 % trait vertical
\vrule height#2 depth0pt width#1 % 1/2 trait horizontal droit
}%
}%
}
\def\plot(#1,#2){% place "\plotstuff" aux coordonn�es #1,#2
\edef\x@plot{#1}\edef\y@plot{#2}% d�velopper au cas o�
\ifinside\x@plot[\graphxmin,\graphxmax]% si #1 est dans les limites
{\ifinside\y@plot[\graphymin,\graphymax]% et si #2 l'est aussi
{\putat% placer aux coordonn�es
{\dimexpr\x@plot\xunit-\graphxmin\xunit\relax}% X=(x-xmin)/xinc
{\dimexpr\y@plot\yunit-\graphymin\yunit\relax}% Y=(y-ymin)/yinc
\plotstuff% le contenu de \plotstuff
}%
\relax
}
\relax
}
\def\showxaxis{% affiche l'axe (Ox)
\ifinside0[\graphymin,\graphymax]%
{\putat\z@{-\graphymin\yunit}{\vlap{\vrule width\graphboxwd height\axiswd}}}%
\relax
}
\def\showyaxis{% affiche l'axe (Oy)
\ifinside0[\graphxmin,\graphxmax]%
{\putat{-\graphxmin\xunit}\z@{\clap{\vrule width\axiswd height\graphboxht}}}%
\relax
}
\def\showaxis{\showxaxis\showyaxis}% affiche les deux axes
\catcode`@12
%%%%%%%%%%%%%%% 1er exemple :
\xunit=1cm \yunit=0.5cm
\def\fonction#1{\dimtodec\dimexpr\decmul{#1}{\decmul{#1}{#1}}pt-%
\decmul{#1}{#1}pt-#1pt*3+2pt\relax}
Exemple 1 :\qquad
\graphzone{-2}[0.5]{2.5}[5]{-5}{5}[2]{%
\let\plotstuff\cross% d�finit ce qu'il faut afficher comme point
\FOR\xx=-2 to 2.5 \do 0.1{%
\plot(\xx,\fonction{\xx})% afficher les points de coordonn�es (x ; f(x))
}%
\putat{5pt}{\dimexpr\graphboxht-10pt\relax}% afficher
{$f(x)=x^3-x^2-3x+2$}% la fonction trac�e
\showaxis% et les axes
}\par\medskip
%%%%%%%%%%%%% 2e exemple
\xunit=0.7cm \yunit=\xunit
\def\foncx#1{\dimtodec\dimexpr\decmul{#1}{\decmul{#1}{#1}}pt-%
\decmul{4}{\decmul{#1}{#1}}pt-#1pt+4pt}
\def\foncy#1{\dimtodec\dimexpr\decmul{#1}{#1}pt-#1pt*2-6pt}
Exemple 2 :\qquad
\graphzone{-12}[2]{12}[2]{-8}[2]{8}[2]{%
\def\plotstuff{\cross[1.25pt]}
\FOR\tt = -5 to 5 \do 0.1 {%
\plot(\foncx\tt,\foncy\tt)%
}%
\putat{5pt}{\dimexpr\graphboxht-20pt\relax}% afficher la fonction param�trique trac�e
{$\left\{\vcenter{\hbox{$x(t)=t^3-4t^2-t-4$}\hbox{$y(t)=t^2-2t-6$}}\right.$}%
\showaxis
}
****************** Fin code ******************
****************** Code 390 ******************
\def\mandeltest#1#2{%
\def\zx{0}\def\zy{0}% zn=0 + i*0
\def\zxx{0}\def\zyy{0}% carr�s de \zx et \zy
\def\mandelresult{1}% le point appartient � M a priori
\for\ii=1to\maxiter\do1{%
\advance\count255 by1
\edef\zy{\dimtodec\dimexpr\decmul{\decmul2\zx}\zy pt+#2pt\relax}%
\edef\zx{\dimtodec\dimexpr\zxx pt-\zyy pt+#1pt\relax}%%
\edef\zxx{\decmul\zx\zx}%
\edef\zyy{\decmul\zy\zy}%
\ifdim\dimexpr\zxx pt+\zyy pt\relax>4pt
\def\mandelresult{0}%
\exitfor\ii
\fi
}%
}
\def\mandel#1#2{% #1=points par unit� #2=nombre maximal d'it�rations
\graphzone{-2}[1]{1}[2]{-1}[1]{1}[2]{%
\def\maxiter{#2}%
\edef\plotstuff{\the\dimexpr\xunit/#1\relax}% taille d'un pixel
\edef\plotstuff{\vrule height\plotstuff width\plotstuff}%
\edef\increment{\decdiv{1}{#1}}% incr�ment
\count255=0 % compteur des it�rations
\FOR\xxx = -2 to 1 \do \increment{% pour chaque
\FOR\yyy = 0 to 1 \do \increment{% pixel du domaine
\mandeltest\xxx\yyy% tester s'il est dans M
\ifnum\mandelresult=1 % si oui,
\plot(\xxx,\yyy)\plot(\xxx,-\yyy)% afficher les 2 points
\fi
}%
}%
\edef\plotstuff{$\scriptstyle\number\count255 $}% affiche la valeur du compteur
\plot(-1.99,0.92)% aux coordonn�es (-1.99 ; 0.92)
}%
}
\xunit=3cm \yunit=3cm \mandel{400}{500}
****************** Fin code ******************
****************** Code 391 ******************
\catcode`\@11
\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@i 1.#1..}% sinon, afficher la virgule et mettre en forme
}
% #1=compteur de caract�res #2= chiffre courant
% #3= chiffres restants #4 = chiffres d�j� trait�s
\def\formatdecpart@i#1.#2#3.#4.{%
\ifempty{#3}% si #2 est le dernier chiffre
{#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.}%
}%
}
a) \formatdecpart{1234567}\qquad
b) \formatdecpart{987125}\qquad
c) \formatdecpart{56}\qquad
d) \edef\foo{\formatdecpart{2014}}\meaning\foo
****************** Fin code ******************
****************** Code 392 ******************
\catcode`\@11
\protected\def\numsep{\kern0.2em }% \numsep est le s�parateur mis tous les 3 chiffres
\def\formatintpart#1{% #1=s�rie de chiffres
\formatintpart@i 1.#1..% appelle la macro r�cursive
}
% #1=compteur de caract�res #2= chiffre courant
% #3= chiffres restants #4 = chiffres d�j� trait�s
\def\formatintpart@i#1.#2#3.#4.{%
\ifempty{#3}% si #2 est le dernier chiffre
{#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 et recommencer
% sinon, mettre #2 en premi�re position et recommencer
% tout en incr�mentant #1 de 1
{\expandafter\formatintpart@i \number\numexpr#1+1.#3.#2#4.}%
}%
}
\catcode`\@12
a) \formatintpart{1234567}\qquad b) \formatintpart{987125}\qquad
c) \formatintpart{56}\qquad
d) \edef\foo{\formatintpart{2014}}\meaning\foo
****************** Fin code ******************
****************** Code 393 ******************
\catcode`\@11
\def\formatintpart#1{% #1=s�rie de chiffres
\expandafter\formatintpart@i\expandafter1\expandafter.\romannumeral\reverse{#1\z@}..%
}
\catcode`\@12
a) \formatintpart{1234567}\qquad b) \formatintpart{987125}\qquad
c) \formatintpart{56}\qquad
d) \edef\foo{\formatintpart{2014}}\meaning\foo
****************** Fin code ******************
****************** Code 394 ******************
\catcode`\@11
\def\ifnodecpart#1{\if@nodecpart#1.\@nil}% teste si #1 est un entier
\def\if@nodecpart#1.#2\@nil{\ifempty{#2}}
\def\formatnum#1{%
\ifnodecpart{#1}% s'il n'y a pas de partie d�cimale
{\formatintpart{#1}}% formatter la partie enti�re
{\formatnum@i#1\@nil}% sinon, formatter les deux parties
}
\def\formatnum@i#1.#2\@nil{%
\formatintpart{#1}% formatte la partie enti�re
\formatdecpart{#2}% et la partie d�cimale
}
\catcode`\@12
a) \formatnum{3.1415926}\qquad
b) \formatnum{1987654.12301}\qquad
c) \edef\foo{\formatnum{0987654.12300}}$\foo$
****************** Fin code ******************
****************** Code 395 ******************
\catcode`\@11
\def\removefirstzeros#1{%
\removefirstzeros@i#1\quark% ajoute "\quark" en dernier
}
\def\removefirstzeros@i#1{% #1=chiffre courant
\ifx\quark#1% fin atteinte donc nombre = 0
\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 #1 et tout afficher jusqu'� \removefirstzeros@i
\expandafter\expandafter\expandafter\removefirstzeros@ii
\expandafter\expandafter\expandafter#1%
\fi
\fi
}
\def\removefirstzeros@ii#1\quark{#1}
\catcode`\@12
a) \removefirstzeros{000325478}\qquad
b) \removefirstzeros{00000}\qquad
c) \edef\foo{\removefirstzeros{001000}}\meaning\foo\qquad
d) \long\def\>#1<{\detokenize{#1}}
\expandafter\>\romannumeral\removefirstzeros{0123}<
****************** Fin code ******************
****************** Code 396 ******************
\long\def\>#1<{\detokenize{#1}}
\expandafter\>\romannumeral-`\@\removefirstzeros{000123}<
****************** Fin code ******************
****************** Code 397 ******************
\catcode`\@11
\def\removelastzeros#1{%
\exparg\reverse% inverser apr�s
{\romannumeral-`\.% tout d�velopper
\expandafter\removelastzeros@i% enlever les 0 de gauche apr�s
\romannumeral\reverse{#1\z@}\quark% avoir invers� #1
}%
}
\def\removelastzeros@i#1{% enl�ve tous les 0 de gauche
\unless\ifx\quark#1% si la fin n'est pas atteinte
\ifx0#1% si le chiffre lu est un 0
\expandafter\expandafter\expandafter\removelastzeros@i% recommencer
\else% sinon remettre le chiffre et tout afficher jusqu'� \removefirstzeros@i
\expandafter\expandafter\expandafter\removelastzeros@ii
\expandafter\expandafter\expandafter#1%
\fi
\fi
}
\def\removelastzeros@ii#1\quark{#1}
\catcode`\@12
a) \removelastzeros{0003254780}\qquad
b) \removelastzeros{00000}\qquad
c) \edef\foo{\removelastzeros{001000}}\foo\qquad
\long\def\>#1<{\detokenize{#1}}
d) \expandafter\>\romannumeral-`\.\removelastzeros{012300}<
****************** Fin code ******************
****************** Code 398 ******************
\catcode`\@11
\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@i 1.#1..}% sinon, afficher la virgule et mettre en forme
}
% #1=compteur de caract�res #2= chiffre courant
% #3= chiffres restants #4 = chiffres d�j� trait�s
\def\formatdecpart@i#1.#2#3.#4.{%
\ifempty{#3}% si #2 est le dernier chiffre
{#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.{%
\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\quark% ajoute "\quark" en dernier
}
\def\removefirstzeros@i#1{% #1=chiffre courant
\ifx\quark#1% fin atteinte donc nombre = 0
\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 #1 et tout afficher jusqu'� \removefirstzeros@i
\expandafter\expandafter\expandafter\removefirstzeros@ii
\expandafter\expandafter\expandafter#1%
\fi
\fi
}
\def\removefirstzeros@ii#1\quark{#1}
\def\removelastzeros#1{%
\exparg\reverse% inverser apr�s
{\romannumeral-`\.% tout d�velopper
\expandafter\removelastzeros@i% enlever les 0 de gauche apr�s
\romannumeral\reverse{#1\z@}\quark% avoir invers� #1
}%
}
\def\removelastzeros@i#1{% enl�ve tous les 0 de gauche
\unless\ifx\quark#1% si la fin n'est pas atteinte
\ifx0#1% si le chiffre lu est un 0
\expandafter\expandafter\expandafter\removelastzeros@i% recommencer
\else% sinon remettre le chiffre et tout afficher jusqu'� \removefirstzeros@i
\expandafter\expandafter\expandafter\removelastzeros@ii
\expandafter\expandafter\expandafter#1%
\fi
\fi
}
\def\removelastzeros@ii#1\quark{#1}
% renvoie vrai s'il n'y a pas de partie d�cimale
\def\if@nodecpart#1.#2\@nil{\ifempty{#2}}
\def\formatnum#1{\formatnum@i1!#1!}
% #1 = <s�rie de signes> suivie de "1"
% #2 = caract�re courant
% #3 = caract�res non trait�s
\def\formatnum@i#1!#2#3!{%
\ifx+#2\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\ifempty{#3}% si #2=+ et #3 est vide
{\number#1 }% afficher "+1" ou "-1" (il n'y avait que des signes)
{\formatnum@i#2#1!#3!}% sinon, mettre le signe #2 devant #1
}
{\ifx-#2\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\ifempty{#3}% si #2=- et #3 est vide
{\number#1 }% afficher "+1" ou "-1" (il n'y avait que des signes)
{\formatnum@i#2#1!#3!}% sinon, mettre le signe #2 devant #1
}% #2 est le dernier caract�re qui n'est pas un signe + ou -
{\ifnum#1<0 -\fi% si "<signes>1" est <0 afficher un "-"
\formatnum@ii{#2#3}% formatter le nombre form� avec "#2#3""
}%
}%
}
\def\formatnum@ii#1{%
\if@comma{#1}% si #1 comporte une virgule
{\formatnum@iii#1\@nil}% la remplacer par un "." et recommencer
{\if@nodecpart#1.\@nil% puis si les chiffres restants sont un entier
{\formatintpart{#1}}% formatter l'entier
{\formatnum@iv#1\@nil}% sinon, formatter le nombre
}%
}
\def\formatnum@iii#1,#2\@nil{\formatnum@ii{#1.#2}}
\def\formatnum@iv#1.#2\@nil{% formatte le nombre d�cimal #1.#2
\exparg\formatintpart{\romannumeral-`\.\removefirstzeros{#1}}%
\exparg\formatdecpart{\romannumeral-`\.\removelastzeros{#2}}%
}
\def\if@comma#1{\if@comma@i#1,\@nil}% teste la pr�sence d'un virgule dans #1
\def\if@comma@i#1,#2\@nil{\ifempty{#2}\secondoftwo\firstoftwo}
\catcode`\@12
a) \formatnum{3,141592653589793238462643383279502884197169399375105820974944592}\par
b) \formatnum{---+69874}\qquad
c) \formatnum{0032100,98000}\qquad
d) \formatnum{+++010.01100}\qquad
e) \formatnum{-+--+}\qquad
f) \formatnum{---00.0000}\qquad
g) \formatnum{+99,0000}\qquad
h) \formatnum{.123456}\par
i) \edef\foo{\formatnum{-+-+-010500,090900}}\meaning\foo
****************** Fin code ******************
****************** Code 399 ******************
\setbox0=\vbox{%
\hbox{Premi�re ligne}
\hbox{Deuxi�me ligne}
\hbox{Avant-derni�re ligne}
\hbox{Derni�re ligne}
}
\frboxsep=0pt % aucun espace entre le contenu et l'encadrement
Boite initiale de hauteur \the\ht0 {} : \frbox{\copy0 }
\splittopskip0pt % ne rajouter aucun espace au sommet de la boite restante
\setbox1=\vsplit0 to 22pt % couper la boite � 22pt de hauteur
Boite 1 de hauteur \the\ht1 {} : \frbox{\box1 }
Boite 0 de hauteur \the\ht0 {} : \frbox{\box0 }
****************** Fin code ******************
****************** Code 400 ******************
\setbox0=\vbox{%
\hbox{Premi�re ligne}
\hbox{Deuxi�me ligne}
\hbox{Avant-derni�re ligne}
\hbox{Derni�re ligne}
}
\edef\restorevbadness{\vbadness=\the\vbadness\relax}% restaurera le \vbadness
\vbadness=10000 % plus d'avertissement pour boite verticale
\frboxsep=0pt % aucun espace entre le contenu et l'encadrement
Boite initiale de hauteur \the\ht0 {} : \frbox{\copy0 }
\splittopskip0pt % ne rajouter aucun espace au sommet de la boite restante
\setbox1=\vsplit0 to 22pt % couper la boite � 22pt de hauteur
\setbox1=\vbox{\unvbox1 }% la boite 1 prend la hauteur naturelle
\restorevbadness\relax% restaure le \vbadness
Boite 1 de hauteur \the\ht1 {} : \frbox{\box1 }
Boite 0 de hauteur \the\ht0 {} : \frbox{\box0 }
****************** Fin code ******************
****************** Code 401 ******************
\catcode`@11
\newbox\remainbox
\newbox\partialbox
\newdimen\cut@ht
\def\breakpar{%
\par\nointerlineskip% termine le paragraphe pr�c�dent
\vskip\frboxsep\relax% et saute une petite espace verticale
\begingroup
\splittopskip\topskip% \topskip en haut des boites coup�es
\topskip=0pt % neutraliser le \topskip
% nbre de r�glures horizontales contribuant � l'encadrement restant (2 au d�but)
\def\coeff@rule{2}%
\setbox\remainbox=\vbox\bgroup% compose la boite apr�s avoir...
\advance\hsize by -2\dimexpr\frboxrule+\frboxsep\relax% ajust� sa largeur
}
\def\endbreakpar{%
\egroup% fin de la composition de la boite
\def\rule@arg{ULR}% prendre l\cut@htes r�glures d'encadrement haute, gauche et droite
\splitbox% puis, aller � l'algorithme de coupure
\endgroup% une fois fini, sortir du groupe semi-simple
}
\def\splitbox{%
\ifvoid\remainbox% si la boite est vide, c'est la fin du processus
\par\nointerlineskip% termine le paragraphe pr�c�dent
\vskip\frboxsep\relax% et saute un petit espace vertical
\else% sinon
\expandafter\splitbox@i% aller � \splitbox@i
\fi
}
\def\splitbox@i{%
\hbox{}% composer un noeud en mode vertical
\nointerlineskip% pas de ressort d'interligne
% calculer la dimension verticale disponible dans la page pour le texte de la boite
\cut@ht=\dimexpr\pagegoal-\pagetotal-(\frboxsep+\frboxrule)*\coeff@rule\relax
% si dimension totale du texte > dimension disponible pour le texte
\ifdim\dimexpr\ht\remainbox+\dp\remainbox>\cut@ht% si une coupure doit �tre faite
\advance\cut@ht\dimexpr% augmenter Dv de l'espace verticale lib�r�e
+\frboxsep+\frboxrule% par la r�glure inf�rieure qui n'est pas sur cette page
\relax
\edef\old@vbadness{\the\vbadness}% sauvegarder \badness
\vbadness=10000 % d�sactive les avertissement lors de la coupure
\def\coeff@rule{1}% ne prendre en compte que r�glure D + espace D
\setbox\partialbox=\vsplit\remainbox to\cut@ht% coupe � la hauteur calcul�e
% \partialbox retrouve sa hauteur naturelle
\setbox\partialbox=\vbox{\unvbox\partialbox}%
\vbadness=\old@vbadness\relax% restaure \vbadness
\printpartialbox% imprime la boite partielle
\vfill\eject% et compose la page en cours
\else% si une coupure n'est pas n�cessaire :
\setbox\remainbox\vbox{\unvbox\remainbox}% reprendre la hauteur naturelle
\setbox\partialbox=\box\remainbox% \partialbox devient \remainbox
% et cette derni�re devient vide
\cut@ht=\dimexpr\ht\partialbox+\dp\partialbox\relax% hauteur � encadrer
\edef\rule@arg{\rule@arg D}% ajouter "D" aux r�glures � tracer
\printpartialbox% afficher la boite restante
\fi
\splitbox
}
\def\printpartialbox{% imprime \partialbox
\expandafter\framebox\expandafter[\rule@arg]{%
\vbox to\cut@ht{\unvbox\partialbox\vss}}%
\def\rule@arg{LR}% ne mettre que les r�glures d et g
}
\def\dummytext#1{%
\for\xx=1to#1\do% composer #1 fois la phrase suivante :
{Ceci est un texte sans aucun int\'er\^et dont le seul but est de meubler
la page artificiellement.
}%
}
\catcode`@12
\dummytext{5}
\frboxsep=5pt
\breakpar
\dummytext{70}
\endbreakpar
\dummytext{5}
****************** Fin code ******************
****************** Code 402 ******************
\setbox0=\vbox{%
\hsize=5cm
Ceci est un texte sans aucun int�r�t dont le seul but est de meubler
la page de fa�on artificielle.
}
Boite 0 : \copy0 % affiche la boite totale
\medbreak
\edef\restorevfuzz{\vfuzz=\the\vfuzz\relax}% appel�e apr�s la coupure
\vfuzz=\maxdimen% annule les avertissements pour d�bordement
\splittopskip=0pt % ne rajouter aucun espace au sommet de la boite restante
\setbox1=\vsplit0 to 0pt % couper la boite � 0pt de hauteur
\restorevfuzz% restaurer \vfuzz
\setbox1=\vbox{\unvbox1}% redonner � la boite sa hauteur d'origine
Boites 1+0 : \vbox{%
\offinterlineskip% annule le ressort d'interligne
\box1 % affiche la premi�re ligne
\box0 %affiche les lignes restantes
}
****************** Fin code ******************
****************** Code 403 ******************
\def\vdim#1{\dimexpr\ht#1+\dp#1\relax}% hauteur totale de la boite #1
\setbox0=\vbox{%
\hsize=5cm Ceci est un texte sans aucun int�r�t dont le seul but est
de meubler la page de fa�on artificielle.
}
\edef\htbefore{\the\vdim0}% hauteur de la boite 0
Boite 0 : \copy0 % affiche la boite totale
\medbreak
\edef\restoreparam{%
\vfuzz=\the\vfuzz\relax% sauvegarde le \vfuzz
\splittopskip=\the\splittopskip% et \splittopskip
}%
\vfuzz=\maxdimen% annule les avertissements pour d�bordement
\splittopskip=0pt % ne rajouter aucun espace au sommet de la boite restante
\setbox1=\vsplit0 to 0pt % couper la boite � 0pt de hauteur
\restoreparam
\setbox1=\vbox{\unvbox1}% redonner � la boite sa hauteur d'origine
\edef\intersplitspace{\the\dimexpr\htbefore-(\vdim0+\vdim1)\relax}%
Boites 1+0 : \vbox{%
\offinterlineskip% annule le ressort d'interligne
\box1 % affiche la premi�re ligne
\vskip\intersplitspace\relax% ajoute le ressort perdu � la coupure
\box0 % affiche les lignes restantes
}
****************** Fin code ******************
****************** Code 404 ******************
\setbox0=\vbox{%
\hsize=5cm Ceci est un texte sans aucun int�r�t dont le seul but est
de meubler la page de fa�on artificielle.
}
Boite 0 : \copy0 % affiche la boite totale
\medbreak
\edef\restoreparam{%
\vfuzz=\the\vfuzz\relax% sauvegarde le \vfuzz
\splittopskip=\the\splittopskip\relax% , le \splittopskip
\savingvdiscards=\the\savingvdiscards\relax% et le \savingvdiscards
}%
\vfuzz=\maxdimen% annule les avertissements pour d�bordement
\splittopskip=0pt % ne rajouter aucun espace au sommet de la boite restante
\savingvdiscards=1 % autorise la sauvagarde des �l�ments supprim�s
\setbox1=\vsplit0 to 0pt % couper la boite � 0pt de hauteur
\setbox1=\vbox{\unvbox1}% redonner � la boite sa hauteur d'origine
\restoreparam
Boites 1+0 : \vbox{%
\offinterlineskip% annule le ressort d'interligne
\box1 % affiche la premi�re ligne
\splitdiscards% affiche les �l�ments ignor�s
\box0 % affiche les lignes restantes
}
****************** Fin code ******************
****************** Code 405 ******************
\catcode`@11
\newbox\remainbox% boite contenant le texte total
\newbox\currentline% boite contenant le ligne en cours
\newcount\linecnt% compteur pour num�roter les lignes
\def\vdim#1{\dimexpr\ht#1+\dp#1\relax}% hauteur totale de la boite #1
\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% par d�faut, afficher chaque ligne telle quelle
% Par d�faut :
\leftline[11pt]{$\scriptscriptstyle\number\linecnt$\kern3pt }% 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
\linecnt=0 % initialiser le compteur de lignes
\savingvdiscards=1 % autorise la sauvagarde des �l�ments supprim�s
\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
\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
}
\def\dummytext#1{%
\for\xx=1to#1\do% composer #1 fois la phrase suivante :
{Ceci est un texte sans aucun int�r�t dont le seul but est de meubler
la page de fa�on artificielle. }%
}
\catcode`@12
\parindent=2em
ESSAI 1 :
\numlines
\dummytext{2}\par% 2 phrases
$$1+1=2$$\par% des maths
\dummytext{1}\par% une phrase
\hrulefill\par% un leaders
\dummytext{2}% 2 phrases
\hrule height2pt depth 2pt %une \hrule
\vskip10pt % saute 10pt verticalement
\dummytext{1}% une phrase
\endnumlines\medbreak
ESSAI 2 :
\leftline{}\rightline{}% rien � gauche et rien � droite
\frboxsep=-\frboxrule% encadrer vers "l'int�rieur"
\let\formatline\frbox% lignes encadr�es
\numlines
\dummytext{4}
\endnumlines\medbreak
ESSAI 3 :
\let\formatline\identity
\leftline[7pt]{%
\for\xx= 1 to 2 \do{% ins�rer 2 fois
\setbox0=\hbox{% % mettre dans une \hbox une \vrule de "bonnes dimensions"
\vrule height\ht\currentline depth\dimexpr\dp\currentline+\intersplitspace
width0.5pt }%
\dp0=\dp\currentline% r�ajuster la profondeur (c-�-d enlever \intersplitspace)
\box0 % afficher le boite
\kern2pt % et ins�rer un espace horizontal de 2pt apr�s chaque r�glure verticale
}%
\kern2pt % ajouter 2pt de plus entre les lignes et le texte
}
\rightline[10pt]{\kern5pt $\scriptscriptstyle\number\linecnt$}% num�roter � droite
\numlines
\dummytext{2}
$$a^2+b^2=c^2$$
\dummytext{2}
\endnumlines
****************** Fin code ******************
****************** Code 406 ******************
% d�finition des ressorts "inter-lettre" et "inter-mot"
\newskip\interletterskip \interletterskip=0.25em plus0.05em minus0.05em
\newskip\interwordskip \interwordskip=3\interletterskip\catcode`\@11
\catcode`@11
\def\spreadtxt@testtoken#1{% macro qui teste le token
\ifcat\noexpand#1\sptoken% si le token est un espace
\parseadd{%
\unskip% retirer le pr�c�dent ressort
\hskip\interwordskip}% et ajouter le ressort inter-mot
\else
\ifcat\noexpand#1a% si le token est une lettre
\parseadd{#1\hskip\interletterskip}% ajouter le ressort inter-lettre
\else
\ifcat\noexpand#1.% si le token est "autre", comme le "."
\parseadd{#1\hskip\interletterskip}% ajouter le ressort inter-lettre
\else% sinon
\parseadd{#1}% ajouter le token lu
\fi
\fi
\fi
\parse@i
}
\def\spreadtxt{%
\ifstarred% si �toil�e
{\spreadtxt@i{\parse*}}% appeler \parse*
{\spreadtxt@i{\parse}}% sinon, appeler \parse
}
\def\spreadtxt@i#1#2{% #1= appel "\parse*" ou "\parse" #2 = texte � espacer
\begingroup% dans un groupe
\let\testtoken=\spreadtxt@testtoken% modifier \testtoken
#1#2\parsestop% et appeler \parse
\endgroup
}
\catcode`@12
\spreadtxt{Comme on le voit sur cet exemple, une espace est ins�r�e apr�s
{\it chaque} caract�re de catcode 10, 11 ou 12.}
\medbreak
\spreadtxt*{Comme on le voit sur cet exemple, une espace est ins�r�e apr�s
{\it chaque} caract�re de catcode 10, 11 ou 12.}
****************** Fin code ******************
****************** Code 407 ******************
\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 -> a 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 plus0.07em minus.07em][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\rightofsc#1#2{%
\exparg\ifin{#1}{#2}% si #1 contient le #2
{\def\right@of##1#2##2\@nil{\def#1{##2}}%
\expandafter\right@of#1\@nil% appelle la macro auxiliaire
}%
{\let#1=\empty}% sinon, #1 est vide
}
\def\spacetxt@nostar{%
\exparg\ifempty{\spacetxt@code}% si texte restant est vide
\spacetxt@endprocess% aller � la fin du processus
{\@indivifoundfalse% sinon, a priori, les motifs non r�guliers ne sont pas trouv�s
% pour chaque \indivi@tmp dans \indivilist
\expsecond{\doforeach\indivi@tmp\in}{\indivilist}% pour chaque motif indivisible
{% si le code commence par le motif courant
\exptwoargs\ifstartwith\spacetxt@code\indivi@tmp
{% l'ajouter dans le registre ainsi que l'espace inter-lettre
\eaddtotoks\spacetxt@toks{\indivi@tmp\hskip\interletterskip}%
% et enlever le motif du texte restant � lire
\expsecond{\rightofsc\spacetxt@code}{\indivi@tmp}%
\@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
}%
\unless\if@indivifound% si aucun motif n'a �t� trouv�
\grab@first\spacetxt@code\spacetxt@temp% retirer le 1er caract�re du texte
\ifx\spacetxt@temp\space% si le 1er caract�re est un espace
\addtotoks\spacetxt@toks{%
\unskip% annuler le pr�c�dent ressort
\hskip\interwordskip}% ajouter l'espace inter-mot au registre de token
\else% si le 1er caract�re n'est pas un espace
% ajouter ce caract�re et l'espace inter-lettre au registre de token
\eaddtotoks\spacetxt@toks{\spacetxt@temp\hskip\interletterskip}%
\fi
\fi
\spacetxt@recurse% enfin, continuer le processus
}%
}
\def\spacetxt@star{%
\exparg\ifempty{\spacetxt@code}% si texte restant est vide
\spacetxt@endprocess% aller � la fin du processus
{% sinon, si texte commence par "{"
\exparg\ifbracefirst{\spacetxt@code}%
{\grab@first\spacetxt@code\spacetxt@temp
% mettre {<argument} dans \spacetxt@temp
\begingroup% ouvrir un groupe
% mettre le contenu de l'argument dans \spacetxt@code
\expandafter\def\expandafter\spacetxt@code\spacetxt@temp
\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
}
\catcode`\@12
\def\indivilist{�,�}% liste des motifs sp�ciaux
\spacetxt*{Comme on le voit sur cet exemple, une espace est ins�r�e apr�s
{\it chaque} caract�re.}
\medbreak
\def\indivilist{�,es,au,<<,>>}
\spacetxt[4pt plus.7pt minus.7pt][12pt plus2pt minus2pt]{Ici, les motifs <<es>> et <<au>>
restent indivisibles et la ligature des guillemets devient possible en d�clarant "<<" et
">>" comme motifs.}
****************** Fin code ******************
****************** Code 408 ******************
\catcode`\@11
\def\ttcode#1{% lit #1, le <d�limiteur> de d�but
\def\ttcode@i##1#1{% ##1 = <texte> entre d�limiteurs
\tt% passe en fonte � chasse fixe
\setbox0=\hbox{ }%
\edef\spc@wd{\the\wd0 }% longueur d'un espace
\spacetxt
[.1pt plus0pt minus.1pt]% espace inter-lettre
[\glueexpr\wd0+.3pt plus.1pt minus.1pt\relax]% espace inter-mot
{##1}% le <texte> est compos� par \spacetxt
\endgroup
}%
\begingroup
\def\indivilist{<<,>>,{,,},--}% (rajouter �, �, �, etc. en codage UTF8)
\def\do##1{\catcode`##1=12 }%
\dospecials% rend inoffensifs tous les tokens sp�ciaux
\letactive\ =\space % rend l'espace actif
\ttcode@i% va lire le <texte> et le d�limiteur de fin
}
\catcode`\@12
\hfill\vrule\vbox{%
\hsize=.75\hsize
Avec \ttcode/\ttcode/, on peut ins�rer une adresse internet <<
\ttcode-
http://www.gutenberg.eu.org/Typographie- >> puis repasser en fonte normale
puis \ttcode+m�me composer un court passage en fonte � chasse fixe -- m�me si les
coupures de mots se font n'importe o� -- et aussi afficher tous les caract�res
sp�ciaux <<{$^ _$#}&+>>, et finir en fonte normale\ldots
}\vrule\hfill\null
****************** Fin code ******************
****************** Code 409 ******************
\def\ttwide{0.7}% coefficient pour la largeur de composition
\def\ttindent{5}% nombre de caract�res d'indentation
\hfill\vrule
\vbox{%
\ttfamily% en TeX, on �crirait "\tt"
\setbox0\hbox{0}% \wd0 est donc la largeur d'un caract�re
\parindent=\ttindent\wd0 % r�glage de l'indentation
\hsize=\ttwide\hsize % compose sur 70% de la largeur
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauches
et droites du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous d'une ligne � l'autre. Des d�bordements dans
la marge deviennent alors in�vitables, car la largeur de composition (ici
\the\hsize) n'est pas un multiple de la largeur d'un caract�re (\the\wd0 ),
le quotient des deux valant environ
\xdef\ttratio{\decdiv{\dimtodec\hsize}{\dimtodec\wd0 }}\ttratio.
}%
\vrule\hfill\null
****************** Fin code ******************
****************** Code 410 ******************
Fonte normale : \fontname\font\par
{\bf Fonte grasse : \fontname\font\par}
{\it Fonte italique : \fontname\font\par}
{\sc Fonte petites majuscules : \fontname\font}
****************** Fin code ******************
****************** Code 411 ******************
\font\gras=LinLibertineTB-tlf-t1 at 8pt
\font\ital= LinLibertineTI-tlf-t1 at 8pt
\font\itgras=LinLibertineTBI-tlf-t1 at 8pt
Du texte normal {\gras puis en gras, \ital en italique,
\itgras en italique gras} et retour � la normale.
****************** Fin code ******************
****************** Code 412 ******************
Code du caract�re de coupure = \number\hyphenchar\font\par
Caract�re de coupure : "\char\hyphenchar\font"
****************** Fin code ******************
****************** Code 413 ******************
\def\longtext{Voici une phrase �crite avec des mots insignifiants mais terriblement,
�pouvantablement, horriblement et ind�niablement longs.}
% cr��r une macro restaurant le \hyphenchar
\edef\restorehyphenchar{\hyphenchar\font=\number\hyphenchar\font}%
%comportement normal, caract�re de coupure "-"
1) \vrule\vbox{\hsize=5cm \longtext}\vrule\hfill
% modification du caract�re de coupure "W"
2) \vrule\vbox{\hsize=5cm \hyphenchar\font=`W \longtext}\vrule
\medbreak
% interdiction des coupures de mots
3) \vrule\vbox{\hsize=5cm \hyphenchar\font=-1 \longtext}\vrule
\restorehyphenchar
****************** Fin code ******************
****************** Code 414 ******************
\def\longtext{Voici une phrase �crite avec des mots insignifiants mais terriblement,
�pouvantablement, horriblement et ind�niablement longs.}
\edef\restorehyphenchar{\hyphenchar\font=\number\hyphenchar\font}%
\vrule\vbox{\hsize=5cm \hyphenchar\font=-1 \sloppy \longtext}\vrule
\restorehyphenchar
****************** Fin code ******************
****************** Code 415 ******************
a) \texttt{\number\hyphenchar\font}\qquad
b) {\ttfamily\number\hyphenchar\font}
****************** Fin code ******************
****************** Code 416 ******************
\leavevmode
\vbox{%
\hsize=.4\hsize
\Souligne{Police � chasse variable}%
\vskip5pt
espace inter-mot = \the\fontdimen2\font\par
�trirement inter-mot = \the\fontdimen3\font\par
compression inter-mot = \the\fontdimen4\font
}\hfill
\vbox{%
\tt
\hsize=.4\hsize
\Souligne{Police � chasse fixe}%
\vskip5pt
espace inter-mot = \the\fontdimen2\font\par
�trirement inter-mot = \the\fontdimen3\font\par
compression inter-mot = \the\fontdimen4\font
}
****************** Fin code ******************
****************** Code 417 ******************
\def\ttwide{0.7}\def\ttindent{5}%
\hfill\vrule
\vbox{%
\ttfamily
\hyphenchar\font=`\- % change le caract�re de coupure de la fonte en cours
\setbox0\hbox{0}\parindent=\ttindent\wd0
\hsize=\ttwide\hsize % compose sur 70% de la largeur
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous des autres d'une ligne � l'autre. Des d�bordements
dans la marge deviennent in�vitables m�me si les coupures des mots sont
� nouveau rendues possibles.%
}%
\vrule\hfill\null
****************** Fin code ******************
****************** Code 418 ******************
\frboxsep=0.5pt
\def\printallchars{%
\leavevmode
\for\xx=0 to255\do{%
\vbox{% empiler verticalement
\offinterlineskip% en d�sactivant le ressort d'interligne
\setbox0\hbox{\frbox{\char\xx}}%
\copy0 % la boite contenant le caract�re encadr�
\kern1pt% saute 1pt vertical
\hbox to\wd0{\hss$\scriptscriptstyle\xx$\hss}% le num�ro
}\hskip0.5em plus1pt minus1pt % saute 0.5em horizontalement
}%
}
\tt
Nom de la fonte = \fontname\font\par
\printallchars
****************** Fin code ******************
****************** Code 419 ******************
\setbox0=\hbox{\tt\char23}
Largeur = \the\wd0 \qquad Hauteur = \the\ht0 \qquad Profondeur = \the\dp0
****************** Fin code ******************
****************** Code 420 ******************
{\tt\xdef\nfont{\the\font}}
Largeur = \the\fontcharwd\nfont23 \qquad Hauteur = \the\fontcharht\nfont23
\qquad Profondeur = \the\fontchardp\nfont23
****************** Fin code ******************
****************** Code 421 ******************
\newmacro\ttstart[5]{%
\begingroup
\tt
\edef\restorefontsettings{% stocke les param�tres de fonte
\hyphenchar\font=\the\hyphenchar\font\relax% le \hyphenchar
\fontdimen2\font=\the\fontdimen2\font\relax% et les param�tres d'espacement
\fontdimen3\font=\the\fontdimen3\font\relax
\fontdimen4\font=\the\fontdimen4\font\relax
}%
\fontdimen3\font=0.30\fontdimen2\font% composante + = 30% de la dimension naturelle
\fontdimen4\font=0.20\fontdimen2\font% composante - = 20% de la dimension naturelle
\hyphenchar\font=`\- % on autorise la coupure des mots (au cas o� on utilise latex)
\setbox0\hbox{0}% largeur d'un caract�re
\parindent=#1\wd0 % indentation (en nombre de caract�res)
\ignorespaces
}
\def\ttstop{%
\restorefontsettings% restaure les param�tres de fonte
\endgroup% et ferme le groupe
}
\hfill\vrule
\def\ttwide{0.70}%
\vbox{%
\hsize=\ttwide\hsize % compose sur 70% de la largeur
\ttstart[5]
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res ne sont pas
exactement les uns au-dessous des autres entre les lignes du paragraphe.
Puisque les espaces sont redevenus �tirables, les d�bordements dans la marge
(m�me s'ils restent possibles), sont bien plus rares et ce d'autant plus que
le nombre d'espaces dans une ligne est grand.%
\ttstop
}%
\vrule\hfill\null
****************** Fin code ******************
****************** Code 422 ******************
\catcode`\@11
\newcount\brktt@cnt
\newdimen\brktt@interletter
\newif\ifline@start% bool�en vrai lorsqu'aucun caract�re n'est encore affich�
\newif\if@indivifound% bool�en qui sera vrai si un motif sp�cial est rencontr�
\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% feerme la \hbox pr�c�dente
\hbox\bgroup% ouvre la suivante
\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
}
\newmacro\breaktt[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 fonte � chasse fixe
\setbox0 = \hbox{M}% la boite 0 contient un caract�re
\edef\ttchar@width{\the\wd0 }% largeur de chaque caract�re en fonte \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�re 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
% stocke le texte apr�s avoir enlev� les �ventuels espaces extremes :
\expsecond{\expsecond{\def\tt@remaintext}}{\removetrailspaces{#3}}%
\unless\ifx\tt@remaintext\empty% 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
\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\breaktt@i% aller � la macro r�cursive
\fi
}
\def\breaktt@i{%
\print@nchar\maxchar@num% afficher \maxchar@num caract�res
\ifx\tt@remaintext\empty% si texte restant est vide
\egroup% fermer la hbox
\par% aller � la ligne
\endgroup% fermer le groupe ouvert au d�but
\else
\unless\ifnum\brktt@cnt<\maxchar@num\relax% si la ligne est remplie
\exparg\restart@hbox{\tt@remaintext}% ferme la hbox et en r�-ouvre une
\fi
\expandafter\breaktt@i% enfin, continuer le processus
\fi
}
\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, a 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 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}% l'enlever du texte restant
\@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
}%
}
\catcode`\@12
\def\liglist{<<,>>}% liste des motifs de ligature
% ajouter �, �, etc si codage UTF8 + moteur 8 bits
\def\ttindent{3}% valeur de l'indentation'
\vrule\vbox{\breaktt[4pt][.7\hsize]{%
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous des autres d'une ligne � l'autre. Plus aucun
d�bordement n'a lieu, car une espace correctement calcul�e est ins�r�e entre
chaque caract�re. Les mots, en revanche, sont toujours coup�s <<sauvagement>>.%
}%
}\vrule\smallbreak
\vrule\vbox{\breaktt[1pt][6cm]{%
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous des autres d'une ligne � l'autre. Plus aucun
d�bordement n'a lieu, car une espace correctement calcul�e est ins�r�e entre
chaque caract�re. Les mots, en revanche, sont toujours coup�s <<sauvagement>>.%
}%
}\vrule
****************** Fin code ******************
****************** Code 423 ******************
\catcode`\@11
\newcount\brktt@cnt
\newdimen\brktt@interletter
\newif\ifline@start% bool�en vrai lorsqu'aucun caract�re n'est encore affich�
\newif\if@indivifound% bool�en qui sera vrai si un motif sp�cial est rencontr�
\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 fonte � chasse fixe
\setbox0 = \hbox{M}% la boite 0 contient un caract�re
\edef\ttchar@width{\the\wd0 }% largeur de chaque caract�re en fonte \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
% stocke le texte apr�s avoir enlev� les �ventuels espaces extremes :
\expsecond{\expsecond{\def\tt@remaintext}}{\removetrailspaces{#3}}%
\unless\ifx\tt@remaintext\empty% 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
\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\breakttA@i{%
\edef\remaining@chars{% calculer le nombre de caract�res restant � placer sur la ligne
\numexpr\maxchar@num-\brktt@cnt\relax}%
\len@tonextword% \next@len contient le nombre de caract�res du prochain mot
% si le mot + l'eventuel "-" qui le suit ne peut pas loger sur la ligne en cours
\ifnum\numexpr\next@len+\extra@char\relax>\remaining@chars\relax
\ifline@start% et si c'est le d�but d'une ligne
% avertir l'utilisateur
\message{Largeur de composition trop faible pour
\unexpanded\expandafter{\next@word}^^J}%
% et composer tout de m�me "� la sauvage" jusqu'� la fin de la ligne
\exparg\print@nchar{\number\numexpr\maxchar@num-\brktt@cnt}%
\else% si la ligne en cours n'est pas au d�but
\insert@blankchar*{\maxchar@num-\brktt@cnt}% remplir la ligne d'espaces
\fi
\exparg\restart@hbox{\tt@remaintext}% commencer une nouvelle ligne
\expandafter\breakttA@i% et poursuivre le processus
% s'il y a assez de place pour accueillir ce qui est avant la prochaine coupure
\else
\print@nchar\next@len% afficher le mot
\ifx\tt@remaintext\empty% si texte restant est vide
\insert@blankchar*{\maxchar@num-\brktt@cnt}% remplir la ligne
\egroup% fermer la hbox en cours
\par% aller � la ligne
\endgroup% fermer le groupe ouvert au d�but. Fin du processus
\else% si le texte restant n'est pas vide
\ifnum\brktt@cnt<\maxchar@num\relax% si la ligne n'est pas remplie
\print@nchar{1}% afficher le caract�re qui suit le mot (" " ou "-")
\else% si la ligne est remplie
\exparg\restart@hbox{\tt@remaintext}% ferme la hbox et en r�-ouvre une
\fi
\expandafter\expandafter\expandafter\breakttA@i% enfin, continuer le processus
\fi
\fi
}
\def\leftofsc#1#2{% dans la macro #1, garde ce qui est � gauche de #2
\def\leftofsc@i##1#2##2\@nil{\def#1{##1}}%
\expandafter\leftofsc@i#1#2\@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 = dim(boite)/dim(caract�re)
\edef\next@len{\number\numexpr\dimexpr\wd0 \relax/\dimexpr\ttchar@width\relax\relax}%
}
\catcode`\@12
\def\liglist{<<,>>}% liste des motifs de ligature (mettre �, �, etc si codage UTF8)
\def\ttindent{3}
\vrule\vbox{\breakttA[3pt][8cm]{%
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous d'une ligne � l'autre. Plus aucun d�bordement
n'a lieu, car une espace correctement calcul�e est ins�r�e entre chaque
caract�re. Dor�navant, les mots ne sont plus coup�s <<~sauvagement~>>.
}}\vrule\medbreak
\leavevmode\vrule\vbox{\breakttA[1pt][5cm]{%
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous d'une ligne � l'autre. Plus aucun d�bordement
n'a lieu, car une espace correctement calcul�e est ins�r�e entre chaque
caract�re. Dor�navant, les mots ne sont plus coup�s <<~sauvagement~>>.
}}\vrule\qquad\def\ttindent{0}%
\vrule\vbox{\breakttA[0.6pt][2cm]{mot-compos� mot-cl� passe-droit au-dessus
l�-bas remonte-pente vingt-huit Notre-Dame-de-Lourdes Mont-Blanc
Saint-Jean-de-Luz}}\vrule
****************** Fin code ******************
****************** Code 424 ******************
\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 p�nalit� suppl�mentaire apr�s la premi�re ligne
\interlinepenalty=0 % pas de p�nalit� inter-ligne
\widowpenalty=0 % pas de 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
}%
}
\zerocompose{0}{Programmation}%
\leavevmode\box0
\hskip 5cm
\zerocompose{0}{Composer en largeur nulle}%
\box0
****************** Fin code ******************
****************** Code 425 ******************
\def\dummytext{Ceci est un texte sans aucun int�r�t dont le seul but est de meubler
la page de fa�on artificielle. }
\setbox0=\vtop{% d�finit la boite 0
\hsize=8cm
\dummytext\dummytext
}
a) Boite pleine : \copy0
b) \setbox0=\vtop{%
\unvbox0 % boite pr�c�demment compos�e
\global\setbox1=\lastbox% et capture la derni�re ligne dans la boite 1
}%
Derni�re ligne = |\hbox{\unhbox1 }|\par% redonne � box1 sa largeur naturelle
Boite restante = \box0
****************** Fin code ******************
****************** Code 426 ******************
\def\dummytext{Ceci est un texte sans aucun int�r�t dont le seul but est de meubler
la page de fa�on artificielle. }
\setbox0=\vtop{% d�finit la boite 0
\hsize=8cm
\dummytext\dummytext
}
\setbox0=\vtop{\unvbox0 \global\setbox1=\lastbox}
\setbox1=\hbox{\unhbox1 }
1) |\box1|
\setbox0=\vtop{\unvbox0 \global\setbox1=\lastbox}
\setbox1=\hbox{\unhbox1 }
2) |\box1|
\setbox0=\vtop{\unvbox0 \global\setbox1=\lastbox}
\setbox1=\hbox{\unhbox1 }
3) |\box1|
****************** Fin code ******************
****************** Code 427 ******************
\setbox0=\vbox{\hsize=2.5cm Programmer en TeX est facile}%
\showboxbreadth=5 \showboxdepth=3 \tracingonline=1
\showbox0
****************** Fin code ******************
****************** Code 428 ******************
\newbox\tempbox
\def\reversebox#1{% affiche le contenu de la boite verticale #1
\setbox#1=\vbox{%
\unvbox#1% composer la boite #1
\unskip\unpenalty% retirer ce qui n'est pas capturable par \lastbox
\global\setbox0=\lastbox% la boite 1 devient la derni�re ligne
}%
|\hbox{\unhbox0 }|\par% afficher la boite 1 dans sa largeur d'origine
\ifvoidorempty{#1}% si le registre #1 contient une boite vide
\relax% ne rien faire
{\reversebox{#1}}% sinon, rencommencer
}
\def\dummytext{Ceci est un texte sans aucun int�r�t dont le seul but est de meubler
la page de fa�on artificielle. }
\setbox\tempbox=\vbox{% d�finit la boite 0
\hsize=8cm \dummytext\dummytext
}
\reversebox\tempbox
****************** Fin code ******************
****************** Code 429 ******************
% compose "Programmation" en largeur 0 dans la boite 0 :
\zerocompose{0}{Programmation}%
Boite initiale : \copy0 \par% compose la boite r�sultante
\vfuzz=\maxdimen% annule les avertissements pour d�bordements
\splittopskip=0pt % ne rajouter aucun espace au sommet de la boite restante
\setbox1 =\vsplit0 to 0pt % coupe la boite 0 � 0pt
{% dans un groupe (o� la boite 0 sert de brouillon)
\setbox0 =\vbox{% affecter � la boite brouillon
\unvbox1 % la boite 1 compos�e dans sa largeur naturelle
\unskip\unpenalty% annule ce qui n'est pas une boite
\global\setbox2 =\lastbox% affecte globalement la derni�re (et unique) ligne
% � la boite 1
}%
}% ferme le groupe
\setbox2=\hbox{\unhbox2}% rend � la boite 2 sa largeur naturelle
Premi�re ligne = "\box2 "% compose la boite 2
****************** Fin code ******************
****************** Code 430 ******************
\catcode`@11
\def\hyphlengths#1#2{%#2 = macro contenant les longueurs de coupures du mot #1
\begingroup
\zerocompose
[\tt% passer en fonte � chasse fixe
\setbox\z@\hbox{M}\xdef\ttwidth{\the\wd\z@}% mesurer la largeur des caract�res
]\z@{#1}% compose en 0pt dans la boite 0
\let#2 = \empty% initialise la macro #2
\def\cumul@length{0}% le cumul des longueurs initialis� � 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
}
\catcode`\@12
a) \hyphlengths{programmation}\foo liste = "\foo"\par
b) \hyphlengths{typographie}\foo liste ="\foo"\par
c) \hyphlengths{j'entendrai}\foo liste ="\foo"\par
d) \hyphlengths{vite}\foo liste ="\foo"
****************** Fin code ******************
****************** Code 431 ******************
\catcode`\@11
\newcount\brktt@cnt
\newdimen\brktt@interletter
\newif\ifline@start% bool�en vrai lorsqu'aucun caract�re n'est encore affich�
\newif\if@indivifound% bool�en qui sera vrai si un motif sp�cial est rencontr�
\let\breakttB=\breakttA
\def\breakttA@i{%
\edef\remaining@chars{% calculer le nombre de caract�res restant � placer sur la ligne
\numexpr\maxchar@num-\brktt@cnt\relax}%
\len@tonextword% calculer dans \next@len le nombre de caract�res avant le prochain mot
\def\next@hyphlen{0}% initialiser la longueur de coupure possible du mot
% si le mot + l'eventuel "-" qui le suit ne rentre pas sur ce qui reste de la ligne
\ifnum\numexpr\next@len+\extra@char\relax>\remaining@chars\relax
\hyphlengths\next@word\list@hyphlengths% b�tir la liste des longueurs de coupures
\unless\ifx\list@hyphlengths\empty% si une coupure est possible
\expsecond{\doforeach\xx\in}{\list@hyphlengths}% les examiner toutes
{% si la coupure examin�e peut loger sur la ligne
\unless\ifnum\xx>\remaining@chars\relax%
\let\next@hyphlen\xx% la stocker
\fi% pour que \next@hyphlen soit maximal
}%
\fi
\fi
\ifnum\next@hyphlen>0 % si une coupure est n�cessaire et a �t� trouv�e
\let\next@len\next@hyphlen% mettre � jour la longueur du mot � placer
\fi
% si le mot + l'eventuel "-" qui le suit ne peut pas loger sur la ligne en cours
\ifnum\numexpr\next@len+\extra@char\relax>\remaining@chars\relax
\ifline@start% si c'est le d�but d'une ligne
% avertir l'utilisateur
\message{Largeur de composition trop faible pour
\unexpanded\expandafter{\next@word}^^J}%
% et composer tout de m�me jusqu'� la fin de la ligne
\exparg\print@nchar{\number\numexpr\maxchar@num-\brktt@cnt}%
\else% sinon
\insert@blankchar*{\maxchar@num-\brktt@cnt}% remplir la ligne
\fi
\exparg\restart@hbox{\tt@remaintext}% r�-ouvrir une boite
\expandafter\breakttA@i% et poursuivre le processus
% s'il y a la place pour accueillir ce qui est avant la prochaine coupure
\else
\ifnum\next@hyphlen>0 % si une coupure de mot doit �tre faite
\exparg\print@nchar{\number\numexpr\next@len-1}% afficher les lettres de la syllabe
\print@hyphchar% et le caract�re de coupure
\insert@blankchar*{\maxchar@num-\brktt@cnt}% remplir la ligne
\exparg\restart@hbox{\tt@remaintext}% r�-ouvrir une boite
\expandafter\expandafter\expandafter\breakttA@i% et continuer le processus
\else% si pas de coupure dans le mot
\print@nchar\next@len% afficher le mot
\ifx\tt@remaintext\tt@emptytext% si texte restant est vide
\insert@blankchar*{\maxchar@num-\brktt@cnt}% remplir la ligne
\egroup% fermer la hbox
\par% aller � la ligne
\endgroup% fermer le groupe ouvert au d�but. Fin du processus
\else% si le texte restant n'est pas vide
\ifnum\brktt@cnt<\maxchar@num\relax% si la ligne n'est pas remplie
\print@nchar{1}% afficher le caract�re qui suit le mot
\else% si la ligne est remplie
\exparg\restart@hbox{\tt@remaintext}% ferme la hbox et en r�-ouvre une
\fi
\expandafter\expandafter\expandafter\breakttA@i% enfin, continuer le processus
\fi
\fi
\fi
}
\def\print@hyphchar{%
\advance\brktt@cnt by 1 % augmenter le compteur de caract�res
\hbox to\ttchar@width{\hss-\hss}% afficher "-"
\ifnum\brktt@cnt<\maxchar@num\relax% si la ligne n'est pas encore remplie
\kern\brktt@interletter\relax% ins�rer le ressort inter-lettre
\fi
}
\catcode`\@12
\def\liglist{<<,>>}% liste des motifs de ligature (mettre �, �, etc si codage UTF8)
\def\ttindent{3}
\vrule\vbox{\breakttB[3pt][8cm]{%
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous d'une ligne � l'autre. Plus aucun d�bordement
n'a lieu, car une espace correctement calcul�e est ins�r�e entre chaque
caract�re. Dor�navant, les mots ne sont plus coup�s <<sauvagement>>.
}%
}\vrule
\vrule\vbox{\breakttB[1pt][5cm]{%
Dans ce paragraphe, compos� en fonte � chasse fixe et o� les limites gauche
et droite du texte ont �t� trac�es, on constate que les caract�res sont
exactement les uns au-dessous d'une ligne � l'autre. Plus aucun d�bordement
n'a lieu, car une espace correctement calcul�e est ins�r�e entre chaque
caract�re. Dor�navant, les mots ne sont plus coup�s <<sauvagement>>.
}%
}\vrule
****************** Fin code ******************
****************** Code 432 ******************
Voici un algorithme �l�mentaire :
\algorithm[\#]{Algorithme {\bf MinMax}}|
macro ~Min_Max~ (#1) % afficher la valeur max et min d'une liste de valeurs #1
$V_{max}:=-\infty$ % $-\infty$ ou la plus petite valeur possible
$V_{min}:=+\infty$ % $+\infty$ ou la plus grande valeur possible
~Pour~ chaque $x$ dans (#1)
~Si~ $x>V_{max}$
~alors~ $V_{max}:=x$
~FinSi~
~Si~ $x<V_{min}$
~alors~ $V_{min}:=x$
~FinSi~
~FinPour~
Afficher "$V_{min}$ et $V_{max}$"
~FinMin_Max~|
Suite du texte...
****************** Fin code ******************
****************** Code 433 ******************
\def\algoindent{1cm}%
\begingroup
\parindent=0pt % pas d'indentation
\defactive\^^M{\leavevmode\par}% rend le retour charriot actif
\defactive\^^I{\hskip\algoindent\relax}% tabulation active
Pas d'indentation ici\ldots
Voici une premi�re ligne
une seconde plus indent�e
retour � l'indentation normale
\for\xx=1to10\do{un long texte }
pour terminer, la derni�re ligne
\endgroup
****************** Fin code ******************
****************** Code 434 ******************
\def\algoindent{1cm}%
\begingroup
\leftskip=0pt \rightskip=0pt plus1fil \relax % initialise les ressorts lat�raux
\parindent=0pt % pas d'indentation
\defactive\^^M{\leavevmode\par\leftskip=0pt }% rend le retour charriot actif
\defactive\^^I{\advance\leftskip by \algoindent\relax}% tabulation active
Pas d'indentation ici\ldots
Voici une premi�re ligne
une seconde plus indent�e
retour � l'indentation normale
\for\xx=1to10\do{un long texte }
pour terminer, la derni�re ligne
\endgroup
****************** Fin code ******************
****************** Code 435 ******************
% compteur de lignes pour l'algorithme
\def\algoindent{1cm}%
\begingroup
\algocnt=1 % initialise le compteur � 1
\leftskip=0pt \rightskip=0pt plus1fil\relax% initialise les ressorts � 0pt
\parindent=0pt % pas d'indentation
\everypar={\llap{$\scriptstyle\number\algocnt$\kern\dimexpr4pt+\leftskip\relax}}%
\defactive\^^M{\leavevmode\par\advance\algocnt by1 \leftskip=0pt }% retour charriot actif
\defactive\^^I{\advance\leftskip by \algoindent\relax}% tabulation active
Pas d'indentation ici\ldots
Voici une premi�re ligne
une seconde plus indent�e
retour � l'indentation normale
\for\xx=1to10\do{un long texte }
pour terminer, la derni�re ligne
\endgroup
****************** Fin code ******************
****************** Code 436 ******************
\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
}
\newmacro\algorithm[\\,\#,\{,\}]2{%
\medbreak
\begingroup% ouvre un groupe (sera ferm� � la fin de l'algorithme)
\algocnt=1 % initialise le compteur de lignes
\leftskip=0pt \rightskip=0pt plus1fil\relax% 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 d'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
}%
\ifnumalgo% si la num�rotation est demand�e,
\everypar={% d�finir le \everypar
\llap{$\scriptstyle\number\algocnt$\kern\dimexpr4pt+\leftskip\relax}%
}%
\fi
\doforeach\currentchar\in{#1}{\catcode\expandafter`\currentchar=12 }%
\def\algocr{% d�finit ce que fait ^^M
\color{black}% repasse en couleur noire
\rm% fonte droite
\leavevmode\par% termine le paragraphe
\advance\algocnt by1 % incr�mente le compteur de lignes
\leftskip=0pt % initialise le ressort gauche
}
\letactive\^^M=\algocr%
\defactive\^^I{\advance\leftskip by \algoindent\relax}%
\defactive\ {\hskip1.25\fontdimen2\font\relax}% espace = 25% de + que
% la largeur naturelle
\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{}% neutralise le \everypar
\par% aller � la ligne
\nointerlineskip% ne pas ins�rer le ressort d'interligne
\kern7pt % et sauter 7pt verticalement
\nobreak% emp�cher une coupure de page
\algohrulefill% tracer la ligne de fin
\endgroup% ferme le groupe ouvert au d�but de l'algorithme
\smallbreak% saute un petit espace vertical
}%
%%%%%%%%%%%%%%%%% 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{% a 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\algocr% 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
}
Voici un algorithme �l�mentaire
\algorithm[\#]{Algorithme {\bf MinMax}}|
macro ~Min_Max~ (#1) % afficher la valeur max et min d'une liste de valeurs #1
W$V_{max}:=-\infty$ % $-\infty$ ou la plus petite valeur possible
W$V_{min}:=+\infty$ % $+\infty$ ou la plus grande valeur possible
W~Pour~ chaque $x$ dans (#1)
WW~Si~ $x>V_{max}$
WWW~alors~ $V_{max}:=x$
WW~FinSi~
WW~Si~ $x<V_{min}$
WWW~alors~ $V_{min}:=x$
WW~FinSi~
W~FinPour~
WAfficher "$V_{min}$ et $V_{max}$"
~FinMin_Max~|
Suite du texte...
****************** Fin code ******************
****************** Code 437 ******************
a) \meaning a\par
b) \meaning {\par
c) \meaning _\par
d) \meaning\def\par % une primitive
e) \meaning\baselineskip\par% une primitive
f) \long\def\foo#1#2.#3{#1 puis #2 et #3 !}\meaning\foo
****************** Fin code ******************
****************** Code 438 ******************
\def\foo#1#2{%
\def\argA{#1}\show\argA% d�bogage
Bonjour #1 et #2}
\foo{{\bf X}}{Y}
****************** Fin code ******************
****************** Code 439 ******************
\def\foo#1#2{%
\showtokens{#1}% d�bogage
Bonjour #1 et #2}
\foo{{\bf X}}{Y}
****************** Fin code ******************
****************** Code 440 ******************
\newtoks\footoks
\footoks={foo bar}
\show\footoks
****************** Fin code ******************
****************** Code 441 ******************
\showthe\baselineskip% registre-primitive
\newtoks\footoks \footoks={foo bar} \showthe\footoks
\newcount\foocount \foocount=987 \showthe\foocount
\newdimen\foodimen \foodimen=3.14pt \showthe\foodimen
\newskip\fooskip \fooskip=10 pt plus 1pt minus 1fil \showthe\fooskip
\newbox\foobox \foobox\hbox{foo} \showthe\foobox
****************** Fin code ******************
****************** Code 442 ******************
\def\foo#1,#2\endfoo{Bonjour #1 et #2}
\tracingmacros=1
\foo moi,toi\endfoo
\tracingmacros=0
****************** Fin code ******************
****************** Code 443 ******************
\tracingcommands=2
Foo \hbox{et \ifnum2>1 bar\else toi\fi}\par
Suite
\tracingcommands=0
****************** Fin code ******************
****************** Code 444 ******************
\def\i{\advance\count255 1 }
\tracingrestores=1
\count255=2 {\i\i\i}
\tracingrestores=0
****************** Fin code ******************
****************** Code 445 ******************
\def\i{\advance\count255 1 } \def\gi{\global\i}
\tracingrestores=1
\count255=2 {\i\i\gi\i\gi\i}
\tracingrestores=0
****************** Fin code ******************
****************** Code 446 ******************
\catcode`@11
\def\ifnodecpart#1{\ifnodecpart@i#1.\@nil}
\def\ifnodecpart@i#1.#2\@nil{\ifempty{#2}}
\def\decadd#1#2{% #1 et #2=nombre � additionner
\ifnodecpart{#1}% si #1 est un entier
{\ifnodecpart{#2}% et #2 aussi, les additionner avec \numexpr
{\number\numexpr#1+#2\relax}%
{\decadd@i#1.0\@nil#2\@nil}% sinon, ajouter ".0" apr�s #1
}
{\ifnodecpart{#2}% si #1 a une partie enti�re mais pas #2
{\decadd@i#1\@nil#2.0\@nil}% ajouter ".0" � #2
{\decadd@i#1\@nil#2\@nil}% sinon, les 2 parties enti�res sont pr�sentes
}%
}
\def\decadd@i#1.#2\@nil#3.#4\@nil{% affiche les parties enti�res et d�cimales re�ues
$x_a=#1\quad y_a=#2\qquad x_b=#3\quad y_b=#4$
}
\catcode`@12
a) \decadd{5}{9.4}\par
b) \decadd{-3.198}{-6.02}\par
c) \decadd{0.123}{123}
****************** Fin code ******************
****************** Code 447 ******************
\def\addzeros#1#2/#3.#4#5/#6.#7/{%
Arguments re�us : #1#2/#3.#4#5/#6.#7/\par% afficher ce que la macro re�oit
\ifempty{#2}% si #1 est le dernier chiffre de y
{\ifempty{#5}% et si #4 est le dernier chiffre de y2
{R�sultat final : \detokenize{{#3#1}{#6#4}{#70}}}% afficher le r�sultat final
{\addzeros0/#3#1.#5/#6#4.#70/}% sinon alimenter #1 avec un 0
}
{\ifempty{#5}% si #4 est le dernier chiffre de y2
{\addzeros#2/#3#1.0/#6#4.#70/}% alimenter #4 avec un 0
{\addzeros#2/#3#1.#5/#6#4.#70/}% #2 et #5 non vides
}%
}
\addzeros457/.689714/.1/
****************** Fin code ******************
****************** Code 448 ******************
\catcode`\@11
\def\addzeros#1#2/#3.#4#5/#6.#7/{%
\ifempty{#2}% si #1 est le dernier chiffre de y1
{\ifempty{#5}% et si #4 est le dernier chiffre de y2
{{#3#1}{#6#4}{#70}}% redonner les 3 arguments
{\addzeros0/#3#1.#5/#6#4.#70/}% sinon alimenter #1 avec un 0
}
{\ifempty{#5}% si #4 est le dernier chiffre de y2
{\addzeros#2/#3#1.0/#6#4.#70/}% alimenter #4 avec un 0
{\addzeros#2/#3#1.#5/#6#4.#70/}% #2 et #5 non vides
}%
}
\def\decadd#1#2{% #1 et #2=nombre � additionner
\ifnodecpart{#1}
{\ifnodecpart{#2}{\number\numexpr#1+#2\relax}{\decadd@i#1.0\@nil#2\@nil}}
{\ifnodecpart{#2}{\decadd@i#1\@nil#2.0\@nil}{\decadd@i#1\@nil#2\@nil}}%
}
\def\decadd@i#1.#2\@nil#3.#4\@nil{%
\expandafter\decadd@ii
\romannumeral-`\0\addzeros#2/.#4/.1/% se d�veloppe en 3 arguments
{#1}
{#3}%
}
\def\decadd@ii#1#2#3#4#5{%
% #1 et #2=parties d�cimales (m�mes longueurs);
% #3=seuil de retenue; #4 et #5=parties enti�res
\exptwoargs{\decadd@iii{#3}}% envoyer le seuil de retenue tel quel
% sommer les parties d�cimales sign�es
{\number\numexpr\true@sgn{#4}#1+\true@sgn{#5}#2\relax}%
% et les parties enti�res
{\number\numexpr#4+#5\relax}%
}
\def\decadd@iii#1#2#3{%
seuil de retenue = #1 \qquad nombre = "#3"."#2"%
}
\catcode`\@12
a) \decadd{6.7}{3.498}\par
b) \decadd{1.67}{-4.9}\par
c) \decadd{3.95}{2.0005}\par
d) \decadd{1.007}{2.008}\par
e) \decadd{-7.123}{3.523}
****************** Fin code ******************
****************** Code 449 ******************
\catcode`\@11
\def\format@dec#1#2{% #1=partie d�cimale #2=seuil de retenue
\expandafter\gobone% le \gobone agira en dernier,
\romannumeral-`\0% mais avant, tout d�velopper
\expandafter\reverse\expandafter% et retarder le \reverse de fin
% pour d�velopper son argument qui
{\number% d�veloppe tout et �value avec \number
\expandafter\reverse\expandafter% l'inversion de
{\number\numexpr\abs{#1}+#2\relax}% |#1|+#2
}%
}
a) \format@dec{710}{100000}\par
b) \format@dec{6}{100}\par
c) \format@dec{-12300}{1000000}
\catcode`\@12
****************** Fin code ******************
****************** Code 450 ******************
\catcode`@11
\def\true@sgn#1{\ifnum#11<\z@-\fi}
\def\decadd#1#2{% #1 et #2=nombre � additionner
\romannumeral-`\.% tout d�velopper jusqu'� l'affichage du nombre (\decadd@iv)
\ifnodecpart{#1}% si #1 est un entier
{\ifnodecpart{#2}% et #2 aussi, les additionner avec \numexpr
{\numexpr#1+#2\relax}%
{\decadd@i#1.0\@nil#2\@nil}% sinon, ajouter ".0" apr�s #1
}
{\ifnodecpart{#2}% si #1 a une partie enti�re mais pas #2
{\decadd@i#1\@nil#2.0\@nil}% ajouter ".0" � #2
{\decadd@i#1\@nil#2\@nil}% sinon, les 2 parties enti�res sont pr�sentes
}%
}
\def\decadd@i#1.#2\@nil#3.#4\@nil{%
\expandafter\decadd@ii
\romannumeral-`\0\addzeros#2/.#4/.10/% se d�veloppe en 3 arguments
{#1}
{#3}%
}
\def\decadd@ii#1#2#3#4#5{%
% #1 et #2=parties d�cimales (m�mes longueurs)
% #3=seuil de retenue; #4 et #5=parties enti�res
\exptwoargs{\decadd@iii{#3}}% envoyer le seuil de retenue tel quel
% sommer les parties d�cimales sign�es
{\number\numexpr\true@sgn{#4}#1+\true@sgn{#5}#2\relax}%
% et les parties enti�res
{\number\numexpr#4+#5\relax}%
}
\def\decadd@iii#1#2#3{% #1=seuil de retenue #2=partie d�cimale #3= partie enti�re
\ifnum\true@sgn{#2}\true@sgn{\ifnum#3=\z@#2\else#3\fi}1=-1 % si les signes sont
% diff�rents
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\exptwoargs\decadd@iv% transmettre les arguments modifi�s :
{\number\numexpr#3-\true@sgn{#3}1}% #3:=#3-sgn(#3)1
{\number\numexpr#2-\true@sgn{#2}#1}% #2:=#2-sgn(#2)10^n
{#1}%
}% si les signes sont �gaux
{\ifnum\abs{#2}<#1 % et si abs(y)<10^n
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\decadd@iv{#3}{#2}{#1}% tranmettre les arguments tels quels
}
{\exptwoargs\decadd@iv% sinon
{\number\numexpr#3+\true@sgn{#3}1}% #3:=#3+sgn(#3)1
{\number\numexpr#2-\true@sgn{#2}#1}% #2:=#2-sgn(#2)10^n
{#1}%
}%
}%
}
\def\decadd@iv#1#2#3{% affiche le d�cimal "#1.#2"
% le d�veloppement maximal initi� par le \romannumeral de \decadd est actif
\ifnum#1=\z@\ifnum#2<\z@% si #1=0 et #2<0
\expandafter\expandafter\expandafter% transmettre le d�veloppement � \number
-% puis afficher le signe "-"
\fi\fi
\number#1% affiche #1 qui est la somme des parties enti�res
% poursuivre le d�veloppement initi� par \number
\unless\ifnum#2=\z@% si la partie d�cimale est diff�rente de 0
\antefi% se d�barrasser de \fi
\expandafter.% afficher le "." d�cimal apr�s avoir
\romannumeral-`\0\format@dec{#2}{#3}% correctement g�r� les 0 de #2
\fi
}
\def\addzeros#1#2/#3.#4#5/#6.#7/{%
\ifempty{#2}% si #1 est le dernier chiffre de y1
{\ifempty{#5}% et si #4 est le dernier chiffre de y2
{{#3#1}{#6#4}{#7}}% redonner les 3 arguments
{\addzeros0/#3#1.#5/#6#4.#70/}% sinon alimenter #1 avec un 0
}
{\ifempty{#5}% si #4 est le dernier chiffre de y2
{\addzeros#2/#3#1.0/#6#4.#70/}% alimenter #4 avec un 0
{\addzeros#2/#3#1.#5/#6#4.#70/}% #2 et #5 non vides
}%
}
\def\format@dec#1#2{% #1=partie d�cimale #2=seuil de retenue
\expandafter\gobone% le \gobone agira en dernier,
\romannumeral-`\0% mais avant, tout d�velopper
\expandafter\reverse\expandafter% et retarder le \reverse de fin
% pour d�velopper son argument qui
{\number% d�veloppe tout et �value avec \number
\expandafter\reverse\expandafter% l'inversion de
{\number\numexpr\abs{#1}+#2\relax}% abs(#1)+#2
}%
}
\catcode`@12
a) $-3.78+1.6987=\decadd{-3.78}{1.6987}$\par
b) $3.56-3.06=\decadd{3.56}{-3.06}$\par
c) $4.125+13.49=\decadd{4.125}{13.49}$\par
d) $-0.99+1.005=\decadd{-0.99}{1.005}$\par
e) $16.6-19.879=\decadd{16.6}{-19.879}$\par
f) $5.789-0.698=\decadd{5.789}{-0.698}$\par
g) $0.123-0.123=\decadd{0.123}{-0.123}$\par
h) $3.14-16.4912=\decadd{3.14}{-16.4912}$\par
i) $0.1-0.98=\decadd{0.1}{-0.98}$\par
j) $2.43+7.57=\decadd{2.43}{7.57}$\par
h) \edef\foo{\decadd{1.23}{9.78}}\meaning\foo\par
j) \detokenize\expandafter\expandafter\expandafter{\decadd{3.14}{-8.544}}
****************** Fin code ******************
****************** Code 451 ******************
a) \pdfstrcmp{foo}{bar}\qquad
b) \pdfstrcmp{bar}{foo}\qquad
c) \def\foo{ABC}\pdfstrcmp{\foo}{ABC}\qquad
d) \edef\foo{\string_}\pdfstrcmp{1_2}{1\foo2}\qquad
e) \pdfstrcmp{\string\relax}{\relax}
****************** Fin code ******************
****************** Code 452 ******************
\edef\tempcompil{\number\pdfelapsedtime}%
Depuis le d�but de la compilation, il s'est �coul� \tempcompil{} secondes d'�chelle,
soit \convertunit{\tempcompil sp}{pt} secondes.
****************** Fin code ******************
****************** Code 453 ******************
%%%%%%%%%% definition de \loop...\repeat comme plain-TeX %%%%%%%%%%
\def\loop#1\repeat{\def\body{#1}\iterate}
\def\iterate{\body \let\next\iterate \else\let\next\relax\fi \next}
\let\repeat=\fi
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcount\testcnt
\pdfresettimer% remet le compteur � 0
\testcnt=0
\loop % Test no 1
\ifnum\testcnt<100000 \advance\testcnt 1
\repeat
Temps 1 = \convertunit{\pdfelapsedtime sp}{pt} s (boucle loop de \TeX)\par
%%%%%%%%%%%% definition de \loop...\repeat comme LaTeX %%%%%%%%%%%%
\def\loop#1\repeat{\def\iterate{#1\relax\expandafter\iterate\fi}%
\iterate \let\iterate\relax}
\let\repeat\fi
\pdfresettimer% remet le compteur � 0
\testcnt=0
\loop % Test no 2
\ifnum\testcnt<100000
\advance\testcnt 1
\repeat
Temps 2 = \convertunit{\pdfelapsedtime sp}{pt} s (boucle loop de \LaTeX)\par
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pdfresettimer% remet le compteur � 0
\for\ii=1 to 100000\do{}% Test no 3
Temps 3 = \convertunit{\pdfelapsedtime sp}{pt} s (boucle for)
****************** Fin code ******************
****************** Code 454 ******************
%%%%%%%%%%%% definition de \loop...\repeat comme LaTeX %%%%%%%%%%%%
\def\loop#1\repeat{\def\iterate{#1\relax\expandafter\iterate\fi}%
\iterate \let\iterate\relax}
\let\repeat\fi
\pdfresettimer% remet le compteur � 0
\def\ii{0}%
\loop % Test no 1
\ifnum\ii<100000
\edef\ii{\number\numexpr\ii+1\relax}%
\repeat
Temps 1 = \convertunit{\pdfelapsedtime sp}{pt} s (boucle loop de \LaTeX)\par
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pdfresettimer% remet le compteur � 0
\for\ii=1 to 100000\do{}% Test no 2
Temps 2 = \convertunit{\pdfelapsedtime sp}{pt} s (boucle for)
****************** Fin code ******************
****************** Code 455 ******************
\newcount\testcnt
\pdfresettimer
\testcnt=0
\for\ii=1 to 100000\do{\advance\testcnt1 }
Temps 1 : \convertunit{\pdfelapsedtime sp}{pt} s (incr�mentation compteur)
\pdfresettimer
\def\foo{0}%
\for\ii=1 to 100000\do{\edef\foo{\number\numexpr\foo+1\relax}}%
Temps 2 : \convertunit{\pdfelapsedtime sp}{pt} s (incr�mentation du texte de remplacement)
****************** Fin code ******************