config-fonctions.php3 inc.php inc_config.php3 inc_majbase.php3 inc_ortho.php inc_version.php3 lab_ortho.php 1.66 1.1 1.51 1.10 1.1 1.350 NONE 1.67 1.2 1.52 1.11 NONE 1.351 1.1

Update of /home/spip-cvs/spip/ecrire
In directory alan:/tmp/cvs-serv5218/ecrire

Modified Files:
  config-fonctions.php3 inc.php inc_config.php3 inc_majbase.php3
  inc_version.php3
Added Files:
  lab_ortho.php
Removed Files:
  inc_ortho.php
Log Message:
preparation d'une 1.8b1

Index: inc.php

RCS file: /home/spip-cvs/spip/ecrire/inc.php,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- inc.php 27 Aug 2004 18:55:23 -0000 1.1
+++ inc.php 27 Aug 2004 21:29:33 -0000 1.2
@@ -20,8 +20,8 @@
           break;
         default:
           // charger la version spip-lab si presente
- if (@file_exists($dir_ecrire.'inc_'.$fichier))
- include_ecrire('inc_'.$fichier);
+ if (@file_exists($dir_ecrire.'lab_'.$fichier))
+ include_ecrire('lab_'.$fichier);
           // sinon prendre la version spip-stable
           else
             if (@file_exists($dir_ecrire.'inc_'.$fichier.'3'))

Index: config-fonctions.php3

RCS file: /home/spip-cvs/spip/ecrire/config-fonctions.php3,v
retrieving revision 1.66
retrieving revision 1.67
diff -u -d -r1.66 -r1.67
--- config-fonctions.php3 26 Aug 2004 03:47:01 -0000 1.66
+++ config-fonctions.php3 27 Aug 2004 21:29:32 -0000 1.67
@@ -277,12 +277,41 @@
   echo "</div>";
     echo "<div style='text-align:$spip_lang_right'><INPUT TYPE='submit' NAME='Valider' VALUE='"._T('bouton_valider')."' CLASS='fondo'></div>";
   
-fin_cadre_trait_couleur();
+ fin_cadre_trait_couleur();

   echo "<p>";
}

//
+// Correcteur d'orthographe
+//
+
+debut_cadre_trait_couleur("ortho-24.gif", false, "", _L('Orthographe'));
+ $articles_ortho = lire_meta("articles_ortho");
+
+ echo "<div class='verdana2'>";
+ echo _L('Un v&eacute;rificateur d\'orthographe est int&eacute;gr&eacute; &agrave; SPIP. Toutefois, avant d\'activer cette fonctionnalit&eacute;, veuillez lire avec attention le paragraphe suivant&nbsp;:');
+ echo "</div>";
+
+ echo "<div class='verdana2'>";
+ echo "<blockquote class='spip'>";
+ echo _L('Pour v&eacute;rifier l\'orthographe d\'un texte, le site va envoyer la liste des mots &agrave; contr&ocirc;ler vers l\'un des &laquo;&nbsp;serveurs d\'orthographe&nbsp;&raquo; externes mis &agrave; votre disposition par diff&eacute;rents membres de la communaut&eacute; SPIP. Les mots sont envoy&eacute;s dans le d&eacute;sordre afin d\'assurer un minimum de confidentialit&eacute;. Si vous avez des craintes pour vos donn&eacute;es, n\'activez pas cette option (et retirez tout de suite vos informations du Web).');
+ echo "</blockquote>\n";
+ echo "</div>";
+
+ echo "<div class='verdana2'>";
+ afficher_choix('articles_ortho', $articles_ortho,
+ array('oui' => _L('Activer le v&eacute;rificateur d\'orthographe'),
+ 'non' => _L('D&eacute;sactiver le v&eacute;rificateur d\'orthographe')));
+ echo "</div>";
+ echo "<div style='text-align:$spip_lang_right'><INPUT TYPE='submit' NAME='Valider' VALUE='"._T('bouton_valider')."' CLASS='fondo'></div>";
+
+ fin_cadre_trait_couleur();
+
+ echo "<p>";
+
+
+//
// Previsualisation sur le site public
//

