diff --git a/ecrire/inc/couleurs.php b/ecrire/inc/couleurs.php
index 80963cd06ce8846bb1fa60687293866e717c0959..22832dd5b1fc92afeb198cda25749d53315cf075 100644
--- a/ecrire/inc/couleurs.php
+++ b/ecrire/inc/couleurs.php
@@ -67,7 +67,7 @@ function inc_couleurs_dist($choix=NULL)
 );
 
 	if (is_numeric($choix)) {
-		// Compatibilite ascendente (plug-ins notamment)
+		// Compatibilite ascendante (plug-ins notamment)
 		$GLOBALS["couleur_claire"] = $couleurs_spip[$choix]['couleur_claire'];
 		$GLOBALS["couleur_foncee"] = $couleurs_spip[$choix]['couleur_foncee'];
 		$GLOBALS["couleur_lien"] = $couleurs_spip[$choix]['couleur_lien'];
@@ -86,16 +86,35 @@ onmouseover="changestyle(\'bandeauinterface\');"
 onfocus="changestyle(\'bandeauinterface\');"
 onblur="changestyle(\'bandeauinterface\');"';
 
+		$bloc = '<span id="selecteur_couleur"'. $evt .'>';
 		foreach ($couleurs_spip as $key => $val) {
-			$res .= "<a href=\""
-			. parametre_url(self(), 'set_couleur', $key)
-			. "\"$evt>"
+			$bloc .=
+			'<a href="'
+				. parametre_url(self(), 'set_couleur', $key)
+				. '"'
+			. ' rel="'.generer_url_public('style_prive','ltr='
+				. $GLOBALS['spip_lang_left'] . '&'
+				. inc_couleurs_dist($key)).'"'
+			.'>'
 			. http_img_pack("rien.gif",
 					_T('choix_couleur_interface') . $key,
 					"width='8' height='8' style='margin: 1px; background-color: "	. $val['couleur_claire'] . ";'")
 			. "</a>";
 		}
-	return $res;
+		$bloc .= "</span>\n";
+
+		// Ce js permet de changer de couleur sans recharger la page
+		$bloc .= "<script type='text/javascript'><!--
+			$('#selecteur_couleur a')
+			.click(function(){
+				$('#cssprivee')
+				.attr('href', $(this).attr('rel'));
+				$.get($(this).attr('href'));
+				return false;
+			});
+		// --></script>\n";
+
+		return $res . $bloc;
 	}
 }
 
