Retour

Source de listing.tex

Fichier TeX
%% fichier 'listing.tex'
% cinquième etape de construction de la macro "listing"~:
% la routine de sortie est modifiee (09/09/96), on reecrit totalement
% le \input, on stocke dans des \vbox, et on donne le choix du
% type de listing pour les coupures de page.
% En plus, on reorganise tout ca, de facon a permettre une
% macro \partiallisting.


\catcode`\@ = 11

% ===== numerotation des lignes
\newif \ifwithlinen@    % avec numerotation des lignes~?
\withlinen@true         % oui par defaut

\def \withlineno{%      % selection de l'option de numerotation
   \withlinen@true}     % par des macros "visibles"
\def \withoutlineno{%
   \withlinen@false}

\def \n@mline{%         % affichage du no de ligne
   \indent
   \llap{\sevenrm \the\lineno~: \hskip .5em}}

\newcount \lineno       % no de la ligne courante
\newcount \listingno    % no de version de la macro (0 = coupure n'importe ou,
                        %                            1 = coupure sur ligne vide)
\newcount \beginlineno  % no de la premiere ligne a afficher
\newcount \endlineno    % no de la derniere ligne a afficher

\def \listingpath{%     % le chemin d'acces, vide par defaut
  }

% ===== affectation des caracteres actifs
{\obeylines \global \def \temoin{^^M}}
% la ligne suivante pose probleme : elle rajoute un caractere dans le
% .dvi (?). A noter que c'est pourtant la solution proposee dans le
% Lachand-Robert... 
%%{\obeyspaces\global\let =\ }% 
% solution de Knuth : voir le fichier info.tex, ligne 41
% ===== la boite pour encadrer le listing ligne par ligne
\newbox \encadrbox
\def \initencadrbox{%
   \setbox \encadrbox =\hbox to \hsize{%
      \vrule height 9pt depth 3pt
      \hfil
      \vrule height 9pt depth 3pt}
   \ht \encadrbox = 0pt
   \dp \encadrbox = 0pt
   \wd \encadrbox = 0pt}

\newbox \box@  % le titre du listing
\newtoks \listingtoks
\newread \currentfile

% ===== passe en mode verbatim
\def \verb@tim{%
   \def \do##1{%                    % on prepare le verbatim
      \catcode`##1=12 }%
   \def°{%                          % pas tres propre ca, il s'agit
      \char23}                      % d'un truc provisoire pour le "degre"
   \dospecials
   \obeyspaces
   \def \par{%
      \leavevmode
      \endgraf}%
   \obeylines
   \eightpoint \tt}                  % style de fonte

\def \writelistingline#1{%           % #1 contient la ligne a traiter
   \ifnum \lineno < \beginlineno     % qu'on affiche seulement si
   \else                             % le no de ligne courante 
      \ifnum \lineno > \endlineno    % est dans l'intervalle convenable
      \else
         #1
      \fi
   \fi}

% ===== traitement d'une ligne du fichier
\def \traite@ne{%
   \ifx \temoin \next             % si le 1er caractere est RET
      \writelistingline{\next}    % c'est que la ligne est vide => on l'affiche
      \ifeof \currentfile         % si le fichier n'est pas fini
      \else                       % alors on sauvegarde le no de ligne
         \global \edef \rest@renum{\lineno \the \lineno} 
         \vss
         \egroup                  % puis on ferme la boite
         \mark{\the \listingtoks}
         \immediate \wlog{*************** \the \listingtoks ******** }
         \vbox\bgroup             % on en ouvre une nouvelle
         \rest@renum              % et on restaure le no de ligne              
         \verb@tim
      \fi
   \else                          % la ligne n'est pas vide
      \writelistingline{\next}    % et on l'affiche telle que
   \fi}