--- NEW FILE: lab_ortho.php ---
<?php

// Ce fichier ne sera execute qu'une fois
if (defined("_ECRIRE_INC_ORTHO")) return;
define("_ECRIRE_INC_ORTHO", "1");

// Mettre a jour la liste locale des miroirs
function maj_miroirs_ortho() {
  $liste = explode(" ", lire_meta("liste_miroirs_ortho"));
  $miroirs_old = array();
  foreach ($liste as $index) {
    list($url) = explode(" ", lire_meta("miroir_ortho_$index"));
    $miroirs_old[$url] = $index;
  }

  // TODO: recuperer la liste dynamiquement depuis ortho.spip.net
  $urls = array(
    'http://tony.ortho.spip.net/ortho_serveur.php’,
    'http://ortho.spip.net/ortho_serveur.php’,
    'http://spip-ortho.linagora.org:18080/ortho_serveur.php
  );
  $liste = array();
  $miroirs_new = array();
  $index = 1;
  foreach ($urls as $url) {
    if ($miroirs_old[$url]) {
      $s = lire_meta("miroir_ortho_$index");
    }
    else {
      $s = $url." ".time();
    }
    $miroirs_new[$index] = $s;
    $liste = $index++;
  }
  foreach ($miroirs_old as $index) {
    effacer_meta("miroir_ortho_$index");
  }
  foreach ($miroirs_new as $index => $s) {
    ecrire_meta("miroir_ortho_$index", $s);
  }
  ecrire_meta("liste_miroirs_ortho", join(" ", $liste));
}

// Lire la liste des miroirs et les langues associees
function lire_miroirs_ortho() {
  global $miroirs_ortho, $index_miroirs_ortho, $duree_cache_miroirs_ortho;

  $miroirs_ortho = array();
  $index_miroirs_ortho = array();

  $t = time();
  $maj = lire_meta("maj_miroirs_ortho");
  if ($maj < $t - $duree_cache_miroirs_ortho) {
    maj_miroirs_ortho();
    ecrire_meta("maj_miroirs_ortho", $t);
    lire_metas();
  }

  $liste = explode(" ", lire_meta("liste_miroirs_ortho"));
  foreach ($liste as $index) {
    $s = explode(" ", lire_meta("miroir_ortho_$index"));
    $url = $s[0];
    $maj = $s[1];
    $langs = explode(",", $s[2]);
    // Reinitialiser periodiquement la liste des langues non-supportees
    if ($maj < $t - $duree_cache_miroirs_ortho) {
      foreach ($langs as $lang)
        if (substr($lang, 0, 1) == '!') unset($langs[$lang]);
      $s[1] = $t;
      $s[2] = join(",", $langs);
      ecrire_meta("miroir_ortho_$index", join(" ", $s));
    }
    $index_miroirs_ortho[$url] = $index;
    $miroirs_ortho[$url] = array();
    foreach ($langs as $lang) {
      if ($lang) $miroirs_ortho[$url][$lang] = $lang;
    }
  }
  srand(time());
}

// Sauvegarder les infos de langues pour le miroir
function ecrire_miroir_ortho($url, $langs) {
  global $index_miroirs_ortho;

  $index = $index_miroirs_ortho[$url];
  $s = explode(" ", lire_meta("miroir_ortho_$index"));
  $s[2] = join(",", $langs);
  ecrire_meta("miroir_ortho_$index", join(" ", $s));
}

function ajouter_langue_miroir($url, $lang) {
  global $miroirs_ortho;
  $langs = $miroirs_ortho[$url];
  $langs[$lang] = $lang;
  unset($langs["!$lang"]);
  ecrire_miroir_ortho($url, $langs);
}

function enlever_langue_miroir($url, $lang) {
  global $miroirs_ortho;
  $langs = $miroirs_ortho[$url];
  unset($langs[$lang]);
  $langs["!$lang"] = "!$lang";
  ecrire_miroir_ortho($url, $langs);
}

