Index: admin/js/jquery/jquery.pageTabs.js
===================================================================
--- admin/js/jquery/jquery.pageTabs.js	(revision 2479)
+++ admin/js/jquery/jquery.pageTabs.js	(revision 3333)
@@ -1,5 +1,5 @@
 (function($) {
 	'use strict';
-    
+
 	$.pageTabs = function(start_tab, opts) {
 		var defaults = {
@@ -10,8 +10,9 @@
 			idTabPrefix: 'part-tabs-'
 		};
-		
+
 		$.pageTabs.options = $.extend({}, defaults, opts);
 		var active_tab = start_tab || '';
 		var hash = $.pageTabs.getLocationHash();
+		var subhash = $.pageTabs.getLocationSubhash();
 
 		if (hash !== undefined && hash) {
@@ -23,5 +24,5 @@
 
 		createTabs();
-		
+
 		$('ul li', '.'+$.pageTabs.options.containerClass).click(function(e) {
 			if ($(this).hasClass($.pageTabs.options.activeClass)) {
@@ -40,5 +41,5 @@
 				part_to_activate.addClass('loaded');
 			}
-			
+
 			part_to_activate.tabload();
 		});
@@ -49,11 +50,16 @@
 
 		$.pageTabs.clickTab(active_tab);
-		
+
+		if (subhash !== undefined) {
+			// Tab displayed, now scroll to the sub-part if defined in original document.location (#tab.sub-part)
+			document.getElementById(subhash).scrollIntoView();
+		}
+
 		return this;
 	};
-	
+
 	var createTabs = function createTabs() {
 		var lis = [], li_class = '';
-		
+
 		$('.'+$.pageTabs.options.contentClass).each(function() {
 			$(this).hide();
@@ -62,9 +68,9 @@
 			$(this).attr('id', $.pageTabs.options.partPrefix + $(this).attr('id')).prop('title','');
 		});
-		
+
 		$('<div class="'+$.pageTabs.options.containerClass+'"><ul>'+lis.join('')+'</ul></div>')
 			.insertBefore($('.'+$.pageTabs.options.contentClass).get(0));
 	};
-	
+
 	var getHash = function getHash(href) {
 		var href = href || '';
@@ -72,5 +78,5 @@
 		return href.replace(/.*#/, '');
 	};
-	
+
 	$.pageTabs.clickTab = function(tab) {
 		if (tab=='') {
@@ -96,5 +102,12 @@
 
 	$.pageTabs.getLocationHash = function() {
-		return getHash(document.location.hash);
+		// Return the URL hash (without subhash — #hash[.subhash])
+		var h = getHash(document.location.hash).split('.');
+		return h[0];
+	};
+	$.pageTabs.getLocationSubhash = function() {
+		// Return the URL subhash if present (without hash — #hash[.subhash])
+		var sh = getHash(document.location.hash).split('.');
+		return sh[1];
 	};
 })(jQuery);
Index: admin/plugin.php
===================================================================
--- admin/plugin.php	(revision 2708)
+++ admin/plugin.php	(revision 3333)
@@ -78,4 +78,11 @@
 	call_user_func($open_f,$p_title,$p_head);
 	echo $p_content;
+	if (!$popup) {
+		// Add direct links to plugin settings if any
+		$settings = adminModulesList::getSettingsUrls($core,$p,true,false);
+		if (!empty($settings)) {
+			echo '<hr class="clear"/><p class="right modules">'.implode(' - ',$settings).'</p>';
+		}
+	}
 	call_user_func($close_f);
 }
Index: admin/preferences.php
===================================================================
--- admin/preferences.php	(revision 3330)
+++ admin/preferences.php	(revision 3333)
@@ -490,5 +490,5 @@
 echo
 '<div class="fieldset">'.
-'<h4>'.__('Interface').'</h4>'.
+'<h4 id="user_options_interface">'.__('Interface').'</h4>'.
 
 '<p><label for="user_ui_enhanceduploader" class="classic">'.
@@ -524,5 +524,5 @@
 echo
 '<div class="fieldset">'.
-'<h4>'.__('Optional columns displayed in lists').'</h4>';
+'<h4 id="user_options_columns">'.__('Optional columns displayed in lists').'</h4>';
 $odd = true;
 foreach ($cols as $col_type => $col_list) {
@@ -541,5 +541,5 @@
 echo
 '<div class="fieldset">'.
-'<h4>'.__('Edition').'</h4>';
+'<h4 id="user_options_edition">'.__('Edition').'</h4>';
 
 echo '<div class="two-boxes odd">';
Index: inc/admin/lib.moduleslist.php
===================================================================
--- inc/admin/lib.moduleslist.php	(revision 3327)
+++ inc/admin/lib.moduleslist.php	(revision 3333)
@@ -466,5 +466,7 @@
 				'sshot' 			=> '',
 				'score'				=> 0,
-				'type' 				=> null
+				'type' 				=> null,
+				'require'			=> array(),
+				'settings'			=> array()
 			),
 			# Module's values
@@ -744,5 +746,5 @@
 					if (!empty($more)) {
 						echo
-						'<li>'.implode(' - ', $more).'</li>';
+						'<li>'.implode(' - ',$more).'</li>';
 					}
 
@@ -753,11 +755,11 @@
 				$config = !empty($module['root']) && file_exists(path::real($module['root'].'/_config.php'));
 
-				if ($config || !empty($module['section']) || !empty($module['tags'])) {
+				if ($config || !empty($module['section']) || !empty($module['tags']) || !empty($module['settings'])) {
 					echo
 					'<div><ul class="mod-more">';
 
-					if ($config) {
-						echo
-						'<li><a class="module-config" href="'.$this->getURL('module='.$id.'&amp;conf=1').'">'.__('Configure plugin').'</a></li>';
+					$settings = $this->getSettingsUrls($this->core,$id);
+					if (!empty($settings)) {
+						echo '<li>'.implode(' - ',$settings).'</li>';
 					}
 
@@ -806,4 +808,63 @@
 
 		return $this;
+	}
+
+	/**
+	 * Get settings URLs if any
+	 *
+	 * @param object $core
+	 * @param string $id module ID
+	 * @param boolean $check check permission
+	 * @param boolean $self include self URL (→ plugin index.php URL)
+	 * @return Array of settings URLs
+	 */
+	public static function getSettingsUrls($core,$id,$check=false,$self=true)
+	{
+		$st = array();
+
+		$config = !empty($core->plugins->moduleRoot($id)) &&
+			file_exists(path::real($core->plugins->moduleRoot($id).'/_config.php'));
+		$settings = $core->plugins->moduleInfo($id,'settings');
+		if ($config || !empty($settings)) {
+			if ($config) {
+				$st[] = '<a class="module-config" href="'.
+					$core->adminurl->get('admin.plugins',array('module' => $id,'conf' => '1')).
+					'">'.__('Configure plugin').'</a>';
+			}
+			if (is_array($settings)) {
+				foreach ($settings as $sk => $sv) {
+					switch ($sk) {
+						case 'blog':
+							if ((!$check) ||
+								($check && $core->auth->check('admin',$core->blog->id))) {
+								$st[] = '<a class="module-config" href="'.
+									$core->adminurl->get('admin.blog.pref').$sv.
+									'">'.__('Plugin settings (in blog parameters)').'</a>';
+							}
+							break;
+						case 'pref':
+							if ((!$check) ||
+								($check && $core->auth->check('usage,contentadmin',$core->blog->id))) {
+								$st[] = '<a class="module-config" href="'.
+									$core->adminurl->get('admin.user.preferences').$sv.
+									'">'.__('Plugin settings (in user preferences)').'</a>';
+							}
+							break;
+						case 'self':
+							if ($self) {
+								if ((!$check) ||
+									($check && $core->auth->check($core->plugins->moduleInfo($id,'permissions'),$core->blog->id))) {
+									$st[] = '<a class="module-config" href="'.
+										$core->adminurl->get('admin.plugin.'.$id).$sv.
+										'">'.__('Plugin settings').'</a>';
+								}
+							}
+							break;
+					}
+				}
+			}
+		}
+
+		return $st;
 	}
 
Index: inc/core/class.dc.modules.php
===================================================================
--- inc/core/class.dc.modules.php	(revision 3135)
+++ inc/core/class.dc.modules.php	(revision 3333)
@@ -283,5 +283,5 @@
 	(currently available keys : permissions, priority, type)
 	*/
-	public function registerModule($name,$desc,$author,$version, $properties = array())
+	public function registerModule($name,$desc,$author,$version,$properties = array())
 	{
 		if ($this->disabled_mode) {
@@ -320,5 +320,6 @@
 				'type' => null,
 				'enabled' => true,
-				'requires' => array()
+				'requires' => array(),
+				'settings' => array()
 			), $properties
 		);
Index: locales/fr/main.po
===================================================================
--- locales/fr/main.po	(revision 3330)
+++ locales/fr/main.po	(revision 3333)
@@ -2979,4 +2979,13 @@
 msgstr "Configurer le plugin"
 
+msgid "Plugin settings (in blog parameters)"
+msgstr "Réglages du plugin (paramètres du blog)"
+
+msgid "Plugin settings (in user preferences)"
+msgstr "Réglages du plugin (mes préférences)"
+
+msgid "Plugin settings"
+msgstr "Réglages du plugin"
+
 msgid "No plugins matched your search."
 msgstr "Aucun plugin ne correspond à votre recherche."
Index: plugins/antispam/_admin.php
===================================================================
--- plugins/antispam/_admin.php	(revision 2849)
+++ plugins/antispam/_admin.php	(revision 3333)
@@ -91,5 +91,5 @@
 		$ttl = $settings->antispam->antispam_moderation_ttl;
 		echo
-		'<div class="fieldset"><h4>Antispam</h4>'.
+		'<div class="fieldset"><h4 id="antispam_params">Antispam</h4>'.
 		'<p><label for="antispam_moderation_ttl" class="classic">'.__('Delete junk comments older than').' '.
 		form::field('antispam_moderation_ttl', 3, 3, $ttl).
Index: plugins/antispam/_define.php
===================================================================
--- plugins/antispam/_define.php	(revision 2566)
+++ plugins/antispam/_define.php	(revision 3333)
@@ -19,5 +19,9 @@
 	array(
 		'permissions' =>	'usage,contentadmin',
-		'priority' =>		10
+		'priority' =>		10,
+		'settings'	=>		array(
+								'self' => '',
+								'blog' => '#params.antispam_params'
+							)
 	)
 );
Index: plugins/breadcrumb/_admin.php
===================================================================
--- plugins/breadcrumb/_admin.php	(revision 3009)
+++ plugins/breadcrumb/_admin.php	(revision 3333)
@@ -25,5 +25,5 @@
 		$settings->addNameSpace('breadcrumb');
 		echo
-		'<div class="fieldset"><h4>'.__('Breadcrumb').'</h4>'.
+		'<div class="fieldset"><h4 id="breadcrumb_params">'.__('Breadcrumb').'</h4>'.
 		'<p><label class="classic">'.
 		form::checkbox('breadcrumb_enabled','1',$settings->breadcrumb->breadcrumb_enabled).
Index: plugins/breadcrumb/_define.php
===================================================================
--- plugins/breadcrumb/_define.php	(revision 3085)
+++ plugins/breadcrumb/_define.php	(revision 3333)
@@ -20,5 +20,8 @@
 	array(
 		/* Permissions */	'permissions' =>	'usage,contentadmin',
-		/* Type */			'type' =>			'plugin'
+		/* Type */			'type' =>			'plugin',
+		'settings'	=>		array(
+								'blog' => '#params.breadcrumb_params'
+							)
 	)
 );
Index: plugins/dcCKEditor/_define.php
===================================================================
--- plugins/dcCKEditor/_define.php	(revision 3090)
+++ plugins/dcCKEditor/_define.php	(revision 3333)
@@ -19,5 +19,9 @@
 	array(
 		'permissions' =>	'usage,contentadmin',
-		'type'		=>		'plugin'
+		'type'		=>		'plugin',
+		'settings'	=>		array(
+								'self' => '',
+								'pref' => '#user-options.user_options_edition'
+							)
 	)
 );
Index: plugins/dcLegacyEditor/_define.php
===================================================================
--- plugins/dcLegacyEditor/_define.php	(revision 3258)
+++ plugins/dcLegacyEditor/_define.php	(revision 3333)
@@ -19,5 +19,9 @@
 	array(
 		'permissions' =>	'usage,contentadmin',
-		'type'		=>		'plugin'
+		'type'		=>		'plugin',
+		'settings'	=>		array(
+								'self' => '',
+								'pref' => '#user-options.user_options_edition'
+							)
 	)
 );
Index: plugins/maintenance/_define.php
===================================================================
--- plugins/maintenance/_define.php	(revision 2257)
+++ plugins/maintenance/_define.php	(revision 3333)
@@ -19,5 +19,8 @@
 	array(
 		'permissions' =>	'admin',
-		'type'		=>		'plugin'
+		'type'		=>		'plugin',
+		'settings'	=>		array(
+								'self' => '#settings'
+							)
 	)
 
Index: plugins/pings/_define.php
===================================================================
--- plugins/pings/_define.php	(revision 2566)
+++ plugins/pings/_define.php	(revision 3333)
@@ -19,5 +19,8 @@
 	array(
 		'permissions' =>	'usage,contentadmin',
-		'type'		=>		'plugin'
+		'type'		=>		'plugin',
+		'settings'	=>		array(
+								'self' => ''
+							)
 	)
 );
