diff -rupN content.module content.module
--- content.module	2008-11-10 16:56:35.000000000 +0100
+++ content.module	2008-11-27 15:22:37.000000000 +0100
@@ -485,6 +485,9 @@ function theme_content_multiple_values($
       ),
       t('Order'),
     );
+    if ($field['multiple'] == 1) {
+      $header[] = t('Delete');
+    }
     $rows = array();
 
     // Sort items according to '_weight' (needed when the form comes back after
@@ -492,20 +495,26 @@ 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']);
+      if ($field['multiple'] == 1) {
+        $delete_element = drupal_render($item['_delete']);
+      }
       $cells = array(
         array('data' => '', 'class' => 'content-multiple-drag'),
         drupal_render($item),
         array('data' => $delta_element, 'class' => 'delta-order'),
       );
+      if ($field['multiple'] == 1) {
+        $cells[] = array('data' => $delete_element);
+      }
       $rows[] = array(
         'data' => $cells,
         'class' => 'draggable',
@@ -709,9 +718,21 @@ function content_field($op, &$node, $fie
         $items = _content_sort_items($field, $items);
       }
 
+      // Remove items marked for deletion.
+      foreach ($items as $delta => $item) {
+        if (isset($item['_delete']) && $item['_delete']) {
+          unset($items[$delta]);
+        }
+      }
+
       // Filter out empty values.
       $items = content_set_empty($field, $items);
 
+      // Rebuild deltas for fields with multiple values.
+      if ($field['multiple'] >= 1) {
+        $items = array_values($items);
+      }
+
       break;
 
     case 'view':
@@ -724,6 +745,13 @@ function content_field($op, &$node, $fie
           $items = _content_sort_items($field, $items);
         }
 
+        // Remove items marked for deletion.
+        foreach ($items as $delta => $item) {
+          if (isset($item['_delete']) && $item['_delete']) {
+            unset($items[$delta]);
+          }
+        }
+
         // Filter out empty values.
         $items = content_set_empty($field, $items);
       }
@@ -762,10 +790,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,
           );
         }
 
@@ -885,22 +913,37 @@ function content_field($op, &$node, $fie
  *   returns filtered and adjusted item array
  */
 function content_set_empty($field, $items) {
-  // Filter out empty values.
+  // 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) {
-    if (!$function($item, $field)) {
-      $filtered[] = $item;
-    }
+    $filtered[$delta] = $function($item, $field) ? $empty : $item;
   }
 
   // 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 = max(array_keys($filtered)) + 1;
+      for ($i = $count; $i < $pad; $i++) {
+        $filtered[$delta++] = $empty;
+      }
+    }
   }
-  $pad = $field['multiple'] > 1 ? $field['multiple'] : 1;
-  $filtered = array_pad($filtered, $pad, $empty);
 
   return $filtered;
 }
@@ -911,7 +954,7 @@ function content_set_empty($field, $item
  */
 function _content_sort_items($field, $items) {
   if ($field['multiple'] >= 1 && isset($items[0]['_weight'])) {
-    usort($items, '_content_sort_items_helper');
+    uasort($items, '_content_sort_items_helper');
     foreach ($items as $delta => $item) {
       if (is_array($items[$delta])) {
         unset($items[$delta]['_weight']);
@@ -994,7 +1037,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;
+            }
           }
         }
       }
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-11-27 14:43:18.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 = max($deltas);
+      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,17 @@ function content_multiple_value_form(&$f
         );
       }
 
+      // Add a checkbox to delete items for unlimited multiple value fields.
+      if ($field['multiple'] == 1) {
+        // We name the element '_delete' to avoid clashing with column names
+        // defined by field modules.
+        $element['_delete'] = array(
+          '#type' => 'checkbox',
+          '#default_value' => isset($items[$delta]['_delete']) ? $items[$delta]['_delete'] : 0,
+          '#weight' => 100,
+        );
+      }
+
       $form_element[$delta] = array_merge($element, $defaults);
     }
   }