//
// Renvoie la liste des miroirs utilisables pour une langue donnee
//
function chercher_miroirs_ortho($lang) {
  global $miroirs_ortho;
  
  $result = array();
  $chercher = true;
  foreach ($miroirs_ortho as $url => $langs) {
    if ($langs[$lang]) {
      $result = $url;
    }
    else if ($chercher && !$langs["!$lang"]) {
      //echo "test $lang $url<br />";
      if (verifier_langue_miroir($url, $lang)) $result = $url;
      // Ne recuperer la langue d'un miroir qu'une seule fois par requete
      if ($result) $chercher = false;
    }
  }
  return $result;
}

function choisir_miroir_ortho($lang) {
  $miroirs = chercher_miroirs_ortho($lang);
  if (!($n = count($miroirs))) return false;
  return $miroirs[($n > 1) ? rand(0, $n - 1) : 0];
}

//
// Envoyer une requete a un serveur d'orthographe
//
function post_ortho($url, $texte, $lang) {
  $errno = $errstr = "";

  $t = parse_url($url);
  if ($t['scheme'] != 'http') return false;
  $host = $t['host'];
  $port = $t['port'] ? $t['port'] : 80;
  $path = $t['path'] ? $t['path'] : "/";

  // Envoyer la requete en POST
  $f = @fsockopen($host, $port, $errno, $errstr, 2);
  if (!$f) return false;
  fputs($f, "POST $path HTTP/1.0\r\n");

  // Si le texte est petit, l'overhead du multipart est dispendieux
  if (!$GLOBALS['flag_gz'] || strlen($texte) < 200) {
    $gz = false;
    $body = "op=spell&lang=".urlencode($lang)."&texte=".urlencode($texte);
    fputs($f, "Content-Type: application/x-www-form-urlencoded\r\n");
  }
  // Sinon, on passe en multipart pour compresser la chaine a corriger
  else {
    // Il faut eliminer les caracteres 0 sinon PHP ne lit pas la suite du parametre
    // passe en multipart/form-data (gros hack bien sale)
    $texte_gz = gzcompress($texte);
    for ($echap = 255; $echap > 0; $echap--) {
      $str_echap = chr($echap ^ 1).chr($echap).chr($echap).chr($echap ^ 2);
      if (!is_int(strpos($texte_gz, $str_echap))) break;
    }
    $texte_gz = str_replace("\x00", $str_echap, $texte_gz);
    $gz = true;
    $vars = array('op' => 'spell', 'lang' => $lang, 'texte' => $texte_gz, 'gz' => 1, 'nul_echap' => $str_echap);
    $boundary = substr(md5(rand().'ortho'), 0, 8);
    $body = '';
    foreach ($vars as $key => $val) {
      $body .= "\r\n--$boundary\r\n";
      $body .= "Content-Disposition: form-data; name=\"$key\"\r\n";
      $body .= "\r\n";
      $body .= $val;
    }
    $body .= "\r\n--$boundary\r\n";
    fputs($f, "Content-Type: multipart/form-data; boundary=$boundary\r\n");
  }

  // On envoie le contenu
  fputs($f, "Content-Length: ".strlen($body)."\r\n");
  fputs($f, "Host: $host\r\n\r\n");
  fputs($f, $body);

  // Lire les en-tetes HTTP de la reponse et decoder le Content-Length
  $length = 0;
  $s = fgets($f, 1000);
  $statut = 0;
  if (preg_match(',^HTTP/\d+\.\d+ (\d+) ,', $s, $r))
    $statut = intval($r[1]);
  if ($statut != 200) {
    fclose($f);
    return false;
  }
  while ($s = trim(fgets($f, 1000))) {
    if (preg_match(',Content-Length:(.*),i', $s, $r))
      $length = intval($r[1]);
  }
  $r = "";

  // Lire le corps de la reponse HTTP
  if ($length) {
    while (($l = strlen($r)) < $length) $r .= fread($f, $length - $l);
  }
  else while (!feof($f) AND $r .= fread($f, 1024));

  fclose($f);
  if ($gz) $r = gzuncompress($r);
  return $r;
}

