diff --git a/ecrire/inc/validateur.php b/ecrire/inc/validateur.php
index be132ac09ab913dfdf5831a81a9a83be0f15219c..f1b3bd1e7aa057d08c6dccf7c0bbb7103fee1844 100644
--- a/ecrire/inc/validateur.php
+++ b/ecrire/inc/validateur.php
@@ -70,8 +70,11 @@ function inc_validateur_dist($data)
 	    $val = expanserEntite($val, $phraseur_xml->entites);
 	    $att = array();
 	    if (preg_match_all("/\s*(\S+)\s+(([(][^)]*[)])|(\S+))\s+(\S+)(\s*'[^']*')?/", $val, $r2, PREG_SET_ORDER)) {
-	      foreach($r2 as $m2)
-		$att[$m2[1]] = $m2[5];
+		foreach($r2 as $m2) {
+			$v = preg_match('/^\w+$/', $m2[2]) ? ''
+			  : ('/^' . preg_replace('/\s+/', '', $m2[2]) . '$/');
+			$att[$m2[1]] = array($v, $m2[5]);
+		}
 	    }
 	    $res[$nom] = $att;
 	  }
@@ -120,7 +123,7 @@ function validerElement($parser, $name, $attrs)
 	    }
 	  }
 	  foreach ($phraseur_xml->attributs[$name] as $n => $v)
