diff --git a/ecrire/public/iterateur.php b/ecrire/public/iterateur.php
index 991eb129ce835901d6f516ee4978bab894e09f3e..e51b463a62b4926d551647a3fc94af805dff8719 100644
--- a/ecrire/public/iterateur.php
+++ b/ecrire/public/iterateur.php
@@ -12,30 +12,112 @@
 \***************************************************************************/
 
 
-//
-// Iterateur SQL
-//
-
+/**
+ * Iterateurs
+ * http://php.net/manual/fr/class.iterator.php
+ */
 class Iter implements Iterator {
-	# http://php.net/manual/fr/class.iterator.php
-	public function __construct() {} // initialise
-	public function rewind() {} // revient au depart
-	public function valid() {} // avons-nous un element
-	public function current() {} // quel est sa valeur
-	public function key() {} // quelle est sa cle
-	public function next() {} // avancer d'un cran
-
-	# Iter SPIP
-	var $type; # type de l'iterateur
-	var $command; # parametres de l'iterateur
-	var $info; # infos de compilateur
-
-	// avancer en position n
+	/**
+	 * Constructeur & initialise
+	 */
+	public function __construct() {
+		$this->pos = 0;
+		$this->total = $this->total();
+	}
+
+	/**
+	 * revient au depart
+	 * @return void
+	 */
+	public function rewind() {
+		$this->pos = 0;
+	}
+
+	/**
+	 * avons-nous un element
+	 * @return void
+	 */
+	public function valid() {
+		return $this->pos<$this->total;
+	}
+
+	/**
+	 * Valeur courante
+	 * @return void
+	 */
+	public function current() {}
+
+	/**
+	 * Cle courante
+	 * @return void
+	 */
+	public function key() {}
+
+	/**
+	 * avancer d'un cran
+	 * @return void
+	 */
+	public function next() {
+		$this->pos++;
+	}
+
+	# Extension SPIP des iterateurs PHP
+	/**
+	 * type de l'iterateur
+	 * @var string
+	 */
+	protected $type;
+
+	/**
+	 * parametres de l'iterateur
+	 * @var array
+	 */
+	protected $command;
+
+	/**
+	 * infos de compilateur
+	 * @var array
+	 */
+	protected $info;
+
+	/**
+	 * position courante de l'iterateur
+	 * @var int
+	 */
+	protected $pos=null;
+
+	/**
+	 * nombre total resultats dans l'iterateur
+	 * @var int
+	 */
+	protected $total=null;
+
+	/**
+	 * avancer en position n,
+	 * comptee en absolu depuis le debut
+	 *
+	 * @param int $n
+	 *   absolute pos
+	 * @param string $continue
+	 *   param for sql_ api
+	 * @return bool
+	 *   success or fail if not implemented
+	 */
 	public function seek($n=0, $continue=null) {
-		$this->rewind();
-		while($n-->0 AND $this->valid()) $this->next();
+		if ($this->pos>$n)
+			$this->rewind();
+		
+		while($this->pos<$n AND $this->valid())
+			$this->next();
 		return true;
 	}
+
+	/**
+	 * Renvoyer un tableau des donnees correspondantes
+	 * a la position courante de l'iterateur
+	 *
+	 * @return array|bool
+	 */
 	public function fetch() {
 		if ($this->valid()) {
 			$r = array('cle' => $this->key(), 'valeur' => $this->current());
@@ -44,21 +126,58 @@ class Iter implements Iterator {
 			$r = false;
 		return $r;
 	}
-	public function free() {} // liberer la ressource
-	public function total() {} // #TOTAL_BOUCLE
+
+	/**
+	 * liberer la ressource
+	 * @return bool
+	 */
+	public function free() {
+		$this->pos = $this->total = 0;
+	  return true;
+	}
+
+	/**
+	 * Compter le nombre total de resultats
+	 * pour #TOTAL_BOUCLE
+	 * @return int
+	 */
+	public function total() {
+		if (is_null($this->total))
+			$this->total = 0;
+		return $this->total;
+	}
 }
 
+/**
+ * Iterateur SQL
+ */
 class IterSQL extends Iter {
 
-	private $sqlresult = false; # ressource sql
-	private $row = null; # row sql courante
+	/**
+	 * ressource sql
+	 * @var resource|bool
+	 */
+	protected $sqlresult = false;
+
+	/**
+	 * row sql courante
+	 * @var array|null
+	 */
+	protected $row = null;
 
-	private function select() {
+	/**
+	 * selectionner les donnees, ie faire la requete SQL
+	 * @return void
+	 */
+	protected function select() {
+		$this->row = null;
 		$v = &$this->command;
 		$this->sqlresult = calculer_select($v['select'], $v['from'], $v['type'], $v['where'], $v['join'], $v['groupby'], $v['orderby'], $v['limit'], $v['having'], $v['table'], $v['id'], $v['connect'], $this->info);
-		$this->ok = !!$this->sqlresult;
-		if ($this->ok)
+		$ok = !!$this->sqlresult;
+		if ($ok)
 			$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
+	  $this->pos = 0;
+	  $this->total = $this->total();
 	}
 
 	/*
@@ -71,27 +190,65 @@ class IterSQL extends Iter {
 		$this->info = $info;
 		$this->select();
 	}
+
+	/**
+	 * Rembobiner
+	 * @return bool
+	 */
 	public function rewind() {
+		parent::rewind();
 		return $this->seek(0);
 	}
+
+	/**
+	 * Verifier l'etat de l'iterateur
+	 * @return bool
+	 */
 	public function valid() {
-		return is_array($this->row);
+		return $this->sqlresult AND is_array($this->row);
 	}
+
+	/**
+	 * Valeurs sur la position courante
+	 * @return array
+	 */
 	public function current() {
 		return $this->row;
 	}
+	
+	/**
+	 * Sauter a une position absolue
+	 * @param int $n
+	 * @param null|string $continue
+	 * @return bool
+	 */
 	public function seek($n=0, $continue=null) {
-		# SQLite ne sait pas seek(), il faut relancer la query
-		if (!$a = sql_seek($this->sqlresult, $this->command['connect'], $n, $continue)) {
+		if (!sql_seek($this->sqlresult, $n, $this->command['connect'], $continue)) {
+			// SQLite ne sait pas seek(), il faut relancer la query
 			$this->free();
 			$this->select();
+			// et utiliser la methode par defaut pour se deplacer au bon endroit
+			parent::seek($n);
 			return true;
 		}
-		return $a;
+		$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
+		$this->pos = min($n,$this->total());
+		return true;
 	}
+
+	/**
+	 * Avancer d'un cran
+	 * @return void
+	 */
 	public function next(){
 		$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
+		parent::next();
 	}
+
+	/**
+	 * Avancer et retourner les donnees pour le nouvel element
+	 * @return array|bool|null
+	 */
 	public function fetch(){
 		if ($this->valid()) {
 			$r = $this->current();
@@ -100,22 +257,38 @@ class IterSQL extends Iter {
 			$r = false;
 		return $r;
 	}
+
+	/**
+	 * liberer les ressources
+	 * @return bool
+	 */
 	public function free(){
+		parent::free();
 		return sql_free($this->sqlresult, $this->command['connect']);
 	}
+	
+	/**
+	 * Compter le nombre de resultats
+	 * @return int
+	 */
 	public function total() {
-		return sql_count($this->sqlresult, $this->command['connect']);
+		if (is_null($this->total))
+			if (!$this->sqlresult)
+				$this->total = 0;
+			else
+				$this->total = sql_count($this->sqlresult, $this->command['connect']);
+	  return $this->total;
 	}
 }
 
 class IterENUM extends Iter {
-	private $n = 0;
-	private $pos = 0;
-	private $start = 0;
-	private $offset = 0;
-	private $total = 1000000;
-	private $max = 1000000;
-	private $filtre = array();
+	protected $n = 0;
+	#protected $pos = 0;
+	protected $start = 0;
+	protected $offset = 0;
+	#protected $total = 1000000;
+	protected $max = 1000000;
+	protected $filtre = array();
 
 	public function __construct($command=array(), $info=array()) {
 		$this->type='ENUM';
@@ -202,10 +375,10 @@ class IterENUM extends Iter {
 
 
 class IterDATA extends Iter {
-	private $tableau = array();
-	private $filtre = array();
-	private $cle = null;
-	private $valeur = null;
+	protected $tableau = array();
+	protected $filtre = array();
+	protected $cle = null;
+	protected $valeur = null;
 
 	public function __construct($command, $info=array()) {
 		$this->type='DATA';
@@ -220,7 +393,7 @@ class IterDATA extends Iter {
 		list($this->cle, $this->valeur) = each($this->tableau);
 	}
 
-	private function select($command) {
+	protected function select($command) {
 		// les commandes connues pour l'iterateur POUR
 		// sont : tableau=#ARRAY ; cle=...; valeur=...
 		// source URL