--- form.inc.orig	2009-07-22 14:21:19.328125000 +0200
+++ form.inc	2009-09-03 11:15:20.234375000 +0200
@@ -675,7 +675,8 @@ function _form_validate($elements, &$for
       // A simple call to empty() will not cut it here as some fields, like
       // checkboxes, can return a valid value of '0'. Instead, check the
       // length if it's a string, and the item count if it's an array.
-      if ($elements['#required'] && (!count($elements['#value']) || (is_string($elements['#value']) && strlen(trim($elements['#value'])) == 0))) {
+      // Unchecked checkbox has #value of numeric 0 (for now).
+      if ($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'])));
       }
 
@@ -1172,11 +1173,18 @@ function form_type_image_button_value($f
  */
 function form_type_checkbox_value($form, $edit = FALSE) {
   if ($edit !== FALSE) {
-    if (empty($form['#disabled'])) {
-      return !empty($edit) ? $form['#return_value'] : 0;
+    if (!empty($form['#disabled'])) {
+      // Disabled controls are never successful.
+      // Always return default.
+      return $form['#default_value'];
     }
     else {
-      return $form['#default_value'];
+      // Successful checkboxes are present with a value (possibly '0').
+      // http://www.w3.org/TR/html401/interact/forms.html#successful-controls
+      // For an unchecked checkbox, we should return '' or maybe NULL, but for
+      // now we return numeric 0 since other core modules use a numeric database 
+      // column for a checkbox value and assume its value will be 0 or 1.
+      return isset($edit) ? $form['#return_value'] : 0;
     }
   }
 }
@@ -1870,17 +1878,20 @@ function theme_item($element) {
  * @ingroup themeable
  */
 function theme_checkbox($element) {
+  $t = get_t();
   _form_set_class($element, array('form-checkbox'));
   $checkbox = '<input ';
   $checkbox .= 'type="checkbox" ';
   $checkbox .= 'name="'. $element['#name'] .'" ';
   $checkbox .= 'id="'. $element['#id'] .'" ' ;
   $checkbox .= 'value="'. $element['#return_value'] .'" ';
-  $checkbox .= $element['#value'] ? ' checked="checked" ' : ' ';
+  // Unchecked checkbox has #value of numeric 0 (for now).
+  $checkbox .= ($element['#value'] !== 0 && $element['#value'] == $element['#return_value']) ? ' checked="checked" ' : ' ';
   $checkbox .= drupal_attributes($element['#attributes']) .' />';
 
   if (!is_null($element['#title'])) {
-    $checkbox = '<label class="option" for="'. $element['#id'] .'">'. $checkbox .' '. $element['#title'] .'</label>';
+    $required = !empty($element['#required']) ? ' <span class="form-required" title="' . $t('This field is required.') . '">*</span>' : '';
+    $checkbox = '<label class="option" for="' . $element['#id'] . '">' . $checkbox . ' ' . $element['#title'] . $required . '</label>';
   }
 
   unset($element['#title']);
@@ -1926,7 +1937,7 @@ function expand_checkboxes($element) {
           '#processed' => TRUE,
           '#title' => $choice,
           '#return_value' => $key,
-          '#default_value' => isset($value[$key]),
+          '#default_value' => isset($value[$key]) ? $key : NULL,
           '#attributes' => $element['#attributes'],
           '#ahah' => isset($element['#ahah']) ? $element['#ahah'] : NULL,
         );
