%+----------------------------------------------------------------------------+
%|                                                                            |
%|        Listing de fichiers en mode verbatim avec réduction A4-> A5         |
%|                                                                            |
%|                                                      M.Quercia le 04/10/95 |
%+----------------------------------------------------------------------------+

%------------------------------------------------------------------------------
%                     Accumulation des pages 2 par 2 sur une même page physique

\newbox\gauche              % la demi-page gauche
\newbox\droite              % sa voisine
\newcount\numpage           % numéro de demi-page
\numpage=1

\def\makepage#1{%           % constitue une demi-page -> \box#1
  \global\setbox#1=\vbox{   % assemblage vertical
     \makeheadline          % titre supérieur (vide ici)
     \pagebody              % la demi-page
     \kern1mm\hrule\kern1mm % tire un trait
     \makefootline          % titre inférieur (numéro de demi-page ici)
}}

\def\reducoutput{%          % nouvelle routine de sortie
 \ifodd\numpage             % page impaire ?
   \makepage\gauche         % elle va à gauche
 \else
   \makepage\droite         % sinon à droite
   \shipout\hbox{\box\gauche\kern1true cm\box\droite}% et expédie le tout
   \advancepageno           % mise à jour numéro de page physique
 \fi
 \global\advance\numpage 1  % mise à jour numéro de demi-page
}

\def\normaloutput{%         % sortie sans réduction
 \makepage\gauche           % assemble la page
 \shipout\box\gauche        % l'expédie
 \advancepageno             % mise à jour numéro de page physique
 \global\advance\numpage 1  % mise à jour numéro de page logique
}

%-----------------------------------------------------------------------------
%                               dimensions fonction d'une réduction éventuelle

\hsize = 18 cm              % dimensions d'une page
\vsize = 25 cm
\hoffset = -1.04 cm         % pour DVIWINDO
\voffset = -0.21 cm
\output = {\normaloutput}

\font\typewriter=cmtt10
\font\slanted=cmsltt10
\let\normalfont=\typewriter

\def\reduction{%
 \magnification 707         % ceci assure la réduction
 \hsize   = 12.73 true cm   % redéfinit les dimensions
 \vsize   = 17.68 true cm
 \hoffset =-0.92  true cm
 \voffset =-1.04  true cm
 \output  = {\reducoutput}% % nouvelle routine de sortie
 \font\typewriter=cmtt10 scaled 1200 % police agrandie pour compenser la réduction
 \font\slanted=cmsltt10 scaled 1200
 \let\normalfont=\typewriter
 \special{landscape}
}

%------------------------------------------------------------------------------
%                                   Code indépendant d'une réduction éventuelle

\newdimen\coldim            % \coldim = taille d'un caractère
\newdimen\tabdim            % \tabdim = taille de 8 caractères
\newbox\ligne               % contiendra une ligne en cours de composition

\def\initdims{%
 \normalfont                 % fonte machine à écrire
 \setbox0=\hbox{0}%          % mesure un caractère
 \coldim=\wd0
 \tabdim=8\wd0
 \raggedbottom               % évite les Underfull vboxes
 \parindent=0pt%             % pas d'indentation
}

%------------------------------------------------------------------------------
%                                                      Gestion des tabulations

\catcode9=\active                   % accepte ^^I dans la définition qui suit
\def^^I{%
 \egroup                            % termine la ligne
 \dimen0=\wd\ligne                  % étend au prochain multiple de 8 colonnes
 \divide   \dimen0 by \tabdim
 \multiply \dimen0 by \tabdim
 \advance  \dimen0 by \tabdim
 \wd\ligne=\dimen0
 \setbox\ligne=\hbox\bgroup\normalfont\box\ligne   % continue la ligne
}

%------------------------------------------------------------------------------
%                                                    Gestion des fins de ligne

\catcode13=\active%           % accepte ^^M dans la définition qui suit
\def^^M{%
 \endofline                   % macro pour fermer les commentaires TeX
 \egroup                      % termine la ligne
 \wd\ligne=\hsize             % falsifie la dimension pour éviter les Overfull
 \box\ligne                   % sort la ligne
 \setbox\ligne=\hbox\bgroup\normalfont   % commence une nouvelle ligne
}%
\catcode13=5 %                % redonne (provisoirement) sa fonction à ^^M
                              % l'espace après le 5 est volontaire

%------------------------------------------------------------------------------
%                                                         Gestion des FormFeed

\catcode12=\active    % accepte ^^L dans la définition qui suit
\def^^L#1{%
 \endofline                         % macro pour fermer les commentaires TeX
 \egroup                            % termine la ligne
 \ifdim\wd\ligne>0pt                % non vide ?
   \wd\ligne=\hsize\box\ligne       % imprime ce qui précède
 \fi
 \vfil\eject                        % change de page
 \ifx#1^^M                          % caractère suivant = retour charriot ?
      \let\next=\relax              % alors l'ignore
 \else\let\next=#1%                 % sinon  le conserve
 \fi
 \setbox\ligne=\hbox\bgroup\normalfont\next    % commence une nouvelle ligne
}

\let\endofline=\relax

%-----------------------------------------------------------------------------
%                                                          Gestion des espaces

\catcode32=\active% % accepte <espace> dans la définition qui suit
\def {\hskip\coldim\relax}%
\catcode32=10\relax      % remet provisoirement l'espace normal

%-----------------------------------------------------------------------------
%                                                     Gestion des commentaires
\newcount\comment\comment=0