//
// Verifier si un serveur gere une langue donnee
//
function verifier_langue_miroir($url, $lang) {
  // Envoyer une requete bidon
  $result = post_ortho($url, " ", $lang);
  //if (!$result) return false;
  if (preg_match(',<ortho>.*</ortho>,s', $result) &&
    !preg_match(',<erreur>.*<code>E_LANG_ABSENT</code>.*</erreur>,s', $result)) {
    ajouter_langue_miroir($url, $lang);
    return true;
  }
  enlever_langue_miroir($url, $lang);
  return false;
}

//
// Gestion du dictionnaire local
//
function suggerer_dico_ortho(&$mots, $lang) {
  $lang = addslashes($lang);
  $query = "SELECT mot FROM spip_ortho_dico WHERE lang='$lang' ".
    "AND mot IN ('".join("', '", array_map('addslashes', $mots))."')";
  $result = spip_query($query);

  $mots = array_flip($mots);
  $bons = array();
  if (isset($mots[''])) unset($mots['']);
  while ($row = spip_fetch_array($result)) {
    $mot = $row['mot'];
    if (isset($mots[$mot])) {
      unset($mots[$mot]);
      $bons = $mot;
    }
  }

  if (count($mots)) $mots = array_flip($mots);
  else $mots = array();
  return $bons;
}

function ajouter_dico_ortho($mot, $lang) {
  global $connect_id_auteur;

  $lang = addslashes($lang);
  $mot = addslashes($mot);
  $id_auteur = intval($connect_id_auteur);
  $query = "INSERT IGNORE INTO spip_ortho_dico (lang, mot, id_auteur) ".
    "VALUES ('$lang', '$mot', '$id_auteur')";
  spip_query($query);
}

function supprimer_dico_ortho($mot, $lang) {
  $lang = addslashes($lang);
  $mot = addslashes($mot);
  $query = "DELETE FROM spip_ortho_dico WHERE lang='$lang' AND mot='$mot'";
  spip_query($query);
}

function gerer_dico_ortho($lang) {
  global $ajout_ortho, $supp_ortho;
  if ($mot = strval($ajout_ortho)) {
    ajouter_dico_ortho($mot, $lang);
  }
  if ($mot = strval($supp_ortho)) {
    supprimer_dico_ortho($mot, $lang);
  }
}

//
// Gestion du cache de corrections
//
function suggerer_cache_ortho(&$mots, $lang) {
  global $duree_cache_ortho;

  $lang = addslashes($lang);
  $query = "SELECT mot, ok, suggest FROM spip_ortho_cache WHERE lang='$lang' ".
    "AND mot IN ('".join("', '", array_map('addslashes', $mots))."') ".
    "AND maj > FROM_UNIXTIME(".(time() - $duree_cache_ortho).")";
  $result = spip_query($query);
  
  $mots = array_flip($mots);
  $suggest = array();
  if (isset($mots[''])) unset($mots['']);
  while ($row = spip_fetch_array($result)) {
    $mot = $row['mot'];
    if (isset($mots[$mot])) {
      unset($mots[$mot]);
      if (!$row['ok']) {
        if (strlen($row['suggest']))
          $suggest[$mot] = explode(",", $row['suggest']);
        else
          $suggest[$mot] = array();
      }
    }
  }
  if (count($mots)) $mots = array_flip($mots);
  else $mots = array();
  return $suggest;
}

function ajouter_cache_ortho($tous, $mauvais, $lang) {
  global $duree_cache_ortho;

  $values = array();
  $lang = addslashes($lang);
  if (count($mauvais)) {
    foreach ($mauvais as $mot => $suggest) {
      $values = "('$lang', '".addslashes($mot)."', 0, '".addslashes(join(",", $suggest))."')";
    }
  }
  if (count($tous)) {
    foreach ($tous as $mot) {
      if (!isset($mauvais[$mot]))
        $values = "('$lang', '".addslashes($mot)."', 1, '')";
    }
  }
  if (count($values)) {
    $query = "DELETE FROM spip_ortho_cache ".
      "WHERE maj < FROM_UNIXTIME(".(time() - $duree_cache_ortho).")";
    spip_query($query);
    $query = "INSERT IGNORE INTO spip_ortho_cache (lang, mot, ok, suggest) ".
      "VALUES ".join(", ", $values);
    spip_query($query);
  }
}