% ===== lecture d'une ligne du fichier
\def \read@ne{%                   % lit la ligne suivante et la
   \read \currentfile to \next    % stocke dans \next
   \global \advance \lineno by 1
   \ifnum \listingno = 1          % suivant le no de version
      \traite@ne                  % on fait un traitement adequat
   \else
      \writelistingline{\next}    % ou on affiche tel que
   \fi
   \ifeof \currentfile            % si c'est fini,
      \closein \currentfile       % on ferme le fichier
      \let \next \relax           % et on arrete,
   \else                          % sinon
      \let \next \read@ne         % on recommence
   \fi
   \next}

\def \listing#1#2#3{%    #1 = version number #2 = file name, #3 = title
   \partiallisting{#1}{#2}{#3}{0}{10000}}  % rque~: 10 000 en attendant mieux . . .

\def \partiallisting#1#2#3#4#5{%    #1 = version number #2 = file name, #3 = title
   \bigbreak                   %    #4 = no de la 1ere ligne, #5 = no de la derniere ligne
   \vskip 2\baselineskip
   \penalty -200
   \vskip -2\baselineskip
   \listingno = #1
   \beginlineno = #4
   \endlineno = #5
   \immediate \wlog{Beginning listing of \listingpath #2}
   \initencadrbox
   \begingroup                         % DEBUT
      \offinterlineskip
      \listingtoks = {\tensl #3}
      \everypar = {%
         \hskip -\parindent
         \copy \encadrbox
         \strut
         \ifwithlinen@
            \n@mline
         \else
            \indent
         \fi}
      \parskip = 0pt
      \lineno = 0
      \ifwithlinen@
         \parindent = 30pt   
      \else
         \parindent = 20pt   
      \fi
      \mark{\the\listingtoks}  
      \ifnum \listingno = 1              % si version 1, on met dans des \vbox
         \vbox
      \fi
      \bgroup                            % debut du groupe listing
         \setbox\box@ = \hbox{\tensl #3} % recupere le titre pour en calculer la profondeur
         \line{%                                 % la 1ere ligne du cadre
            \vrule height 0.4pt depth \dp\box@
            \hrulefill
            \quad \the \listingtoks \quad
            \hrulefill
            \vrule height 0.4pt depth \dp\box@}
         \hbox to \hsize{%                        % la ligne vide qui suit
            \vrule height 9pt depth 3pt
            \hfil
            \vrule height 9pt depth 3pt}
         \verb@tim
         \openin \currentfile = \listingpath #2  % ici on change le \input
         \read@ne                                % et c'est \read@ne qui va lire le fichier
         \endgraf
         \nobreak
         \hbox to \hsize{%                 % la ligne vide finale
            \vrule height 9pt depth 0pt
            \hfil 
            \vrule height 9pt depth 0pt}
         \hrule                            % la \hrule de fin de listing
      \egroup                              % fin du groupe listing
   \endgroup                         % FIN
   \mark{}                           % on restaure la marque
   \immediate \wlog{End listing of #2}
   \bigbreak}%

% puis on modifie la routine de sortie
\output = {%
   \expandafter \listingchek \botmark \end} % c'est une astuce pour lire
                                            % la \botmark en argument
\def \listingchek#1\end{%
   \def \next{#1} %                         % #1 contient la \botmark
   \ifx \next \empty %                      % vide => pas de coupure
   \else %                                  % sinon
      \setbox255 = \vbox to \vsize{%        % on rajoute la ligne
         \unvbox255                         % correspondante a la page
         \nointerlineskip                   % deja composee
         \line{\copy \encadrbox \hfil \strut}
         \nointerlineskip
         \hbox to \hsize{%
            \vsize = 0pt
            \dotfill}}
%      \advance \dimen0 by -\prevdepth %
%      \kern \dimen0 %
      \line{%
         \vrule height 0pt depth 2.5pt
         \dotfill \quad \sl \next            % et la ligne (suite) a la
         \hskip 1em (suite)\quad \dotfill    % page suivante
         \vrule height 0pt depth 2.5pt}   
      \line{\copy \encadrbox \strut \hfill}  % avec une ligne vide
   \fi
   \plainoutput}                             % final~: on appelle la routine
%                                            % habituelle
\catcode`\@ = 12

\endinput