Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.324
diff -u -p -r1.324 form.inc
--- includes/form.inc	14 Mar 2009 20:13:26 -0000	1.324
+++ includes/form.inc	26 Mar 2009 01:46:39 -0000
@@ -1866,7 +1866,9 @@ function form_process_radios($element) {
  * Add text format selector to text elements with the #text_format property.
  *
  * The #text_format property should be the ID of an text format, found in
- * {filter_format}.format, which gets passed to filter_form().
+ * {filter_format}.format, which gets passed to filter_form(). Alternatively,
+ * it can be an array of arguments for filter_form(), using a string for the
+ * last argument (since the parents are defined by the text element already).
  *
  * If the property #text_format is set, the form element will be expanded into
  * two separate form elements, one holding the content of the element, and the
@@ -1882,6 +1884,12 @@ function form_process_radios($element) {
  *     '#title' => t('Body'),
  *     '#text_format' => isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT,
  *   );
+ *   // Example for passing an array to filter_form().
+ *   $form['body'] = array(
+ *     '#type' => 'textarea',
+ *     '#title' => t('Body'),
+ *     '#text_format' => array($node->format, NULL, 'custom_format_name'),
+ *   );
  * @endcode
  *
  * Becomes:
@@ -1920,14 +1928,22 @@ function form_process_text_format($eleme
     // parents that filter_form() expects.
     $element_parents = $element['#parents'];
     $element_name = array_pop($element_parents);
-    $element_parents[] = $element_name . '_format';
+    if (is_array($element['#text_format'])) {
+      list($format, $weight, $parent) = $element['#text_format'];
+      $element_parents[] = $parent;
+    }
+    else {
+      $format = $element['#text_format'];
+      $weight = 1;
+      $element_parents[] = $element_name . '_format';
+    }
 
     // We need to break references, otherwise form_builder recurses infinitely.
     $element['value'] = (array)$element;
     $element['#type'] = 'markup';
     $element['#theme'] = NULL;
     $element['#theme_wrapper'] = NULL;
-    $element['format'] = filter_form($element['#text_format'], 1, $element_parents);
+    $element['format'] = filter_form($format, $weight, $element_parents);
 
     // We need to clear the #text_format from the new child otherwise we
     // would get into an infinite loop.
Index: modules/filter/filter.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.test,v
retrieving revision 1.16
diff -u -p -r1.16 filter.test
--- modules/filter/filter.test	15 Mar 2009 01:53:16 -0000	1.16
+++ modules/filter/filter.test	26 Mar 2009 01:25:29 -0000
@@ -241,3 +241,30 @@ class FilterTestCase extends DrupalWebTe
     $this->assertEqual(_filter_internal('[internal:foo/bar] [internal:foo2/bar2]'), url('foo/bar') . ' ' . url('foo2/bar2'), t('The internal filter works'));
   }
 }