//
// Cette fonction doit etre appelee pour reecrire le texte en utf-8 "propre"
//
function preparer_ortho($texte, $lang) {
  include_spip("charsets.php");

  $charset = lire_meta('charset');

  if ($charset == 'utf-8')
    return unicode_to_utf_8(html2unicode($texte));
  return unicode_to_utf_8(html2unicode(charset2unicode($texte, $charset, true)));
}

function afficher_ortho($texte) {
  $charset = lire_meta('charset');
  if ($charset == 'utf-8') return $texte;

  if (!is_array($texte)) return charset2unicode($texte, 'utf-8');
  foreach ($texte as $key => $val) {
    $texte[$key] = afficher_ortho($val);
  }
  return $texte;
}

//
// Cette fonction envoie le texte prepare a un serveur d'orthographe
// et retourne un tableau de mots mal orthographies associes chacun a un tableau de mots suggeres
//
function corriger_ortho($texte, $lang, $charset = 'AUTO') {
  include_spip("charsets.php");
  include_spip("index.php");
  include_spip("filtres.php");

  $texte = preg_replace(',<code>.*?</code>,is', '', $texte);
  $texte = preg_replace(',<cadre>.*?</cadre>,is', '', $texte);
  $texte = preg_replace(',\[([^]*)->([^]*)\],is', '\\1', $texte);
  $texte = supprimer_tags($texte);

  $texte = " ".$texte." ";
  
  // Virer les caracteres non-alphanumeriques
  if (test_pcre_unicode()) {
    $texte = preg_replace(',[^-\''.pcre_lettres_unicode().']+,us', ' ', $texte);
  }
  else {
    // Ici bidouilles si PCRE en mode UTF-8 ne fonctionne pas correctement ...
    // Guillemets francais (plage iso-latin)
    $trans = array(chr(194).chr(171) => ' ', chr(194).chr(187) => ' ');
    $texte = strtr($texte, $trans);
    // Saloperies non-conformes
    $trans = array(chr(194).chr(133) => ' ', chr(194).chr(150) => ' ', chr(194).chr(151) => ' ');
    $texte = strtr($texte, $trans);
    // Plage ponctuation de 0x2000 a 0x206F
    // (i.e. de 226-128-128 a 226-129-176)
    $texte = preg_replace(",\xE2(\x80[\x80-\xBF]|\x81[\x80-\xAF]),", ' ', $texte);
    // Caracteres ASCII non-alphanumeriques
    $texte = preg_replace(",[^-a-zA-Z0-9\x80-\xFF']+,", ' ', $texte);
  }
  $texte = preg_replace(',\s[-\']+,', ' ', $texte); // tirets de typo
  $texte = preg_replace(',\'\s,', ' ', $texte); // apostrophes utilisees comme guillemets
  $texte = preg_replace(',\s+,', ' ', $texte);

  // Virer les mots contenant au moins un chiffre
  $texte = preg_replace(', ([^ ]*\d[^ ]* )+,', ' ', $texte);

  // Melanger les mots
  $mots = preg_split(',\s+,u', $texte);
  sort($mots);
  $mots = array_unique($mots);

  // 1. Enlever les mots du dico local
  $bons = suggerer_dico_ortho($mots, $lang);

  // 2. Enlever les mots du cache local
  $result_cache = suggerer_cache_ortho($mots, $lang);

  // 3. Envoyer les mots restants a un serveur
  $mauvais = array();

  if (count($mots)) {
    #echo count($mots);
    $texte = join(' ', $mots);
    $url = choisir_miroir_ortho($lang);
    $xml = post_ortho($url, $texte, $lang);
    if (!$xml) return false;
    if (!preg_match(',<ortho>(.*)</ortho>,s', $xml, $r)) return false;
    $xml = $r[1];
    $erreur = false;
    if (preg_match(',<erreur>.*<code>(.*)</code>.*</erreur>,s', $xml, $r))
      $erreur = $r[1];
    if (!preg_match(',<ok>(.*)</ok>,s', $xml, $r))
      return $erreur;

    // Remplir le tableau des resultats (mots mal orthographies)
    $ok = $r[1];
    while (preg_match(',<mot>(.*?)</mot>(\s*<suggest>(.*?)</suggest>)?,s', $ok, $r)) {
      $p = strpos($ok, $r[0]);
      $ok = substr($ok, $p + strlen($r[0]));
      $mot = $r[1];
      if ($suggest = $r[3]) {
        $mauvais[$mot] = preg_split('/[\s,]+/', $suggest);
      }
      else {
        $mauvais[$mot] = array();
      }
    }
  }
  if (!$erreur) ajouter_cache_ortho($mots, $mauvais, $lang);

  // Retour a l'envoyeur
  $mauvais = array_merge($result_cache, $mauvais);
  $result = array(
    'bons' => $bons,
    'mauvais' => $mauvais
  );
  if ($erreur) $result['erreur'] = $erreur;
  return $result;
}

