Index: modules/upload/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v
retrieving revision 1.160
diff -u -r1.160 upload.module
--- modules/upload/upload.module	14 May 2007 13:43:38 -0000	1.160
+++ modules/upload/upload.module	27 May 2007 09:43:25 -0000
@@ -365,6 +365,7 @@
     if ($form['type']['#value'] .'_node_form' == $form_id && variable_get("upload_$node->type", TRUE)) {
       drupal_add_js('misc/progress.js');
       drupal_add_js('misc/upload.js');
+      drupal_add_js(array('fileDeleteButton' => array(t('Delete'), t('Cancel'))), 'setting');
 
       // Attachments fieldset
       $form['attachments'] = array(
@@ -791,7 +792,17 @@
       $form['files'][$key]['description'] = array('#type' => 'textfield', '#default_value' => !empty($file->description) ? $file->description : $file->filename, '#maxlength' => 256, '#description' => $description );
 
       $form['files'][$key]['size'] = array('#value' => format_size($file->filesize));
-      $form['files'][$key]['remove'] = array('#type' => 'checkbox', '#default_value' => !empty($file->remove));
+      $form['files'][$key]['remove'] = array(
+        '#type' => 'checkbox',
+        '#default_value' => !empty($file->remove),
+        '#prefix' => '<div id="files-'. $key .'-remove" class="file-delete-button-wrapper">',
+        '#suffix' => '</div>',
+      );
+      $form['files'][$key]['delete-text'] = array(
+        '#value' => '<p>"'. $file->filename .'" is scheduled for deletion. '.
+                    'Mind that it will not be deleted until you save '.
+                    'this post.</p>',
+      );
       $form['files'][$key]['list'] = array('#type' => 'checkbox',  '#default_value' => $file->list);
       // if the file was uploaded this page request, set value. this fixes the problem
       // formapi has recognizing new checkboxes. see comments in _upload_prepare.
@@ -833,14 +844,20 @@
  * Theme the attachments list.
  */
 function theme_upload_form_current(&$form) {
-  $header = array(t('Delete'), t('List'), t('Description'), t('Size'));
+  $header = array(t('Description'), t('Size'), t('List'), t('Delete'));
 
   foreach (element_children($form) as $key) {
+    // Mark the items that will be hidden or shown when a file is deleted.
+    $div_hide = '<div class="files-'. $key .'-remove-hide">';
+    $div_show = '<div class="files-'. $key .'-remove-show" style="display: none;">';
+    $div_end = '</div>';
+    // Construct the row containing file information.
     $row = array();
+    $row[] = $div_hide . drupal_render($form[$key]['description']) . $div_end .
+             $div_show . drupal_render($form[$key]['delete-text']) . $div_end;
+    $row[] = $div_hide . drupal_render($form[$key]['size']) . $div_end;
+    $row[] = $div_hide . drupal_render($form[$key]['list']) . $div_end;
     $row[] = drupal_render($form[$key]['remove']);
-    $row[] = drupal_render($form[$key]['list']);
-    $row[] = drupal_render($form[$key]['description']);
-    $row[] = drupal_render($form[$key]['size']);
     $rows[] = $row;
   }
   $output = theme('table', $header, $rows);
Index: misc/upload.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/upload.js,v
retrieving revision 1.11
diff -u -r1.11 upload.js
--- misc/upload.js	31 Aug 2006 23:31:25 -0000	1.11
+++ misc/upload.js	27 May 2007 09:43:25 -0000
@@ -13,6 +13,11 @@
     var hide = base + '-hide';
     var upload = new Drupal.jsUpload(uri, button, wrapper, hide);
   });
+
+  $('.file-delete-button-wrapper').each(function () {
+    fileDeleteData = Drupal.getFileDeleteData(this.id);
+    Drupal.initFileDelete(fileDeleteData);
+  });
 }
 
 /**
@@ -55,6 +60,12 @@
  * Handler for the form redirection completion.
  */
 Drupal.jsUpload.prototype.oncomplete = function (data) {
+  // Store status of the Delete checkboxes, so that they can be restored later
+  var fileDeleteData = new Array();
+  $('.file-delete-button-wrapper').each(function () {
+    fileDeleteData[this.id] = Drupal.getFileDeleteData(this.id);
+  });
+
   // Remove old form
   Drupal.freezeHeight(); // Avoid unnecessary scrolling
   $(this.wrapper).html('');
@@ -90,6 +101,9 @@
     $('table tr:last-of-type td', div).fadeIn('slow');
     $(this.hide, div).fadeIn('slow');
     Drupal.uploadAutoAttach();
+    for (key in fileDeleteData) { // update previous marked-for-deletion status
+      Drupal.updateFileDelete(fileDeleteData[key], 'show');
+    }
   }
   Drupal.unfreezeHeight();
 }
