diff -rupN content.module content.module
--- content.module	2008-11-10 16:56:35.000000000 +0100
+++ content.module	2008-12-06 14:53:58.000000000 +0100
@@ -492,13 +492,13 @@ function theme_content_multiple_values($
     $items = array();
     foreach (element_children($element) as $key) {
       if ($key !== $element['#field_name'] .'_add_more') {
-        $items[] = &$element[$key];
+        $items[$element[$key]['#delta']] = &$element[$key];
       }
     }
-    usort($items, '_content_sort_items_value_helper');
+    uasort($items, '_content_sort_items_value_helper');
 
     // Add the items as table rows.
-    foreach ($items as $key => $item) {
+    foreach ($items as $delta => $item) {
       $item['_weight']['#attributes']['class'] = $order_class;
       $delta_element = drupal_render($item['_weight']);
       $cells = array(
@@ -710,7 +710,7 @@ function content_field($op, &$node, $fie
       }
 
       // Filter out empty values.
-      $items = content_set_empty($field, $items);
+      $items = content_set_empty($field, $items, FALSE);
 
       break;
 
@@ -725,7 +725,7 @@ function content_field($op, &$node, $fie
         }
 
         // Filter out empty values.
-        $items = content_set_empty($field, $items);
+        $items = content_set_empty($field, $items, FALSE);
       }
 
       // NODE_BUILD_NORMAL is 0, and ('whatever' == 0) is TRUE, so we need a ===.
@@ -762,10 +762,10 @@ function content_field($op, &$node, $fie
         );
 
         // Fill-in items.
-        foreach ($items as $delta => $item) {
+        foreach (array_keys($items) as $weight => $delta) {
           $element['items'][$delta] = array(
-            '#item' => $item,
-            '#weight' => $delta,
+            '#item' => $items[$delta],
+            '#weight' => $weight,
           );
         }
 
@@ -881,26 +881,54 @@ function content_field($op, &$node, $fie
  *
  * @param array $field
  * @param array $items
+ * @param bollean $keep_empty_items
  * @return array
  *   returns filtered and adjusted item array
  */
-function content_set_empty($field, $items) {
-  // Filter out empty values.
+function content_set_empty($field, $items, $keep_empty_items = TRUE) {
+  // Prepare an empty item.
+  $empty = array();
+  foreach (array_keys($field['columns']) as $column) {
+    $empty[$column] = NULL;
+  }
+
+  // Keep track of empty values.
   $filtered = array();
   $function = $field['module'] .'_content_is_empty';
   foreach ((array) $items as $delta => $item) {
+    // Get the item if it isn't empty.
     if (!$function($item, $field)) {
-      $filtered[] = $item;
+      $filtered[$delta] = $item;
+    }
+    // When the item is empty, keep it only if requested to.
+    else if ($keep_empty_items || (isset($item['_keep_empty']) && $item['_keep_empty'])) {
+      $filtered[$delta] = $empty;
     }
   }
 
   // Make sure we store the right number of 'empty' values.
-  $empty = array();
-  foreach (array_keys($field['columns']) as $column) {
-    $empty[$column] = NULL;
+  if ($field['multiple'] == 1) {
+    // Remove last element if empty for multi-valued fields.
+    $last_item = end($filtered);
+    if ($function($last_item, $field)) {
+      unset($filtered[key($filtered)]);
+    }
+  }
+  else {
+    $pad = $field['multiple'] > 1 ? (int)$field['multiple'] : 1;
+    $count = count($filtered);
+    if ($count < $pad) {
+      $delta = $count > 0 ? max(array_keys($filtered)) + 1 : 0;
+      for ($i = $count; $i < $pad; $i++) {
+        $filtered[$delta++] = $empty;
+      }
+    }
+  }
+
+  // Rebuild deltas for fields with multiple values.
+  if ($field['multiple'] >= 1) {
+    $filtered = array_values($filtered);
   }
-  $pad = $field['multiple'] > 1 ? $field['multiple'] : 1;
-  $filtered = array_pad($filtered, $pad, $empty);
 
   return $filtered;
 }
@@ -913,7 +941,7 @@ function _content_sort_items($field, $it
   if ($field['multiple'] >= 1 && isset($items[0]['_weight'])) {
     usort($items, '_content_sort_items_helper');
     foreach ($items as $delta => $item) {
-      if (is_array($items[$delta])) {
+      if (is_array($item) && isset($item['_weight'])) {
         unset($items[$delta]['_weight']);
       }
     }
@@ -994,7 +1022,14 @@ function content_storage($op, $node) {
             if (!isset($additions[$field_name])) {
               $additions[$field_name] = array();
             }
-            $additions[$field_name][] = $item;
+
+            // Preserve deltas when loading items from database.
+            if (isset($row['delta'])) {
+              $additions[$field_name][$row['delta']] = $item;
+            }
+            else {
+              $additions[$field_name][] = $item;
+            }
           }
         }
       }
@@ -2381,8 +2416,7 @@ function content_extra_field_weight($typ
  * Do we want to eliminate them from the results?
  */
 function content_max_delta($field_name, $type_name = NULL) {
-  $fields = content_fields();
-  $field = $fields[$field_name];
+  $field = content_fields($field_name);
 
   // Non-multiple value fields don't use the delta column,
   // but could exist in multiple databases. If any value
@@ -2393,8 +2427,7 @@ function content_max_delta($field_name, 
       if (empty($type_name) || $content_type['type'] == $type_name) {
         foreach ($content_type['fields'] as $field) {
           $db_info = content_database_info($field);
-          $table = $db_info['table'];
-          if (db_result(db_query("SELECT COUNT(*) FROM {$table}")) >= 1) {
+          if (db_result(db_query('SELECT COUNT(*) FROM {'. $db_info['table'] .'}')) >= 1) {
             return 0;
           }
         }
@@ -2406,14 +2439,13 @@ function content_max_delta($field_name, 
   // in the node table to limit the type.
   else {
     $db_info = content_database_info($field);
-    $table = $db_info['table'];
     if (!empty($type_name)) {
-      $delta = db_result(db_query("SELECT MAX(delta) FROM {$table} f LEFT JOIN {node} n ON f.vid = n.vid WHERE n.type = '%s'", $type_name));
+      $delta = db_result(db_query('SELECT MAX(delta) FROM {'. $db_info['table'] ."} f LEFT JOIN {node} n ON f.vid = n.vid WHERE n.type = '%s'", $type_name));
     }
     else {
-      $delta = db_result(db_query("SELECT MAX(delta) FROM {$table}"));
+      $delta = db_result(db_query('SELECT MAX(delta) FROM {'. $db_info['table'] .'}'));
     }
-    if ($delta >= 0) {
+    if ($delta !== FALSE && $delta >= 0) {
       return $delta;
     }
   }
diff -rupN includes/content.node_form.inc includes/content.node_form.inc
--- includes/content.node_form.inc	2008-10-04 15:14:21.000000000 +0200
+++ includes/content.node_form.inc	2008-12-06 13:48:57.000000000 +0100
@@ -157,21 +157,24 @@ function content_multiple_value_form(&$f
 
   switch ($field['multiple']) {
     case 0:
+      $deltas = array(0);
       $max = 0;
       break;
+
     case 1:
-      $filled_items = content_set_empty($field, $items);
-      $current_item_count = isset($form_state['item_count'][$field_name])
-                            ? $form_state['item_count'][$field_name]
-                            : count($items);
+      $deltas = array_keys(content_set_empty($field, $items));
       // We always want at least one empty icon for the user to fill in.
-      $max = ($current_item_count > count($filled_items))
-              ? $current_item_count - 1
-              : $current_item_count;
-
+      $current_item_count = (isset($form_state['item_count'][$field_name]) ? $form_state['item_count'][$field_name] : count($deltas) + 1);
+      $max = (!empty($deltas) ? max($deltas) : -1);
+      while (count($deltas) < $current_item_count) {
+        $max++;
+        $deltas[] = $max;
+      }
       break;
+
     default:
       $max = $field['multiple'] - 1;
+      $deltas = array_keys(array_fill(0, $field['multiple'], 0));
       break;
   }
 
@@ -186,7 +189,7 @@ function content_multiple_value_form(&$f
   );
   $function = $field['widget']['module'] .'_widget';
 
-  for ($delta = 0; $delta <= $max; $delta++) {
+  foreach ($deltas as $delta) {
     if ($element = $function($form, $form_state, $field, $items, $delta)) {
       $defaults = array(
         '#title' => ($field['multiple'] >= 1) ? '' : $title,
@@ -212,6 +215,18 @@ function content_multiple_value_form(&$f
         );
       }
 
+      // Add a hidden element to allow the multigroup module tell us if content
+      // module needs to keep track of empty fields. Disabled by default.
+      // See content_set_empty().
+      if ($field['multiple'] == 1) {
+        // We name the element '_keep_empty' to avoid clashing with column names
+        // defined by field modules.
+        $element['_keep_empty'] = array(
+          '#type' => 'hidden',
+          '#value' => isset($items[$delta]['_keep_empty']) ? $items[$delta]['_keep_empty'] : 0,
+        );
+      }
+
       $form_element[$delta] = array_merge($element, $defaults);
     }
   }
@@ -324,6 +339,7 @@ function content_add_more_js($type_name_
   $_POST[$field_name] = _content_sort_items($field, $_POST[$field_name]);
 
   // Build our new form element for the whole field, asking for one more element.
+  $delta = max(array_keys($_POST[$field_name])) + 1;
   $form_state['item_count'] = array($field_name => count($_POST[$field_name]) + 1);
   $form_element = content_field_form($form, $form_state, $field);
   // Let other modules alter it.
@@ -343,7 +359,6 @@ function content_add_more_js($type_name_
 
   // Build the new form against the incoming $_POST values so that we can
   // render the new element.
-  $delta = max(array_keys($_POST[$field_name])) + 1;
   $_POST[$field_name][$delta]['_weight'] = $delta;
   $form_state = array('submitted' => FALSE);
   $form += array(