//
// Fonctions d'affichage HTML
//

function panneau_ortho($ortho_result) {
  global $id_suggest;

  $id_suggest = array();
  $i = 1;

  $mauvais = $ortho_result['mauvais'];
  $bons = $ortho_result['bons'];
  if (!count($mauvais) && !count($bons)) return;
  ksort($mauvais);

  echo "<script type='text/javascript'><!--
  var curr_suggest = null;
  function suggest(id) {
    var menu_box;
    if (curr_suggest)
      document.getElementById('suggest' + curr_suggest).className = 'suggest-inactif';
    if (1 || id!=curr_suggest) {
      document.getElementById('suggest' + id).className = 'suggest-actif';
      curr_suggest = id;
    }
    else curr_suggest = null;
    menu_box = document.getElementById('select_ortho');
    if (menu_box.length > id) menu_box.selectedIndex = id;
  }";
  echo "//--></script>";

  echo "<form class='form-ortho verdana2' action='' method='get'>\n";
  echo "<select name='select_ortho' id='select_ortho' onChange='suggest(this.selectedIndex);'>\n";
  echo "<option value='0'>"._L("... mots &agrave; corriger ...")."</option>\n";
  foreach ($mauvais as $mot => $suggest) {
    $id = $id_suggest[$mot] = "$i";
    $i++;
    $mot_html = afficher_ortho($mot);
    echo "<option value='$id'>$mot_html</option>\n";
  }
  foreach ($bons as $mot) {
    $id = $id_suggest[$mot] = "$i";
    $i++;
  }
  echo "</select>\n";
  echo "</form>\n";
  // Mots mal orthographies :
  // liste des suggestions plus lien pour ajouter au dico
  foreach ($mauvais as $mot => $suggest) {
    $id = $id_suggest[$mot];
    $mot_html = afficher_ortho($mot);
    echo "<div class='suggest-inactif' id='suggest$id'>";
    echo "<span class='ortho'>$mot_html</span>\n";
    echo "<div class='detail'>\n";
    if (is_array($suggest) && count($suggest)) {
      echo "<ul>\n";
      $i = 0;
      foreach ($suggest as $sug) {
        if (++$i > 12) {
          echo "<li><i>(...)</i></li>\n";
          break;
        }
        echo "<li>".afficher_ortho(typo($sug))."</li>\n";
      }
      echo "</ul>\n";
    }
    else {
      echo "<i>Aucune suggestion n'a &eacute;t&eacute; trouv&eacute;e pour ce mot.</i>";
    }
    echo "<br />";
    $link = new Link;
    $link->delVar('supp_ortho');
    $link->addVar('ajout_ortho', $mot);
    icone_horizontale(_L("Ajouter ce mot au dictionnaire"), $link->getUrl(), "ortho-24.gif", "creer.gif");
    echo "</div>\n";
    echo "</div>\n\n";
  }
  // Mots trouves dans le dico :
  // message plus lien pour retirer du dico
  foreach ($bons as $mot) {
    $id = $id_suggest[$mot];
    $mot_html = afficher_ortho($mot);
    echo "<div class='suggest-inactif' id='suggest$id'>";
    echo "<span class='ortho-dico'>$mot_html</span>";
    echo "<div class='detail'>\n";
    echo "<i>"._L("Ce mot fait partie du dictionnaire du site.")."</i>";
    echo "<br />";
    $link = new Link;
    $link->delVar('ajout_ortho');
    $link->addVar('supp_ortho', $mot);
    icone_horizontale(_L("Enlever ce mot du dictionnaire"), $link->getUrl(), "ortho-24.gif", "supprimer.gif");
    echo "</div>\n";
    echo "</div>\n";
  }
}

