Index: wp-admin/includes/plugin.php
===================================================================
--- wp-admin/includes/plugin.php	(revision 18542)
+++ wp-admin/includes/plugin.php	(working copy)
@@ -868,6 +868,12 @@
 
 	$menu_slug = plugin_basename( $menu_slug );
 
+	if( isset( $admin_page_hooks[ $menu_slug ] ) ) {
+		$hookname = get_plugin_page_hookname( $menu_slug, '' );
+		//Avoid registering the same hook twice. Note that any later registrations won't get the display action automatically added to avoid complete page from being rendered twice
+		return $hookname;
+	}
+
 	$admin_page_hooks[$menu_slug] = sanitize_title( $menu_title );
 
 	$hookname = get_plugin_page_hookname( $menu_slug, '' );
@@ -1715,12 +1721,12 @@
  *
  * @since 2.7.0
  *
- * @param string $option_group A settings group name.  This should match the group name used in register_setting().
+ * @param string $page_id The slug name of the settings page.  This should match the group name used in register_setting().
  */
-function settings_fields($option_group) {
-	echo "<input type='hidden' name='option_page' value='" . esc_attr($option_group) . "' />";
+function settings_fields($page_id) {
+	echo "<input type='hidden' name='option_page' value='" . esc_attr($page_id) . "' />";
 	echo '<input type="hidden" name="action" value="update" />';
-	wp_nonce_field("$option_group-options");
+	wp_nonce_field("$page_id-options");
 }
 
 ?>
Index: wp-admin/includes/template.php
===================================================================
--- wp-admin/includes/template.php	(revision 18542)
+++ wp-admin/includes/template.php	(working copy)
@@ -1078,27 +1078,31 @@
  *
  * @global $wp_settings_sections Storage array of all settings sections added to admin pages
  *
- * @param string $id Slug-name to identify the section. Used in the 'id' attribute of tags.
+ * @param string $section_id Slug-name to identify the section. Used in the 'id' attribute of tags.
  * @param string $title Formatted title of the section. Shown as the heading for the section.
- * @param string $callback Function that echos out any content at the top of the section (between heading and fields).
- * @param string $page The slug-name of the settings page on which to show the section. Built-in pages include 'general', 'reading', 'writing', 'discussion', 'media', etc. Create your own using add_options_page();
+ * @param string $pre_callback Function that echos out any content at the top of the section (between heading and fields).
+ * @param string $page_id The slug-name of the settings page on which to show the section. Built-in pages include 'general', 'reading', 'writing', 'discussion', 'media', etc. Create your own using add_options_page();
  */
-function add_settings_section($id, $title, $callback, $page) {
+function add_settings_section( $section_id, $title = '', $pre_callback = '', $page_id ) {
 	global $wp_settings_sections;
 
-	if ( 'misc' == $page ) {
+	//leaving this in for now in case we don't change this function much
+	if( 'misc' == $page_id ) {
 		_deprecated_argument( __FUNCTION__, '3.0', __( 'The miscellaneous options group has been removed. Use another settings group.' ) );
-		$page = 'general';
+		$page_id = 'general';
 	}
 
-	if ( !isset($wp_settings_sections) )
+	if( !isset( $wp_settings_sections ) )
 		$wp_settings_sections = array();
-	if ( !isset($wp_settings_sections[$page]) )
-		$wp_settings_sections[$page] = array();
-	if ( !isset($wp_settings_sections[$page][$id]) )
-		$wp_settings_sections[$page][$id] = array();
+	if( !isset( $wp_settings_sections[$page_id] ) )
+		$wp_settings_sections[$page_id] = array();
+	if( isset( $wp_settings_sections[$page_id][$section_id] ) )
+		return; //avoid overwriting the previous registration and adding additional pre-section callback.  If output other than a description is needed before the section, the action can be hooked into on it's own
 
-	$wp_settings_sections[$page][$id] = array('id' => $id, 'title' => $title, 'callback' => $callback);
+		$wp_settings_sections[$page_id][$section_id] = array('id' => $section_id, 'title' => $title);
+
+	if( $pre_callback )
+		add_action( "pre_setting_section_{$page_id}_{$section_id}", $pre_callback );
 }
 
 /**
@@ -1116,29 +1120,44 @@
  *
  * @global $wp_settings_fields Storage array of settings fields and info about their pages/sections
  *
- * @param string $id Slug-name to identify the field. Used in the 'id' attribute of tags.
+ * @param string $field_id Slug-name to identify the field. Used in the 'id' attribute of tags.
  * @param string $title Formatted title of the field. Shown as the label for the field during output.
- * @param string $callback Function that fills the field with the desired form inputs. The function should echo its output.
- * @param string $page The slug-name of the settings page on which to show the section (general, reading, writing, ...).
- * @param string $section The slug-name of the section of the settingss page in which to show the box (default, ...).
+ * @param string $display_callback Function that fills the field with the desired form inputs. The function should echo its output.
+ * @param string $page_id The slug-name of the settings page on which to show the section (general, reading, writing, ...).
+ * @param string $section_id The slug-name of the section of the settingss page in which to show the box (default, ...).
  * @param array $args Additional arguments
+ * @param string $sanitize_callback Function that sanitizes the field on save
+ * @param string $option_name Optional name of otion that will be updated from the field, will use the field_id if not set.
  */
-function add_settings_field($id, $title, $callback, $page, $section = 'default', $args = array()) {
+function add_settings_field($field_id, $title, $display_callback, $page_id, $section_id = 'default', $args = array(), $sanitize_callback = '', $option_name = '' ) {
 	global $wp_settings_fields;
 
-	if ( 'misc' == $page ) {
+	if ( 'misc' == $page_id ) {
 		_deprecated_argument( __FUNCTION__, '3.0', __( 'The miscellaneous options group has been removed. Use another settings group.' ) );
-		$page = 'general';
+		$page_id = 'general';
 	}
 
-	if ( !isset($wp_settings_fields) )
-		$wp_settings_fields = array();
-	if ( !isset($wp_settings_fields[$page]) )
-		$wp_settings_fields[$page] = array();
-	if ( !isset($wp_settings_fields[$page][$section]) )
-		$wp_settings_fields[$page][$section] = array();
+	//we set the field data here because I want the option_name to still be empty if it wasn't passed in
+	if( $option_name )
+		$the_option_name = $option_name;
+	else
+		$the_option_name = $field_id;
 
-	$wp_settings_fields[$page][$section][$id] = array('id' => $id, 'title' => $title, 'callback' => $callback, 'args' => $args);
+	if( !isset( $wp_settings_fields ) )
+		$wp_settings_fields = array( );
+	if( !isset( $wp_settings_fields[ $page_id ] ) )
+		$wp_settings_fields[ $page_id ] = array( );
+	if( !isset( $wp_settings_fields[ $page_id ][ $section_id ] ) )
+		$wp_settings_fields[ $page_id ][ $section_id ] = array( );
+
+	if( !isset( $wp_settings_fields[ $page_id ][ $section_id ][ $the_option_name ] ) )
+		$wp_settings_fields[ $page_id ][ $section_id ][ $the_option_name ] = array( );
+
+	if( !isset( $wp_settings_fields[ $page_id ][ $section_id ][ $the_option_name ][ $field_id ] ) )
+		$wp_settings_fields[ $page_id ][ $section_id ][ $the_option_name ][ $field_id ] = array( 'id' => $field_id, 'title' => $title, 'callback' => $display_callback, 'args' => $args, 'option_name' => $option_name ); //don't override a previously registered field
+
+	if( $sanitize_callback )
+		add_filter( "sanitize_setting_{$page_id}_{$section_id}_{$field_id}", $sanitize_callback, 10, 3 );	//args planned to be $new_value, $old_value, $args from previous
 }
 
 /**
@@ -1152,23 +1171,26 @@
  * @global $wp_settings_fields Storage array of settings fields and info about their pages/sections
  * @since 2.7.0
  *
- * @param string $page The slug name of the page whos settings sections you want to output
+ * @param string $page_id The slug name of the page whos settings sections you want to output
  */
-function do_settings_sections($page) {
+function do_settings_sections($page_id) {
 	global $wp_settings_sections, $wp_settings_fields;
 
-	if ( !isset($wp_settings_sections) || !isset($wp_settings_sections[$page]) )
+	if( !isset( $wp_settings_sections ) || !isset( $wp_settings_sections[ $page_id ] ) )
 		return;
 
-	foreach ( (array) $wp_settings_sections[$page] as $section ) {
-		if ( $section['title'] )
-			echo "<h3>{$section['title']}</h3>\n";
-		call_user_func($section['callback'], $section);
-		if ( !isset($wp_settings_fields) || !isset($wp_settings_fields[$page]) || !isset($wp_settings_fields[$page][$section['id']]) )
-			continue;
-		echo '<table class="form-table">';
-		do_settings_fields($page, $section['id']);
-		echo '</table>';
+	foreach( ( array ) $wp_settings_sections[ $page_id ] as $section ) {
+		if( $section[ 'title' ] )
+			echo "<h3>{$section[ 'title' ]}</h3>\n";
+
+		do_action( "pre_setting_section_{$page_id}_{$section[ 'id' ]}" );
+
+		if( isset( $wp_settings_fields ) && isset( $wp_settings_fields[ $page_id ] ) && isset( $wp_settings_fields[ $page_id ][ $section[ 'id' ] ] ) ) {
+			echo '<table class="form-table">';
+			do_settings_fields( $page_id, $section[ 'id' ] );
+			echo '</table>';
+		}
+		do_action( "post_setting_section_{$page_id}_{$section[ 'id' ]}" );
 	}
 }
 
@@ -1186,26 +1208,87 @@
  * @param string $page Slug title of the admin page who's settings fields you want to show.
  * @param section $section Slug title of the settings section who's fields you want to show.
  */
-function do_settings_fields($page, $section) {
+function do_settings_fields( $page_id, $section_id ) {
 	global $wp_settings_fields;
 
-	if ( !isset($wp_settings_fields) || !isset($wp_settings_fields[$page]) || !isset($wp_settings_fields[$page][$section]) )
+	if( !isset( $wp_settings_fields ) || !isset( $wp_settings_fields[ $page_id ] ) || !isset( $wp_settings_fields[ $page_id ][ $section_id ] ) )
 		return;
 
-	foreach ( (array) $wp_settings_fields[$page][$section] as $field ) {
-		echo '<tr valign="top">';
-		if ( !empty($field['args']['label_for']) )
-			echo '<th scope="row"><label for="' . $field['args']['label_for'] . '">' . $field['title'] . '</label></th>';
-		else
-			echo '<th scope="row">' . $field['title'] . '</th>';
-		echo '<td>';
-		call_user_func($field['callback'], $field['args']);
-		echo '</td>';
-		echo '</tr>';
+	foreach( ( array ) $wp_settings_fields[ $page_id ][ $section_id ] as $option_group ) {	//downside here obviously is that items that share option_names have to be grouped
+		foreach( ( array ) $option_group as $field ) {
+			echo '<tr valign="top">';
+			if( !empty( $field[ 'args' ][ 'label_for' ] ) )
+				echo '<th scope="row"><label for="' . $field[ 'args' ][ 'label_for' ] . '">' . $field[ 'title' ] . '</label></th>';
+			else
+				echo '<th scope="row">' . $field[ 'title' ] . '</th>';
+			echo '<td>';
+			if( empty( $field[ 'option_name' ] ) )
+				$current_value = get_option( $field[ 'id' ] );
+			else {
+				$option_value = get_option( $field[ 'option_name' ] );
+				if( is_array( $option_value ) && isset( $option_value[ $field[ 'id' ] ] ) )
+					$current_value = $option_value[ $field[ 'id' ] ];
+				else
+					$current_value = false;
+			}
+			call_user_func( $field[ 'callback' ], $field[ 'args' ], $current_value, $field, $section_id, $page_id );
+			echo '</td>';
+			echo '</tr>';
+		}
 	}
 }
 
 /**
+ * Saves the registered settings fields for the given page_id
+ *
+ * Part of the Settings API.  This method should be called on 'load-{$page_slug}'
+ * to save any fields that have been registered for that page.
+ *
+ * @global $wp_settings_fields $wp_settings_fields
+ * @staticvar array $saved_settings_pages
+ *
+ * @since 3.3
+ *
+ * @param string $page_id slug name of the page to identify the page used for the settings
+ */
+function save_settings_page( $page_id ) {
+	global $wp_settings_fields;
+
+	static $saved_settings_pages = array( ); //local storage to keep pages from being processed multiple times
+
+	if( !isset( $saved_settings_pages[ $page_id ] ) && isset( $wp_settings_fields[ $page_id ] ) && is_array( $wp_settings_fields[ $page_id ] ) ) {
+		foreach( $wp_settings_fields[ $page_id ] as $section_id => $section ) {
+			if( is_array( $section ) ) {
+				foreach( $section as $option_name => $fields ) {
+					$option_value = get_option( $option_name );
+					if( is_array( $fields ) && count( $fields ) ) {
+						if( 1 === count( $fields ) && isset( $fields[ $option_name ] ) && $fields[ $option_name ][ 'id' ] == $option_name ) {
+							//if there is only one field for the option and it matches the option_name, this is a singular option
+							$new_value = isset( $_POST[ $fields[ $option_name ][ 'id' ] ] ) ? $_POST[ $fields[ $option_name ][ 'id' ] ] : false;
+							$option_value = apply_filters( "sanitize_setting_{$page_id}_{$section_id}_{$fields[ $option_name ][ 'id' ]}", $new_value, $option_value, $fields[ $option_name ] );
+						} else {
+							//this is an set of fields stored under one option
+							if( !is_array( $option_value ) )
+								$option_value = array( );
+
+							foreach( $fields as $field ) {
+								$new_value = isset( $_POST[ $field[ 'id' ] ] ) ? $_POST[ $field[ 'id' ] ] : false;
+								$old_value = isset( $option_value[ $field[ 'id' ] ] ) ? $option_value[ $field[ 'id' ] ] : false;
+								$option_value[ $field[ 'id' ] ] = apply_filters( "sanitize_setting_{$page_id}_{$section_id}_{$field[ 'id' ]}", $new_value, $old_value, $field );
+							}
+						}
+						update_option( $option_name, $option_value );
+					}
+				}
+			}
+		}
+		$saved_settings_pages[ $page_id ] = true;
+	}
+	if( !count( get_settings_errors( $page_id ) ) )
+		add_settings_error( $page_id, 'settings_updated', __( 'Settings saved.' ), 'updated' );
+}
+
+/**
  * Register a settings error to be displayed to the user
  *
  * Part of the Settings API. Use this to show messages to users about settings validation
@@ -1312,15 +1395,15 @@
  *
  * @since 3.0.0
  *
- * @param string $setting Optional slug title of a specific setting who's errors you want.
+ * @param string $page_id Optional slug title of a specific setting page who's errors you want.
  * @param boolean $sanitize Whether to re-sanitize the setting value before returning errors.
  * @param boolean $hide_on_update If set to true errors will not be shown if the settings page has already been submitted.
  */
-function settings_errors( $setting = '', $sanitize = FALSE, $hide_on_update = FALSE ) {
+function settings_errors( $page_id = '', $sanitize = FALSE, $hide_on_update = FALSE ) {
 
 	if ($hide_on_update AND $_GET['settings-updated']) return;
 
-	$settings_errors = get_settings_errors( $setting, $sanitize );
+	$settings_errors = get_settings_errors( $page_id, $sanitize );
 
 	if ( !is_array($settings_errors) ) return;
 