+
+class FormatTestCase extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('Text formats'),
+      'description' => t('Verify that text formats are properly attached and processed in forms.'),
+      'group' => t('Filter'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('form_test');
+
+    $admin_user = $this->drupalCreateUser(array('administer filters'));
+    $this->drupalLogin($admin_user);
+  }
+
+  /**
+   * Verify that #text_format's #parents work.
+   */
+  function testTextFormatProperty() {
+    $output = $this->drupalPost('form_test/text_format', NULL, 'Submit');
+    $this->assertText("body:1
+another_body:2
+complex[field_custom]:1", t('#text_format values were found in expected $form_state keys.'));
+  }
+}
Index: modules/simpletest/tests/form_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v
retrieving revision 1.2
diff -u -p -r1.2 form_test.module
--- modules/simpletest/tests/form_test.module	17 Mar 2009 23:26:33 -0000	1.2
+++ modules/simpletest/tests/form_test.module	26 Mar 2009 01:25:22 -0000
@@ -10,8 +10,19 @@
  * Implementation of hook_menu().
  */
 function form_test_menu() {
-  $items = array();
-
+  $items['form_test/form_clean_id'] = array(
+    'title' => 'form_clean_id test',
+    'page callback' => 'form_test_form_clean_id_page',
+    'access arguments' => array('access content'),
+    'type' => MENU_CALLBACK,
+  );
+  $items['form_test/text_format'] = array(
+    'title' => 'text_format test',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('form_test_text_format_form'),
+    'access arguments' => array('access content'),
+    'type' => MENU_CALLBACK,
+  );
   $items['form_test/tableselect/multiple-true'] = array(
     'title' => 'Tableselect checkboxes test',
     'page callback' => 'drupal_get_form',
@@ -19,7 +30,6 @@ function form_test_menu() {
     'access arguments' => array('access content'),
     'type' => MENU_CALLBACK,
   );
-
   $items['form_test/tableselect/multiple-false'] = array(
     'title' => 'Tableselect radio button test',
     'page callback' => 'drupal_get_form',
@@ -27,7 +37,6 @@ function form_test_menu() {
     'access arguments' => array('access content'),
     'type' => MENU_CALLBACK,
   );
-
   $items['form_test/tableselect/empty-text'] = array(
     'title' => 'Tableselect empty text test',
     'page callback' => 'drupal_get_form',
@@ -35,7 +44,6 @@ function form_test_menu() {
     'access arguments' => array('access content'),
     'type' => MENU_CALLBACK,
   );
-
   $items['form_test/tableselect/advanced-select'] = array(
     'title' => 'Tableselect js_select tests',
     'page callback' => 'drupal_get_form',
@@ -44,13 +52,6 @@ function form_test_menu() {
     'type' => MENU_CALLBACK,
   );
 
-  $items['form_test/form_clean_id'] = array(
-    'title' => 'form_clean_id test',
-    'page callback' => 'form_test_form_clean_id_page',
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
-  );
-
   return $items;
 }
 
@@ -77,6 +78,53 @@ function form_test_test_form(&$form_stat
 }
 
 /**
+ * A simple form to test #text_format processing.
+ *
+ * We want to test a real form submission, expecting form values in certain
+ * places.
+ *
+ * @see form_test_text_format_form_submit()
+ * @see filter.test
+ */
+function form_test_text_format_form(&$form_state) {
+  $form['body'] = array(
+    '#type' => 'textarea',
+    '#title' => 'Simple textarea with text format attached',
+    '#default_value' => 'body',
+    '#text_format' => FILTER_FORMAT_DEFAULT,
+  );
+  $form['another_body'] = array(
+    '#type' => 'textarea',
+    '#title' => 'Second textarea with text format attached',
+    '#default_value' => 'another_body',
+    '#text_format' => 2,
+  );
+  $form['complex'] = array(
+    '#tree' => TRUE,
+  );
+  $form['complex']['field_custom'] = array(
+    '#type' => 'textarea',
+    '#title' => 'Custom, complex field with text format attached, submitted using custom key',
+    '#default_value' => 'complex[field_custom]',
+    '#text_format' => array(FILTER_FORMAT_DEFAULT, NULL, 'complex_format_value'),
+  );
+  $form['submit'] = array('#type' => 'submit', '#value' => 'Submit');
+  return $form;
+}
+
+/**
+ * Submit handler for form_test_text_format_form().
+ */
+function form_test_text_format_form_submit($form, &$form_state) {
+  $output = '';
+  $output .= $form_state['values']['body'] . ':' . $form_state['values']['body_format'] . "\n";
+  $output .= $form_state['values']['another_body'] . ':' . $form_state['values']['another_body_format'] . "\n";
+  $output .= $form_state['values']['complex']['field_custom'] . ':' . $form_state['values']['complex']['complex_format_value'] . "\n";
+  echo $output;
+  exit;
+}
+
+/**
  * Create a header and options array. Helper function for callbacks.
  */
 function _form_test_tableselect_get_data() {
