Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.762
diff -u -p -r1.762 common.inc
--- includes/common.inc	31 Mar 2008 20:50:05 -0000	1.762
+++ includes/common.inc	5 Apr 2008 09:49:48 -0000
@@ -3005,6 +3005,9 @@ function drupal_common_theme() {
     'file' => array(
       'arguments' => array('element' => NULL),
     ),
+    'tableselect' => array(
+      'arguments' => array('element' => NULL),
+    ),
     'form_element' => array(
       'arguments' => array('element' => NULL, 'value' => NULL),
     ),
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.268
diff -u -p -r1.268 form.inc
--- includes/form.inc	15 Mar 2008 11:02:47 -0000	1.268
+++ includes/form.inc	5 Apr 2008 09:38:07 -0000
@@ -1896,6 +1896,57 @@ function expand_checkboxes($element) {
   return $element;
 }
 
+function theme_tableselect($element) {
+  $rows = array();
+  foreach ($element['#options'] as $key => $value) {
+    $row = array();
+
+    // Render the checkbox / radio element.
+    unset($element[$key]['#printed']);
+    $row[] = drupal_render($element[$key]);
+
+    foreach ($element['#header'] as $fieldname => $title) {
+      $row[] = $element['#options'][$key][$fieldname];
+    }
+    $rows[] = $row;
+  }
+  $first_col = $element['#advanced_select'] ? array(theme('table_select_header_cell')) : array('');
+  $header = array_merge($first_col, $element['#header']);
+  return theme('table', $header, $rows);
+}
+
+/**
+ * Create the right amount of checkboxes or radios to populate the table.
+ */
+function expand_tableselect($element) {
+
+  if ($element['#multiple']) {
+    $value = is_array($element['#value']) ? $element['#value'] : array();
+  }
+  else {
+    // Advanced select is only possible if #multiple is true.
+    $element['#advanced_select'] = FALSE;
+  }
+
+  $element['#tree'] = TRUE;
+
+  if (count($element['#options']) > 0) {
+    if (!isset($element['#default_value']) || $element['#default_value'] === 0) {
+      $element['#default_value'] = array();
+    }
+
+    foreach ($element['#options'] as $key => $choice) {
+      if ($element['#multiple']) {
+        $element[$key] = array('#type' => 'checkbox', '#processed' => TRUE, '#title' => '', '#return_value' => $key, '#default_value' => isset($value[$key]), '#attributes' => $element['#attributes']);
+      }
+      else {
+        $element[$key] = array('#type' => 'radio', '#title' => '', '#return_value' => $key, '#default_value' => ($element['#default_value'] == $key) ? $key : NULL, '#attributes' => $element['#attributes'], '#parents' => $element['#parents'], '#spawned' => TRUE);
+      }
+    }
+  }
+  return $element;
+}
+
 /**
  * Theme a form submit button.
  *
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.594
diff -u -p -r1.594 system.module
--- modules/system/system.module	1 Apr 2008 20:05:15 -0000	1.594
+++ modules/system/system.module	5 Apr 2008 09:39:29 -0000
@@ -281,6 +281,13 @@ function system_elements() {
     '#size' => 60,
   );
 
+  $type['tableselect'] = array(
+    '#input' => TRUE,
+    '#advanced_select' => TRUE,
+    '#multiple' => TRUE,
+    '#process' => array('expand_tableselect'),
+  );
+
 
   /**
    * Form structure.