function souligner_ortho($texte, $lang, $ortho_result) {
  global $id_suggest;
  $vu = array();

  $mauvais = $ortho_result['mauvais'];
  $bons = $ortho_result['bons'];

  $texte = " ".$texte." ";
  // Chercher et remplacer les mots un par un
  $t0 = explode(" ", microtime());
  $delim = '[^-\''.pcre_lettres_unicode().']';
  foreach ($mauvais as $mot => $suggest) {
    $pattern = ",$delim".$mot."$delim,us";
    // Recuperer les occurences du mot dans le texte
    if (preg_match_all($pattern, $texte, $regs, PREG_SET_ORDER)) {
      $id = $id_suggest[$mot];
      $mot_html = afficher_ortho($mot);
      foreach ($regs as $r) {
        if ($vu[$cherche = $r[0]]) continue;
        $vu[$cherche] = 1;
        $html = "<a class='ortho' onclick=\"suggest($id);return false;\" href=''>$mot_html</a>";
        $remplace = str_replace($mot, $html, $cherche);
        $table = explode($cherche, $texte);
        unset($avant);
        $texte = '';
        foreach ($table as $s) {
          if (!isset($avant)) {
            $avant = $s;
            continue;
          }
          $ok = true;
          $texte .= $avant;
          if (is_int($deb_tag = strrpos($texte, '<'))) {
            if (strrpos($texte, '>') <= $deb_tag)
              $ok = false;
          }
          if ($ok) {
            $texte .= $remplace;
          }
          else {
            $texte .= $cherche;
          }
          $avant = $s;
        }
        $texte .= $avant;
      }
    }
  }
  foreach ($bons as $mot) {
    $pattern = ",$delim".$mot."$delim,us";
    // Recuperer les occurences du mot dans le texte
    if (preg_match_all($pattern, $texte, $regs, PREG_SET_ORDER)) {
      $id = $id_suggest[$mot];
      $mot_html = afficher_ortho($mot);
      foreach ($regs as $r) {
        if ($vu[$cherche = $r[0]]) continue;
        $vu[$cherche] = 1;
        $html = "<a class='ortho-dico' onclick=\"suggest($id);return false;\" href=''>$mot_html</a>";
        $remplace = str_replace($mot, $html, $cherche);
        $table = explode($cherche, $texte);
        unset($avant);
        $texte = '';
        foreach ($table as $s) {
          if (!isset($avant)) {
            $avant = $s;
            continue;
          }
          $ok = true;
          $texte .= $avant;
          if (is_int($deb_tag = strrpos($texte, '<'))) {
            if (strrpos($texte, '>') <= $deb_tag)
              $ok = false;
          }
          if ($ok) {
            $texte .= $remplace;
          }
          else {
            $texte .= $cherche;
          }
          $avant = $s;
        }
        $texte .= $avant;
      }
    }
  }
  $t1 = explode(" ", microtime());
  $dt = floor(1000 * ($t1[0] + $t1[1] - $t0[0] - $t0[1])) / 1000;
  //echo "<div style='font-weight: bold; color: red;'>$dt s.</div>";
  
  $texte = preg_replace(',(^ | $),', '', $texte);
  $texte = afficher_ortho($texte);
  return $texte;
}

// Test de fonctionnement du support UTF-8 dans PCRE
// (contournement bug Debian Woody)
function test_pcre_unicode() {
  static $pcre_ok = 0;

  if (!$pcre_ok) {
    include_spip("charsets.php");
    $s = " ".chr(195).chr(169)."t".chr(195).chr(169)." ";
    if (preg_match(',\W\w\w\w\W,u', $s)) $pcre_ok = 1;
    else $pcre_ok = -1;
  }
  return $pcre_ok == 1;
}

