diff --git a/dist/article.html b/dist/article.html
index c2dc45ac71b5c156ced8f4ad5237f2e29b56b2eb..d8924374b369c661afed6f5d8f0079468c68eb84 100644
--- a/dist/article.html
+++ b/dist/article.html
@@ -98,9 +98,12 @@
 			</div>
 			</B_documents_joints>
 
-			[(#REM) Petition ]
+			[(#REM) Petition
+				la petition ayant une PAGINATION il faut absolument
+				lui passer SELF en argument.
+			]
 			[ #REM Conserver cet invalideur : (#PETITION|?{'',''}) ]
-			<INCLURE{fond=inc-petition}{id_article}{debut_signatures}>
+			<INCLURE{fond=inc-petition}{id_article}{self=#SELF}>
 
 			[<div class="notes"><h2><:info_notes:></h2>#DEBUT_SURLIGNE(#NOTES)#FIN_SURLIGNE</div>]
 
diff --git a/dist/inc-petition.html b/dist/inc-petition.html
index 31aae3196f9a97dd7149a5a99de1b511384c4ebc..6956eb889f8181a8f4b7c23645237a98f01fd7d9 100644
--- a/dist/inc-petition.html
+++ b/dist/inc-petition.html
@@ -4,16 +4,10 @@
 [(#REM) Signatures de la petition ]
 <B_signatures>
 <div id="signatures">
-	<B_signatures_decompte>
-	[(#REM) S'affiche s'il y a pagination]
-	<h2>#TOTAL_BOUCLE <:signatures_petition:></h2>
-	[(#ENV{debut_signatures,0}|=={0}|?{'<strong>',<a href="[(#SELF|parametre_url{debut_signatures,''})]#signatures"[ title="(#DATE|affdate)"]>})] [(#TOTAL_BOUCLE|>={30}|?{'0',''})] [(#ENV{debut_signatures,0}|=={0}|?{'</strong>',</a>})]
-	<BOUCLE_signatures_decompte(SIGNATURES){id_article}{par date} {inverse}>
-	[|(#COMPTEUR_BOUCLE|modulo{30}|?{'',[(#COMPTEUR_BOUCLE|=={#ENV{debut_signatures,0}}|?{'<strong>',<a href="[(#SELF|parametre_url{debut_signatures,#COMPTEUR_BOUCLE})]#signatures"[ title="(#DATE|affdate)"]>})] #COMPTEUR_BOUCLE [(#COMPTEUR_BOUCLE|=={#ENV{debut_signatures,0}}|?{'</strong>',</a>})]})]
-	</BOUCLE_signatures_decompte>
-	[(#REM) S'affiche s'il n'y a pas de signature]
-	<h2>0 <:signatures_petition:></h2>
-	<//B_signatures_decompte>
+
+	#ANCRES_PAGINATION
+
+	<h2>#GRAND_TOTAL <:signatures_petition:></h2>
 
 	<table summary="<:signatures_petition:>">
 	<caption class="invisible"><:signatures_petition:></caption>
@@ -25,16 +19,17 @@
 		</tr>
 	</thead>
 	<tbody>
-	<BOUCLE_signatures(SIGNATURES) {id_article} {par date}{inverse}
-	{debut_signatures,30}>
+<BOUCLE_signatures(SIGNATURES) {id_article} {par date} {inverse} {pagination}>
 		<tr>
 		<td class="signature-date">[(#DATE|affdate)]</td>
 		<td class="signature-nom">#NOM[<br /><a href="(#URL_SITE)" class="spip_out"><small>[(#NOM_SITE|sinon{[(#URL_SITE|couper{80})]})</small>]</a>]</td>
 		[<td class="signature-message">(#MESSAGE|PtoBR)</td>]
 		</tr>
-	</BOUCLE_signatures>
+</BOUCLE_signatures>
 	</tbody>
 	</table>
 
+	[<p class="pagination">(#PAGINATION)</p>]
+
 </div>
 </B_signatures>
diff --git a/dist/rubrique.html b/dist/rubrique.html
index f1e6b90a5e4f99d85ecf8ed628a3cfd7ef8aa9c1..57c9e6bd3d5f4e4d1b32068659cbc684c0dc4f88 100644
--- a/dist/rubrique.html
+++ b/dist/rubrique.html
@@ -48,11 +48,10 @@
 
 				[(#REM) Articles de la rubrique ]
 				
-				<BOUCLE_pages(ARTICLES) {id_rubrique} {par date}{inverse}></BOUCLE_pages>
-				<p class="pagination" id="articles">#PAGINATION{_articles}</p>
-				<//B_pages>
-				
 				<B_articles>
+
+				[<p class="pagination">(#PAGINATION)</p>]
+
 				<h2 class="invisible"><:articles_rubrique:></h2>
 				<ul>
 					<BOUCLE_articles(ARTICLES) {id_rubrique} {par date}{inverse}{pagination}>
diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php
index b90c3f39bfe091cae53cb4a2bec894a70a5a3313..7c5ba6e91274bad66556779f4fb5120e696837e7 100644
--- a/ecrire/inc/filtres.php
+++ b/ecrire/inc/filtres.php
@@ -2648,12 +2648,14 @@ function form_hidden($action) {
 	return $hidden;
 }
 
-function pagination($total, $debut, $pas) {
+function pagination($total, $nom, $pas, $liste = true) {
 	global $pagination_item_avant, $pagination_item_apres, $pagination_separateur;
 	global $pagination_max, $pagination_max_texte;
 	tester_variable('pagination_separateur', '&nbsp;| ');
 	tester_variable('pagination_max_texte', '...');
 
+	$debut = 'debut'.$nom;
+
 	$pagination = array(
 		'lien_base' => self(),
 		'total' => $total,
@@ -2664,6 +2666,9 @@ function pagination($total, $debut, $pas) {
 		'lien_pagination' => '<a href="@url@">@item@</a>'
 	);
 
+	$ancre='pagination'.$nom;
+	$bloc_ancre = unique("<a name='$ancre' id='$ancre'></a>");
+
 	if($pagination_max == 0 OR $pagination_max>=$pagination['nombre_pages']) {
 		$premiere = 1;
 		$derniere = $pagination['nombre_pages'];
@@ -2678,20 +2683,30 @@ function pagination($total, $debut, $pas) {
 		$texte_apres = $derniere<$pagination['nombre_pages'] ? ' '.$pagination_max_texte : '';
 	}
 
+
+	// Pas de pagination
+	if($pagination['nombre_pages']<=1)
+		return '';
+
+	// liste = false : on ne veut que l'ancre
+	if (!$liste)
+		return $bloc_ancre;
+
+	// liste  = true : on retourne tout (ancre + bloc de navigation)
 	$texte = '';
-	if($pagination['nombre_pages']>1) {
-		for($i = $premiere;$i<=$derniere;$i++) {
-			$url = parametre_url($pagination['lien_base'], $debut, strval(($i-1)*$pas));
-			$_item = strval($i);
-			$item = ($i != $pagination['page_courante']) ?
-				preg_replace(array(',@url@,', ',@item@,'), array($url, $_item), $pagination['lien_pagination']) :
-				$_item;
-			$texte .= $pagination_item_avant.$item.$pagination_item_apres;
-			if($i<$pagination['nombre_pages']) $texte .= $pagination_separateur;
-		}
-		return $texte_avant.$texte.$texte_apres;
-	}
-	return '';
+	for($i = $premiere;$i<=$derniere;$i++) {
+		$url = parametre_url($pagination['lien_base'], $debut, strval(($i-1)*$pas));
+		$_item = strval($i);
+		$item = ($i != $pagination['page_courante']) ?
+			preg_replace(
+				array(',@url@,', ',@item@,'),
+				array($url.'#'.$ancre, $_item),
+				$pagination['lien_pagination']) :
+			$_item;
+		$texte .= $pagination_item_avant.$item.$pagination_item_apres;
+		if($i<$pagination['nombre_pages']) $texte .= $pagination_separateur;
+	}
+	return $bloc_ancre.$texte_avant.$texte.$texte_apres;
 }
 
 ### fonction depreciee, laissee ici pour compat ascendante 1.9
diff --git a/ecrire/public/balises.php b/ecrire/public/balises.php
index b15a898519b1fc749be8e98ba2568f0004973620..73c89ac422d637b8f8c8a79c7c818e8469430318 100644
--- a/ecrire/public/balises.php
+++ b/ecrire/public/balises.php
@@ -558,8 +558,9 @@ function balise_POPULARITE_dist ($p) {
 
 // #PAGINATION
 // http://www.spip.net/fr_articleXXXX.html
-function balise_PAGINATION_dist($p) {
+function balise_PAGINATION_dist($p, $liste='true') {
 	$b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
+
 	if ($b === '') {
 		erreur_squelette(
 			_T('zbug_champ_hors_boucle',
@@ -567,27 +568,55 @@ function balise_PAGINATION_dist($p) {
 			), $p->id_boucle);
 		$p->code = "''";
 	}
-	elseif (!$p->param || $p->param[0][0]) {
+
+	if ($p->param) {
+		$option = calculer_liste($p->param[0][1],
+			$p->descr,
+			$p->boucles,
+			$p->id_boucle);
+		$option = str_replace("'", '', $option);
+	}
+
+	$pas = _PAS > 0 ? _PAS : 10;
+	$p->boucles[$b]->numrows = true;
+
+	if ($option)
+		$nom_boucle = $option;
+	else
+		$nom_boucle = $b;
+
+	$p->code = "pagination(
+	(isset(\$Numrows['$b']['grand_total']) ?
+		\$Numrows['$b']['grand_total'] : \$Numrows['$b']['total']
+	), '$nom_boucle', $pas, $liste)";
+
+	$p->interdire_scripts = false;
+	return $p;
+}
+
+// N'afficher que les ancres de la pagination (au-dessus, par exemple, alors
+// qu'on mettra les liens en-dessous de la liste paginee)
+function balise_ANCRES_PAGINATION_dist($p) {
+	$p = balise_PAGINATION_dist($p, $liste='false');
+	return $p;
+}
+
+// equivalent a #TOTAL_BOUCLE sauf pour les boucles paginees, ou elle
+// indique le nombre total d'articles repondant aux criteres hors pagination
+function balise_GRAND_TOTAL_dist($p) {
+	$b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
+	if ($b === '' || !isset($p->boucles[$b])) {
 		erreur_squelette(
-			/*_T('zbug_champ_manquant',
-				array('champ' => '#PAGINATION')*/
-			_L('param&eacute;tre manquant pour #PAGINATION')
-			, $p->id_boucle);
+			_T('zbug_champ_hors_boucle',
+				array('champ' => "#$b" . 'TOTAL_BOUCLE')
+			), $p->id_boucle);
 		$p->code = "''";
-	}
-	else {
-		$nom_boucle = calculer_liste($p->param[0][1],
-					$p->descr,
-					$p->boucles,
-					$p->id_boucle);
-  $nom_boucle = str_replace("'", '', $nom_boucle);
-  $pas = _PAS>0 ? _PAS : 10;
-  
+	} else {
+		$p->code = "(isset(\$Numrows['$b']['grand_total'])
+			? \$Numrows['$b']['grand_total'] : \$Numrows['$b']['total'])";
 		$p->boucles[$b]->numrows = true;
-		$p->code = "pagination(\$Numrows['$b']['total'],'debut".$nom_boucle."',".$pas.")";
+		$p->interdire_scripts = false;
 	}
-
-	$p->interdire_scripts = true;
 	return $p;
 }
 
diff --git a/ecrire/public/compiler.php b/ecrire/public/compiler.php
index 2e7c26284313e1eee1acfd21226cbcc1e1275219..09c00621d2ba335153dfa7aee34f6fa71ac28e6f 100644
--- a/ecrire/public/compiler.php
+++ b/ecrire/public/compiler.php
@@ -340,7 +340,7 @@ function calculer_parties($boucles, $id_boucle) {
 		$boucle->sql_serveur .
 		'");';
 
-	ereg("([+-/])([+-/])?", $mode_partie, $regs);
+	ereg("([+-/p])([+-/])?", $mode_partie, $regs);
 	list(,$op1,$op2) = $regs;
 
 	// {1/3}
@@ -365,6 +365,12 @@ function calculer_parties($boucles, $id_boucle) {
 		$retour .= "\n	"
 			. '$debut_boucle = $nombre_boucle - ' . $partie . ';';
 	}
+	// {pagination}
+	elseif ($op1 == 'p') {
+		$retour .= "\n	"
+			. '$debut_boucle = ' . $partie . ';';
+	}
+
 	// {x,1}
 	if ($op2 == '+') {
 		$fin = '$debut_boucle'
@@ -385,6 +391,8 @@ function calculer_parties($boucles, $id_boucle) {
 
 	// calcul du total boucle final
 	$retour .= "\n	"
+		.'$Numrows[\''.$id_boucle.'\']["grand_total"] = $nombre_boucle;'
+		. "\n	"
 		.'$Numrows[\''.$id_boucle.'\']["total"] = max(0,$fin_boucle - $debut_boucle + 1);';
 
 	return $retour;
diff --git a/ecrire/public/criteres.php b/ecrire/public/criteres.php
index b4081f861ca2b55a811e677ee72fff040e01704a..80d736f0edc493b5a51703077a7ea9046f65334f 100644
--- a/ecrire/public/criteres.php
+++ b/ecrire/public/criteres.php
@@ -93,9 +93,11 @@ function critere_debut_dist($idb, &$boucles, $crit) {
 // {pagination}
 // http://www.spip.net/@pagination
 function critere_pagination_dist($idb, &$boucles, $crit) {
- $pas = _PAS>0 ? _PAS : 10;
+	$pas = _PAS>0 ? _PAS : 10;
 	$boucle = &$boucles[$idb];
-	$boucle->limit = 'intval($GLOBALS["debut'.$idb.'"]) . ",'.$pas.'"';
+	$boucle->mode_partie = 'p+';
+	$boucle->partie = 'intval(_request("debut'.$idb.'"))';
+	$boucle->total_parties = $pas;
 }