diff --git a/ecrire/inc/presentation.php b/ecrire/inc/presentation.php
index 8a5759a4ce1d0646042902cfbbceb3eec0794de8..2cdc0425a5b10500841c68f57bc9e37cc1715cb6 100644
--- a/ecrire/inc/presentation.php
+++ b/ecrire/inc/presentation.php
@@ -794,7 +794,7 @@ function envoi_link($nom_site_spip, $minipres=false) {
 	
 	// CSS espace prive : la vraie
 	. '<link rel="stylesheet" type="text/css" href="'
-	. generer_url_public('style_prive', $paramcss) .'" />' . "\n"
+	. generer_url_public('style_prive', $paramcss) .'" id="cssprivee" />' . "\n"
   . "<!--[if lt IE 8]>\n"
   . '<link rel="stylesheet" type="text/css" href="'
   . generer_url_public('style_prive_ie', $paramcss) .'" />' . "\n"
diff --git a/ecrire/inc/utils.php b/ecrire/inc/utils.php
index 90cdb6ac520ab56db7d00b211f18051b27a0a900..1950241544017d69b9783091ed770144c219a52a 100644
--- a/ecrire/inc/utils.php
+++ b/ecrire/inc/utils.php
@@ -1247,18 +1247,19 @@ function lang_select ($lang=NULL) {
 // Par convention cette chaine ne doit pas contenir de caracteres [^0-9A-Za-z]
 // Attention on ne peut *pas* inferer id_auteur a partir de la session, qui
 // est une chaine arbitraire
-// Cette chaine est courte (6 cars) pour pouvoir etre utilisee dans un nom
+// Cette chaine est courte (8 cars) pour pouvoir etre utilisee dans un nom
 // de fichier cache
 // http://doc.spip.org/@spip_session
-function spip_session() {
+function spip_session($force = false) {
 	static $session;
-	if (!isset($session)) {
-		$session = $GLOBALS['auteur_session']
-			? substr(md5(
-				$GLOBALS['auteur_session']['id_auteur']
-				.'_'
-				.$_COOKIE['spip_session']), 0, 6)
-			: '';
+	if ($force OR !isset($session)) {
+		$s = pipeline('definir_session',
+			$GLOBALS['auteur_session']
+			? $GLOBALS['auteur_session']['id_auteur']
+				. '_' . @$_COOKIE['spip_session']
+			: ''
+		);
+		$session = $s ? substr(md5($s), 0, 8) : '';
 	}
 	#spip_log('session: '.$session);
 	return $session;
@@ -1285,7 +1286,41 @@ function exec_info_dist() {
 		echo "pas admin";
 }
 
+// La fonction de base de SPIP : un squelette + un contexte => une page
+// on recupere le resultat sous la forme d'une $page['texte', 'headers'...]
+// options :
+// 'protect_xml' => false,  conserver le \1 du xml-hack
+function assembler($fond, $contexte=array(), $options=array(), $connect=null) {
+	charger_fonction('assembler', 'public');
+
+	// on est peut etre dans l'espace prive au moment de l'appel
+	if (!isset($GLOBALS['_INC_PUBLIC'])) $GLOBALS['_INC_PUBLIC'] = 0;
+	$GLOBALS['_INC_PUBLIC']++;
+
+	// option[s] par defaut
+	$options = array_merge( array('protect_xml' => false), $options);
+
+	if (isset($contexte['fond'])
+	AND $fond === '')
+		$fond = $contexte['fond'];
+
+	$page = inclure_page($fond, $contexte, $connect);
+	if ($GLOBALS['flag_ob'] AND ($page['process_ins'] != 'html')) {
+		ob_start();
+		eval('?' . '>' . $page['texte']);
+		$page['texte'] = ob_get_contents();
+		$page['process_ins'] = 'html';
+		ob_end_clean();
+	}
+
+	if (!isset($options['protect_xml'])
+	AND isset($page['entetes']['X-Xml-Hack']))
+		$page['texte'] = str_replace("<\1?xml", '<'.'?xml', $page['texte']);
 
+	$GLOBALS['_INC_PUBLIC']--;
+
+	return $page;
+}
 
 
 /*
diff --git a/ecrire/inc_version.php b/ecrire/inc_version.php
index e29d63a14be98902270a503c52565adbb8d672eb..2dcea9ebe3dca6aa27d207ff48cf2959b11e86f7 100644
--- a/ecrire/inc_version.php
+++ b/ecrire/inc_version.php
@@ -217,6 +217,7 @@ $spip_pipeline = array(
 	'ajouter_boutons' => '',
 	'ajouter_onglets' => '',
 	'body_prive' => '',
+	'definir_session' => '',
 	'delete_all' => '',
 	'delete_statistiques' => '',
 	'exec_init' => '',
diff --git a/ecrire/index.php b/ecrire/index.php
index 741ffe6e432686ba5bb08d6670f53800164ea5dd..07c751bc649a752d98a5cd9777b69eb6257e78c5 100644
--- a/ecrire/index.php
+++ b/ecrire/index.php
@@ -70,16 +70,19 @@ if (autoriser_sans_cookie($exec)) {
 $prefs_mod = false;
 
 if (isset($_GET['set_couleur'])) {
-	$GLOBALS['auteur_session']['prefs']['couleur'] = floor($_GET['set_couleur']);
+	$GLOBALS['auteur_session']['prefs']['couleur'] = intval($_GET['set_couleur']);
 	$prefs_mod = true;
 }
 if (isset($_GET['set_disp'])) {
-	$GLOBALS['auteur_session']['prefs']['display'] = floor($_GET['set_disp']);
+	$GLOBALS['auteur_session']['prefs']['display'] = intval($_GET['set_disp']);
 	$prefs_mod = true;
 }
 if ($prefs_mod AND !$var_auth) {
 	sql_updateq('spip_auteurs', array('prefs' => serialize($GLOBALS['auteur_session']['prefs'])), "id_auteur=" .intval($GLOBALS['auteur_session']['id_auteur']));
- }
+
+	// Si modif des couleurs en ajax, stop ici
+	if ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') exit;
+}
 
 // compatibilite ascendante
 $GLOBALS['spip_display'] = isset($GLOBALS['auteur_session']['prefs']['display'])
diff --git a/ecrire/public/assembler.php b/ecrire/public/assembler.php
index b99d87642c309c8633b43adabb504a336ad9e2f6..3819d6d03edad4e6d387343280158d538a470237 100644
--- a/ecrire/public/assembler.php
+++ b/ecrire/public/assembler.php
@@ -537,29 +537,19 @@ function message_erreur_404 ($erreur= "") {
 // fonction permettant de recuperer le resultat du calcul d'un squelette
 // pour une inclusion dans un flux
 // http://doc.spip.org/@recuperer_fond
-function recuperer_fond($fond, $contexte=array(),$protect_xml=false, $trim=true, $connect='') {
-	// on est peut etre dans l'espace prive au moment de l'appel
-	if (!isset($GLOBALS['_INC_PUBLIC'])) $GLOBALS['_INC_PUBLIC'] = 0;
-	$GLOBALS['_INC_PUBLIC']++;
-	if (($fond=='')&&isset($contexte['fond']))
-		$fond = $contexte['fond'];
+function recuperer_fond($fond, $contexte=array(), $protect_xml=false, $trim=true, $connect='') {
+	$options = array(
+		'protect_xml' => $protect_xml,
+		'trim' => $trim
+	);
 
 	$texte = "";
 	foreach(is_array($fond) ? $fond : array($fond) as $f){
-		$page = inclure_page($f, $contexte, $connect);
-		if ($GLOBALS['flag_ob'] AND ($page['process_ins'] != 'html')) {
-			ob_start();
-			eval('?' . '>' . $page['texte']);
-			$page['texte'] = ob_get_contents();
-			ob_end_clean();
-		}
-		if (!$protect_xml && isset($page['entetes']['X-Xml-Hack']))
-			$page['texte'] = str_replace("<\1?xml", '<'.'?xml', $page['texte']);
-	// pas de trim, pour etre homogene avec <INCLURE>
+		$page = assembler($f, $contexte, $options, $connect);
 		$texte .= $trim ? rtrim($page['texte']) : $page['texte'];
 	}
-	$GLOBALS['_INC_PUBLIC']--;
-	return $trim ?  ltrim($texte) : $texte;
+
+	return $trim ? ltrim($texte) : $texte;
 }
 
 // temporairement ici : a mettre dans le futur inc/modeles
@@ -635,7 +625,7 @@ function inclure_modele($type, $id, $params, $lien, $connect='') {
 		'fond' => $fond, 
 		'dir_racine' => _DIR_RACINE # eviter de mixer un cache racine et un cache ecrire (meme si pour l'instant les modeles ne sont pas caches, le resultat etant different il faut que le contexte en tienne compte 
 	); 
-	// Le numerdo du modele est mis dans l'environnement 
+	// Le numero du modele est mis dans l'environnement
 	// d'une part sous l'identifiant "id"
 	// et d'autre part sous l'identifiant de la cle primaire supposee
 	// par la fonction table_objet, 
@@ -670,7 +660,14 @@ function inclure_modele($type, $id, $params, $lien, $connect='') {
 	$GLOBALS['compt_note'] = 0;
 
 	// Appliquer le modele avec le contexte
-	$retour = trim(recuperer_fond($fond, $contexte, false, true, $connect));
+	$page = assembler($fond, $contexte, array(), $connect);
+	$retour = trim($page['texte']);
+
+	// Lever un drapeau (global) si le modele utilise #SESSION
+	// a destination de public/cacher
+	if (isset($page['invalideurs'])
+	AND isset($page['invalideurs']['session']))
+		$GLOBALS['cache_utilise_session'] = $page['invalideurs']['session'];
 
 	// On restitue les globales de notes telles qu'elles etaient avant l'appel
 	// du modele. Si le modele n'a pas affiche ses notes, tant pis (elles *doivent*
diff --git a/ecrire/public/cacher.php b/ecrire/public/cacher.php
index 307d3ec267363e05c50337b193fd30e0d629863a..eb7a09419433a5d93f758856373b1f7d6ab9319b 100644
--- a/ecrire/public/cacher.php
+++ b/ecrire/public/cacher.php
@@ -131,6 +131,11 @@ function creer_cache(&$page, &$chemin_cache) {
 	// 'tmp/cache/a/c1234-zz.gz'
 	// en prenant soin de supprimer un eventuel cache non-sessionne
 	// si l'ajout de #SESSION dans le squelette est recent
+	// ou si un modele inclus contenait #SESSION
+	if (isset($GLOBALS['cache_utilise_session'])) {
+		$page['invalideurs']['session'] = $GLOBALS['cache_utilise_session'];
+		unset($GLOBALS['cache_utilise_session']);
+	}
 	if (isset($page['invalideurs'])
 	AND isset($page['invalideurs']['session'])) {
 		supprimer_fichier(_DIR_CACHE . $chemin_cache);