function pcre_lettres_unicode() {
  static $plage_unicode;

  if (!$plage_unicode) {
    if (test_pcre_unicode()) {
      // cf. Unicode 16.0 Character Code Charts
      $plage_unicode = '\w' // iso-latin
        . '\x{100}-\x{24f}' // europeen etendu
/* . '\x{370}-\x{3ff}' // grec
        . '\x{400}-\x{52f}' // cyrillique*/
        . '\x{300}-\x{1cff}' // des tas de trucs
      ;
    }
    else {
      // fallback a trois sous
      $plage_unicode = '\w';
    }
  }
  return $plage_unicode;
}

function init_ortho() {
  global $duree_cache_ortho, $duree_cache_miroirs_ortho;

   $duree_cache_ortho = 7 * 24 * 3600;
  $duree_cache_miroirs_ortho = 24 * 3600;
  lire_miroirs_ortho();
}

init_ortho();

?>

Index: inc_version.php3

RCS file: /home/spip-cvs/spip/ecrire/inc_version.php3,v
retrieving revision 1.350
retrieving revision 1.351
diff -u -d -r1.350 -r1.351
--- inc_version.php3 27 Aug 2004 18:55:23 -0000 1.350
+++ inc_version.php3 27 Aug 2004 21:29:33 -0000 1.351
@@ -208,7 +208,7 @@
$spip_version = 1.806;

// version de spip
-$spip_version_affichee = "1.8 alpha 6 CVS";
+$spip_version_affichee = "1.8 beta 1 CVS";

// version de spip / tag cvs
if (ereg('Name: v(.*) ','$Name$', $regs)) $spip_version_affichee = $regs[1];

--- inc_ortho.php DELETED ---

Index: inc_majbase.php3

RCS file: /home/spip-cvs/spip/ecrire/inc_majbase.php3,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- inc_majbase.php3 27 Aug 2004 18:55:23 -0000 1.10
+++ inc_majbase.php3 27 Aug 2004 21:29:33 -0000 1.11
@@ -833,11 +833,11 @@
     maj_version(1.733);
   }

- if ($version_installee < 1.734) {
- // integrer nouvelles tables auxiliaires du compilateur ESJ
- creer_base();
- maj_version(1.734);
- }
+ #if ($version_installee < 1.734) {
+ # // integrer nouvelles tables auxiliaires du compilateur ESJ
+ # creer_base();
+ # maj_version(1.734);
+ #}

   if ($version_installee < 1.801) {
     spip_query("ALTER TABLE spip_rubriques
@@ -867,7 +867,11 @@
     maj_version(1.802);
   }
   if ($version_installee < 1.803) {
- spip_query("DROP TABLE spip_forum_cache");
+
+ # 27 AOUT 2004 : conservons cette table pour autoriser les retours
+ # de SPIP 1.8a6 CVS vers 1.7.2
+ # spip_query("DROP TABLE spip_forum_cache");
+
     spip_query("DROP TABLE spip_inclure_caches");
     maj_version(1.803);
   }
@@ -890,6 +894,10 @@
   if ($version_installee < 1.806)
     maj_version(1.806);

+
+ # A remettre pour la 1.8 finale (cf. ci-dessus)
+ # spip_query("DROP TABLE spip_forum_cache");
+
   return true;
}

Index: inc_config.php3

RCS file: /home/spip-cvs/spip/ecrire/inc_config.php3,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- inc_config.php3 26 Aug 2004 03:47:01 -0000 1.51
+++ inc_config.php3 27 Aug 2004 21:29:33 -0000 1.52
@@ -50,6 +50,7 @@

     'activer_moteur' => 'oui',
     'articles_versions' => 'non',
+ 'articles_ortho' => 'non',
     'preview' => 'non',
     'activer_statistiques' => 'oui',

@@ -228,6 +229,7 @@

     'activer_moteur',
     'articles_versions',
+ 'articles_ortho',
     'preview',
     'activer_statistiques',