-	    { if (($v == '#REQUIRED') AND (!isset($attrs[$n])))
+	    { if (($v[1] == '#REQUIRED') AND (!isset($attrs[$n])))
 		$phraseur_xml->err[]= " <b>$n</b>"
 		. '&nbsp;:&nbsp;'
                 . _L(" attribut obligatoire mais absent dans ")
@@ -134,16 +137,26 @@ function validerElement($parser, $name, $attrs)
 // http://doc.spip.org/@validerAttribut
 function validerAttribut($parser, $name, $val, $bal)
 {
-  global $phraseur_xml;
+	global $phraseur_xml;
 
-	if ($a = $phraseur_xml->attributs[$bal] 
-	    AND !isset($a[$name]))
+	$a = @$phraseur_xml->attributs[$bal]; // vide ou absent, pareil.
+	if (!isset($a[$name]))
 
 		$phraseur_xml->err[]= " <b>$name</b>"
 		. _L(' attribut inconnu de ')
 		. "<b>$bal</b>"
 		.  coordonnees_erreur($parser);
+	elseif ($a[$name][0][0]=='/') {
+	  if (!preg_match($a[$name][0], $val)) {
+		$phraseur_xml->err[]= " <p><b>$val</b>"
+		. _L(" valeur de l'attribut ")
+		. "<b>$name</b>"
+		  . _L(' de ')
+		. "<b>$bal</b>"
+		. _L(" n'est pas conforme au motif</p><p>")
+		. "<b>" . $a[$name][0] . "</b></p>"
+		.  coordonnees_erreur($parser);
+	  }
+	}
 }
-
-
 ?>
diff --git a/ecrire/public/debug.php b/ecrire/public/debug.php
index 624b1ab126717dbfb32b21b2bba488fc55d7c6f4..b8f71372753ba10787b00adf014ce4758677053d 100644
--- a/ecrire/public/debug.php
+++ b/ecrire/public/debug.php
@@ -306,7 +306,7 @@ function reference_boucle_debug($n, $nom, $self)
 function ancre_texte($texte, $fautifs=array())
 {
 	global $var_mode_ligne;
-	if ($var_mode_ligne) $fautifs[]=$var_mode_ligne;
+	if ($var_mode_ligne) $fautifs[]= array($var_mode_ligne);
 	$res ='';
 	$s = highlight_string($texte,true);
 	if (substr($s,0,6) == '<code>') { $s=substr($s,6); $res = '<code>';}
@@ -322,11 +322,27 @@ function ancre_texte($texte, $fautifs=array())
 	$formaterr="<span style='background-color: pink'>%s</span>";
 	$i=1;
 
+	$flignes = array();
+
+	foreach ($fautifs as $lc)
+	  if (is_array($lc))
+	    $flignes[$lc[0]] = $lc[1];
+	  else $flignes[$lc] = 0;
+
 	foreach ($tableau as $ligne) {
-		$res .= "<br />\n"
+	  if (isset($flignes[$i])) {
+	    $ligne = str_replace('&nbsp;',' ', $ligne);
+	    // tentative de pointer sur la colonne fautive;
+	    // marche pas car highlight_string rajoute des entites. A revoir.
+	    // $m = $flignes[$i];
+	    //  $ligne = substr($ligne, 0, $m-1) .
+	    //  sprintf($formaterr, substr($ligne,$m));
+	    $ligne = sprintf($formaterr, $ligne);
+	  }
+	  $res .= "<br />\n"
 		.  sprintf((($i%10) ? $format :$format10), $i, $i)
-		.  sprintf(in_array($i, $fautifs) ? $formaterr : '%s', $ligne);
-		$i++;
+		.   $ligne;
+	  $i++;
 	}
 	return "<div id='T$ancre'>$res</div>";
 }
@@ -510,33 +526,32 @@ function emboite_texte($texte, $fonc='',$self='')
  
 	if (!$texte)
 		return array(ancre_texte($texte, array('','')), false);
-	elseif (preg_match_all(",([^0-9]* )([0-9]+)(.*?<br />),",
+	elseif (!ereg("^[[:space:]]*([^<][^0-9]*)([0-9]*)(.*[^0-9])([0-9]*)$",
+                     $GLOBALS['xhtml_error'],
+                     $eregs))
+		return array(ancre_texte($texte, array('', '')), true);
+	if (!isset($GLOBALS['debug_objets'])) {
+		preg_match_all(",([^0-9]* )([0-9]+)(.*?(\d*)<br />),",
 				$GLOBALS['xhtml_error'],
 				$regs,
-				PREG_SET_ORDER)) {
+			       PREG_SET_ORDER);
 		$err = '';
 		$fautifs = array();
 		foreach($regs as $r) {
 			$err .= $r[1] .
 			  "<a href='#L" . $r[2] . "'>$r[2]</a>$r[3]";
-			$fautifs[]=$r[2];
+			$fautifs[]= array($r[2], $r[4]);
 		}
 		return array(ancre_texte($texte, $fautifs), $err);
-	} elseif (!ereg("^[[:space:]]*([^<][^0-9]*)([0-9]*)(.*[^0-9])([0-9]*)$",
-                     $GLOBALS['xhtml_error'],
-                     $r))
-		return array(ancre_texte($texte, array('', '')), true);
-	else {
-		$fermant = $r[2];
-		$ouvrant = $r[4];
-		if (isset($GLOBALS['debug_objets'])) {
-		  $rf = reference_boucle_debug($fermant, $fonc, $self);
-		  $ro = reference_boucle_debug($ouvrant, $fonc, $self);
-		} else $rf = $ro = '';
-		$err = $r[1] .
-		  "<a href='#L" . $r[2] . "'>$r[2]</a>$rf" .
-		  $r[3] ."<a href='#L" . $r[4] . "'>$r[4]</a>$ro";
-		return array(ancre_texte($texte, array($ouvrant, $fermant)), $err);
+	} else {
+		$fermant = $eregs[2];
+		$ouvrant = $eregs[4];
+		$rf = reference_boucle_debug($fermant, $fonc, $self);
+		$ro = reference_boucle_debug($ouvrant, $fonc, $self);
+		$err = $eregs[1] .
+		  "<a href='#L" . $eregs[2] . "'>$eregs[2]</a>$rf" .
+		  $eregs[3] ."<a href='#L" . $eregs[4] . "'>$eregs[4]</a>$ro";
+		return array(ancre_texte($texte, array(array($ouvrant), array($fermant))), $err);
 	}
 }
 ?>