Index: plugins/simpleMenu/_define.php
===================================================================
--- plugins/simpleMenu/_define.php	(revision 2773)
+++ plugins/simpleMenu/_define.php	(revision 3333)
@@ -19,5 +19,8 @@
 	array(
 		'permissions' =>	'admin',
-		'type'		=>		'plugin'
+		'type'		=>		'plugin',
+		'settings'	=>		array(
+								'self' => ''
+							)
 	)
 );
Index: plugins/tags/_define.php
===================================================================
--- plugins/tags/_define.php	(revision 2924)
+++ plugins/tags/_define.php	(revision 3333)
@@ -20,5 +20,8 @@
 		'permissions' =>	'usage,contentadmin',
 		'priority' =>		1001,	// Must be higher than dcLegacyEditor/dcCKEditor priority (ie 1000)
-		'type'		=>		'plugin'
+		'type'		=>		'plugin',
+		'settings'	=>		array(
+								'pref' => '#user-options.tags_prefs'
+							)
 	)
 );
Index: plugins/tags/inc/tags.behaviors.php
===================================================================
--- plugins/tags/inc/tags.behaviors.php	(revision 3024)
+++ plugins/tags/inc/tags.behaviors.php	(revision 3333)
@@ -363,7 +363,8 @@
 
 		echo
