Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1222
diff -u -p -r1.1222 common.inc
--- includes/common.inc	17 Sep 2010 14:53:21 -0000	1.1222
+++ includes/common.inc	20 Sep 2010 01:26:09 -0000
@@ -5619,7 +5619,8 @@ function element_set_attributes(array &$
     if (is_int($property)) {
       $property = '#' . $attribute;
     }
-    if (isset($element[$property])) {
+    // Do not overwrite already existing attributes.
+    if (isset($element[$property]) && !isset($element['#attributes'][$attribute])) {
       $element['#attributes'][$attribute] = $element[$property];
     }
   }
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.493
diff -u -p -r1.493 form.inc
--- includes/form.inc	16 Sep 2010 20:14:49 -0000	1.493
+++ includes/form.inc	20 Sep 2010 03:34:13 -0000
@@ -1142,6 +1142,27 @@ function _form_validate(&$elements, &$fo
             }
           }
         }
+        // Non-multiple select fields always have a value in HTML. If the user
+        // does not change the form, it will be the value of the first option.
+        // Because of this, form validation for the field will almost always
+        // pass, even if the user did not select anything. To work around this
+        // browser behavior, select fields without a #default_value get an
+        // additional, first empty option by default. In case the submitted
+        // value is identical to the empty option's value, we reset the
+        // element's value to NULL to trigger the regular #required handling
+        // below.
+        // @see form_process_select()
+        // @see form_select_options()
+        elseif ($elements['#type'] == 'select' && !$elements['#multiple'] && !isset($elements['#default_value']) && $elements['#value'] === (string) $elements['#empty_value']) {
+          if (!isset($elements['#required']) || $elements['#required']) {
+            $elements['#value'] = NULL;
+            form_set_value($elements, NULL, $form_state);
+          }
+          else {
+            $elements['#value'] = $elements['#empty_value'];
+            form_set_value($elements, $elements['#empty_value'], $form_state);
+          }
+        }
         elseif (!isset($options[$elements['#value']])) {
           form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));
           watchdog('form', 'Illegal choice %choice in %name element.', array('%choice' => $elements['#value'], '%name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR);
@@ -1188,8 +1209,18 @@ function _form_validate(&$elements, &$fo
     // length if it's a string, and the item count if it's an array.
     // An unchecked checkbox has a #value of integer 0, different than string
     // '0', which could be a valid value.
-    if (isset($elements['#needs_validation']) && $elements['#required'] && (!count($elements['#value']) || (is_string($elements['#value']) && strlen(trim($elements['#value'])) == 0) || $elements['#value'] === 0)) {
-      form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
+    if (isset($elements['#needs_validation']) && !empty($elements['#required']) && (!count($elements['#value']) || (is_string($elements['#value']) && strlen(trim($elements['#value'])) == 0) || $elements['#value'] === 0)) {
+      // Although unusual and actually discouraged, a #title is not mandatory
+      // for form elements. In case the element does not have a title, we cannot
+      // set a form error message. Note that instead of setting no #title, form
+      // constructors are encouraged to set #title_display to 'hidden' instead
+      // to improve accessibility.
+      if (isset($elements['#title'])) {
+        form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
+      }
+      else {
+        form_error($elements);
+      }
     }
 
     // Call user-defined form level validators.
@@ -1540,7 +1571,6 @@ function form_builder($form_id, $element
   }
   // Assign basic defaults common for all form elements.
   $element += array(
-    '#required' => FALSE,
     '#attributes' => array(),
     '#title_display' => 'before',
   );
@@ -1799,7 +1829,7 @@ function _form_builder_handle_input_elem
         }
       }
       // Mark all posted values for validation.
-      if (isset($element['#value']) || (!empty($element['#required']))) {
+      if (isset($element['#value']) || !empty($element['#required'])) {
         $element['#needs_validation'] = TRUE;
       }
     }
@@ -2238,6 +2268,75 @@ function _form_options_flatten($array) {
 }
 
 /**
+ * Processes a select list form element.
+ *
+ * This process callback is mandatory for select fields, since all user agents
+ * automatically preselect the first available option of single (non-multiple)
+ * select lists.
+ *
+ * @param $element
+ *   The form element to process. Properties used:
+ *   - #multiple: (optional) Indicates whether one or more options can be
+ *     selected. Defaults to FALSE.
+ *   - #default_value: Must be NULL or not set in case there is no value for the
+ *     element yet, in which case a first default option is inserted by default.
+ *     Whether this first option is a valid option depends on whether the field
+ *     is #required or not.
+ *   - #required: (optional) Whether the user needs to select an option (TRUE)
+ *     or not (FALSE). Defaults to TRUE.
+ *   - #empty_option: (optional) The label to show for the first default option.
+ *     By default, the label is automatically set to "- Please select -" for a
+ *     required field and "- None -" for an optional field.
+ *   - #empty_value: (optional) The value for the first default option, which is
+ *     used to determine whether the user submitted a value or not. Defaults to
+ *     '' (an empty string). To be used in case the field is optional and the
+ *     empty default value should have a special value (e.g., a constant).
+ *
+ * @see _form_validate()
+ */
+function form_process_select($element) {
+  // #multiple select fields need a special #name.
+  if ($element['#multiple']) {
+    $element['#attributes']['multiple'] = 'multiple';
+    $element['#attributes']['name'] = $element['#name'] . '[]';
+  }
+  // A non-#multiple select needs special handling to prevent user agents from
+  // preselecting the first option without intention.
+  else {
+    // Unless there is a #default_value already, the user has to select a value
+    // for #required select fields. By default, all select fields are treated
+    // as if #required was TRUE.
+    if (!isset($element['#default_value']) && (!isset($element['#required']) || $element['#required'])) {
+      $element['#required'] = TRUE;
+      $element += array(
+        '#empty_value' => '',
+        '#empty_option' => t('- Select -'),
+      );
+      $add_empty_option = TRUE;
+    }
+    // If #required is FALSE, the user may optionally choose a value. The empty
+    // default option is always contained and always available.
+    elseif (isset($element['#required']) && !$element['#required']) {
+      $element['#required'] = FALSE;
+      $element += array(
+        '#empty_value' => '',
+        '#empty_option' => t('- None -'),
+      );
+      $add_empty_option = TRUE;
+    }
+    // If one of the above conditions is met, add a first empty default option,
+    // which is always invalid for #required and not #multiple select lists that
+    // do not specify a #default_value (ensured through special handling in
+    // _form_validate()). A #multiple select list does not get this option,
+    // since it would not make sense, user interface-wise.
+    if (isset($add_empty_option)) {
+      $element['#options'] = array($element['#empty_value'] => $element['#empty_option']) + $element['#options'];
+    }
+  }
+  return $element;
+}
+
+/**
  * Returns HTML for a select form element.
  *
  * It is possible to group options together; to do this, change the format of
@@ -2257,11 +2356,6 @@ function theme_select($variables) {
   element_set_attributes($element, array('id', 'name', 'size'));
   _form_set_class($element, array('form-select'));
 
-  if (!empty($element['#multiple'])) {
-    $element['#attributes']['multiple'] = 'multiple';
-    $element['#attributes']['name'] .= '[]';
-  }
-
   return '<select' . drupal_attributes($element['#attributes']) . '>' . form_select_options($element) . '</select>';
 }
 
@@ -2449,14 +2543,14 @@ function form_process_password_confirm($
     '#type' => 'password',
     '#title' => t('Password'),
     '#value' => empty($element['#value']) ? NULL : $element['#value']['pass1'],
-    '#required' => $element['#required'],
+    '#required' => !empty($element['#required']),
     '#attributes' => array('class' => array('password-field')),
   );
   $element['pass2'] =  array(
     '#type' => 'password',
     '#title' => t('Confirm password'),
     '#value' => empty($element['#value']) ? NULL : $element['#value']['pass2'],
-    '#required' => $element['#required'],
+    '#required' => !empty($element['#required']),
     '#attributes' => array('class' => array('password-confirm')),
   );
   $element['#element_validate'] = array('password_confirm_validate');
@@ -2480,7 +2574,7 @@ function password_confirm_validate($elem
       form_error($element, t('The specified passwords do not match.'));
     }
   }
-  elseif ($element['#required'] && !empty($element_state['input'])) {
+  elseif (!empty($element['#required']) && !empty($element_state['input'])) {
     form_error($element, t('Password field is required.'));
   }
 
Index: includes/install.core.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/install.core.inc,v
retrieving revision 1.30
diff -u -p -r1.30 install.core.inc
--- includes/install.core.inc	14 Sep 2010 21:42:05 -0000	1.30
+++ includes/install.core.inc	20 Sep 2010 01:26:09 -0000
@@ -1715,11 +1715,11 @@ function _install_configure_form($form, 
   );
 
   $countries = country_get_list();
-  $countries = array_merge(array('' => st('No default country')), $countries);
   $form['server_settings']['site_default_country'] = array(
     '#type' => 'select',
     '#title' => t('Default country'),
-    '#default_value' => variable_get('site_default_country', ''),
+    '#required' => FALSE,
+    '#default_value' => variable_get('site_default_country', NULL),
     '#options' => $countries,
     '#description' => st('Select the default country for the site.'),
     '#weight' => 0,
Index: modules/aggregator/aggregator.processor.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.processor.inc,v
retrieving revision 1.12
diff -u -p -r1.12 aggregator.processor.inc
--- modules/aggregator/aggregator.processor.inc	4 Dec 2009 16:49:45 -0000	1.12
+++ modules/aggregator/aggregator.processor.inc	20 Sep 2010 01:26:09 -0000
@@ -70,7 +70,7 @@ function aggregator_aggregator_remove($f
 function aggregator_form_aggregator_admin_form_alter(&$form, $form_state) {
   if (in_array('aggregator', variable_get('aggregator_processors', array('aggregator')))) {
     $info = module_invoke('aggregator', 'aggregator_process', 'info');
-    $items = array(0 => t('none')) + drupal_map_assoc(array(3, 5, 10, 15, 20, 25), '_aggregator_items');
+    $items = drupal_map_assoc(array(3, 5, 10, 15, 20, 25), '_aggregator_items');
     $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
     $period[AGGREGATOR_CLEAR_NEVER] = t('Never');
 
@@ -90,8 +90,10 @@ function aggregator_form_aggregator_admi
 
     $form['modules']['aggregator']['aggregator_summary_items'] = array(
       '#type' => 'select',
-      '#title' => t('Number of items shown in listing pages') ,
+      '#title' => t('Number of items shown in listing pages'),
+      '#required' => FALSE,
       '#default_value' => variable_get('aggregator_summary_items', 3),
+      '#empty_value' => 0,
       '#options' => $items,
     );
 
Index: modules/block/block.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.admin.inc,v
retrieving revision 1.87
diff -u -p -r1.87 block.admin.inc
--- modules/block/block.admin.inc	17 Sep 2010 13:32:56 -0000	1.87
+++ modules/block/block.admin.inc	20 Sep 2010 01:26:09 -0000
@@ -85,9 +85,6 @@ function block_admin_display_form($form,
     $block_regions = system_region_list($theme, REGIONS_VISIBLE);
   }
 
-  // We always add a region for disabled blocks.
-  $block_regions += array(BLOCK_REGION_NONE => '<' . t('none') . '>');
-
   // Weights range from -delta to +delta, so delta should be at least half
   // of the amount of blocks present. This makes sure all blocks in the same
   // region get an unique weight.
@@ -100,7 +97,8 @@ function block_admin_display_form($form,
   );
   $form['block_regions'] = array(
     '#type' => 'value',
-    '#value' => $block_regions,
+    // Add a last region for disabled blocks.
+    '#value' => $block_regions + array(BLOCK_REGION_NONE => BLOCK_REGION_NONE),
   );
   $form['blocks'] = array();
   $form['#tree'] = TRUE;
@@ -127,13 +125,15 @@ function block_admin_display_form($form,
       '#default_value' => $block['weight'],
       '#delta' => $weight_delta,
       '#title_display' => 'invisible',
-      '#title' => t('Weight for @block block', array('%block' => $block['info'])),
+      '#title' => t('Weight for @block block', array('@block' => $block['info'])),
     );
     $form['blocks'][$key]['region'] = array(
       '#type' => 'select',
-      '#default_value' => $block['region'],
+      '#required' => FALSE,
+      '#default_value' => $block['region'] != BLOCK_REGION_NONE ? $block['region'] : NULL,
+      '#empty_value' => BLOCK_REGION_NONE,
       '#title_display' => 'invisible',
-      '#title' => t('Region for @block block', array('%block' => $block['info'])),
+      '#title' => t('Region for @block block', array('@block' => $block['info'])),
       '#options' => $block_regions,
     );
     $form['blocks'][$key]['configure'] = array(
@@ -150,7 +150,7 @@ function block_admin_display_form($form,
     }
   }
   // Do not allow disabling the main system content block.
-  unset($form['blocks']['system_main']['region']['#options'][BLOCK_REGION_NONE]);
+  $form['blocks']['system_main']['region']['#required'] = TRUE;
 
   $form['actions'] = array(
     '#tree' => FALSE,
@@ -302,9 +302,10 @@ function block_admin_configure($form, &$
       $form['regions'][$key] = array(
         '#type' => 'select',
         '#title' => $theme->info['name'],
-        '#default_value' => (!empty($region) ? $region : BLOCK_REGION_NONE),
-        '#options' => array(BLOCK_REGION_NONE => t('<none>')) + system_region_list($key, REGIONS_VISIBLE),
-        '#expandable' => ($key !== $theme_default),
+        '#required' => FALSE,
+        '#default_value' => !empty($region) && $region != -1 ? $region : NULL,
+        '#empty_value' => BLOCK_REGION_NONE,
+        '#options' => system_region_list($key, REGIONS_VISIBLE),
         '#weight' => ($key == $theme_default ? 9 : 10),
       );
     }
@@ -657,7 +658,7 @@ function template_preprocess_block_admin
     $block = &$variables['form']['blocks'][$i];
 
     // Fetch the region for the current block.
-    $region = $block['region']['#default_value'];
+    $region = (isset($block['region']['#default_value']) ? $block['region']['#default_value'] : BLOCK_REGION_NONE);
 
     // Set special classes needed for table drag and drop.
     $block['region']['#attributes']['class'] = array('block-region-select', 'block-region-' . $region);
Index: modules/field_ui/field_ui.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.admin.inc,v
retrieving revision 1.66
diff -u -p -r1.66 field_ui.admin.inc
--- modules/field_ui/field_ui.admin.inc	16 Sep 2010 20:14:49 -0000	1.66
+++ modules/field_ui/field_ui.admin.inc	20 Sep 2010 01:26:09 -0000
@@ -304,7 +304,7 @@ function field_ui_field_overview_form($f
       t('Widget'),
       array('data' => t('Operations'), 'colspan' => 2),
     ),
-    '#parent_options' => array('' => t('<none>')),
+    '#parent_options' => array(),
     '#regions' => array(
       'main' => array(),
       'add_new' => array('title' => '&nbsp;'),
@@ -335,6 +335,7 @@ function field_ui_field_overview_form($f
       'parent_wrapper' => array(
         'parent' => array(
           '#type' => 'select',
+          '#required' => FALSE,
           '#options' => $table['#parent_options'],
           '#attributes' => array('class' => array('field-parent')),
           '#parents' => array('fields', $name, 'parent'),
@@ -401,6 +402,7 @@ function field_ui_field_overview_form($f
       'parent_wrapper' => array(
         'parent' => array(
           '#type' => 'select',
+          '#required' => FALSE,
           '#options' => $table['#parent_options'],
           '#attributes' => array('class' => array('field-parent')),
           '#parents' => array('fields', $name, 'parent'),
@@ -432,8 +434,6 @@ function field_ui_field_overview_form($f
   $field_type_options = field_ui_field_type_options();
   $widget_type_options = field_ui_widget_type_options(NULL, TRUE);
   if ($field_type_options && $widget_type_options) {
-    array_unshift($field_type_options, t('- Select a field type -'));
-    array_unshift($widget_type_options, t('- Select a widget -'));
     $name = '_add_new_field';
     $table[$name] = array(
       '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')),
@@ -458,6 +458,7 @@ function field_ui_field_overview_form($f
       'parent_wrapper' => array(
         'parent' => array(
           '#type' => 'select',
+          '#required' => FALSE,
           '#options' => $table['#parent_options'],
           '#attributes' => array('class' => array('field-parent')),
           '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
@@ -481,14 +482,18 @@ function field_ui_field_overview_form($f
       ),
       'type' => array(
         '#type' => 'select',
+        '#required' => FALSE,
         '#options' => $field_type_options,
+        '#empty_option' => t('- Select a field type -'),
         '#description' => t('Type of data to store.'),
         '#attributes' => array('class' => array('field-type-select')),
         '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
       ),
       'widget_type' => array(
         '#type' => 'select',
+        '#required' => FALSE,
         '#options' => $widget_type_options,
+        '#empty_option' => t('- Select a widget -'),
         '#description' => t('Form element to edit the data.'),
         '#attributes' => array('class' => array('widget-type-select')),
         '#cell_attributes' => array('colspan' => 3),
@@ -500,7 +505,6 @@ function field_ui_field_overview_form($f
   // Additional row: add existing field.
   $existing_field_options = field_ui_existing_field_options($entity_type, $bundle);
   if ($existing_field_options && $widget_type_options) {
-    array_unshift($existing_field_options, t('- Select an existing field -'));
     $name = '_add_existing_field';
     $table[$name] = array(
       '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')),
@@ -526,6 +530,7 @@ function field_ui_field_overview_form($f
       'parent_wrapper' => array(
         'parent' => array(
           '#type' => 'select',
+          '#required' => FALSE,
           '#options' => $table['#parent_options'],
           '#attributes' => array('class' => array('field-parent')),
           '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
@@ -539,7 +544,9 @@ function field_ui_field_overview_form($f
       ),
       'field_name' => array(
         '#type' => 'select',
+        '#required' => FALSE,
         '#options' => $existing_field_options,
+        '#empty_option' => t('- Select an existing field -'),
         '#description' => t('Field to share'),
         '#attributes' => array('class' => array('field-select')),
         '#cell_attributes' => array('colspan' => 2),
@@ -547,7 +554,9 @@ function field_ui_field_overview_form($f
       ),
       'widget_type' => array(
         '#type' => 'select',
+        '#required' => FALSE,
         '#options' => $widget_type_options,
+        '#empty_option' => t('- Select a widget -'),
         '#description' => t('Form element to edit the data.'),
         '#attributes' => array('class' => array('widget-type-select')),
         '#cell_attributes' => array('colspan' => 3),
@@ -844,7 +853,7 @@ function field_ui_display_overview_form(
       'visible' => array('message' => t('No field is displayed.')),
       'hidden' => array('title' => t('Hidden'), 'message' => t('No field is hidden.')),
     ),
-    '#parent_options' => array('' => t('<none>')),
+    '#parent_options' => array(),
     '#attributes' => array(
       'class' => array('field-ui-overview'),
       'id' => 'field-display-overview',
@@ -888,8 +897,8 @@ function field_ui_display_overview_form(
       'parent_wrapper' => array(
         'parent' => array(
           '#type' => 'select',
+          '#required' => FALSE,
           '#options' => $table['#parent_options'],
-          '#default_value' => '',
           '#attributes' => array('class' => array('field-parent')),
           '#parents' => array('fields', $name, 'parent'),
         ),
@@ -1042,8 +1051,8 @@ function field_ui_display_overview_form(
       'parent_wrapper' => array(
         'parent' => array(
           '#type' => 'select',
+          '#required' => FALSE,
           '#options' => $table['#parent_options'],
-          '#default_value' => '',
           '#attributes' => array('class' => array('field-parent')),
           '#parents' => array('fields', $name, 'parent'),
         ),
Index: modules/file/file.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/file/file.module,v
retrieving revision 1.40
diff -u -p -r1.40 file.module
--- modules/file/file.module	13 Sep 2010 01:09:25 -0000	1.40
+++ modules/file/file.module	20 Sep 2010 01:26:09 -0000
@@ -556,7 +556,7 @@ function file_managed_file_validate(&$el
   }
 
   // Check required property based on the FID.
-  if ($element['#required'] && empty($element['fid']['#value']) && !in_array($clicked_button, array('upload_button', 'remove_button'))) {
+  if (!empty($element['#required']) && empty($element['fid']['#value']) && !in_array($clicked_button, array('upload_button', 'remove_button'))) {
     form_error($element['upload'], t('!name field is required.', array('!name' => $element['#title'])));
   }
 
Index: modules/image/image.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/image/image.admin.inc,v
retrieving revision 1.21
diff -u -p -r1.21 image.admin.inc
--- modules/image/image.admin.inc	30 Jul 2010 02:47:28 -0000	1.21
+++ modules/image/image.admin.inc	20 Sep 2010 01:26:09 -0000
@@ -116,7 +116,7 @@ function image_style_form($form, &$form_
   }
 
   // Build the new image effect addition form and add it to the effect list.
-  $new_effect_options = array('' => t('Select a new effect'));
+  $new_effect_options = array();
   foreach (image_effect_definitions() as $effect => $definition) {
     $new_effect_options[$effect] = check_plain($definition['label']);
   }
@@ -127,7 +127,9 @@ function image_style_form($form, &$form_
   );
   $form['effects']['new']['new'] = array(
     '#type' => 'select',
+    '#required' => FALSE,
     '#options' => $new_effect_options,
+    '#empty_option' => t('Select a new effect'),
   );
   $form['effects']['new']['weight'] = array(
     '#type' => 'weight',
@@ -291,11 +293,12 @@ function image_style_delete_form($form, 
   $form_state['image_style'] = $style;
 
   $replacement_styles = array_diff_key(image_style_options(), array($style['name'] => ''));
-  $replacement_styles[''] = t('No replacement, just delete');
   $form['replacement'] = array(
     '#title' => t('Replacement style'),
     '#type' => 'select',
+    '#required' => FALSE,
     '#options' => $replacement_styles,
+    '#empty_option' => t('No replacement, just delete'),
   );
 
   return confirm_form(
Index: modules/image/image.field.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/image/image.field.inc,v
retrieving revision 1.27
diff -u -p -r1.27 image.field.inc
--- modules/image/image.field.inc	9 Sep 2010 23:28:16 -0000	1.27
+++ modules/image/image.field.inc	20 Sep 2010 01:26:09 -0000
@@ -269,7 +269,8 @@ function image_field_widget_settings_for
   $form['preview_image_style'] = array(
     '#title' => t('Preview image style'),
     '#type' => 'select',
-    '#options' => array('' => '<' . t('no preview') . '>') + image_style_options(FALSE),
+    '#required' => FALSE,
+    '#options' => image_style_options(FALSE),
     '#default_value' => $settings['preview_image_style'],
     '#description' => t('The preview image will be shown while editing the content.'),
     '#weight' => 15,
@@ -418,22 +419,24 @@ function image_field_formatter_settings_
   $display = $instance['display'][$view_mode];
   $settings = $display['settings'];
 
-  $image_styles = array('' => t('None (original image)')) + image_style_options(FALSE);
+  $image_styles = image_style_options(FALSE);
   $form['image_style'] = array(
     '#title' => t('Image style'),
     '#type' => 'select',
+    '#required' => FALSE,
     '#default_value' => $settings['image_style'],
+    '#empty_option' => t('None (original image)'),
     '#options' => $image_styles,
   );
 
   $link_types = array(
-    '' => t('<none>'),
     'content' => t('Content'),
     'file' => t('File'),
   );
   $form['image_link'] = array(
     '#title' => t('Link image to'),
     '#type' => 'select',
+    '#required' => FALSE,
     '#default_value' => $settings['image_link'],
     '#options' => $link_types,
   );
Index: modules/locale/locale.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.admin.inc,v
retrieving revision 1.17
diff -u -p -r1.17 locale.admin.inc
--- modules/locale/locale.admin.inc	30 Jul 2010 02:47:28 -0000	1.17
+++ modules/locale/locale.admin.inc	20 Sep 2010 01:26:09 -0000
@@ -854,7 +854,9 @@ function locale_translation_filter_form(
       $form['filters']['status'][$key] = array(
         '#title' => $filter['title'],
         '#type' => 'select',
-        '#multiple' => FALSE,
+        '#required' => FALSE,
+        '#empty_value' => 'all',
+        '#empty_option' => $filter['options']['all'],
         '#size' => 0,
         '#options' => $filter['options'],
       );
Index: modules/menu/menu.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.admin.inc,v
retrieving revision 1.84
diff -u -p -r1.84 menu.admin.inc
--- modules/menu/menu.admin.inc	7 Sep 2010 22:12:05 -0000	1.84
+++ modules/menu/menu.admin.inc	20 Sep 2010 01:26:09 -0000
@@ -680,22 +680,24 @@ function menu_configure() {
   $menu_options = menu_get_menus();
 
   $main = variable_get('menu_main_links_source', 'main-menu');
-  $main_options = array_merge($menu_options, array('' => t('No Main links')));
   $form['menu_main_links_source'] = array(
     '#type' => 'select',
     '#title' => t('Source for the Main links'),
+    '#required' => FALSE,
     '#default_value' => variable_get('menu_main_links_source', 'main-menu'),
-    '#options' => $main_options,
+    '#empty_option' => t('No Main links'),
+    '#options' => $menu_options,
     '#tree' => FALSE,
     '#description' => t('Select what should be displayed as the Main links (typically at the top of the page).'),
   );
 
-  $secondary_options = array_merge($menu_options, array('' => t('No Secondary links')));
   $form['menu_secondary_links_source'] = array(
     '#type' => 'select',
     '#title' => t('Source for the Secondary links'),
+    '#required' => FALSE,
     '#default_value' => variable_get('menu_secondary_links_source', 'user-menu'),
-    '#options' => $secondary_options,
+    '#empty_option' => t('No Secondary links'),
+    '#options' => $menu_options,
     '#tree' => FALSE,
     '#description' => t("Select the source for the Secondary links. An advanced option allows you to use the same source for both Main links (currently %main) and Secondary links: if your source menu has two levels of hierarchy, the top level menu links will appear in the Main links, and the children of the active link will appear in the Secondary links." , array('%main' => $main_options[$main])),
   );
Index: modules/simpletest/tests/actions.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/actions.test,v
retrieving revision 1.18
diff -u -p -r1.18 actions.test
--- modules/simpletest/tests/actions.test	5 Aug 2010 23:53:38 -0000	1.18
+++ modules/simpletest/tests/actions.test	20 Sep 2010 01:26:09 -0000
@@ -67,11 +67,13 @@ class ActionsConfigurationTestCase exten
 /**
  * Test actions executing in a potential loop, and make sure they abort properly.
  */
-class ActionLoopTestCase extends DrupalWebTestCase {
+class ActionsLoopTestCase extends DrupalWebTestCase {
+  protected $profile = 'testing';
+
   public static function getInfo() {
     return array(
-      'name' => 'Actions executing in a potentially infinite loop',
-      'description' => 'Tests actions executing in a loop, and makes sure they abort properly.',
+      'name' => 'Actions infinite loop',
+      'description' => 'Tests actions executing in an infinite loop, and makes sure they abort properly.',
       'group' => 'Actions',
     );
   }
Index: modules/simpletest/tests/ajax_forms_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/ajax_forms_test.module,v
retrieving revision 1.7
diff -u -p -r1.7 ajax_forms_test.module
--- modules/simpletest/tests/ajax_forms_test.module	6 May 2010 05:59:31 -0000	1.7
+++ modules/simpletest/tests/ajax_forms_test.module	20 Sep 2010 01:26:09 -0000
@@ -38,7 +38,6 @@ function ajax_forms_test_menu() {
  * A basic form used to test form_state['values'] during callback.
  */
 function ajax_forms_test_simple_form($form, &$form_state) {
-  $form = array();
   $form['select'] = array(
     '#type' => 'select',
     '#options' => array(
Index: modules/simpletest/tests/form.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v
retrieving revision 1.67
diff -u -p -r1.67 form.test
--- modules/simpletest/tests/form.test	19 Sep 2010 18:39:18 -0000	1.67
+++ modules/simpletest/tests/form.test	20 Sep 2010 03:36:33 -0000
@@ -153,6 +153,67 @@ class FormsTestCase extends DrupalWebTes
   }
 
   /**
+   * Tests validation of #type 'select' elements.
+   */
+  function testSelect() {
+    $form = $form_state = array();
+    $form = form_test_select($form, $form_state);
+    $error = '!name field is required.';
+    $this->drupalGet('form-test/select');
+
+    // Posting without any values should throw validation errors.
+    $this->drupalPost(NULL, array(), 'Submit');
+    $this->assertNoText(t($error, array('!name' => $form['select']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['empty_value']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['empty_value_one']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['no_default']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['no_default_optional']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['no_default_empty_option']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['no_default_empty_option_optional']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['no_default_empty_value']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['no_default_empty_value_one']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['no_default_empty_value_optional']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['multiple']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['multiple_no_default']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['multiple_no_default_required']['#title'])));
+
+    // Post values for required fields.
+    $edit = array(
+      'no_default' => 'three',
+      'no_default_empty_option' => 'three',
+      'no_default_empty_value' => 'three',
+      'no_default_empty_value_one' => 'three',
+      'multiple_no_default_required[]' => 'three',
+    );
+    $this->drupalPost(NULL, $edit, 'Submit');
+    $values = drupal_json_decode($this->drupalGetContent());
+
+    // Verify expected values.
+    $expected = array(
+      'select' => 'one',
+      'empty_value' => 'one',
+      'empty_value_one' => 'one',
+      'no_default' => 'three',
+      'no_default_optional' => '',
+      'no_default_empty_option' => 'three',
+      'no_default_empty_option_optional' => '',
+      'no_default_empty_value' => 'three',
+      'no_default_empty_value_one' => 'three',
+      'no_default_empty_value_optional' => 0,
+      'multiple' => array('two' => 'two'),
+      'multiple_no_default' => array(),
+      'multiple_no_default_required' => array('three' => 'three'),
+    );
+    foreach ($expected as $key => $value) {
+      $this->assertIdentical($values[$key], $value, t('@name: @actual is equal to @expected.', array(
+        '@name' => $key,
+        '@actual' => var_export($values[$key], TRUE),
+        '@expected' => var_export($value, TRUE),
+      )));
+    }
+  }
+
+  /**
    * Test handling of disabled elements.
    *
    * @see _form_test_disabled_elements()
Index: modules/simpletest/tests/form_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v
retrieving revision 1.48
diff -u -p -r1.48 form_test.module
--- modules/simpletest/tests/form_test.module	27 Aug 2010 11:54:32 -0000	1.48
+++ modules/simpletest/tests/form_test.module	20 Sep 2010 03:36:22 -0000
@@ -92,6 +92,12 @@ function form_test_menu() {
     'access callback' => TRUE,
     'type' => MENU_CALLBACK,
   );
+  $items['form-test/select'] = array(
+    'title' => t('Select'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('form_test_select'),
+    'access callback' => TRUE,
+  );
 
   $items['form-test/disabled-elements'] = array(
     'title' => t('Form test'),
@@ -786,6 +792,94 @@ function _form_test_checkbox_submit($for
 }
 
 /**
+ * Builds a form to test #type 'select' validation.
+ */
+function form_test_select($form, &$form_state) {
+  $base = array(
+    '#type' => 'select',
+    '#options' => drupal_map_assoc(array('one', 'two', 'three')),
+  );
+
+  $form['select'] = $base + array(
+    '#title' => '#default_value one',
+    '#default_value' => 'one',
+  );
+  $form['empty_value'] = $base + array(
+    '#title' => '#default_value one, #empty_value 0',
+    '#default_value' => 'one',
+    '#empty_value' => 0,
+  );
+  $form['empty_value_one'] = $base + array(
+    '#title' => '#default_value = #empty_value',
+    '#default_value' => 'one',
+    '#empty_value' => 'one',
+  );
+
+  $form['no_default'] = $base + array(
+    '#title' => 'No #default_value',
+  );
+  $form['no_default_optional'] = $base + array(
+    '#title' => 'No #default_value, not #required',
+    '#required' => FALSE,
+    '#description' => 'Should result in an empty string (default of #empty_value), because it is optional.',
+  );
+
+  $form['no_default_empty_option'] = $base + array(
+    '#title' => 'No #default_value, #empty_option',
+    '#empty_option' => '- Choose -',
+  );
+  $form['no_default_empty_option_optional'] = $base + array(
+    '#title' => 'No #default_value, not #required, #empty_option',
+    '#required' => FALSE,
+    '#empty_option' => '- Dismiss -',
+    '#description' => 'Should result in an empty string (default of #empty_value), because it is optional.',
+  );
+
+  $form['no_default_empty_value'] = $base + array(
+    '#title' => 'No #default_value, #empty_value 0',
+    '#empty_value' => 0,
+    '#description' => 'Should never result in 0.',
+  );
+  $form['no_default_empty_value_one'] = $base + array(
+    '#title' => 'No #default_value, #empty_value one',
+    '#empty_value' => 'one',
+    '#description' => 'A mistakenly assigned #empty_value contained in #options should not be valid.',
+  );
+  $form['no_default_empty_value_optional'] = $base + array(
+    '#title' => 'No #default_value, not #required, #empty_value 0',
+    '#required' => FALSE,
+    '#empty_value' => 0,
+    '#description' => 'Should result in 0, because it is optional.',
+  );
+
+  $form['multiple'] = $base + array(
+    '#title' => '#multiple, #default_value two',
+    '#default_value' => array('two'),
+    '#multiple' => TRUE,
+  );
+  $form['multiple_no_default'] = $base + array(
+    '#title' => '#multiple, no #default_value',
+    '#multiple' => TRUE,
+  );
+  $form['multiple_no_default_required'] = $base + array(
+    '#title' => '#multiple, #required, no #default_value',
+    '#required' => TRUE,
+    '#multiple' => TRUE,
+  );
+
+  $form['submit'] = array('#type' => 'submit', '#value' => 'Submit');
+  return $form;
+}
+
+/**
+ * Form submit handler for form_test_select().
+ */
+function form_test_select_submit($form, &$form_state) {
+  drupal_json_output($form_state['values']);
+  exit();
+}
+
+/**
  * Build a form to test disabled elements.
  */
 function _form_test_disabled_elements($form, &$form_state) {
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.306
diff -u -p -r1.306 system.admin.inc
--- modules/system/system.admin.inc	16 Sep 2010 18:00:43 -0000	1.306
+++ modules/system/system.admin.inc	20 Sep 2010 01:26:09 -0000
@@ -2941,7 +2941,7 @@ function system_actions_manage() {
   actions_synchronize();
   $actions = actions_list();
   $actions_map = actions_actions_map($actions);
-  $options = array(t('Choose an advanced action'));
+  $options = array();
   $unconfigurable = array();
 
   foreach ($actions_map as $key => $array) {
@@ -3013,9 +3013,7 @@ function system_actions_manage_form($for
   );
   $form['parent']['action'] = array(
     '#type' => 'select',
-    '#default_value' => '',
     '#options' => $options,
-    '#description' => '',
   );
   $form['parent']['actions'] = array('#type' => 'actions');
   $form['parent']['actions']['submit'] = array(
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.962
diff -u -p -r1.962 system.module
--- modules/system/system.module	19 Sep 2010 18:10:42 -0000	1.962
+++ modules/system/system.module	20 Sep 2010 01:26:09 -0000
@@ -399,9 +399,8 @@ function system_element_info() {
   );
   $types['select'] = array(
     '#input' => TRUE,
-    '#size' => 0,
     '#multiple' => FALSE,
-    '#process' => array('ajax_process_form'),
+    '#process' => array('form_process_select', 'ajax_process_form'),
     '#theme' => 'select',
     '#theme_wrappers' => array('form_element'),
   );
Index: modules/trigger/trigger.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/trigger/trigger.admin.inc,v
retrieving revision 1.27
diff -u -p -r1.27 trigger.admin.inc
--- modules/trigger/trigger.admin.inc	22 Aug 2010 11:04:09 -0000	1.27
+++ modules/trigger/trigger.admin.inc	20 Sep 2010 01:26:09 -0000
@@ -177,7 +177,6 @@ function trigger_assign_form($form, $for
   );
   // List possible actions that may be assigned.
   if (count($options) != 0) {
-    array_unshift($options, t('Choose an action'));
     $form[$hook]['parent']['aid'] = array(
       '#type' => 'select',
       '#options' => $options,
@@ -201,15 +200,14 @@ function trigger_assign_form($form, $for
  * Makes sure that the user is not re-assigning an action to an event.
  */
 function trigger_assign_form_validate($form, $form_state) {
-  $form_values = $form_state['values'];
-  if (!empty($form_values['aid'])) {
-    $aid = actions_function_lookup($form_values['aid']);
+  if (!empty($form_state['values']['aid'])) {
+    $aid = actions_function_lookup($form_state['values']['aid']);
     $aid_exists = db_query("SELECT aid FROM {trigger_assignments} WHERE hook = :hook AND aid = :aid", array(
-      ':hook' => $form_values['hook'],
+      ':hook' => $form_state['values']['hook'],
       ':aid' => $aid,
     ))->fetchField();
     if ($aid_exists) {
-      form_set_error($form_values['hook'], t('The action you chose is already assigned to that trigger.'));
+      form_set_error($form_state['values']['hook'], t('The action you chose is already assigned to that trigger.'));
     }
   }
 }