@@ -109,6 +123,72 @@
   });
 }
 
+/**
+ * Retrieve some ids and classes that will be modified when Delete is pressed.
+ * The id of each wrapper div is used as base name (e.g. files-0-remove),
+ * other elements will have to adjust their id or class accordingly.
+ */
+Drupal.getFileDeleteData = function(wrapper) {
+  var fileDeleteData = new Array();
+  fileDeleteData['wrapper'] = wrapper;
+  // Transform stuff like update_0 to update-0, like Form API does
+  fileDeleteData['checkbox'] = 'edit-' + wrapper.replace(/_/g, '-');
+  fileDeleteData['button'] = wrapper + '-button';
+  fileDeleteData['classHide'] = '.' + wrapper + '-hide';
+  fileDeleteData['classShow'] = '.' + wrapper + '-show';
+  fileDeleteData['aboutToDelete'] = $('#' + fileDeleteData['checkbox']).attr('checked');
+  fileDeleteData['textDelete'] = Drupal.settings.fileDeleteButton[0];
+  fileDeleteData['textCancel'] = Drupal.settings.fileDeleteButton[1];
+  return fileDeleteData;
+}
+
+/**
+ * Initialize the JS file delete buttons and behaviour.
+ */
+Drupal.initFileDelete = function(fileDeleteData) {
+  // Hide the usual wrapper contents, and add a delete/cancel button instead.
+  $('#' + fileDeleteData['wrapper'] + '/*').hide();
+  $('#' + fileDeleteData['wrapper']).append(
+    "<input type=\"button\" class=\"file-delete-button\"" +
+    " value=\"" + fileDeleteData['textDelete'] + "\"" +
+    " id=\"" + fileDeleteData['button'] + "\" />"
+  );
+
+  // When the button is clicked, toggle the checkbox and css class visibility
+  $('#' + fileDeleteData['button']).click(function () {
+    fileDeleteData['aboutToDelete'] = ! $('#' + fileDeleteData['checkbox']).attr('checked');
+    Drupal.updateFileDelete(fileDeleteData, 'fade');
+  });
+}
+
+/**
+ * Show the right button text (Delete or Cancel) and css class visibility:
+ * when Delete has been pressed, classHide is hidden and classShow is shown.
+ */
+Drupal.updateFileDelete = function(fileDeleteData, appearanceMethod) {
+  $('#' + fileDeleteData['checkbox']).attr('checked', fileDeleteData['aboutToDelete']);
+
+  if (fileDeleteData['aboutToDelete']) {
+    $('#' + fileDeleteData['button']).val(fileDeleteData['textCancel']);
+    $(fileDeleteData['classHide']).hide();
+    toBeShown = $(fileDeleteData['classShow']);
+  }
+  else {
+    $('#' + fileDeleteData['button']).val(fileDeleteData['textDelete']);
+    $(fileDeleteData['classShow']).hide();
+    toBeShown = $(fileDeleteData['classHide']);
+  }
+
+  // When re-initialization is done after an attachment upload,
+  // we don't want stuff to be faded in - just plain show it.
+  if (appearanceMethod == 'show') {
+    toBeShown.show();
+  }
+  else {
+    toBeShown.fadeIn();
+  }
+}
+
 
 // Global killswitch
 if (Drupal.jsEnabled) {
