Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.398
diff -u -p -r1.398 form.inc
--- includes/form.inc	12 Nov 2009 20:07:05 -0000	1.398
+++ includes/form.inc	13 Nov 2009 22:23:58 -0000
@@ -1042,6 +1042,13 @@ function form_builder($form_id, $element
     else {
       $form_state['process_input'] = FALSE;
     }
+    // In addition to submitted form values,
+    // _form_builder_handle_input_elements() automatically takes over stored
+    // form values upon rebuild. If there was a validation error, prevent this
+    // from happening.
+    if (form_get_errors()) {
+      $form_state['values'] = array();
+    }
   }
 
   if (!isset($element['#id'])) {
@@ -1167,10 +1174,16 @@ function _form_builder_handle_input_elem
     $value_callback = !empty($element['#value_callback']) ? $element['#value_callback'] : 'form_type_' . $element['#type'] . '_value';
 
     if ($form_state['programmed'] || ($form_state['process_input'] && (!isset($element['#access']) || $element['#access']))) {
+      // Check for a submitted value.
       $input = $form_state['input'];
       foreach ($element['#parents'] as $parent) {
         $input = isset($input[$parent]) ? $input[$parent] : NULL;
       }
+      // Check for a stored value.
+      $value = $form_state['values'];
+      foreach ($element['#parents'] as $parent) {
+        $value = isset($value[$parent]) ? $value[$parent] : NULL;
+      }
       // If we have input for the current element, assign it to the #value property.
       if (!$form_state['programmed'] || isset($input)) {
         // Call #type_value to set the form value;
@@ -1180,6 +1193,11 @@ function _form_builder_handle_input_elem
         if (!isset($element['#value']) && isset($input)) {
           $element['#value'] = $input;
         }
+        // If no #value was assigned by the value callback or the submitted
+        // values, check whether we have a value in $form_state.
+        if (!isset($element['#value']) && isset($value)) {
+          $element['#value'] = $value;
+        }
       }
       // Mark all posted values for validation.
       if (isset($element['#value']) || (!empty($element['#required']))) {
