Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.21
diff -u -r1.21 form.inc
--- includes/form.inc	23 Nov 2005 16:21:12 -0000	1.21
+++ includes/form.inc	28 Nov 2005 19:25:42 -0000
@@ -161,13 +161,24 @@
     }
   }
 
-  /* Validate the current input */
+  // Validate the current input.
   if (!$elements['#validated'] && $elements['#input']) {
+
+    // Required check.
     // An empty checkbox returns 0, an empty textfield returns '' so we use empty().
     // Unfortunately, empty('0') returns TRUE so we need a special check for the '0' string.
     if ($elements['#required'] && empty($elements['#value']) && $elements['#value'] !== '0') {
       form_error($elements, t('%name field is required', array('%name' => $elements['#title'])));
     }
+
+    // Add legal choice check if element has #options.
+    if (isset($elements['#options'])) {
+      if (!isset($elements['#validate']['form_legal_choice'])) {
+        $elements['#validate']['form_legal_choice_check'] = array();
+      }
+    }
+
+    // User-applied checks.
     if (isset($elements['#validate'])) {
       if (is_array($elements['#validate'])) {
         foreach ($elements['#validate'] as $key => $validate) {
@@ -189,6 +200,36 @@
 }
 
 /**
+ * Validator: Legal choice check.
+ *
+ * @param mixed $element
+ *   The element to be checked.
+ * @return mixed
+ *   False if no error, else message.
+ */
+function form_legal_choice_check($element, $msg = null) {
+  $value = $element['#value'];
+  $choices = $element['#options'];
+  if ($value === '' || $value === null) { // allow no choice
+    return false;
+  }
+  if (!is_array($choices)) { // if no choices return error
+    return $msg !== null ? $msg :
+      t('Illegal choice (none provided).');
+  }
+  if (!is_array($value)) {
+    $value = array($value); // make sure the value is an array
+  }
+  foreach ($value as $v) {
+    if (!array_key_exists($v, $choices)) {
+      return $msg !== null ? $msg :
+        t('Illegal choice "%val".', array('%val' => $v));
+    }
+  }
+  return false;
+}
+
+/**
  * File an error against a form element. If the name of the element is
  * edit[foo][bar] then you may pass either foo or foo][bar as $name
  * foo will set an error for all its children.

Index: modules/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter.module,v
retrieving revision 1.84
diff -u -r1.84 filter.module
--- modules/filter.module	23 Nov 2005 08:21:08 -0000	1.84
+++ modules/filter.module	28 Nov 2005 19:37:42 -0000
@@ -770,7 +770,7 @@
     $form['format'] = array('#type' => 'fieldset', '#title' => t('Input format'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => -16);
     // Multiple formats available: display radio buttons with tips.
     foreach ($formats as $format) {
-      $form['format'][$format->format] = array('#type' => 'filter_format', '#title' => $format->name, '#default_value' => $value, '#return_value' => $format->format, '#parents' => array('format'), '#description' => theme('filter_tips', _filter_tips($format->format, false)), '#validate' => 'filter_form_validate');
+      $form['format'][$format->format] = array('#type' => 'filter_format', '#title' => $format->name, '#default_value' => $value, '#return_value' => $format->format, '#parents' => array('format'), '#description' => theme('filter_tips', _filter_tips($format->format, false)));
     }
     return $form;
   }
@@ -797,18 +797,6 @@
   return $output;
 }
 
-function filter_form_validate($element) {
-  static $validated;
-  if ($validated) {
-    return;
-  }
-  $validated = 1;
-  $formats = filter_formats();
-  if (!isset($formats[$element['#value']])) {
-    form_set_error($element['#parents'][0], t('The supplied input format is invalid.'));
-  }
-}
-
 /**
  * Returns true if the user is allowed to access this format.
  */
