%--------------------------------------------------
% exos.tex
% macros pour feuilles d'exercices
% version 7 bits
% M. Quercia, 08/05/2012
%--------------------------------------------------

\input montchapet-7bits

% autorise @ dans les noms
\catcode64=11

%--------------------------------------------------
% mise en page
%--------------------------------------------------

\def\fiche#1{\vskip0pt\cadreombre\w=\hsize\m=3mm{\Gros\bf#1}\medskip}
\def\titre#1{\bigskip\goodbreak\centerline{\bf#1}\medskip}
\footline={\petit\hfil\jobname.tex --
  \ifnum\pageno=1\date\else page \folio\fi\hfil}

%--------------------------------------------------
% numerotation automatique
%--------------------------------------------------

% \exnum : numero de l'exercice en cours
% \qqnum : numero de la question en cours
% \sqnum : numero de la sous-question en cours
% \numindent = indentation pour numeros
% \qqmarge   = marge no de question
% \sqmarge   = marge no de sous-question

\newcount\exnum\exnum=0   \newdimen\numindent\numindent=5mm
\newcount\qqnum\qqnum=0   \newdimen\qqmarge\qqmarge=\leftskip
\newcount\sqnum\sqnum=96  \newdimen\sqmarge\sqmarge=\leftskip
\let\xe\relax % pas encore d'exercice

% nouvel exercice
\def\ex{\catcode13=12\relax\ex@}     % accepte ^M comme delimiteur

{\catcode13=12
\gdef\ex@#1^^M{%                     % #1 = titre eventuel
\catcode13=5                         % restaure le code de ^M
\global\advance\exnum by 1           % avance le no d'exercice
\EX{\the\exnum}{#1}}}                % annonce l'exercice

\def\EX#1#2{%
\xe                                  % termine l'exercice precedent
\medskip                             % petit espace vertical
\global\exnum=#1%                    % note le numero d'exercice
\global\qqnum=0                      % init le no de question
\global\sqnum=96                     % init le no de sous-question
\begingroup                          % isole l'exercice dans un groupe
\parindent=0pt                       % pas d'indentation
\let\xe\xe@\let\qq\qq@\let\QQ\QQ@    % active les macros \xe, \qq et \QQ
\let\qqsq\qqsq@\let\QQSQ\QQSQ@       % active \qqsq et \QQSQ
\let\reponse\reponse@                % active les reponses
\advance\leftskip by \numindent      % decale la marge
\qqmarge=\leftskip                   % mesure la marge des questions
\hskip-\numindent                    % ecrit dans la marge
{\bf Exercice #1. \sl#2}\par}

% fin d'exercice
\def\xe@{
\vskip 0pt                           % termine le paragraphe
\endgroup                            % referme le groupe de l'exercice
\filbreak}                           % espace vertical

% nouvelle question
\def\qq@{%
\global\advance\qqnum by 1           % avance le no de question
\QQ@{\the\qqnum}}                    % annonce la question

\def\QQ@#1{%
\vskip 0pt                           % changer de ligne
\leftskip=\qqmarge                   % remet la marge en place
\global\qqnum=#1%                    % note le numero de question
\global\sqnum=96                     % init le no de sous-question
\advance\leftskip by \numindent      % decale la marge
\sqmarge=\leftskip                   % mesure la marge des sous-questions
\hskip-\numindent                    % ecrit dans la marge
\hbox to\numindent{\hss\bf#1) }%     % numero de question
\let\sq\sq@\let\SQ\SQ@               % active les macros \sq et \SQ@
\ignorespaces
}

% nouvelle sous-question
\def \sq@{%
\global\advance\sqnum by 1           % avance le no de sous-question
\SQ@{\the\sqnum}}                    % annonce la sous-question

\def\SQ@#1{%
\vskip0pt                            % changer de ligne
\leftskip=\sqmarge                   % remet la marge en place
\global\sqnum=#1%                    % note le numero de sous-question
\advance\leftskip by \numindent      % decale la marge
\hskip-\numindent                    % ecrit dans la marge
\hbox to\numindent{\hss\bf\char#1) }%% numero de sous-question
\ignorespaces
}

% question et sous-question
\def\qqsq@{%
\global\advance\qqnum by 1           % avance le no de question
\global\sqnum=97                     % init le no de sous-question
\QQSQ@{\the\qqnum}{\the\sqnum}}

\def\QQSQ@#1#2{%
\vskip 0pt                           % changer de ligne
\leftskip=\qqmarge                   % remet la marge en place
\global\qqnum=#1%                    % note le numero de question
\global\sqnum=#2%                    % note le no de sous-question
\advance\leftskip by \numindent      % decale la marge
\sqmarge=\leftskip                   % mesure la marge des sous-questions
\advance\leftskip by \numindent      % decale la marge
\hskip-2\numindent                   % ecrit dans la marge
\hbox to\numindent{\hss\bf#1) }%     % numero de question
\hbox to\numindent{\hss\bf\char#2) }%% numero de sous-question
\let\sq\sq@\let\SQ\SQ@               % active les macros \sq et \SQ@
\ignorespaces
}

%--------------------------------------------------
% references en arriere
%--------------------------------------------------

% enregistre un label
\def\label#1{%
\expandafter\ifx\csname ex#1\endcsname\relax
  \expandafter\xdef\csname ex#1\endcsname{\the\exnum}%
  \expandafter\xdef\csname qq#1\endcsname{\the\qqnum}%
  \expandafter\xdef\csname sq#1\endcsname{\char\the\sqnum}%
\else
  \errmessage{label #1 deja defini
    (\csname ex#1\endcsname
    -\csname qq#1\endcsname
    -\csname sq#1\endcsname)}
\fi
\ignorespaces}

% ressort une reference
\def\ref#1{{%
\bf
\expandafter\ifx\csname ex#1\endcsname\relax
   #1 \errmessage{label #1 non defini}
\else
   \expandafter\let\expandafter\exref\csname ex#1\endcsname
   \expandafter\let\expandafter\qqref\csname qq#1\endcsname
   \expandafter\let\expandafter\sqref\csname sq#1\endcsname
   \edef\excur{\number\exnum}%
   \edef\qqcur{\number\qqnum}%
   \edef\sqcur{\char\the\sqnum}%
   \let\t=\relax
   \let\p=\relax
   \ifx\excur\exref\else\exref\def\qqcur{0}\def\sqcur{\char 96}\let\t=-\fi
   \ifx\qqcur\qqref\else\t\qqref\def\sqcur{\char 96}\let\p=)\fi
   \ifx\sqcur\sqref\else\sqref\let\p=)\fi
   \p
\fi}}

%--------------------------------------------------
% Gestion des reponses
%--------------------------------------------------

\newwrite\@answer
\newlinechar=13                 % ^M = nouvelle ligne

% premiere ecriture dans le fichier answer
\def\answerwrite{%
  \immediate\openout\@answer=\jobname.ans
  \immediate\write\@answer{%
    \noexpand\centerline{\noexpand\bf solutions}\noexpand\bigskip}
  \global\let\exobye@\exobye@answers
  \global\let\answerwrite\answerwrite@
  \answerwrite@
}

% ecritures suivantes
\def\answerwrite@{%
 \begingroup\desactive                    % desactive les caracteres speciaux
 \catcode`\{=1                            % sauf { et }
 \catcode`\}=2
 \answerwrite@@}