+		'<div class="fieldset"><h5 id="tags_prefs">'.__('Tags').'</h5>'.
 		'<p><label for="user_tag_list_format" class="classic">'.__('Tags list format:').'</label> '.
 		form::combo('user_tag_list_format',$combo,$value).
-		'</p>';
+		'</p></div>';
 	}
 
Index: plugins/themeEditor/_admin.php
===================================================================
--- plugins/themeEditor/_admin.php	(revision 3257)
+++ plugins/themeEditor/_admin.php	(revision 3333)
@@ -60,5 +60,5 @@
 		echo
 			'<div class="fieldset two-cols clearfix">'.
-			'<h5>'.__('Syntax highlighting').'</h5>';
+			'<h5 id="themeEditor_prefs">'.__('Syntax highlighting').'</h5>';
 		echo
 			'<div class="col">'.
Index: plugins/themeEditor/_define.php
===================================================================
--- plugins/themeEditor/_define.php	(revision 3251)
+++ plugins/themeEditor/_define.php	(revision 3333)
@@ -18,5 +18,8 @@
 	/* Version */			'1.3',
 	array(
-		'type'		=>		'plugin'
+		'type'		=>		'plugin',
+		'settings'	=>		array(
+								'pref' => '#user-options.themeEditor_prefs'
+							)
 	)
 );
