diff --git a/.gitattributes b/.gitattributes
index 0826c38c8f008eb8a290ec1b25824a220e5102fb..c62c56e496f2efa4e01533b58585d23d5b2ba6c8 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -614,6 +614,7 @@ ecrire/inc/instituer_site.php -text
 ecrire/inc/joindre.php -text
 ecrire/inc/lang_liste.php -text
 ecrire/inc/legender.php -text
+ecrire/inc/lien.php -text
 ecrire/inc/message_select.php -text
 ecrire/inc/minipres.php -text
 ecrire/inc/modifier.php -text
diff --git a/ecrire/inc/lien.php b/ecrire/inc/lien.php
new file mode 100644
index 0000000000000000000000000000000000000000..0417946ef92e14c3a543cc1da15c9d4aff017dd3
--- /dev/null
+++ b/ecrire/inc/lien.php
@@ -0,0 +1,123 @@
+<?php
+
+/***************************************************************************\
+ *  SPIP, Systeme de publication pour l'internet                           *
+ *                                                                         *
+ *  Copyright (c) 2001-2007                                                *
+ *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
+ *                                                                         *
+ *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
+ *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
+\***************************************************************************/
+
+if (!defined("_ECRIRE_INC_VERSION")) return;
+
+function inc_lien_dist($type,$id,$args,$ancre,$texte='',$pour='url',$connect='') {
+	if ($connect) {
+		$id_type = ($type != 'site') ? "id_$type" : 'id_syndic';
+		$res = get_spip_script('./')
+		. "?page=$type&$id_type=$id&connect=$connect"
+		. (!$args ? '' : "&$args");
+	} else {
+		charger_generer_url();
+		$g = 'generer_url_' . $type;
+		if (function_exists($g) OR function_exists($g .= '_dist')) 
+				$res = $g($id, $args, $ancre);
+		
+		if (!$res) return false;
+	}
+	if ($pour == 'url') return array($res);
+	$g = 'calculer_url_' . $type;
+	if (!(function_exists($g) OR function_exists($g .= '_dist')))
+		return array($res);
+	return $g($id, $texte, $res, $connect);
+}
+
+function calculer_url_article_dist($id, $texte='', $lien='', $connect='') {
+
+	$row = sql_fetsel('titre,lang', 'spip_articles', "id_article=$id",'','','','','','','',$connect);
+	if (!trim($texte))
+		$texte = supprimer_numero($row['titre']);
+	if (!trim($texte))
+		$texte = _T('article') . $id;
+	return array($lien, 'spip_in', $texte, $row['lang']);
+}
+
+function calculer_url_rubrique_dist($id, $texte='', $lien='', $connect='')
+{
+	$row = sql_fetsel('titre,lang', 'spip_rubriques', "id_rubrique=$id",'','','','','','','',$connect);
+	if (!trim($texte)) {
+		$texte = supprimer_numero($row['titre']);
+		if (!trim($texte)) $texte = $id;
+	}
+
+	return array($lien, 'spip_in', $texte, $row['lang']);
+}
+
+function calculer_url_breve_dist($id, $texte='', $lien='', $connect='')
+{
+	$row = sql_fetsel('titre,lang', 'spip_breves', "id_breve=$id",'','','','','','','',$connect);
+	if (!trim($texte)) {
+		$texte = supprimer_numero($row['titre']);
+		if (!trim($texte)) $texte = $id;
+	}
+	return array($lien, 'spip_in', $texte, $row['lang']);
+}
+
+function calculer_url_auteur_dist($id, $texte='', $lien='', $connect='')
+{
+	if ($texte=='') {
+		$row = sql_fetsel('nom', 'spip_auteurs', "id_auteur=$id",'','','','','','','',$connect);
+		$texte = $row['nom'];
+	}
+	return array($lien, 'spip_in', $texte); # pas de hreflang
+}
+
+function calculer_url_mot_dist($id, $texte='', $lien='', $connect='')
+{
+	if (!trim($texte)) {
+		$row = sql_fetsel('titre', 'spip_mots', "id_mot=$id",'','','','','','','',$connect);
+		$texte = supprimer_numero($row['titre']);
+		if (!trim($texte)) $texte = $id;
+	}
+	return array($lien, 'spip_in', $texte);
+}
+
+function calculer_url_document_dist($id, $texte='', $lien='', $connect='')
+{
+	if ($texte=='') {
+		$row = sql_fetsel('titre,fichier', 'spip_documents', "id_document=$id",'','','','','','','',$connect);
+
+		$texte = $row['titre'];
+		if (!trim($texte))
+			$texte = preg_replace(",^.*/,","",$row['fichier']);
+		if (!trim($texte))
+		    $texte = $id;
+	}
+	return array($lien, 'spip_in', $texte); # pas de hreflang
+}
+
+function calculer_url_site_dist($id, $texte='', $lien='', $connect='')
+{
+	# attention dans le cas des sites le lien pointe non pas sur
+	# la page locale du site, mais directement sur le site lui-meme
+	$row =sql_fetsel('nom_site,url_site', 'spip_syndic', "id_syndic=$id",'','','','','','','',$connect);
+	if ($row) {
+		$lien = $row['url_site'];
+		if (!trim($texte))
+			$texte = supprimer_numero($row['nom_site']);
+		if (!trim($texte)) $texte = $id;
+	}
+	return array($lien, 'spip_out', $texte, $row['lang']);
+}
+
+function calculer_url_forum_dist($id, $texte='', $lien='', $connect='')
+{
+	if (!trim($texte)) {
+		$row = sql_fetsel('titre', 'spip_forum', "id_forum=$id AND statut='publie'",'','','','','','','',$connect);
+		$texte = $row['titre'];
+		if (!trim($texte)) $texte = $id;
+	}
+	return array($lien, 'spip_in', $texte); # pas de hreflang
+}
+?>
diff --git a/ecrire/inc/texte.php b/ecrire/inc/texte.php
index 86e9e07a219d73d86f7384d0fa67a8bbd82d0e11..2b496ad37b6393f89667ead1da62ad336c3c6728 100644
--- a/ecrire/inc/texte.php
+++ b/ecrire/inc/texte.php
@@ -604,45 +604,23 @@ function typer_raccourci ($lien) {
 // 'url':   seulement U  (i.e. generer_url_RACCOURCI)
 
 // http://doc.spip.org/@calculer_url
-function calculer_url ($lien, $texte='', $pour='url', $connect='') {
+function calculer_url ($ref, $texte='', $pour='url', $connect='') {
 	include_spip('base/abstract_sql');
-	if ($match = typer_raccourci($lien)) {
-		@list($f,,$id,,$param,,$ancre) = $match;
-		$res = '';
-		if ($connect) {
-			$id_type = ($f != 'site') ? "id_$f" : 'id_syndic';
-			$res = get_spip_script('./')
-			. "?page=$f&$id_type=$id&connect=$connect"
-			. (!$param ? '' : "&$param");
-		} else {
-			charger_generer_url();
-			$g = 'generer_url_' . $f;
-			if (function_exists($g) OR function_exists($g .= '_dist')) 
-				$res = $g($id, $param, $ancre);
-		}
-		if ($res) {
-			if ($pour == 'url') return $res;
-			$g = 'calculer_url_' . $f;
-			if (function_exists($g) OR function_exists($g .= '_dist')) { 
-				if ($pour == 'tout')
-					return $g($id, $texte, $res, $connect);
-				$res = $g($id, $texte, $res, $connect);
-				return $res[2];
-			} 
+	if ($match = typer_raccourci($ref)) {
+		@list($f,,$id,,$args,,$ancre) = $match;
+		$lien = charger_fonction('lien', 'inc', true);
+		if ($lien) {
+			$r = $lien($f,$id,$args,$ancre,$texte,$pour,$connect);
+			if ($r)
+			  return ($pour=='tout') ? $r : 
+				(($pour=='url') ? $r[0] :$r[2]);
 		}
 		spip_log("raccourci indefini $f");
 	}
-	return calculer_url_sans_rac($lien, $texte, $pour);
-}
-
-// cf specif ci-dessus
-
-// http://doc.spip.org/@calculer_url_sans_rac
-function calculer_url_sans_rac ($lien, $texte='', $pour='url') {
-	if (preg_match(",^\s*(http:?/?/?|mailto:?)\s*$,iS", $lien))
+	if (preg_match(",^\s*(http:?/?/?|mailto:?)\s*$,iS", $ref))
 		return ($pour != 'tout') ? '' : array('','','','');
 
-	$lien = entites_html(trim($lien));
+	$lien = entites_html(trim($ref));
 
 	// Liens explicites
 	if (!$texte) {
@@ -668,102 +646,6 @@ function calculer_url_sans_rac ($lien, $texte='', $pour='url') {
 	return ($pour == 'url') ? $lien : array($lien, $class, $texte, '');
 }
 
-// http://doc.spip.org/@calculer_url_article_dist
-function calculer_url_article_dist($id, $texte='', $lien='', $connect='') {
-
-	$row = sql_fetsel('titre,lang', 'spip_articles', "id_article=$id",'','','','','','','',$connect);
-	if (!trim($texte))
-		$texte = supprimer_numero($row['titre']);
-	if (!trim($texte))
-		$texte = _T('article') . $id;
-	return array($lien, 'spip_in', $texte, $row['lang']);
-}
-
-// http://doc.spip.org/@calculer_url_rubrique_dist
-function calculer_url_rubrique_dist($id, $texte='', $lien='', $connect='')
-{
-	$row = sql_fetsel('titre,lang', 'spip_rubriques', "id_rubrique=$id",'','','','','','','',$connect);
-	if (!trim($texte)) {
-		$texte = supprimer_numero($row['titre']);
-		if (!trim($texte)) $texte = $id;
-	}
-
-	return array($lien, 'spip_in', $texte, $row['lang']);
-}
-
-// http://doc.spip.org/@calculer_url_breve_dist
-function calculer_url_breve_dist($id, $texte='', $lien='', $connect='')
-{
-	$row = sql_fetsel('titre,lang', 'spip_breves', "id_breve=$id",'','','','','','','',$connect);
-	if (!trim($texte)) {
-		$texte = supprimer_numero($row['titre']);
-		if (!trim($texte)) $texte = $id;
-	}
-	return array($lien, 'spip_in', $texte, $row['lang']);
-}
-
-// http://doc.spip.org/@calculer_url_auteur_dist
-function calculer_url_auteur_dist($id, $texte='', $lien='', $connect='')
-{
-	if ($texte=='') {
-		$row = sql_fetsel('nom', 'spip_auteurs', "id_auteur=$id",'','','','','','','',$connect);
-		$texte = $row['nom'];
-	}
-	return array($lien, 'spip_in', $texte); # pas de hreflang
-}
-
-// http://doc.spip.org/@calculer_url_mot_dist
-function calculer_url_mot_dist($id, $texte='', $lien='', $connect='')
-{
-	if (!trim($texte)) {
-		$row = sql_fetsel('titre', 'spip_mots', "id_mot=$id",'','','','','','','',$connect);
-		$texte = supprimer_numero($row['titre']);
-		if (!trim($texte)) $texte = $id;
-	}
-	return array($lien, 'spip_in', $texte);
-}
-
-// http://doc.spip.org/@calculer_url_document_dist
-function calculer_url_document_dist($id, $texte='', $lien='', $connect='')
-{
-	if ($texte=='') {
-		$row = sql_fetsel('titre,fichier', 'spip_documents', "id_document=$id",'','','','','','','',$connect);
-
-		$texte = $row['titre'];
-		if (!trim($texte))
-			$texte = preg_replace(",^.*/,","",$row['fichier']);
-		if (!trim($texte))
-		    $texte = $id;
-	}
-	return array($lien, 'spip_in', $texte); # pas de hreflang
-}
-
-// http://doc.spip.org/@calculer_url_site_dist
-function calculer_url_site_dist($id, $texte='', $lien='', $connect='')
-{
-	# attention dans le cas des sites le lien pointe non pas sur
-	# la page locale du site, mais directement sur le site lui-meme
-	$row =sql_fetsel('nom_site,url_site', 'spip_syndic', "id_syndic=$id",'','','','','','','',$connect);
-	if ($row) {
-		$lien = $row['url_site'];
-		if (!trim($texte))
-			$texte = supprimer_numero($row['nom_site']);
-		if (!trim($texte)) $texte = $id;
-	}
-	return array($lien, 'spip_out', $texte, $row['lang']);
-}
-
-// http://doc.spip.org/@calculer_url_forum_dist
-function calculer_url_forum_dist($id, $texte='', $lien='', $connect='')
-{
-	if (!trim($texte)) {
-		$row = sql_fetsel('titre', 'spip_forum', "id_forum=$id AND statut='publie'",'','','','','','','',$connect);
-		$texte = $row['titre'];
-		if (!trim($texte)) $texte = $id;
-	}
-	return array($lien, 'spip_in', $texte); # pas de hreflang
-}
-
 //
 // Tableaux
 //