\def\recslant{%              % ouverture d'un commentaire imbriquable
 \global\advance\comment1
 \global\let\normalfont=\slanted
 \normalfont}

\def\slant{%                 % ouverture d'un commentaire non imbriquable
 \ifnum\comment=0\recslant\fi}

\def\unslant{%               % fermeture d'un commentaire
 \ifnum\comment>0
   \global\advance\comment-1
   \ifnum\comment=0
     \global\let\normalfont=\typewriter
     \normalfont
 \fi\fi}

%-----------------------------------------------------------------------------
%                                                            Commentaires C
{\catcode`/=\active\catcode`*=\active

\gdef\cpar{\futurelet\next\ctestetoile}%
\gdef\ctestetoile{\ifx*\next\recslant\fi\char47 }%

\gdef\cetoile{\char42\futurelet\next\ctestepar}%
\gdef\ctestepar{\ifx/\next\def\next##1{##1\unslant}\else\let\next=\relax\fi\next}%

\gdef\creactive{%
  \catcode`/=\active\let/=\cpar
  \catcode`*=\active\let*=\cetoile}

\gdef\c{\let\reactive=\creactive}
}

%-----------------------------------------------------------------------------
%                                                            Commentaires Caml
{\catcode`(=\active\catcode`*=\active

\gdef\camlpar{\futurelet\next\camltestetoile}%
\gdef\camltestetoile{\ifx*\next\recslant\fi\char40 }%

\gdef\camletoile{\char42\futurelet\next\camltestepar}%
\gdef\camltestepar{\if)\next\def\next##1{##1\unslant}\else\let\next=\relax\fi\next}%

\gdef\camlreactive{%
  \catcode`(=\active\let(=\camlpar
  \catcode`*=\active\let*=\camletoile}

\gdef\caml{\let\reactive=\camlreactive}
}

%-----------------------------------------------------------------------------
%                                                            Commentaires Lisp
{\catcode`;=\active

\gdef\lispptv{\slant\char59 }
\gdef\lispreactive{\catcode`;=\active\let;=\lispptv\let\endofline=\unslant}
\gdef\lisp{\let\reactive=\lispreactive}
}

%-----------------------------------------------------------------------------
%                                                           Commentaires Pascal
\bgroup
\catcode`(=\active\catcode`*=\active
\catcode`\{=\active\catcode`\}=\active
\catcode`<=1\catcode`>=2

\gdef\pascalpar<\futurelet\next\pascaltestetoile>%
\gdef\pascaltestetoile<\ifx*\next\slant\fi\char40 >%

\gdef\pascaletoile<\char42\futurelet\next\pascaltestepar>%
\gdef\pascaltestepar<\if)\next\def\next##1<##1\unslant>\else\let\next=\relax\fi\next>%

\gdef\pascalreactive<%
  \catcode`(=\active\let(=\pascalpar
  \catcode`*=\active\let*=\pascaletoile
  \catcode`\{=\active\def{<\slant\char123 >%
  \catcode`\}=\active\def}<\char125\unslant>%
>

\gdef\pascal<\let\reactive=\pascalreactive>
\egroup

%-----------------------------------------------------------------------------
%                                                            Commentaires shell
{\catcode`#=\active

\gdef\shellnum{\slant\char35 }
\gdef\shellreactive{\catcode`#=\active\let#=\shellnum\let\endofline=\unslant}
\gdef\shell{\let\reactive=\shellreactive}
}

%-----------------------------------------------------------------------------
%                                                            Commentaires TeX
{\catcode`\%=\active

\gdef\texpourcent{\slant\char37 }
\gdef\texreactive{\catcode`\%=\active\let%=\texpourcent\let\endofline=\unslant}
\gdef\tex{\let\reactive=\texreactive}
}

%-----------------------------------------------------------------------------
%                                           Désactive les caractères spéciaux

\def\desactive{%
 \catcode 92=12       % \
 \catcode123=12       % {
 \catcode125=12       % }
 \catcode 36=12       % $
 \catcode 38=12       % &
 \catcode 95=12       % _
 \catcode 35=12       % #
 \catcode 37=12       % %
 \catcode126=12       % ~
 \catcode 64=12       % @
 \catcode 39=12       % '
 \catcode 96=12       % `
 \catcode 94=12       % ^
 \catcode 34=12       % "
 \catcode 32=\active  % espace
 \catcode 13=\active  % ^^M
}
\let\reactive=\relax

%-----------------------------------------------------------------------------
%                                                          La macro principale

\def\listing{\desactive\catcode123=1 \catcode125=2 \suitelisting}
\def\suitelisting#1{%
  \initdims
  \desactive\reactive
  \footline={%                         % titre de bas de page
    \typewriter                        % texte droit
    \hfil #1                           % le nom du fichier
    \ifnum\numpage=1                   % en première demi-page,
      \the\day/\the\month/\the\year    % la date d'impression
    \else                              % sur les suivantes,
      page \the\numpage                % le numéro de demi-page
    \fi                                %
    \ifodd\numpage\hfill\fi}%          % cadre à gauche les dp impaires
 \setbox\ligne=\hbox\bgroup\normalfont\input#1 \egroup  % attention à l'espace après #1
  \ifdim\wd\ligne>0pt                  % dernière ligne non vide ?
     \wd\ligne=\hsize\box\ligne        % l'imprime
  \fi
  \vfil\eject                          % sort la dernière demi-page
  \def\makefootline{}%                 % plus de bas de page
  \def\hrule{}%                        % pour la demi-page de complément
  \csname bye\endcsname                % contourne le \outer de \bye
}