\def\answerwrite@@#1{%
  \immediate\write\@answer{#1}%           % ecrit la  reponse
  \endgroup\relax}                        % restaure les caracteres speciaux

% references de la derniere reponse
\newcount\exnum@\exnum@=0
\newcount\qqnum@\qqnum@=0 
\newcount\sqnum@\sqnum@=96

\def\reponse@{%
\ifnum\exnum=\exnum@\else
  \answerwrite{\noexpand\EX{\the\exnum}{}}\global\qqnum@=0\global\sqnum@=96 \fi
\ifnum\qqnum=\qqnum@
  \ifnum\sqnum=\sqnum@\else\answerwrite{\noexpand\SQ{\the\sqnum}}\fi
\else
  \ifnum\sqnum=96
    \answerwrite{\noexpand\QQ{\the\qqnum}}\else
    \answerwrite{\noexpand\QQSQ{\the\qqnum}{\the\sqnum}}\fi
\fi
\global\exnum@=\exnum
\global\qqnum@=\qqnum
\global\sqnum@=\sqnum
\answerwrite}

%--------------------------------------------------
% intercepte la fin du fichier
%--------------------------------------------------

\def\exobye@{\xe\exobye@old}                    % \bye sans reponses
\def\exobye@answers{%                           % \bye avec reponses
 \xe                                            % referme le dernier exercice
 \vfill\supereject                              % sort la derniere page
 \immediate\closeout\@answer                    % referme le fichier
 \let\answerwrite\undefined                     % desactive les reponses
 \input\jobname.ans                             % compose les reponses
 \xe\exobye@old
}
\let\exobye@old\bye                             % sauve l'ancien \bye
\outer\def\bye{\exobye@}                        % nouveau \bye

%--------------------------------------------------
% termine
\catcode64=\active
