%--------------------------------------------------
% pb.tex
% macros pour sujets de problemes
% M. Quercia, 19/04/2013
%--------------------------------------------------

\input montchapet-7bits

% autorise @ dans les noms
\catcode64=11

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

\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
%--------------------------------------------------

% \pnum      = numero de la partie en cours
% \pnumtxt   = titre de la partie 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

\def\pnum{}\def\pnumtxt{} \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 de partie

\def\razqq{\global\qqnum=0}

% nouvelle partie
\def\partie{\catcode13=12\relax\partie@} % accepte ^M comme delimiteur

{\catcode13=12
\gdef\partie@#1#2^^M{%               % #1 = numero, #2 = titre eventuel
\catcode13=5                         % restaure le code de ^M
\xe                                  % termine la partie precedente
\bigskip                             % petit espace vertical
\xdef\pnum{#1}%                      % note le no de partie
\xdef\pnumtxt{#2}%                   % note le titre de partie
\razqq                               % init le no de question
\global\sqnum=96                     % init le no de sous-question
\begingroup                          % isole la partie 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
\leftskip=0pt                        % initialise la marge
\qqmarge=\leftskip                   % mesure la marge des questions
\centerline{\bf #2}\medskip}}

% fin de partie
\def\xe@{
\vskip 0pt                           % termine le paragraphe
\endgroup                            % referme le groupe de la partie
\vskip3cm\goodbreak\vskip-3cm}       % change de page s'il reste moins de 3cm

% 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 p#1\endcsname\relax
  \expandafter\xdef\csname p#1\endcsname{\pnum}%
  \expandafter\xdef\csname qq#1\endcsname{\the\qqnum}%
  \expandafter\xdef\csname sq#1\endcsname{\char\the\sqnum}%
\else
  \errmessage{label #1 deja defini
    (\csname p#1\endcsname
    -\csname qq#1\endcsname
    -\csname sq#1\endcsname)}
\fi
\ignorespaces}

% ressort une reference
\def\ref#1{{%
\bf
\expandafter\ifx\csname p#1\endcsname\relax
   #1 \errmessage{label #1 non defini}
\else
   \expandafter\let\expandafter\pref\csname p#1\endcsname
   \expandafter\let\expandafter\qqref\csname qq#1\endcsname
   \expandafter\let\expandafter\sqref\csname sq#1\endcsname
   \edef\pcur{\pnum}%
   \edef\qqcur{\number\qqnum}%
   \edef\sqcur{\char\the\sqnum}%
   \let\t=\relax
   \let\p=\relax
   \ifx\pcur\pref\else\pref\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 Corrig\'e}\noexpand\bigskip}
  \global\let\pbbye@\pbbye@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
\def\pnum@{}
\newcount\qqnum@\qqnum@=0 
\newcount\sqnum@\sqnum@=96

\def\reponse@{%
\ifx\pnum\pnum@\else
  \answerwrite{\noexpand\partie{\pnum}{\pnumtxt}}\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\let\pnum@=\pnum
\global\qqnum@=\qqnum
\global\sqnum@=\sqnum
\answerwrite}

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

\def\pbbye@{\xe\pbbye@old}                      % \bye sans reponses
\def\pbbye@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\pbbye@old
}
\let\pbbye@old\bye                              % sauve l'ancien \bye
\outer\def\bye{\pbbye@}                         % nouveau \bye

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