Subversion Repositories wimsdev

Rev

Rev 17221 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #!/usr/bin/perl
  2.  
  3. use strict "vars";
  4. use strict "subs";
  5. use locale;
  6. use warnings;
  7. use Text::Balanced qw (extract_bracketed extract_tagged);
  8.  
  9. $/ = undef; # slurp
  10. #
  11. ###############################################################################
  12. #
  13. #    This file is part of latex2wims
  14. #
  15. #    latex2wims is free software; you can redistribute it and/or modify
  16. #    it under the terms of the GNU General Public License as published by
  17. #    the Free Software Foundation; either version 2 of the License, or
  18. #    (at your option) any later version.
  19. #
  20. #    latex2wims is distributed in the hope that it will be useful,
  21. #    but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23. #    GNU General Public License for more details.
  24. #
  25. #    You should have received a copy of the GNU General Public License
  26. #    along with latex2wims; if not, write to the Free Software
  27. #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  28. #
  29. ###############################################################################
  30. #
  31. my ($FILE, $MACRO, $EMBED, $NUMERO, $doc_DIR, $DIR, $author, $email, $worksheet, $SHEET,$ABOUT, $SUBDIR) ;
  32. my $verbose = 0;
  33. my $depth = 2 ;
  34. my $INDEX = 0 ;
  35. my $TOOLTIP = 0 ;
  36. my $STYLE = '' ;
  37. my $OPTION = '' ;
  38. my $tooltip_prompt = '<img src="gifs/picto.gif" alt="picto">' ;
  39. $tooltip_prompt='';
  40. my $linkout='' ;
  41. $worksheet= '';
  42. $SHEET = '' ;
  43. $DIR = '';
  44. $doc_DIR = '';
  45. $SUBDIR='1';
  46. $EMBED='.';
  47. my @SECTIONS = qw(document part chapter section subsection subsubsection);
  48. #my @SECTIONS = ( document part entete frame subsection subsubsection );
  49. #TODO biblio dans un fichier separe si on a rencontre \begin{thebibliography} Non,
  50. # on n'a qu'a mettre cet environnement de type link
  51. #$doc_DIR=$ENV{'w_docdir'};
  52. #$DIR=$ENV{'w_dir'};
  53. #$DIR =~ s/ +//;
  54. push (@ARGV,split(' ', $ENV{'wims_exec_parm'})) if ($ENV{'wims_exec_parm'}) ;
  55.  
  56. while ($_ = shift (@ARGV))
  57. {
  58.   last if (!/^--/);
  59.      if (/^--style=(.*)$/) { $STYLE   = $1; }
  60.   elsif (/^--macro=(.*)$/) { $MACRO   = $1; }
  61.   elsif (/^--docdir=(.*)$/){ $doc_DIR = $1; }
  62.   elsif (/^--dir=(.*)$/)   { $DIR     = $1; }
  63.   elsif (/^--subdir=(.*)$/){ $SUBDIR  = $1; }
  64.   elsif (/^--embed=(.*)$/) { $EMBED   = $1; }
  65.   elsif (/^--verbose$/)    { $verbose = 1; }
  66.   elsif (/^--author=(.*)$/){ $author  = $1; }
  67.   elsif (/^--email=(.*)$/) { $email   = $1; }
  68.   elsif (/^--worksheet=(.*)$/) { $worksheet = $1; }
  69.   elsif (/^--tooltip_prompt=(.*)$/) { $tooltip_prompt = $1; }
  70.   elsif (/^--linkout=(.*)$/) { $linkout = $1; }
  71.   elsif (/^--cut=(.*)$/) { @SECTIONS = split(',',$1) ;}
  72.   elsif (/^--help$/) {
  73.    usage(); # includes --help !
  74.     exit 1;
  75.   }
  76. } ;
  77.  
  78. $FILE = $_;
  79.  
  80. $DIR = $DIR . '/' if ($DIR) ;
  81. $doc_DIR = $doc_DIR . '/' if ($doc_DIR) ;
  82. my $BASE = $doc_DIR . "doc/$SUBDIR/src";
  83. my $BASE0= $doc_DIR . "doc/$SUBDIR";
  84. my $BASEtmp= $doc_DIR . "doc/$SUBDIR/.src";
  85. my $LOAD = '\reload{<img src="gifs/doc/etoile.gif" alt="rechargez" style="width:20px;height:20px;">}';
  86. my $FLECHE = '&#8594;';
  87. $linkout = "\\doc{module=$linkout}" . $FLECHE if ($linkout) ;
  88. my $fig_cnt=-1;
  89.  
  90. ##################################
  91. ##Initialisation
  92. #si je rajoute les listes : type=fold : signifierait que les item sont en fold [demande
  93. #d'avoir des titres, ca serait du type description en latex
  94. #pas de titre ? deb fin <ul ... >  </ul>
  95. #type =
  96. #hash contenant les caracteristiques des environnements latex, voir \environmentwims
  97. my %hash_environ = (
  98.   titre  => {},
  99.   style  => {},
  100.   type   => {},
  101.   deb    => {},
  102.   fin    => {},
  103.   parm   => {},
  104.   origin => {},
  105.   list   => {},
  106.   tabular => {},
  107. );
  108.  
  109. #hash contenant les commandes venant de \defwims, \def & co ou par defaut
  110. my %hash_command = (
  111.   cnt_arg    => {},
  112.   definition => {},
  113.   origin     => {},
  114. );
  115. my @liste_env_list = ('itemize', 'description', 'enumerate', 'trivlist') ;
  116.   $hash_environ{type}{'description_item'} = 'fold' ;
  117.   $hash_environ{titre}{'description_item'} = ' ' ;
  118.  
  119. my @liste_env_tabular = ('tabular') ;
  120.  
  121. my @liste_env_spec = ('equation', 'multline', 'latexonly',
  122.   'pmatrix','smallmatrix', 'eqnarray', 'array', 'algorithmic', 'algorithm', 'align',
  123.   'thebibliography', 'pspicture', 'picture', 'cases', 'gather',
  124.   'displaymath', 'math', 'center', 'minipage', 'lstlisting', 'columns', 'column', 'figure',
  125.   'tikzpicture');
  126.  
  127. my @liste_com_spec = ('paragraph', 'href', 'url', 'exercise', 'doc') ; #je ne m'en sers pas encore
  128.  
  129. #commandes par defaut : sont ecrases par un \def ou un \defwims
  130.  
  131. #$hash_command{cnt_arg}{text} = 1 ;
  132. #$hash_command{definition}{text} = '\) #1 \(' ;
  133. #$hash_command{origin}{text} = 'defaut' ;
  134.  
  135. $hash_command{cnt_arg}{paragraph} = 1 ;
  136. $hash_command{definition}{paragraph} = '<p class="paragraph"> #1 </p>' ;
  137. $hash_command{origin}{paragraph} = 'defaut' ;
  138.  
  139. $hash_command{cnt_arg}{href} = 2 ;
  140. $hash_command{definition}{href} = '<a href="http:#1" target="wims_external">#2</a>';
  141. $hash_command{origin}{href} = 'defaut' ;
  142.  
  143. $hash_command{cnt_arg}{url} = 1 ;
  144. $hash_command{definition}{url} = '<a href="http:#1" target="wims_external">#1</a>';
  145. $hash_command{origin}{url} = 'defaut' ;
  146.  
  147. $hash_command{cnt_arg}{exercise} = 2 ;
  148. $hash_command{definition}{exercise} = "\\exercise\{\#1\}\{\#2\}";
  149. $hash_command{origin}{exercise} = 'defwims' ;
  150.  
  151. $hash_command{cnt_arg}{doc} = 2 ;
  152. $hash_command{definition}{doc} = '\doc{#1&cmd=new}{#2}';
  153. $hash_command{origin}{doc} = 'defwims' ;
  154.  
  155. #a un label est associe son bloc [nom de fichier]
  156. my %hash_bloc = (
  157.   fichier  => {},
  158.   titre    => {},
  159. );
  160.  
  161. my %hash_index = (
  162.   page    => {},
  163. );
  164.  
  165. #type sert a reperer les fichiers embed ou fold.
  166. my %hash = (
  167.   text   => {},
  168.   prev   => {},
  169.   next   => {},
  170.   upbl   => {},
  171.   titb   => {},
  172.   tittoc => {},
  173.   keyw   => {},
  174.   datm   => {},
  175.   label  => {},
  176.   toc    => {},
  177.   chemin => {},
  178.   niveau => {},
  179.   type   => {},
  180.   author => {},
  181.   title => {},
  182.   email => {},
  183.   toctip => {},
  184.   tikzsetfigurename=>{},
  185. );
  186.  
  187. my %hash_toc = ();
  188.  
  189. my %prefixe = ( fold => 'F_' , link => 'L_' );
  190.  
  191. my %hash_secinv;
  192. for (my $i = 0; $i <= $#SECTIONS; $i++) { $hash_secinv{$SECTIONS[$i]} = $i; }
  193.  
  194. my (%errmsg); # empeche le re-affichage d'un meme warning.
  195. $SIG{__WARN__} = sub { my ($x) = @_;
  196.   return if $errmsg{$x};
  197.   $errmsg{$x} = 1;
  198.   print STDERR "### $x";
  199. };
  200. system("mkdir -p $BASE0;mkdir -p $BASE;
  201.  mkdir -p $BASEtmp; mv $BASE/* $BASEtmp/") if (!$ENV{'wims_exec_parm'});
  202. $hash{niveau}{'main'} = 0;
  203. #pour algorithmic
  204. #TODO recuperer les informations dans le fichier de l'utilisateur
  205.  
  206. my %hash_algo = (
  207.   titre => {},
  208.   apres => {},
  209.   avant => {},
  210.   suite => {}
  211. ) ;
  212. my $algo_noend = 0 ;
  213. my $voca = %{$hash_algo{titre}} ;
  214. my @liste_voca = ('FOR', 'IF','WHILE','REPEAT','ELSE','ELSIF','ENDIF','DO',
  215.  'ENDWHILE', 'REQUIRE','ENSURE','ENDFOR','STATE','UNTIL','THEN', 'RETURN');
  216.  
  217. $hash_command{definition}{algorithmicrequire}='<b>Require</b>';
  218. $hash_command{origin}{algorithmicrequire}='defaut';
  219. $hash_command{cnt_arg}{algorithmicrequire}= 0 ;
  220. $hash_command{definition}{algorithmicensure}='<b>Ensure</b>';
  221. $hash_command{definition}{algorithmicend}='<b>end</b>';
  222. $hash_command{definition}{algorithmicif}='<b>if</b>';
  223. $hash_command{definition}{algorithmicthen}='<b>then</b>';
  224. $hash_command{definition}{algorithmicelse}='<b>else</b>';
  225. $hash_command{definition}{algorithmicelsif}="<b>$hash_command{definition}{algorithmicelse} $hash_command{definition}{algorithmicif}</b>";
  226. $hash_command{definition}{algorithmicendif}="<b>$hash_command{definition}{algorithmicend} $hash_command{definition}{algorithmicif}</b>";
  227. $hash_command{definition}{algorithmicfor}='<b>for</b>';
  228. $hash_command{definition}{algorithmicforall}='<b>for all</b>';
  229. $hash_command{definition}{algorithmicdo}='<b>do</b>';
  230. $hash_command{definition}{algorithmicendfor}="<b>$hash_command{definition}{algorithmicend} $hash_command{definition}{algorithmicfor}</b>";
  231. $hash_command{definition}{algorithmicwhile}='<b>while</b>';
  232. $hash_command{definition}{algorithmicendwhile}="<b>$hash_command{definition}{algorithmicend} $hash_command{definition}{algorithmicwhile}</b>";
  233. $hash_command{definition}{algorithmicloop}='<b>loop</b>';
  234. $hash_command{definition}{algorithmicendloop}="<b>$hash_command{definition}{algorithmicend} $hash_command{definition}{algorithmicloop}</b";
  235. $hash_command{definition}{algorithmicrepeat}='<b>repeat</b>';
  236. $hash_command{definition}{algorithmicuntil}='<b>until</b>';
  237. $hash_command{definition}{algorithmicprint}='<b>print</b>';
  238. $hash_command{definition}{algorithmicreturn}='<b>return</b>';
  239.  
  240. for my $cmd (@liste_voca) { $hash_command{origin}{"algorithmic\L$cmd\E"} = 'defaut' }
  241.  
  242. for my $cmd ('FOR','IF','WHILE','REPEAT','ELSE','ELSIF') {
  243.           $hash_algo{apres}{$cmd} = 1 ;
  244. } ;
  245. for my $cmd ('IF') { $hash_algo{suite}{$cmd} = 'THEN' ;} ;
  246. for my $cmd ('FOR','WHILE') { $hash_algo{suite}{$cmd} = 'DO' ;} ;
  247. for my $cmd ('ENDFOR','ENDIF', 'ENDWHILE','UNTIL','ELSE','ELSIF') {
  248.           $hash_algo{avant}{$cmd} = -1 ;
  249. } ;
  250. for my $cmd ('FOR','IF','WHILE','REQUIRE','ENSURE', 'STATE','UNTIL') {
  251.           $hash_algo{avant}{$cmd} = 0 ;
  252. } ;
  253. for my $cmd ('ENDFOR','ENDIF','ENDWHILE','REQUIRE','ENSURE', 'STATE','UNTIL') {
  254.           $hash_algo{apres}{$cmd} = 0 ;
  255. }
  256.  
  257. # lit les fichiers wims.sty puis les fichers .tex. pour eviter : un seul fichier tex, le premier ?
  258.  
  259. my $TEXT = Init($FILE, \%hash_environ, \%hash_command, \%hash, \%hash_algo);
  260. out1 ('sheet', $SHEET) ;
  261. $ABOUT = $hash{about}{main} ;
  262. out1 ('about.phtml', (($ABOUT)? $ABOUT :'') . '
  263. <p>
  264. Ce document a été créé par Latex2wims.</p>
  265.  
  266. !changeto docu/about.phtml') ;
  267. if (!($hash{author}{main})) {
  268.   warn " ATTENTION : Vous devez mettre un nom d'auteur \\author{xxx}" ;
  269.   $hash{author}{main}=$author } ;
  270. if (!($hash{title}{main})) {
  271.   warn " ATTENTION : Vous devez mettre un titre : \\title{xx} " ;
  272.   $hash{title}{main} = '??' } ;
  273. if (!($hash{email}{main})) {
  274.   warn " ATTENTION : Vous devez mettre un email \\email{xxx}" ;
  275.   $hash{email}{main}=$email } ;
  276.  
  277. # PASSE 2: ferme les \section & co
  278. my $SEC_MIN_GLOBAL = 10; # = \infty
  279. #$SEC_MIN_GLOBAL = 3 ;
  280. my @cnt = (0) x ($#SECTIONS + 1);
  281. my ($secpattern) = join('|', @SECTIONS);
  282. $TEXT =~ s/\\begin\s*\{($secpattern)\s*\}/cnt_section($1,\@cnt)/eg;
  283. $TEXT =~ s/\[fragile\]//g;
  284. $TEXT =~ s/\\end\s*\{\s*($secpattern)\s*\}/<\/$1>/g;
  285. $TEXT =~ s/\\wimsentre\{($secpattern)\}/\\wimsentre$1/g;
  286. $TEXT =~ s/\\(wimsentre)?($secpattern)\b\*?/open_close($2,\@cnt,$1)/eg;
  287. $TEXT =~ s|</document>.*||s;
  288. $TEXT =~ s|.*<document>||s;
  289. if($SEC_MIN_GLOBAL == 10) {$SEC_MIN_GLOBAL = 0} ;
  290. my ($NIVEAU, $NIVEAU_max) = ($SEC_MIN_GLOBAL, $SEC_MIN_GLOBAL + $depth - 1);
  291.  
  292. # PASSE 3: cree les blocs venant des sections et co
  293. #  et renvoie une partie de la table des matieres
  294. my $toc = analyse_texte ($TEXT, \%hash, 'main', $NIVEAU, $NIVEAU_max, '');
  295. # PASSE 4: creation de tous les blocs ( environnements de type fold ou link)
  296. {
  297.   my ($ref, $ref_env) = (\%hash, \%hash_environ);
  298.   my (@TODO);
  299.   while (my ($Id, $TEXT) = each (%{$hash{text}})) { push(@TODO, [$Id,$TEXT]); }
  300.   for (@TODO) {
  301.     my ($Id, $TEXT) = @{$_};
  302.     $TEXT = TraiteText ($TEXT, $ref, $ref_env, $Id);
  303.     $ref->{text}{$Id} = $TEXT;
  304.   }
  305. }
  306. #recuperation de tous les labels et rajout du titre en haut de la table dans la toc du tag
  307. #On les traite pour que le label soit associe au nom du fichier cree automatiquement.
  308. #$hash{toc}{$tag} contient les fichiers des sections en dessous de $tag
  309.  
  310. # PASSE 5
  311. for my $tag (keys %{$hash{text}}) {
  312.   my $T = $hash{text}{$tag};
  313.   $T =~ s/\\label\s*\{([^\}]+)\}/store_label($1, $tag, \%hash_bloc)/eg;
  314.   $T =~ s/\\index\s*\{([^\}]+)\}/store_index($1, $tag, \%hash_index)/eg;
  315.   $hash{text}{$tag} = $T;
  316.   my $tagupbl = $hash{upbl}{$tag};
  317.   #plus utilise, mais j'hesite !
  318. #  $hash_toc{$tag} = "\\link{$tagupbl}\n\n" . $hash{toc}{$tagupbl};
  319. }
  320.  
  321. # PASSE 6: sort l'index mis a jour des ref a l'aide des labels crees auparavant et rajoute
  322. #TODO rajouter eqref mais ca depend vraiment de la phrase !
  323. for my $tag (keys %{$hash{text}}) {
  324.   my $macro = '\\\\ref|\\\\cite|\\\\eqref';
  325.   my $T = $hash{text}{$tag};
  326.   my $cle = 'prev|next|upbl|titb|keyw|datm';
  327.   $T =~ s/($macro)\{([^\}]+)\}\{([^\}]+)\}/store_ref($2, $3, $2, \%hash_bloc)/eg;
  328. # repere toto~\cite{}
  329.   $T =~ s/([^\s]+)\~($macro)\s*([.*])?\s*\{([^\}]+)\}/store_ref($4, $1 .
  330.     ($3||''), $4, \%hash_bloc)/eg;
  331.   $T =~ s/($macro)\s*([.*])?\{([^\}]+)\}/store_ref($3, ($2 ? "$3: $2" : $3), $3, \%hash_bloc)/eg;
  332.   $T =~ s/\\($cle)\s*\{(\w*)\}/store_tag($1, $2, $tag, \%hash, \%hash_bloc)/eg;
  333.   $hash{text}{$tag} = $T;
  334. }
  335. my @ListIndex = sort {$a cmp $b} (keys %{$hash_index{page}}) ;
  336. out('index', selection('<div class="index">' . makeindex (\%hash_index, 0, @ListIndex) . '</div>'
  337.        ,'left-selection','index')) if ((@ListIndex) && $INDEX == 1 && makeindex (\%hash_index));
  338.  
  339. #cree les blocs [entoures de la table des matieres]
  340.  
  341. #cree les deux sortes de fichiers demandes par wims .def (fichier de definition general) +
  342. # nom.hd qui gere les regles de navigation pour chaque bloc
  343. #attention : dans le cas ou il y a un \\embed{toto}, il faut creer le fichier toto.hd ...
  344. #TODO : \embed{toto} : je suppose ici que le contenu de toto est du wims a ne pas
  345. #interpreter
  346. #pour l'instant je m'en suis servi pour stocker des programmes qui interviennent plusieurs fois.
  347.  
  348. #Cree le vrai fichier qui est mis dans le dossier src
  349. #On ne met pas de table de matieres si le bloc est de type fold
  350. #TODO option = chemin tout seul, toc a gauche + chemin, toc a gauche et a droite + chemin,
  351. #style selection droite, selection gauche
  352.  
  353. for my $tag (keys %{$hash{text}}) {
  354.   complete ($tag, \%hash);
  355.   out ("$tag.hd", hd($tag,\%hash));
  356.   my $txt = traitement_final($hash{text}{$tag});
  357.   my $tagupbl = $hash{upbl}{$tag};
  358.   my $type = $hash{type}{$tag};
  359.   my $style = $hash{style}{$tag};
  360.  #si type est non vide il est egal a embed ou fold
  361.  
  362.   my $dotoc_left = ($OPTION =~ /toc_left/ && !$type);
  363.   my $dotoc_right = ($OPTION =~ /toc_right/ && !$type);
  364.   my $dotoc_partial = ($OPTION =~ /toc_partial/ && !$type);
  365.   my $dotoc_up = ($OPTION =~ /toc_up/ && !$type);
  366.   my $dotoc_down = ($OPTION =~ /toc_down/ && !$type);
  367.   my $CHEMIN = chemin($tag, \%hash);
  368.   #J'ai enleve $LOAD
  369.   $CHEMIN = ($dotoc_up || $dotoc_down) && ($CHEMIN =~ $FLECHE) ? $CHEMIN : '';
  370.   my $CHEMIN_up=($dotoc_up) ? "<div id=\"up_toc\">$CHEMIN</div>": '' ;
  371.   my $CHEMIN_down=($dotoc_down) ? "<div id=\"down_toc\">$CHEMIN</div>" : '' ;
  372.   my @Chemin = split(',', $hash{chemin}{$tag});
  373.   my $TOCg = $dotoc_left ? selection($hash{toc}{main}, 'left_selection', @Chemin) : '';
  374.   my $TOCd = ($dotoc_right && $tag ne 'main' && (!($dotoc_left) || $tagupbl ne 'main' )) ? selection($hash{toc}{$tagupbl}, 'right_selection', @Chemin) : '';
  375.   my $TOCp = ($dotoc_partial && !($dotoc_left)) ? selection($hash{toc}{$tagupbl}, 'left_selection', @Chemin) : '';
  376.   my $tit_index = ($hash{titb}{index})? $hash{titb}{index} : 'Index' ;
  377.   my $index = ($INDEX == 1 && (@ListIndex)) ? "<li>\\link{index}{$tit_index}</li>" : '';
  378.   my $tooltip = "";
  379.   ##$txt="<div class=\"fold\"> ".$txt ."<\/div>" if ($type=~/fold/) ;
  380.   my $pat= '<br\s+class="spacer">';
  381.   $txt = $tooltip . toc_HTML ($txt, clean($TOCg,\%hash), clean($TOCd,\%hash), clean($TOCp,\%hash), $CHEMIN_up, $CHEMIN_down, $index);
  382.   $txt =~ s/$pat\s*$pat/<br class="spacer">/g;
  383.   out ($tag, $txt );
  384. }
  385. if ($INDEX == 1) { out ('index.hd', hd('index',\%hash) )};
  386. my @style = sortuniq(split(',',$STYLE)) if ($STYLE) ;
  387. out_def ('.def', def (\%hash, @style ));
  388.  
  389. ##############
  390.  
  391. sub analyse_texte { my ($TEXT, $ref, $Id, $niveau, $niveau_max, $Toc) = @_;
  392.   my $link = ($niveau <= $niveau_max);
  393.   return $Toc if $niveau > $#SECTIONS ;
  394.   my $section = $SECTIONS[$niveau];
  395.   my $sectiontag = "<$section>";
  396.   my @decoup = split (/$sectiontag/, $TEXT);
  397.   my $text = $decoup[0];
  398.   my $toc_titre ;
  399.   my ($cnt, $id) = (1, "");
  400.   #On parcourt un texte $Id : $text et on enleve tous les niveaux inferieurs
  401.  # (boucle while)
  402.   while ( $decoup[$cnt]) {
  403.   #tient compte des titres courts pour la toc
  404.     my @u = extract_tagged ($decoup[$cnt],'\[','\]');
  405.     $toc_titre = ($u[4]) ? $u[4] : '' ;
  406.     @u = extract_tagged ($u[1],'\{','\}');
  407.     if (!$u[4]) { $NUMERO = 1 ; warn " ATTENTION : section dans $Id sans titre ; l'option numerotation a eté rajoutée"};
  408.     my @extract = extract_tagged ($sectiontag . $u[1], $sectiontag);
  409.     my $idold = $id;
  410.     $id = $Id . ($link? 'S': "$prefixe{fold}S") . $cnt;
  411.     $cnt++;
  412.     my $titre = $u[4];
  413.     $toc_titre = $titre if (!$toc_titre) ;
  414.     $titre =~ s/\n/ /g;
  415.     $titre = Numero($id) . " $titre" if ($NUMERO);
  416.     $toc_titre = Numero($id) . " $toc_titre" if ($NUMERO);
  417.     $text .= $link ?"<p>\\link{$id}</p>"
  418.                     :"<div class=\"spacer\">\\fold{$id}{<span class=\"$section\">$titre</span>}</div>";
  419.     if ($link) {
  420.       $Toc .= "<p><XXXX=\"$id\">\\link{$id}{$toc_titre}<YYYY=\"$id\"></p>";
  421.     }
  422.     $text .= $extract[1];
  423.     $ref->{titb}{$id} = $titre;
  424.     $ref->{tittoc}{$id} = $toc_titre;
  425.     $ref->{text}{$id} = $extract[4];
  426.     $ref->{type}{$id} = 'fold' if !$link ;
  427.     $Toc = analyse_texte ($ref->{text}{$id}, $ref, $id, $niveau + 1, $niveau_max, $Toc) ;
  428.     $ref->{upbl}{$id} = $Id;
  429.     $ref->{prev}{$id} = $idold;
  430.     $ref->{next}{$idold} = $id;
  431.    #modifier avec selection
  432.     my $tp = '' ;
  433.     if ($TOOLTIP==1) {
  434.     if (!$ref->{toctip}{$Id}) {$ref->{toctip}{$Id}=($ref->{tittoc}{$id}) && !($id =~/F_/) ?
  435.       "<li>\\link{$id}{$ref->{tittoc}{$id}}</li>": '' ; }
  436.     else {
  437.       $ref->{toctip}{$Id} .= ($ref->{tittoc}{$id} && !($id =~/F_/)) ? "<li>\\link{$id}{$ref->{tittoc}{$id}}</li>": '' ;
  438.     }
  439.     #$ref->{toctip}{$Id} .= $ref->{tittoc}{$id} ;
  440.     $tp = "ZZZZZ$id" ; }
  441.     $ref->{toc}{$Id} .= "\n<XXXX=\"$id\">\\link{$id}{$ref->{tittoc}{$id}
  442.    }$tp <YYYY=\"$id\">";
  443.   }
  444.  #maintenant, ce qui reste dans $text est exactement ce qu'on doit mettre dans le hash->{text}{$Id}
  445.   $ref->{text}{$Id} = $text;
  446.   $ref->{titb}{main} = $ref->{title}{main};
  447.   $ref->{tittoc}{main} = $ref->{title}{main} if (!$ref->{tittoc}{main});
  448.   $Toc;
  449. }
  450. sub treate_accent {my ($txt) = @_;
  451.   #$txt=decode('iso-8859-1',$txt);
  452.   $txt =~ tr/éèêëàáâãäåùìíîïóôòç/eeeeaaaaaauiiiioooc/;
  453.   $txt =~ s/[ÀÁÂÃÄÅ]/A/g;
  454.   $txt =~ s/Ç/C/g;
  455.   $txt =~ s/[ÈÉÊË]/E/g;
  456.   $txt =~ s/[ÌÏÎÍ]/I/g;
  457.   $txt =~ s/'/ /g;
  458.   #$txt= encode("iso-8859-1",$txt);
  459.   $txt
  460. }
  461.  
  462. sub store_tag { my ($cle, $label, $tag, $ref, $ref_bloc) = @_;
  463.   $label=~s/[^\w]+//g;
  464.   $label=treate_accent($label);
  465.   $ref->{$cle}{$tag} = $ref_bloc->{fichier}{$label} ;
  466.   '';
  467. }
  468.  
  469. sub store_label { my ($label, $Id, $ref) = @_;
  470.   $label=~s/[^\w]+//g;
  471.   $label=treate_accent($label);
  472.   $ref->{fichier}{$label} = $Id;
  473.   "<a id=\"$label\"></a>";
  474. }
  475.  
  476. sub dbg { print STDERR "$_[0]\n" if ($verbose); }
  477.  
  478. sub store_index { my ($label, $Id, $ref_index) = @_;
  479.   dbg("... index: \"$label\"");
  480.   my $labelmod=$label;
  481.   $label=~s/[^\w]+//g;
  482.   $label=treate_accent($label);
  483.   my $L = $ref_index->{page}{$labelmod};
  484.   $ref_index->{page}{$label} = !$L ? $Id : "$L,$Id";
  485.   "<a id=\"$label\"></a>";
  486. }
  487. ## FIXME ! has disappeared in store_index because of label
  488. sub class_index { my ($index,$level) = @_ ;
  489.      my @a = split('!', $index) ;
  490.      ($a[$level])? $a[$level] : $index ;
  491.  }
  492.  #!(keys %{$ref_index->{page}}
  493.  #sort keys %{$ref_index->{page}} ;
  494.  
  495. sub makeindex { my ($ref_index, $level, @L ) = @_;
  496.    return '' if (!$#L) ;
  497.    my $dejavu = '' ;
  498.    my $TEXT = "\n<ul class=\"index\">";
  499.    for my $index (@L) {
  500.       next if ($dejavu =~ /\b$index\b/) ;
  501.       my @list = sort {$a cmp $b} grep {class_index($_, $level) eq class_index($index, $level)} @L ;
  502.       my @l = split('!', $index) ;
  503.       if ($l[$level]) {
  504.           $TEXT .= "<li> " ;
  505.           for my $ind (split(',',$ref_index->{page}{$index})) {
  506.              if ($ind && !($dejavu =~ /\b$ind\b/)) {
  507.                  $TEXT .= "\\link{$ind}{". $l[$level] . " }{$ind}" ;
  508.              }
  509.           }
  510.           $dejavu .= ' ' . join (' , ', @list) ;
  511.           $TEXT .= makeindex ($ref_index, $level + 1, @list) . "</li>" ;
  512.       };
  513.    }
  514.    "$TEXT </ul>";
  515. }
  516.  
  517. sub TraiteText {my ($TEXT, $ref, $ref_env, $Id) = @_;
  518.   $TEXT =~ s/\s*$//; # strip trailing whitespace
  519.  #0 ul et li sans rien
  520.  #1 avec style
  521.  $TEXT =~ s/\\(begin|end)\s*\{wimsonly\}//g;
  522.  for my $rubrique (keys %{$ref_env->{list}}) {
  523.      $TEXT = traite_list ($TEXT, $ref, $ref_env, $Id, $rubrique,1);
  524.  }
  525.  
  526.  for my $rubrique (@liste_env_list) {
  527.      $TEXT = traite_list ($TEXT, $ref, $ref_env, $Id, $rubrique,0);
  528.  }
  529.  
  530. for my $rubrique (keys %{$ref_env->{tabular}}) {
  531.      if ($TEXT =~ /\\begin\{$rubrique\}/) {
  532.        $TEXT = traite_environ ($TEXT, $ref, $ref_env, $Id, $rubrique,0);
  533.      }
  534.  }
  535.  
  536. for my $rubrique (@liste_env_tabular) {
  537.    if ($TEXT =~ /\\begin\{$rubrique\}/) {
  538.      $TEXT = traite_environ ($TEXT, $ref, $ref_env, $Id, $rubrique,0);
  539.    }
  540. }
  541.  
  542.  for my $rubrique (@liste_env_spec) {
  543.     if ($TEXT =~ /\\begin\{$rubrique(\*)?\}/) {
  544.       $TEXT = traite_environ ($TEXT, $ref, $ref_env, $Id, $rubrique, 1);
  545.     }
  546.   }
  547. #le 1 et 0 servent a initialiser le compteur dans le cas ou on doit creer de nouveaux blocs dans la même page
  548.  
  549.   for my $rubrique (keys %{$ref_env->{titre}}) {
  550.     if ($TEXT =~ /\\begin\{$rubrique\}/) {
  551.       $TEXT = traite_environ ($TEXT, $ref, $ref_env, $Id, $rubrique,1);
  552.     }
  553.   }
  554.   for my $rubrique (keys %{$ref_env->{list}}) {
  555.      $TEXT = traite_environ ($TEXT, $ref, $ref_env, $Id, $rubrique,0);
  556.      $TEXT = traite_environ ($TEXT, $ref, $ref_env, $Id, $rubrique . '_item',0);
  557.   }
  558.  
  559.   if ($TEXT =~ /\\begin\{\s*(\w*)\s*\}/g) {
  560.      warn " ATTENTION : environnement non répertorié : $1" if $1 ne 'matrix' && $1 ne 'split';
  561.   }
  562.   $TEXT =~ s,<li>\n+</li>,<li></li>,g;
  563.   $TEXT =~ s,</div>\s+</div>,</div></div>,g;
  564.   $TEXT =~ s,</div>\s+<,</div>\n<,g;
  565.   $TEXT =~ s,<div ([^>]+)>\s+<,<div $1><,g;
  566.   $TEXT =~ s/\n{2,5}/<br class=\"spacer\">/g;
  567.   $TEXT;
  568. }
  569.  
  570. #on pourrait faire une boucle while ; on pourrait avoir deux fois le meme environnement imbrique ?
  571. #begin{proof} \begin{proof} \end{proof}\end{proof} Je crois que c'est pour cela que je fais ce truc
  572. #tordu. En fait split me sert uniquement a trouver le premier <$environ>
  573. #$cnt sert a numeroter semi-globalement (creation de blocs correspondant a un meme environnement dans une meme page
  574. #exemple mainS4S3F_proof1,mainS4S3F_proof2,mainS4S3F_proof3,mainS4S3F_proof4,mainS4S3F_proof5
  575.  
  576. sub traite_list {my ($TEXT, $ref, $ref_env, $Id, $environ, $option) = @_;
  577.  my ($e_item, $b_item , $b_class, $e_class) = (' ',' ', ' ', ' ');
  578.   if ( $option == 1 ) {
  579.          $e_item = "\\end{$environ\_item}" ;
  580.          $b_item = "\\begin{$environ\_item}" ;
  581.       my $style = $ref_env->{style}{$environ} ;
  582.       $style = ($style) ? $style : $environ;
  583.       $b_class= "ul class=\"$style\"" ;
  584.       $e_class= "\/ul" ;
  585.       }
  586.       {
  587.         if    ($environ eq 'enumerate'){ $b_class = "ol class=\"enumerate\"" ; $e_class= "\/ol" ; }
  588.         elsif ($environ eq 'itemize'){ $b_class = "ul class=\"itemize\"" ; $e_class= "\/ul" ;}
  589.         elsif ($environ eq 'description'){
  590.               $b_class = "ul style=\"list-style:none;\"" ;
  591.               $e_class= "\/ul" ;
  592.               $e_item = "\\end{$environ\_item}" ;
  593.               $b_item = "\\begin{$environ\_item}"
  594.               }
  595.         elsif ($environ eq 'trivlist') { $b_class = "ul class=\"wims_nopuce\"" ;
  596.                $e_class= "\/ul" ;
  597.         }
  598.       };
  599.   $TEXT =~ s/\\begin\{$environ(\*)?\}/<$environ>/g;
  600.   $TEXT =~ s|\\end\{$environ(\*)?\}|<\/$environ>|g;
  601.  
  602.   my @decoup = split ("<$environ>", $TEXT);
  603.  
  604.   my $a = join ("<$environ>", @decoup[1..$#decoup]);
  605.   return $TEXT if (!$a) ;
  606.   my @u = extract_tagged ("<$environ>$a", "<$environ>");
  607.   my $milieu = "<$environ>" . $u[4] . "<\/$environ>" ;
  608. #FIXME pas de listes emboitees de type different !
  609.   $milieu =~ s|<$environ>\s*\\item|<$environ><li>$b_item|g ;
  610.   $milieu =~ s|</$environ>|</li><$e_class>|g;
  611.   $milieu =~ s|\\item|$e_item</li><li>$b_item|g;
  612.   $milieu =~ s|</li><$e_class>|$e_item</li><$e_class>|g;
  613.   $milieu =~ s|<$environ>|<$b_class>|g;
  614.   $decoup[0] . $milieu . traite_list ($u[1], $ref, $ref_env, $Id, $environ,$option);
  615. }
  616.  
  617. sub traite_environ {my ($TEXT, $ref, $ref_env, $Id, $environ, $cnt) = @_;
  618.   $TEXT =~ s/\\begin\{$environ\*?\}/<$environ>/g;
  619.   $TEXT =~ s|\\end\{$environ\*?\}|</$environ>|g;
  620.  
  621.   my @decoup = split ("<$environ>", $TEXT);
  622.  
  623.   my $a = join ("<$environ>", @decoup[1..$#decoup]);
  624.   return $TEXT if (!$a);
  625.  
  626.   my @u = extract_tagged ("<$environ>$a", "<$environ>");
  627.   my $milieu = $u[4];
  628.   return $TEXT if (!$milieu);
  629.  
  630.   my $pat_env = join('|', @liste_env_spec);
  631.   my $patt_env = join('|', @liste_env_tabular);
  632.   if ($environ =~ /\b($pat_env)\b/) { $milieu = $1->($milieu) ; }
  633.   elsif ($environ =~ /\b($patt_env)\b/) { $milieu = tabular->($milieu,$environ) ; }
  634.   else { my @milieu1 = extract_bracketed ($milieu, '\{\}');
  635.     if ($milieu1[0]) { $milieu = $milieu1[4] ; };
  636.     my $type = $ref_env->{type}{$environ};
  637.  
  638.     if ($type && ($type eq 'fold' || $type eq 'link')) {
  639.       my $titre = $ref_env->{titre}{$environ};
  640.       my $newtag = $Id . $prefixe{$type} . $environ . $cnt;
  641.       $ref->{type}{$newtag} = 'fold' if $type eq 'fold' ;
  642.       $cnt++;
  643.       # LaTeX interdit des [ ] imbriques.
  644.       if ($milieu =~ s/^\s*\[([^\]]+)\]//) {
  645.         $titre = ($titre) ? "$titre [ $1 ]" : $1 ;
  646.       }
  647.       $ref->{titb}{$newtag} = $titre;
  648.       $ref->{text}{$newtag} = encadrement("<$environ>$milieu<\/$environ>", $environ, $ref_env);
  649.       $ref->{upbl}{$newtag} = $Id;
  650.       $milieu = "\n\\$type\{$newtag\}\{"
  651.         . encadr_defaut("<$environ>$titre<\/$environ>", $environ, $ref_env,'titre')
  652.         . "\}\n" ;
  653.     } else { my $milieu1 = $milieu ;
  654.       $milieu = encadrement("<$environ>$milieu<\/$environ>", $environ, $ref_env, 'full');
  655.     }
  656.   }
  657.   $decoup[0] . $milieu . traite_environ ($u[1], $ref, $ref_env, $Id, $environ, $cnt);
  658. }
  659.  
  660. sub hd {my ($tag, $ref) = @_;
  661.   my $txt = '';
  662.   for my $cle ('prev','next','upbl','titb','keyw','datm') {
  663.     my $KEY = $ref->{$cle}{$tag};
  664.     $txt .= "!set $cle=$KEY\n" if ($KEY);
  665.   }
  666.   $txt;
  667. }
  668. #rajoute un next aux section/subsection/ si cela n'existe pas [dernier] dernier sur index si il y a
  669. #rajoute main pour ceux qui n'ont pas de parents.
  670. sub complete {my ($tag, $ref) = @_;
  671.   $ref->{datm}{$tag} = isotime() if !($ref->{datm}{$tag}) ;
  672.   $ref->{upbl}{$tag} = 'main' if !($ref->{upbl}{$tag}) ;
  673.   my $upbl = $ref->{upbl}{$tag};
  674.   if (!$ref->{next}{$tag}) {
  675.     my $a = $ref->{next}{$upbl};
  676.     $ref->{next}{$tag} = $a || 'main';
  677.   };
  678.   if (!$ref->{prev}{$tag}) {
  679.     my $b = $ref->{prev}{$upbl};
  680.     $ref->{prev}{$tag} = $b || 'main';
  681.   };
  682.   if ($INDEX == 1 && !($ref->{titb}{index})) { $ref->{titb}{index} = 'Index' ;}
  683. }
  684.  
  685. #option full <h3 class="l2w_content defn">Definition [titre perso]</h3> <div class= "l2w_content definition">  </div> si cela existe
  686. #option bloc <div class= "definition"> </div> si cela existe (interieur d'un fold ou d'un link)
  687. #option titre <h3 class="l2w_content defn">Definition </h3> si cela existe (titre d'un fold)
  688. sub encadr_defaut { my ($TEXT, $rubrique, $ref_env, $option) = @_;
  689.   my $a = $ref_env->{titre}{$rubrique};
  690.   my $b = $ref_env->{style}{$rubrique};
  691.   if (!$b) {
  692.     $b = $rubrique;
  693.     $ref_env->{style}{$rubrique} = $b;
  694.     dbg("... environnement $rubrique sans style css, par defaut $rubrique")
  695.   };
  696.   my $div_d = "<div class=\"l2w_content $b\">";
  697.   my $div_f = '</div>';
  698.   if ( $option eq 'titre') {
  699.     $TEXT =~ s/<$rubrique>/<span class=\"l2w_content $b\">/g;
  700.     $TEXT =~ s/<\/$rubrique>/<\/span>\n/g;
  701.   } elsif (!$a || $option eq 'bloc') {
  702.     $TEXT =~ s/<$rubrique>\s*(\[[^\]]+\])?/$div_d/g;
  703.     $TEXT =~ s/<\/$rubrique>/$div_f/g;
  704.   } elsif ($option eq 'full') {
  705.     $TEXT =~ s/<$rubrique>\s*(\[[^\]]+\])/<h3 class=\"l2w_content $b\">$a $1<\/h3>$div_d/g;
  706.     $TEXT =~ s/<$rubrique>/<h3 class=\"l2w_content $b\">$a<\/h3>$div_d/g;
  707.     $TEXT =~ s/<\/$rubrique>/$div_f/g;
  708.   } else {
  709.     $TEXT =~ s/<$rubrique>/<span class=\"$b\">/g;
  710.     $TEXT =~ s/<\/$rubrique>/<\/span>\n/g;
  711.   }
  712.   $TEXT;
  713. }
  714. sub encadrement { my ($TEXT, $rubrique, $ref_env) = @_;
  715.   my $debut = $ref_env->{deb}{$rubrique};
  716.   my $fin   = $ref_env->{fin}{$rubrique};
  717.   my $opt= ($ref_env->{type}{$rubrique} && $ref_env->{type}{$rubrique}=~ /fold/) ? 'bloc' : 'full' ;
  718.   return encadr_defaut ($TEXT, $rubrique, $ref_env, $opt) if (!$debut && !$fin);
  719.  
  720.   $TEXT =~ s/<$rubrique>//;
  721.   my $cnt_arg = $ref_env->{cnt_arg}{$rubrique};
  722.   my $d = join('   ', subst($TEXT, $cnt_arg, $debut, $rubrique, $ref_env));
  723.   my ($com,$txt) = subst($TEXT, $cnt_arg, $fin);
  724.   $d =~ s/<\/$rubrique>/$com/;
  725.   $d;
  726. }
  727.  
  728. sub tabular { my ( $b, $style ) = @_;
  729.   my @v = extract_bracketed ($b, '\{\}') ;
  730.   my $stylerow = $style . "_row";
  731.   my $stylecell = $style . "_cell";
  732.   $b = "<table class=\"$style\"><tr class=\"$stylerow\"><td class=\"$stylecell\">" . $v[1] . '</table>';
  733.   $b =~ s|\&|&nbsp;</td><td class=\"$stylecell\">&nbsp;|g;
  734.  $b =~ s/\\hline//g;
  735.  $b =~ s|\\\\\s*</table>|</td></tr></table>|g;
  736.  my $par="\\\\\\(|\\\\\\)" ;
  737.  my @dectab = split(/$par/, $b) ;
  738.  $b = $dectab[0] ;
  739.  $b =~ s|\\\\|</td></tr><tr class=\"$stylerow\"><td class=\"$stylecell\">|g;
  740.  my $cnt = 0; $b = '' ;
  741.  while ($cnt <= $#dectab/2) {
  742.     my $c = $dectab[2*$cnt] ;
  743.     $c =~ s|\\\\|</td></tr><tr class=\"stylerow\"><td class=\"$stylecell\">|g;
  744.     $b .= $c . (($dectab[2*$cnt+1]) ? "\\(" . $dectab[2*$cnt+1] . "\\)" : '' );
  745.     $cnt ++ ;
  746. };
  747. $b ;
  748. }
  749.  
  750. ###demande de convertir d'abord de maniere independante les pdf tiff eps svg en un format d'image png
  751. sub includegraphics{ my ( $b, $opt ) = @_;
  752.  $b=~ s/.(pdf|tiff|eps|svg)/.png/ ;
  753.  if ($opt) {
  754.    $opt =~ s/.*(width|height)\s*=\s*([0-9]*\.?[0-9]*\s*)(\\(line|text)width)/linewidth("$2$3",$1)/eg;
  755.    $opt =~ s/.*(width|height)\s*=\s*([0-9]*\.?[0-9]*\s*)(cm|px)/ style=\"$1:$2$3;\"/;
  756.  };
  757.  "<img src=\"\\filedir\/$b\" $opt alt=\"\">";
  758. }
  759.  
  760. sub tikzpicture{ my ($b)=@_;
  761.   if($hash{'tikzsetfigurename'}{main}){
  762.     $fig_cnt++;
  763.     $b=$hash{'tikzsetfigurename'}{main} . "$fig_cnt";
  764.   }
  765.   else
  766.   {
  767.     ## ne fonctionne pas car \tikzsetnextfilename
  768.     ## doit être mis à l'extérieur, il faudrait donc
  769.     ## dans le texte latex le répéter à l'intérieur
  770.     ## en le commentant (non testé)
  771.     ## il est conseillé de faire plutot tikzsetfigurename
  772.     ## en preambule
  773.     $b =~ s/\tikzsetnextfilename\s*\{([^\}]+)\}/$1/eg;
  774.   }
  775.   includegraphics("$b.png");
  776. }
  777.  
  778. sub minipage { my ( $b ) = @_;
  779.  my @v = extract_bracketed ($b, '\[\]') ;
  780.  my $option = $v[0] ;
  781.  if($option) {
  782.  $option=~ s/\[\s*b\s*\]/bottom/ ;
  783.  $option=~ s/\[\s*t\s*\]/top/ ;
  784.  $option=~ s/\[\s*c\s*\]/middle/ ;
  785.  $option=~ s/\[\s*\]/middle/;
  786.  } else {
  787.  $option='middle'} ;
  788.  @v = extract_bracketed ($v[1], '\{\}') ;
  789.  my $width = $v[0] ;
  790.  $width =~ s/\{(.*)\}/$1/;
  791.  $width = linewidth($width);
  792.   "<div style=\"width:$width; display:inline-block;vertical-align:$option;\" class=\"minipage\">
  793.   $v[1]
  794.   </div>";
  795. }
  796. sub columns { my ( $b ) = @_;
  797.   "<div class=\"columns\">$b</div>"
  798. }
  799.  
  800. sub column { my ( $b ) = @_;
  801.  my @v = extract_bracketed ($b, '\[\]') ;
  802.  my $option = '';
  803.  $option= $v[0] ;
  804.  if($option) {
  805.   $option=~ s/\[\s*b\s*\]/bottom/ ;
  806.   $option=~ s/\[\s*t\s*\]/top/ ;
  807.   $option=~ s/\[\s*c\s*\]/middle/ ;
  808.   $option=~s/\[\s*\]/middle/;
  809.   }
  810.  else{ $option='top'} ;
  811.  @v = extract_bracketed ($v[1], '\{\}') ;
  812.  my $width = $v[0] ;
  813.  $width =~ s/\{(.*)\}/$1/;
  814.  $width = linewidth($width) ;
  815.   "<div style=\"width:$width; display:inline-block;vertical-align:$option;\" class=\"column\">
  816.   $v[1]
  817.   </div>";
  818. }
  819.  
  820. sub lstlisting { my ($b,$id ) = @_ ;
  821.   $b =~ s ,\\,\\\\,g ;
  822.   "<pre class=\"lstlisting\" id=\"lstlisting$id\">$b</pre>";
  823. }
  824.  
  825. sub verbatim { my ($b,$id ) = @_ ;
  826.   $b =~ s ,\\,\\\\,g ;
  827.   "<pre class=\"verbatim\" id=\"verbatim$id\">$b</pre>";
  828. }
  829.  
  830. sub multline { my ( $b) = @_;
  831.   $b =~ s/\\\\\s*=/\\)<br>\\(== /g;
  832.   $b =~ s|\\\\|\\)<br>\\(|g;
  833.   "<div class=\"math\">\\(" . $b . "\\)</div>\n";
  834. }
  835.  
  836. sub equation { my ( $b) = @_;
  837.   $b = "\\( $b \\)";
  838.   if ($b =~ s/\\label\{([^\}]+)\}//) { $b = "\\label\{$1\}" . $b };
  839.   $b =~ s/\n{2,}/\n/;
  840.   '<div class="math">' . $b . '</div>' ;
  841. }
  842.  
  843. sub align1 { my ( $b) = @_;
  844.   $b = "\\(\\begin\{matrix\} $b \\end\{matrix\} \\)";
  845.   if ($b =~ s/\\label\{([^\}])\}//) { $b = "\\label\{$1\}" . $b };
  846.   '<div class="math">' . $b . '</div>' ;
  847. }
  848. sub align { my ( $b) = @_;
  849.   $b = '<table class="wimscenter wimsnoborder tableau" style="width:100%"><tr><td>\\(' . $b . '\\\\</table>';
  850.   if ($b =~ s/\\label\{([^\}])\}//) { $b = "\\label\{$1\}" . $b };
  851.   $b =~ s|\&|\\)&nbsp;</td><td>&nbsp;\\(|g;
  852.   $b =~ s|\\\\\s*</table>|\\)</td></tr></table>|g;
  853.   $b =~ s|\\\\|\\)</td></tr><tr><td>\\(|g;
  854.   $b =~ s|\\\(\s+\\\)||g;
  855.   $b =~ s|\n\\\)|\\\)|g;
  856.   $b =~ s|\\\(\n|\\\(|g;
  857.   '<div class="math">' . $b . '</div>' ;
  858. }
  859.  
  860. sub pmatrix {"\\left ( \\begin{matrix} " . $_[0] . "\\end{matrix} \\right )" ;}
  861. sub smallmatrix {"\\left ( \\begin{matrix} " . $_[0] . "\\end{matrix} \\right )" ;}
  862. sub eqnarray {" <div class=\"math\">\\(\\begin{matrix} " . $_[0] . "\\end{matrix})</div> " ;}
  863. sub center {" <div class=\"center\">" . $_[0] . "</div>"}
  864.  
  865. sub array {my ( $b ) = @_ ;
  866.   my @v = extract_bracketed ($b, '\{\}');
  867.   "\\begin{matrix} " . $v[1] . "\\end{matrix} ";
  868. }
  869. #TODO pour l'instant
  870. sub cases {"\\left \\lbrace\\begin{array}{ll} " . $_[0] . "\\end{array} \\right ." ; }
  871.  
  872. sub gather { my ($b) = @_;
  873.   my @decoup = split ('\\\\intertext', $b);
  874.   my $cnt = 1;
  875.   $b = equation($decoup[0]);
  876.   while ($cnt <= $#decoup) {
  877.     my @a = extract_bracketed ( $decoup[$cnt], '\{\}' );
  878.     my $c = $a[0];
  879.     $c =~ s/\{(.*)\}/$1/;
  880.     $b .= $c . equation($a[1]);
  881.     $cnt ++;
  882.   }
  883.   $b;
  884. }
  885.  
  886. sub displaymath {"<div class=\"math\">\\(\\displaystyle\{ " . $_[0]. "\}\\)</div>"; }
  887. sub math {" \\( " . $_[0]. "\\) "; }
  888.  
  889. sub figure { my $caption=''; my $c =$_[0];
  890.   $c =~ s /^\[([^\]]+)//; print $c;
  891.   if ( $c =~ s/\\caption\{([^\}]+)\}//) {$caption=$1 };
  892.   "<div class=\"figure\"> " .
  893.   (($caption) ? "<div class=\"caption\">". $caption . "</div>":"")
  894.     . $c . "</div>" ;}
  895.  
  896. sub thebibliography { my ( $b ) = @_;
  897.   $b =~ s/\\bibitem\{([^\}]+)\}/<\/li>\n<li>\[$1\]\\label\{$1\} /g;
  898.   $b =~ s/\{\d+\}\s*<\/li>//;
  899.   '<h2 class="thebibliography">' . $hash{titb}{ref}
  900.   . "</h2>\n<ul class=\"thebibliography\">$b </li></ul>\n";
  901. }
  902. sub pspicture { '<p>dessin à faire dans wims</p>' ; }
  903. sub picture { '<p>dessin à faire dans wims</p>' ; }
  904.  
  905. #decoupe ce qui se trouve a l'interieur de \begin{wims} \end{wims} pour ne pas y toucher.
  906. # meme pour verbatim, lstlisting
  907. sub traite_special { my ( $TEXT, $ref_spec, $ref, $environ ) = @_;
  908.   $TEXT = recup_embed($TEXT, $ref) ;
  909.   $TEXT =~ s/\\begin\{$environ\}/<$environ>/g;
  910.   $TEXT =~ s/\\end\{$environ\}/<\/$environ>/g;
  911.   $TEXT =~ s/\r\n/\n/gs ;
  912.   my @decoup = split ("<$environ>", $TEXT);
  913.   my $cnt = 1;
  914.   if ($#decoup) {
  915.     $TEXT = $decoup[0];
  916.     while ($cnt <= $#decoup) {
  917.       my @a = extract_tagged("<$environ>" . $decoup[$cnt], "<$environ>");
  918.       die "Bug dans $environ insertion: $decoup[$cnt]" if (!defined($a[4]));
  919.       $TEXT .= $environ . 'insertion' . $cnt . $a[1];
  920.       $ref_spec->{$cnt} = $a[4];
  921.       $cnt++;
  922.     }
  923.   }
  924.   $TEXT;
  925. }
  926.  
  927. sub latexonly { '' }
  928.  
  929. sub store_cmd { my ($def, $id, $narg, $val, $ref_command) = @_;
  930.   if ($hash_secinv{$id}) {
  931.     warn " ATTENTION : commande perso \"$id: argument invalide\n";
  932.     return '';
  933.   }
  934.   my $origin = $ref_command->{origin}{$id};
  935.   return '' if ($origin && $origin eq 'defwims' && $def ne 'defwims');
  936.   $ref_command->{origin}{$id} = $def;
  937.   $ref_command->{cnt_arg}{$id} = $narg;
  938.   $ref_command->{definition}{$id} = $val;
  939.   dbg("... commande perso \"$id\": argument: \"$narg\" definition: \"$val\"");
  940.  '' ;
  941. }
  942.  
  943. sub store_environ { my ($def, $cmd, $narg, $titre, $deb, $fin, $ref_env) = @_;
  944.   my $origin = $ref_env->{origin}{$cmd};
  945.   return '' if ($origin && $origin eq 'environmentwims' && $def ne 'environmentwims');
  946.   $ref_env->{deb}{$cmd} = $deb;
  947.   $ref_env->{fin}{$cmd} = $fin;
  948.   $ref_env->{cnt_arg}{$cmd} = $narg;
  949. ## one can have macro in definition of an environment - not general but useful for language
  950.   if ($titre=~/\\(\w+)/) {
  951.     $titre=$hash_command{definition}{$1} if $hash_command{definition}{$1}
  952.   }
  953.   $ref_env->{titre}{$cmd} = $titre;
  954.   $ref_env->{origin}{$cmd} = $def;
  955.   my $style = $ref_env->{style}{$cmd} ;
  956.   $style = ($style)? $style : $cmd ;
  957.   #if (!$ref_env->{deb}{$cmd}) { $ref_env->{deb}{$cmd} = "<div class=\"$style\"> "; }
  958.   #if (!$ref_env->{fin}{$cmd}) { $ref_env->{fin}{$cmd} = "</div> "; }
  959.   dbg("... environnement perso \"$cmd\" argument: \"$narg\" titre: \"$titre\" style: \"$style\" debut: \"$deb\"  fin: \"$fin\"");
  960.   '';
  961. }
  962.  
  963. sub recup_command {my ($TEXT, $ref_command) = @_;
  964.   my $DEF = '(defwims|def|newcommand|renewcommand)';
  965.   #FIXME ? mauvais pour def \def\toto#1#2 ... demander de le refaire avec defwims s'il y a plus de 3 arguments ?
  966.   $TEXT =~ s/\\$DEF\s*\\(\w*)#(\d)\{(.*)\}/store_cmd($1,$2,$3,$4,$ref_command)/eg;
  967.   #2 arguments
  968.   $TEXT =~ s/\\$DEF\s*\\(\w*)#(\d)#(\d)\{(.*)\}/store_cmd($1,$2,$4,$5,$ref_command)/eg;
  969.   $TEXT =~ s/\\$DEF\s*\\(\w*)\s*\{(.*)\}/store_cmd($1,$2,0,$3,$ref_command)/eg;
  970.   #3 arguments
  971.   $TEXT =~ s/\\$DEF\s*\\(\w*)#(\d)#(\d)#(\d)\{(.*)\}/store_cmd($1,$2,$5,$6,$ref_command)/eg;
  972.   # newcommand avec parametres
  973.   $TEXT =~ s/\\$DEF\s*\{\\(\w*)\}\s*\[(\d)\]\s*\{(.*)\}/store_cmd($1,$2,$3,$4,$ref_command)/eg;
  974.   # newcommand sans parametres
  975.   $TEXT =~ s/\\$DEF\s*\{\\(\w*)\}\s*\{(.*)\}/store_cmd($1,$2,0,$3,$ref_command)/eg;
  976.   $TEXT;
  977. }
  978.  
  979. sub recup_config { my ($cmd, $arg, $ref_env) = @_;
  980.   my @L = (split (',', $arg));
  981.   my $style = $L[0];
  982.   my $type = 'style';
  983.   if ($cmd eq 'typefold') { $style = 'fold'; $type = 'type' };
  984.   if ($cmd eq 'typelink') { $style = 'link' ; $type = 'type' };
  985.   if ($cmd eq 'tablewims') { $type = 'tabular' ; };
  986.   if ($cmd eq 'listwims') { $type = 'list' };
  987.   for my $rubrique (@L) {
  988.     $ref_env->{$type}{$rubrique} = $style;
  989.     dbg("... commande $rubrique de $type $style");
  990.     if ($cmd eq 'listwims') { $ref_env->{'style'}{$rubrique . '_item'} = $style . '_item' ;
  991.                               $ref_env->{'titre'}{$rubrique . '_item'} = '' }
  992.   }
  993.   push @liste_env_tabular, (keys %{$ref_env->{tabular}}) ;
  994.  '';
  995. }
  996. sub recup_environ {my ($TEXT, $ref_env) = @_;
  997.   my $pat = '\s*\{(.*)\}';
  998.   $TEXT =~ s/\\(typefold|typelink|samestyle|listwims|tablewims)\{([^\}]+)\}/recup_config($1,$2, $ref_env)/eg;
  999.   # {nom}[#param]{titre}{debut}{fin}
  1000.   $TEXT =~ s/\\(environmentwims|[re]?newenvironment)\s*\{(\w*)\}\[(\d)\]$pat$pat$pat/store_environ($1,$2,$3,$4,$5,$6,$ref_env)/eg;
  1001.   # {nom}{titre}{debut}{fin}
  1002.   $TEXT =~ s/\\(environmentwims|[re]?newenvironment)\s*\{(\w*)\}$pat$pat/store_environ($1,$2,0,'', $3,$4,$ref_env)/eg;
  1003.  #\newtheorem{nom}[]?{titre}[]?
  1004.   $TEXT =~ s /(\\newtheorem\*?)\s*\{(\w*)\}\s*(\[[^\]]*\])?\s*\{([^\}]*)\}\s*(\[[^\]]*\])?\s*/store_environ($1,$2,0,$4,'','',$ref_env)/ge;
  1005.   $TEXT;
  1006. }
  1007.  
  1008. #on suppose que le texte commence par \command{}{}{}{} avec le bon nombre d'arguments
  1009.  
  1010. sub traite_command {my ($TEXT, $command, $ref_command) = @_;
  1011.   my $cnt_arg = $ref_command->{cnt_arg}{$command};
  1012.   my $com = $ref_command->{definition}{$command};
  1013.   if ($cnt_arg) {
  1014.     $TEXT =~ s/\\$command\s*\{/\{/;
  1015.     $TEXT = join ( "", subst($TEXT, $cnt_arg, $com));
  1016.   } else {
  1017.     $TEXT =~ s/\\$command\_/$com . '_'/ge;
  1018.     $TEXT =~ s/\\$command\b/$com/ge;
  1019.   }
  1020.   $TEXT;
  1021. }
  1022. #Texte = {}{}{} ou []{}{} qui sont les arguments
  1023. sub subst { my ($TEXT, $cnt_arg, $com, $environ, $ref_env ) = @_;
  1024.   my (@a,$u,$v);
  1025.   my $cnt = 0;
  1026.   while ($cnt < $cnt_arg) {
  1027.     @a = extract_tagged($TEXT, '\{','\}');
  1028.     ($u,$v) = ($a[1],$a[4]);
  1029.     if (!$a[0]) {
  1030.       @a = extract_tagged($TEXT, '\[','\]');
  1031.       ($u,$v) = ($a[1],$a[4]);
  1032.     }
  1033.     $TEXT = $u;
  1034.     $cnt ++;
  1035.      my $sub="" ;
  1036.     if ($v) {
  1037.        $sub = $environ && $ref_env->{titre}{$environ} ? join (' ' , ( $ref_env->{titre}{$environ}, $v)) : $v;}
  1038.     else {$sub=''} ;
  1039.      if (($com) && ("#$cnt")) { $com =~ s/#$cnt/$sub/ge ;};
  1040.   }
  1041.   ($com, $TEXT);
  1042. }
  1043.  
  1044. sub Traite_command { my ($TEXT, $command, $ref_command) = @_;
  1045.   my $cnt_arg = $ref_command->{cnt_arg}{$command};
  1046.   if ($cnt_arg) {
  1047.     my @decoup = split ("\\\\$command\\\{", $TEXT );
  1048.     my $cnt = 1;
  1049.     $TEXT = $decoup[0];
  1050.     while ($cnt <= $#decoup) {
  1051.       $TEXT .= traite_command ('{' . $decoup[$cnt], $command, $ref_command);
  1052.       $cnt++;
  1053.     }
  1054.   } else {
  1055.     while( $TEXT =~ /\\$command\b/) {
  1056.       $TEXT = traite_command ($TEXT, $command, $ref_command);
  1057.     }
  1058.   }
  1059.   $TEXT;
  1060. }
  1061.  
  1062. my %outagain;
  1063. sub out { my ($bloc, $text) = @_;
  1064.   warn "Ecrase $bloc" if ($outagain{$bloc});
  1065.   $outagain{$bloc} = 1;
  1066.   open (OUT, ">$BASE/$bloc") || die "ne peut pas créer $BASE/$bloc";
  1067.   print OUT $text ; close OUT;
  1068. }
  1069.  
  1070. sub out1 { my ($bloc, $text) = @_;
  1071.   warn "Ecrase $bloc" if ($outagain{$bloc});
  1072.   $outagain{$bloc} = 1;
  1073.   open (OUT, ">$doc_DIR$bloc") || die "ne peut pas créer $doc_DIR/$bloc";
  1074.   print OUT $text ; close OUT;
  1075. }
  1076.  
  1077. sub out_def { my ($bloc, $text) = @_;
  1078.   open (OUT, ">$BASE0/$bloc") || die "peut pas créer $BASE0/$bloc";
  1079.   print OUT $text ; close OUT;
  1080. }
  1081.  
  1082. # PASSE 1: developpe 'input/include'
  1083. sub find_expand { my ($file) = @_;
  1084.   if (!open(IN, $DIR . $file)) { warn "$DIR$file n'existe pas"; return; }
  1085.   dbg("... lecture de $file");
  1086.   my $text = <IN>; close(IN);
  1087.   $text =~ s/([^%]\s*\\end\{document\})[[:print:][:space:]]+/$1/;
  1088.   $text =~ s/([^%])\s*\\endinput[[:print:][:space:]]+/$1/;
  1089.   $text =~ s/\%\\(input|include|wimsinclude)([^\n]+)?//g;
  1090.   $text =~ s/\\(input|include|wimsinclude)\s*\{?([a-zA-Z0-9\-_\/]+)\.(sty|tex)\s*\}?/find_expand("$2.$3")/eg;
  1091.   $text =~ s/\\lstinputlisting\s*\{([a-zA-Z0-9\-_\/\.]+)\s*\}/"\\begin\{lstlisting\}\n" . find_expand($1) . "\n\\end\{lstlisting\}"/eg;
  1092.  
  1093.   $text;
  1094. }
  1095.  
  1096. sub open_close { my ($sec, $cnt, $entre) = @_;
  1097.   my ($txt) = '';
  1098.   my ($ind) = $hash_secinv{$sec};
  1099.   #ferme
  1100.   for (my $i = $#SECTIONS; $i >= $ind; $i--)
  1101.   {
  1102.     if ($cnt->[$i]) { $txt .= "</$SECTIONS[$i]>\n"; $cnt->[$i] = 0; }
  1103.   }
  1104.   #ouvre
  1105.   if (!$entre) {
  1106.     $txt .= "<$sec>"; $cnt->[$ind] = 1;
  1107.     $SEC_MIN_GLOBAL = $ind if ($ind < $SEC_MIN_GLOBAL && $ind);
  1108.   }
  1109.   $txt;
  1110. }
  1111.  
  1112. sub cnt_section { my ($sec, $cnt) = @_ ;
  1113.   my ($txt) = '';
  1114.   my ($ind) = $hash_secinv{$sec};
  1115.   $SEC_MIN_GLOBAL = $ind if ($ind < $SEC_MIN_GLOBAL && $ind);
  1116.   "<$sec>"
  1117.  }
  1118.  
  1119. sub store { my ($ref, $cle, $id, $text, $court) = @_ ;
  1120.    $ref->{$cle}{$id}=$text ;
  1121.    if (defined($court)) { $court =~ s/\[|\]//g ; $ref->{tittoc}{$id} = $court ; } ;
  1122.    '';
  1123.  }
  1124. sub store_option { my ($A) = @_ ; $A = join(' ' , split(',', $A)) ;
  1125.     if ($A =~ s/numero//) { $NUMERO = 1 ;} ;
  1126.     if ($A =~ s/index//) { $INDEX = 1 ;}
  1127.     if ($A =~ s/tooltip//) { $TOOLTIP = 1 ;}
  1128.     if ($A =~ s/depth\s*=\s*([0-8])//) { $depth = $1 ; }
  1129.     $OPTION .= $A ;
  1130.    '' ;
  1131.  }
  1132.  
  1133. sub store_include { my ($A) = @_ ; $A = join(' ' , split(',', $A)) ;
  1134.     if ($A =~ s/(\w*)\.(tex|sty)//) {
  1135.          if ($MACRO) {$MACRO .= ",$1.$2" } else {$MACRO = "$1.$2" }
  1136.     };
  1137.     if ($A =~ s/(\w*\.css)\b//) { if ($STYLE) {$STYLE .= ",$1" } else {$STYLE = $1 } };
  1138.     if ($A =~ s/embed\s*=\s*([^\}]+)//) { $EMBED = $1 ; }
  1139.    '' ;
  1140.  }
  1141.  
  1142. sub add { my ($a,$b)=@_ ;
  1143.     if ($a) {$a .= ",$b" } else {$a = $b }
  1144.  }
  1145.  
  1146. sub Init { my ($file, $ref_env, $ref_command, $ref, $ref_algo) = @_;
  1147.   my ($total, $TEXT) = (0, find_expand($file));
  1148.   my %hash_spec = (wims =>{}, verbatim =>{}, lstlisting => {});
  1149.   my $ref_spec = \%hash_spec;
  1150.   $TEXT = traite_special ($TEXT, $ref_spec->{wims}, $ref,'wims');
  1151.   $TEXT = traite_special ($TEXT, $ref_spec->{verbatim}, $ref,'verbatim');
  1152.   $TEXT = traite_special ($TEXT, $ref_spec->{lstlisting}, $ref,'lstlisting');
  1153.   $TEXT = traitement_initial ($TEXT);
  1154.   $TEXT =~ s/\\wimsoption\s*\{([^\}]+)\}/store_option($1)/eg ;
  1155.   $TEXT =~ s/\\makeindex/store_option('index')/eg ;
  1156.   $TEXT =~ s/\\wimsinclude\s*\{([^\}]+)\}/store_include($1)/eg ;
  1157.   $TEXT =~ s/\\(title|email|author|about)\s*(\[[^\]]+\])?\s*\{([^\}]+)\}/store($ref,$1,'main',$3,$2)/eg ;
  1158.   $TEXT =~ s/\\(tikzsetfigurename)\s*\{([^\}]+)\}/store($ref,$1,'main',$2,)/eg ;
  1159.   $TEXT = traite_preambule ($TEXT, $ref_env, $ref_command, $ref);
  1160.   for my $command (keys %{$ref_command->{definition}}) {
  1161.     $TEXT = Traite_command ($TEXT, $command, $ref_command);
  1162.   }
  1163.   for my $A (@liste_voca) {
  1164.    $ref_algo->{titre}{$A} = $ref_command->{definition}{"algorithmic\L$A\E"} if ($ref_command->{definition}{"algorithmic\L$A\E"}) ;
  1165. } ;
  1166.   $TEXT =~ s/wimsinsertion(\d*)/$ref_spec->{'wims'}{$1}/g;
  1167.   $TEXT =~ s/verbatiminsertion(\d*)/verbatim($ref_spec->{'verbatim'}{$1},$1)/eg;
  1168.   $TEXT =~ s/lstlistinginsertion(\d*)/lstlisting($ref_spec->{'lstlisting'}{$1},$1)/eg;
  1169.   $TEXT;
  1170. }
  1171.  
  1172. #sub store_makeindex { my ($txt) = @_ ;
  1173. #    $txt =~ s/\\printindex/\link{index}{Index}/ ;
  1174. #   }
  1175. sub traitement_final { my ($TEXT) = @_;
  1176.  #FIXME : je ne peux pas faire ca a cause des exercices de developpement dont l'adresse
  1177.  #contienne un ~. De toute facon
  1178.  #ca ne devrait pas exister, mais quand meme. ou les wims only
  1179. #   $TEXT =~ s/~/&nbsp;/g;
  1180.    $TEXT =~ s:(<br class="spacer">\s*<br class="spacer">):<br class="spacer">:g;
  1181.    $TEXT =~ s:<br class="spacer">\s*(</?div):$1:g;
  1182.    $TEXT =~ s:(class="minipage">)\s*<br class="spacer">:$1:g;
  1183.    $TEXT;
  1184. }
  1185.  
  1186. sub traitemath {my ($txt) = @_;
  1187.   my $test = 0;
  1188.   while ($txt =~ /\$\$/) {
  1189.     $txt = $` . ($test == 0 ? '<div class="math">\\(\\displaystyle{' : '}\\)</div>') . $';
  1190.     $test = 1-$test;
  1191.   }
  1192.   $txt;
  1193. }
  1194.  
  1195. sub traitement_initial { my ($TEXT) = @_;
  1196.   $TEXT =~ s/\s*$//; # strip trailing whitespace
  1197.   $TEXT =~ s/\r\n/\n/gs ;
  1198.   $TEXT = traitemath($TEXT);
  1199.   $TEXT =~ s/{\s*\\(bf|tt|it)\b/\\text$1\{/g;
  1200.   $TEXT =~ s/\\begin\b\s*/\\begin/g;
  1201.   $TEXT =~ s/\\end\b\s*/\\end/g;
  1202.   #$TEXT =~ s/\\text\b/\\hbox/g;
  1203.   $TEXT =~ s,\\\[,<p class="math">\\(,g;
  1204.   $TEXT =~ s,\\\],\\)</p>,g;
  1205.   $TEXT =~ s/\$([^\$]+)\$/\\( $1 \\)/g;
  1206.  
  1207.   $TEXT =~ s/\\`\s*\{a\}/à/g;
  1208.   $TEXT =~ s/\\\^\s*\{a\}/â/g;
  1209.   $TEXT =~ s/\\'\s*\{a\}/á/g;
  1210.   $TEXT =~ s/\\'\s*\{e\}/é/g;
  1211.   $TEXT =~ s/\\`\s*\{e\}/è/g;
  1212.   $TEXT =~ s/\\\^\s*\{e\}/ê/g;
  1213.   $TEXT =~ s/\\\^\s*\{i\}/î/g;
  1214.   $TEXT =~ s/\\\`\s*\{i\}/ì/g;
  1215.   $TEXT =~ s/\\\"\s*\{i\}/ï/g;
  1216.   $TEXT =~ s/\\\"\s*\{\\i\}/ï/g;
  1217.   $TEXT =~ s/\\\^\s*\{o\}/ô/g;
  1218.   $TEXT =~ s/\\\"\s*\{o\}/ö/g;
  1219.   $TEXT =~ s/\\\`\s*\{o\}/ò/g;
  1220.   $TEXT =~ s/\\\^\s*\{u\}/û/g;
  1221.   $TEXT =~ s/\\`\s*\{u\}/ù/g;
  1222.   $TEXT =~ s/\\c\s*\{c\}/ç/g;
  1223.  
  1224.   $TEXT =~ s/\\`\s*a/à/g;
  1225.   $TEXT =~ s/\\\^\s*a/â/g;
  1226.   $TEXT =~ s/\\'\s*a/á/g;
  1227.   $TEXT =~ s/\\'\s*e/é/g;
  1228.   $TEXT =~ s/\\`\s*e/è/g;
  1229.   $TEXT =~ s/\\\^\s*e/ê/g;
  1230.   $TEXT =~ s/\\`\s*E/È/g;
  1231.   $TEXT =~ s/\\\'\s*E/É/g;
  1232.   $TEXT =~ s/\\\^\s*E/Ê/g;
  1233.   $TEXT =~ s/\\\^\s*i/î/g;
  1234.   $TEXT =~ s/\\\`\s*i/ì/g;
  1235.   $TEXT =~ s/\\\"\s*i/ï/g;
  1236.   $TEXT =~ s/\\\^\s*o/ô/g;
  1237.   $TEXT =~ s/\\\"\s*o/ö/g;
  1238.   $TEXT =~ s/\\\`\s*o/ò/g;
  1239.   $TEXT =~ s/\\\^\s*u/û/g;
  1240.   $TEXT =~ s/\\`\s*u/ù/g;
  1241.   $TEXT =~ s/\\c \s*c/ç/g;
  1242.  
  1243.   $TEXT =~ s/\{\s*\\`\s*a\s*\}/à/g;
  1244.   $TEXT =~ s/\{\s*\\\^\s*a\s*\}/â/g;
  1245.   $TEXT =~ s/\{\s*\\'\s*a\s*\}/á/g;
  1246.   $TEXT =~ s/\{\s*\\'\s*e\s*\}/é/g;
  1247.   $TEXT =~ s/\{\s*\\`\s*e\s*\}/è/g;
  1248.   $TEXT =~ s/\{\s*\\\^\s*e\s*\}/ê/g;
  1249.   $TEXT =~ s/\{\s*\\\^\s*i\s*\}/î/g;
  1250.   $TEXT =~ s/\{\s*\\\`\s*i\s*\}/ì/g;
  1251.   $TEXT =~ s/\{\s*\\\"\s*i\s*\}/ï/g;
  1252.   $TEXT =~ s/\{\s*\\\^\s*o\s*\}/ô/g;
  1253.   $TEXT =~ s/\{\s*\\\"\s*o\s*\}/ö/g;
  1254.   $TEXT =~ s/\{\s*\\\`\s*o\s*\}/ò/g;
  1255.   $TEXT =~ s/\{\s*\\\^\s*u\s*\}/û/g;
  1256.   $TEXT =~ s/\{\s*\\`\s*u\s*\}/ù/g;
  1257.   $TEXT =~ s/\{\s*\\c \s*c\s*\}/ç/g;
  1258.   $TEXT =~ s/\\maketitle//g;
  1259.   $TEXT =~ s/\{\\textquotesingle\}/'/g;
  1260.   $TEXT =~ s/\\textquotesingle/'/g;
  1261.   $TEXT =~ s/\\guillemotleft/<</g;
  1262.   $TEXT =~ s/\\guillemotright/>>/g;
  1263. # MODIF YVES NOEL 19/09/2011 (debut)
  1264.   $TEXT =~ s/>>/&gt;&gt;/g;
  1265.   $TEXT =~ s/~~/&nbsp;&nbsp;/g;
  1266.   $TEXT =~ s/\\onslide\+<[0-9]*>//g;
  1267.   $TEXT =~ s/\\onslide<[0-9]*->//g;
  1268.   $TEXT =~ s/\\onslide<[0-9]*>//g;
  1269.   $TEXT =~ s/\\onslide\+<[0-9]*\-[0-9]*>//g;
  1270.   $TEXT =~ s/\\onslide<[0-9]*\-[0-9]*->//g;
  1271.   $TEXT =~ s/\\onslide<[0-9]*\-[0-9]*>//g;
  1272.   $TEXT =~ s/\[<\+->\]//g;
  1273.  
  1274. # MODIF YVES NOEL 19/09/2011 (fin)
  1275.   $TEXT =~ s/\{\}//g;
  1276.   $TEXT =~ s/\\selectlanguage\{french\}\\sffamily//g;
  1277.  
  1278.  #$TEXT =~ s/([^\\])\%+/$1/g;
  1279.   $TEXT =~ s/([^\\])\%.*/$1/g;
  1280.   $TEXT =~ s/\n\%.*/\n/g;
  1281.   $TEXT =~ s/\\\\\[\S*\]/\n\n/g;
  1282.   $TEXT =~ s/\\(vspace|hspace|vskip|hskip)\**{\S*}//g;
  1283.   $TEXT =~ s/\\parskip=*[a-z0-9 \.]+//g;
  1284.   $TEXT =~ s/\\(vskip|hskip)\s*[a-z0-9 \.]+//g;
  1285.   $TEXT =~ s/\\smallskip/\n/g;
  1286.   $TEXT =~ s/\\(med|big)skip/\n\n/g;
  1287. #  $TEXT =~ s/\\makebox\[(\w)cm\]{ }/\&nbsp\&nbsp\&nbsp/g;
  1288.   $TEXT =~ s/~(:|;|\?|\!)/&nbsp;$1/g;
  1289.  #utiliser verb uniquement dans le cas d'un mot
  1290. #FIXME: $TEXT =~ s/\verb"([^"]+)"/<tt class=verb>$1<\/tt>/g;
  1291.   $TEXT =~ s/\\includegraphics\s*\[(.*)\]\s*\{(.*)\}/includegraphics($2,$1)/eg;
  1292.   $TEXT =~ s/\\includegraphics\s*\{([^\}]+)\}/includegraphics($1)/eg;
  1293.   $TEXT =~ s/\\(begin|end)\{document\}/\\document /g;
  1294.   $TEXT =~ s/\\exercise\{module=([^\&]+)\&([^\}]+)\}\{([^\}]+)\}/store_sheet($1,$2,$3,$worksheet)/eg ;
  1295.   $TEXT =~ s/\\xspace//g;
  1296.   $TEXT = traite_beamer($TEXT) ;
  1297.   $TEXT;
  1298. }
  1299.  
  1300. sub traite_beamer { my ($TEXT) = @_;
  1301.    $TEXT =~ s/\\uncover\s*(<([^>]+)>)?\s*\{(.*)\}/\\fold\{.\}\{-->\}\{$3\}/g ;
  1302.    $TEXT =~ s/\s*\\frametitle\{([^\}]+)\}/store_frametitle($1)/ge;
  1303.    $TEXT =~ s/\\pause//g;
  1304.    $TEXT ;
  1305. }
  1306.  
  1307. sub store_frametitle{ my ($TEXT)= @_ ;
  1308.   "<div class=\"frametitle\">$TEXT</div>"
  1309. }
  1310. sub linewidth { my ($line,$w)= @_ ;
  1311.   $line =~ s/1\.[0]\s*\\(line|text)width/100\%/g;
  1312.   $line =~ s/0?\.([0-9])\s*\\(line|text)width/$1 0\%/g;
  1313.   $line =~ s/0?\.([0-9]\{2\})[0-9]?\s*\\(line|text)width/$1\%/g;
  1314.   $line =~ s/ //g;
  1315.   $line = "style=\"$w:$line\"" if ($w);
  1316.   $line ;
  1317. }
  1318. sub store_sheet { my ($ad1,$ad2,$titre,$worksheet) = @_;
  1319.    $ad2 =~ s/worksheet=(\d)+//g;
  1320.    $SHEET .= ":$ad1\n$ad2\n10\n1\n$titre\n\n";
  1321.    if ($worksheet) {
  1322.      "\\exercise\{module=$ad1\&$ad2\&worksheet=$worksheet\}\{$titre\}"
  1323.    }
  1324.    else {
  1325.       "\\exercise\{module=$ad1\&$ad2\}\{$titre\}"
  1326.    };
  1327. }
  1328.  
  1329. sub traite_preambule { my ($TEXT, $ref_env, $ref_command, $ref) = @_;
  1330.   if ($TEXT=~ s/\\usepackage\[([^]]+)\]\{algorithmic\}//) {
  1331.        $algo_noend = 1 if ($1 =~ /noend/);
  1332.   };
  1333.   $TEXT = recup_command($TEXT, $ref_command);
  1334.   $TEXT = traite_command($TEXT, $ref_command);
  1335.   $TEXT = recup_environ($TEXT, $ref_env);
  1336.  
  1337.   $TEXT = recup_embed($TEXT, $ref) ;
  1338.   for my $cmd ('ref','index') {
  1339.      $ref->{titb}{$cmd} = $ref_command->{definition}{$cmd . "name"}
  1340.   }
  1341.   $TEXT;
  1342. }
  1343.  
  1344. sub store_embed { my ($id, $titre, $ref) = @_ ;
  1345.      $ref->{titb}{$id} = $titre ; $ref->{text}{$id} = `cat $EMBED/$id` ;
  1346.      $ref->{upbl}{$id}='main'; $ref->{type}{$id}='embed';
  1347.      "\\embed\{$id\}\{$titre\}" ;
  1348. }
  1349.  
  1350. sub recup_embed { my ($TEXT, $ref) = @_ ;
  1351.      $TEXT =~ s /\\embed\s*\{([^\}]+)\}\s*\{(.*)\}/store_embed ($1, $2, $ref)/eg ;
  1352.      $TEXT ;
  1353.  }
  1354.  
  1355. #FIXME on ne peut prendre qu'un seul fichier de style
  1356. #cree le fichier 1/.def
  1357. sub def { my ($ref, @style) = @_;
  1358.   my $tit = $ref->{title}{main};
  1359.   my $aut = $ref->{author}{main};
  1360.   my $mail= $ref->{email}{main};
  1361.   my $datm= $ref->{datm}{main};
  1362.   my $header = '<link rel="stylesheet" href="html/themes/_css/l2w.css">';
  1363.   my $header_tmp ;
  1364.   for my $file (@style){
  1365.     if (!open(IN, $DIR . $file)) { die "le fichier $DIR$file n'existe pas";}
  1366.     open (IN, $DIR . $file);
  1367.     ($header_tmp = <IN>) =~ s/\n/\t/g;
  1368.     $header .= "\t $header_tmp" ;
  1369.   }
  1370.   close IN;
  1371.   $header .= "\t<script>"
  1372.    . "jQuery\(function\(\) \{jQuery\( \"#left_toc\" \).menu\(\);\}\);"
  1373.    . "jQuery\(function\(\) \{jQuery\( \"#right_toc\" \).menu\(\);\}\);"
  1374.    . "</script>" if ($TOOLTIP==1);
  1375.  
  1376. "copyright=gnu
  1377. docopen=yes
  1378. dlang=fr
  1379. tit=$tit
  1380. author=$aut
  1381. email=$mail
  1382. header=$header
  1383. datm=$datm";
  1384. }
  1385. #TODO en fait il faudrait renvoyer dans le cas ou le fichier est de type fold a la page en dessus
  1386. # depliee. Je ne suis pas sure de savoir faire ! sinon, on perd la table des matieres.
  1387.  
  1388. sub store_ref { my ($link, $titre, $anchor, $ref_bloc) = @_;
  1389.   my $txt = '' ;
  1390.   my @list = (split(',', $link)) ;
  1391.   for my $l (@list) {
  1392.   dbg("... reference fichier: \"$l\" titre \"$l\"");
  1393.   my $page = $ref_bloc->{fichier}{$l} ;
  1394.   warn "label $link n'existe pas" if !($page) ;
  1395.   $txt .= ($#list) ? " \\link\{$page\}\{$l\}\{$anchor\}":
  1396.              " \\link\{$page\}\{$titre\}\{$anchor\}";
  1397.  }
  1398.  $txt ;
  1399. };
  1400.  
  1401. #cree la page
  1402.  
  1403. sub toc_HTML {my ($text, $toc_g, $toc_d, $toc_p, $CHEMIN_up, $CHEMIN_down, $index,$type) = @_ ;
  1404.    my $s='' ;
  1405.    $s= "l" if($toc_g || $toc_p) ; $s .= "r" if($toc_d) ;
  1406.   if (($toc_g) || ($toc_d) || ($toc_p)) {
  1407.     $CHEMIN_up . '<div class="doc_latex2wims' . $s . '">'
  1408.    . (($toc_g) ? '<ul id="left_toc" class="left_toc">'. $toc_g . $index . '</ul>' : '')
  1409.    . '<div class="wimsdoc">' . $text . '</div>'
  1410.    . (($toc_d) ? '<ul id="right_toc" class="right_toc">' . $toc_d . '</ul>' : '')
  1411.    . (($toc_p && !$toc_g) ? '<ul id="left_toc" class="left_toc">' . $toc_p . '</ul>' : '')
  1412.    . $CHEMIN_down .
  1413.    '</div>';
  1414.    }
  1415.    else {
  1416.     if (!(defined $type) || $type=~/fold|embed/) {$CHEMIN_up . $text . $CHEMIN_down }
  1417.       else {'<div class="wimsdoc">' . $CHEMIN_up . $text . $CHEMIN_down . '</div>'};
  1418.     }
  1419.  }
  1420.  
  1421.  #################################
  1422.  
  1423. sub store_algo { my ($txt, $acc, $cmd, $comment, $indent) = @_ ;
  1424.   $txt .= " " . $acc ;
  1425.   $txt .= $hash_algo{titre}{$hash_algo{suite}{$cmd}} if ($hash_algo{suite}{$cmd}) ;
  1426.   $indent = $indent + $hash_algo{avant}{$cmd} ;
  1427.   if($hash_algo{titre}{$cmd}) {
  1428.    $txt = "\n" . indent($indent) . $hash_algo{titre}{$cmd} . $txt if ( !($cmd =~ /END/) || $algo_noend == 0);
  1429.   }
  1430.   else
  1431.   {
  1432.    $txt = "\n" . indent($indent) . $txt if ( !($cmd =~ /END/) || $algo_noend == 0);
  1433.   }
  1434.   $txt .= indent('3') . "\{<i>$comment</i>\}" if ($comment) ;
  1435.   $txt .= "\n" ;
  1436.   $txt =~ s/\n+/\n/ ;
  1437.   $indent += $hash_algo{apres}{$cmd} ;
  1438.   ($txt, $indent) ;
  1439. }
  1440.  
  1441. sub algorithm { '<div class="algorithm">' . algorithmic (@_) . '</div>' } ;
  1442.  
  1443. sub algorithmic { my ($Text) = @_;
  1444.   my $text ='' ; my $indent = 0 ;
  1445.   my @T = split('\n', $Text);
  1446.   for my $i (1..$#T) {
  1447.     my $ligne = $T[$i];
  1448.  #   $ligne =~ s/\$([^\$]+)\$/$1/g;
  1449.   #  $ligne =~ s/\\\(//g;
  1450.  #   $ligne =~ s/\\\)//g;
  1451.     $ligne =~ s/\$([^\$]+)\$/\\( $1 \\)/g;
  1452.     $ligne =~ s/^\[H\]//;
  1453.     next if ($ligne =~ /\\begin\{algorithmic\}\[1\]/);
  1454.     $ligne = "\n\n" if ($ligne =~ /\\end\{algorithmic\}/);
  1455.     $ligne =~ s/\\caption\s*\{\s*([^\}]*)\}/<h4 class=\"algo_titre\"> $1 <\/h4>/;
  1456.     $ligne =~ s/\\cdots/.../g;
  1457.     $ligne =~ s/\\geq/>=/g;
  1458.     $ligne =~ s/\\leq/<=/g;
  1459.     $ligne =~ s/\\bmod/mod/g;
  1460. #    $ligne =~ s/\[/<i>/g;
  1461. #    $ligne =~ s/\]/<\/i>/g;
  1462.     my $cle = 'FOR|WHILE|IF|UNTIL|ELSE|ELSIF|REQUIRE|ENSURE|STATE|ENDFOR|ENDWHILE|ENDIF' ;
  1463.     if ($ligne =~ /\s*\\($cle)\s*(\[[^\]]+\]*)?\{([^\n]+)\}\s*([^\n]*)/) {
  1464.          ($ligne,$indent) = store_algo($3, $4, $1, $2, $indent) ;
  1465.     }
  1466.     if ($ligne =~ /\s*\\($cle)\s*(\[[^\]]+\]*)?\s*([^\n]*)/) {($ligne,$indent) = store_algo('',$3, $1, $2, $indent);}
  1467. # TODO accepter des commentaires de plusieurs lignes ; presentation
  1468. # des commentaires ?
  1469.     if ($ligne =~ /^\s*\\COMMENT/) { $ligne = "<i>$ligne</i>\n" };
  1470.     $text .= "\n" . $ligne;
  1471.     $text =~ s/\n{2,}/\n/g;
  1472.     $text =~ s/(<br\s*\/>)+/<br>/g;
  1473.   }
  1474.   $text =~ s/\n/<br>/g;
  1475.   $text ;
  1476. }
  1477.  
  1478. sub indent { my $espace = "&nbsp;" x  6 ; $espace x $_[0]; }
  1479.  
  1480. sub Numero { my ($id) = @_;
  1481.   return '' if ($id =~ /F_[^S]\d/) || ($id =~ /L_/); #cela ne provient pas d'une section et co
  1482.   $id =~ s /(F|L)_//g;
  1483.   $id =~ s/mainS(\d+)/&Roman($1)/e;
  1484.   $id =~ s/S(\d+)S(\d+)S(\d+)/-$1-$2-$3/;
  1485.   $id =~ s/S(\d+)S(\d+)/-$1-$2/;
  1486.   $id =~ s/S(\d+)/-$1/;
  1487.   $id;
  1488. }
  1489.  
  1490. # permet de faire modifier quelque chose dans la table pour un tag
  1491. #TODO j'ai rajoute l'option couleur, du coup je ne sais plus faire fonctionner le shif
  1492. sub selection { my ($text, $couleur, @tag) = @_ ;
  1493.   return '' if !defined($text);
  1494.   for my $ta (@tag) {
  1495.     $text =~ s/XXXX="$ta">/li class="$couleur">/g;
  1496.     $text =~ s/YYYY="$ta">/\/li>/g;
  1497.   };
  1498.   $text;
  1499. }
  1500.  
  1501. sub clean { my ($text, $ref) = @_;
  1502.    return '' if !defined($text);
  1503.    $text =~ s/<XXXX="\w*">/<li class="no_selected">/g;
  1504.    $text =~ s/<YYYY="\w*">/<\/li>/g;
  1505.    $text =~ s/ZZZZZ(\w+)/store_tip($1,$ref)/ge;
  1506.    $text;
  1507. }
  1508.  
  1509. sub store_tip { my ($tag, $ref)=@_ ;
  1510.   my $tip = $ref->{toctip}{$tag} ;
  1511.   my $title=$ref->{tittoc}{$tag} ;
  1512.   #$tip =~ s/'/\\\\'/g if ($tip) ;
  1513.   $title =~ s/'/\\\\'/g if ($title) ;
  1514.   $ref->{toctip}{$tag} ? "<ul>$tip</ul>" : '' ;
  1515. }
  1516.  
  1517. sub chemin { my ($tag, $ref) = @_;
  1518.   my $tagsup = $tag;
  1519.   my $ch = $tag;
  1520.   my $txt = ($ref->{tittoc}{$tagsup}) ? $ref->{tittoc}{$tagsup} : $ref->{titb}{$tagsup} ;
  1521.   my $niv = 0;
  1522.   while ($tagsup !~ /^main\b/) {
  1523.     $niv++;
  1524.     $tagsup = $ref->{upbl}{$tagsup};
  1525.     $ch = "$tagsup,$ch"; if (!$ref->{tittoc}{$tagsup}) { $ref->{tittoc}{$tagsup}=$tagsup};
  1526.     $txt = "\\link\{$tagsup\}\{$ref->{tittoc}{$tagsup}\} $FLECHE $txt" if ($tagsup) ; #if ($tagsup !~ /^main\b/);
  1527.   }
  1528.   $ref->{chemin}{$tag} = $ch;
  1529.   $ref->{niveau}{$tag} = $niv;
  1530.   return if (!$txt);
  1531.   '<div class="wims_chemin">' . "$LOAD $linkout $txt" . '</div>';}
  1532.  
  1533. sub sortuniq {
  1534.   my $prev = "not $_[0]";
  1535.   grep { $_ ne $prev && ($prev = $_, 1) } sort @_;
  1536. }
  1537.  
  1538. sub isotime {
  1539.     my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
  1540.     $year += 1900;
  1541.     $mon += 1 ; $mday += 1 ;
  1542.     $mday = sprintf("%02d", $mday);
  1543.     $mon = sprintf("%02d", $mon);
  1544.     "$year-$mon-$mday $hour:$min:$sec";
  1545. }
  1546.  
  1547.  sub usage {
  1548.   print STDERR << "EOT"
  1549. latex2wims [--style=style.css] [--macro=wims.sty] [--dir=dossier1] [--docdir=dossier2] [--embed=dossier3] [--verbose] file
  1550.  
  1551.   --style=style.css : style.css fichier de style css à utiliser
  1552.      (peut aussi être mis dans le fichier file : \\wimsinclude{style.css})
  1553.   --macro=wims.sty : wims.sty fichier de style a utiliser
  1554.      (peut aussi être mis dans le fichier file : \\wimsinclude{wims.sty})
  1555.   --dir=dossier1 : dossier1 est le repertoire où se trouvent tous les fichiers dont le fichier file
  1556.   --docdir=dossier2 : dossier2 est le repertoire dans lequel sera cree le document
  1557.      (un dossier dans le compte Modtool par exemple)
  1558.   --embed=dossier3 : les fichiers de dossier3 sont appeles dans file
  1559.      par la commande \embed{} (pour expert)
  1560.   --verbose : details
  1561. EOT
  1562. ;
  1563.   exit 1;
  1564. }
  1565.  
  1566. ##======================================================================##
  1567. ## Adapted from work by OZAWA Sakuro <ozawa@prince.pe.u-tokyo.ac.jp>
  1568. ## Copyright (c) 1995 OZAWA Sakuro. All rights reserved. This
  1569. ## program is free software; you can redistribute it and/or modify
  1570. ## it under the same terms as Perl itself.
  1571. ##======================================================================##
  1572.  
  1573. sub Roman { my($arg) = shift;
  1574.   my %roman_digit = qw(1 IV 10 XL 100 CD 1000 MMMMMM);
  1575.   my @figure = reverse sort keys %roman_digit;
  1576.   grep($roman_digit{$_} = [split(//, $roman_digit{$_}, 2)], @figure);
  1577.   0 < $arg and $arg < 4000 or return undef;
  1578.   my($x, $roman);
  1579.   foreach (@figure) {
  1580.     my($digit, $i, $v) = (int($arg / $_), @{$roman_digit{$_}});
  1581.     if (1 <= $digit and $digit <= 3) {
  1582.       $roman .= $i x $digit;
  1583.     } elsif ($digit == 4) {
  1584.       $roman .= "$i$v";
  1585.     } elsif ($digit == 5) {
  1586.       $roman .= $v;
  1587.     } elsif (6 <= $digit and $digit <= 8) {
  1588.       $roman .= $v . $i x ($digit - 5);
  1589.     } elsif ($digit == 9) {
  1590.       $roman .= "$i$x";
  1591.     }
  1592.     $arg -= $digit * $_;
  1593.     $x = $i;
  1594.   }
  1595.   $roman
  1596.  }
  1597.