Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.144
diff -u -F^f -r1.144 form.inc
--- includes/form.inc	29 Aug 2006 09:12:02 -0000	1.144
+++ includes/form.inc	29 Aug 2006 13:40:44 -0000
@@ -156,16 +156,15 @@ function drupal_retrieve_form($form_id) 
  *   The path to redirect the user to upon completion.
  */
 function drupal_process_form($form_id, &$form) {
-  global $form_values, $form_submitted, $user, $form_button_counter;
+  global $form_values, $submit_suffix, $user;
   static $saved_globals = array();
   // In some scenerios, this function can be called recursively. Pushing any pre-existing
   // $form_values and form submission data lets us start fresh without clobbering work done
   // in earlier recursive calls.
-  array_push($saved_globals, array($form_values, $form_submitted, $form_button_counter));
+  array_push($saved_globals, array($form_values, $submit_suffix));
 
   $form_values = array();
-  $form_submitted = FALSE;
-  $form_button_counter = array(0, 0);
+  unset($submit_suffix);
 
   drupal_prepare_form($form_id, $form);
   if (($form['#programmed']) || (!empty($_POST) && (($_POST['form_id'] == $form_id) || ($_POST['form_id'] == $form['#base'])))) {
@@ -173,8 +172,8 @@ function drupal_process_form($form_id, &
     // IE does not send a button value when there is only one submit button (and no non-submit buttons)
     // and you submit by pressing enter.
     // In that case we accept a submission without button values.
-    if ((($form['#programmed']) || $form_submitted || (!$form_button_counter[0] && $form_button_counter[1])) && !form_get_errors()) {
-      $redirect = drupal_submit_form($form_id, $form);
+    if ((($form['#programmed']) || isset($submit_suffix)) && !form_get_errors()) {
+      $redirect = drupal_submit_form($form_id, $form, $submit_suffix);
       if (!$form['#programmed']) {
         drupal_redirect_form($form, $redirect);
       }
@@ -183,7 +182,7 @@ function drupal_process_form($form_id, &
 
   // We've finished calling functions that alter the global values, so we can
   // restore the ones that were there before this function was called.
-  list($form_values, $form_submitted, $form_button_counter) = array_pop($saved_globals);
+  list($form_values, $submit_suffix) = array_pop($saved_globals);
   return $redirect;
 }
 
@@ -262,17 +261,6 @@ function drupal_prepare_form($form_id, &
     }
   }
 
-  if (!isset($form['#submit'])) {
-    if (function_exists($form_id .'_submit')) {
-      // we set submit here so that it can be altered but use reference for
-      // $form_values because it will change later
-      $form['#submit'] = array($form_id .'_submit' => array());
-    }
-    elseif (function_exists($base .'_submit')) {
-      $form['#submit'] = array($base .'_submit' => array());
-    }
-  }
-
   foreach (module_implements('form_alter') as $module) {
     $function = $module .'_form_alter';
     $function($form_id, $form);
@@ -323,17 +311,36 @@ function drupal_validate_form($form_id, 
  *   theming, and hook_form_alter functions.
  * @param $form
  *   An associative array containing the structure of the form.
+ * @param $submit_suffix
+ *   The suffix used to build the default submission function.
  * @return
  *   A string containing the path of the page to display when processing
  *   is complete.
  *
  */
-function drupal_submit_form($form_id, $form) {
+function drupal_submit_form($form_id, $form, $submit_suffix) {
   global $form_values;
   $default_args = array($form_id, &$form_values);
 
-  if (isset($form['#submit'])) {
-    foreach ($form['#submit'] as $function => $args) {
+  // First execute the default callback, if it exists.
+  if (function_exists($form_id .'_' .$submit_suffix)) {
+    $function = $form_id .'_' .$submit_suffix;
+  }
+  elseif (function_exists($form['#base'] .'_' .$submit_suffix)) {
+    $function = $form['#base'] .'_' .$submit_suffix;
+  }
+ 
+  if (isset($function)) {
+    $redirect = call_user_func_array($function, $default_args);
+    if (isset($redirect)) {
+      $goto = $redirect;
+    }
+  }
+
+  // Now execute any additional callback functions that were added to the callback
+  // list by other modules.
+  if (isset($form['#submit'][$submit_suffix])) {
+    foreach ($form['#submit'][$submit_suffix] as $function => $args) {
       if (function_exists($function)) {
         $args = array_merge($default_args, (array) $args);
         // Since we can only redirect to one page, only the last redirect will work
@@ -537,7 +544,7 @@ function form_error(&$element, $message 
  *   An associative array containing the structure of the form.
  */
 function form_builder($form_id, $form) {
-  global $form_values, $form_submitted, $form_button_counter;
+  global $form_values, $submit_suffix;
 
   // Initialize as unprocessed.
   $form['#processed'] = FALSE;
@@ -620,12 +627,20 @@ function form_builder($form_id, $form) {
         }
       }
     }
-    if (isset($form['#executes_submit_callback'])) {
-      // Count submit and non-submit buttons
-      $form_button_counter[$form['#executes_submit_callback']]++;
-      // See if a submit button was pressed
+    if (isset($form['#button_type'])) {
+      // This is an element capable of initiating a form submit. See if it was clicked.
       if (isset($form['#post'][$form['#name']]) && $form['#post'][$form['#name']] == $form['#value']) {
-        $form_submitted = $form_submitted || $form['#executes_submit_callback'];
+        // We use the #submit_suffix of a form element to determine what function
+        // the Form API should fire during the submit process. It defaults to 'submit',
+        // but modules can use different submit_suffixes to implement previews,
+        // next/previous buttons, and so on.
+        if (isset($form['#submit_suffix'])) {
+          $submit_suffix = $form['#submit_suffix'];
+        }
+        // In most cases, we want to use form_set_value() to manipulate the global variables.
+        // In this special case, we want to make sure that the value of this element is listed
+        // in $form_variables under 'op'.
+        $form_values[$form['#name']] = $form['#value'];
 
         // In most cases, we want to use form_set_value() to manipulate the global variables.
         // In this special case, we want to make sure that the value of this element is listed
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.353
diff -u -F^f -r1.353 system.module
--- modules/system/system.module	29 Aug 2006 09:12:03 -0000	1.353
+++ modules/system/system.module	29 Aug 2006 13:40:44 -0000
@@ -64,8 +64,8 @@ function system_elements() {
 
   // Inputs
   $type['checkbox'] = array('#input' => TRUE, '#return_value' => 1);
-  $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => TRUE);
-  $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => FALSE);
+  $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#submit_suffix' => 'submit');
+  $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit');
   $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE);
   $type['password'] = array('#input' => TRUE, '#size' => 30);
   $type['password_confirm'] = array('#input' => TRUE, '#process' => array('expand_password_confirm' => array()));
