/***************************************************************************/
/***************************************************************************/
/*                                                                         */
/*   (c) 1995-1999.  The Regents of the University of California.  All     */
/*   rights reserved.                                                      */
/*                                                                         */
/*   This work was produced at the University of California, Lawrence      */
/*   Livermore National Laboratory (UC LLNL) under contract no.            */
/*   W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy     */
/*   (DOE) and The Regents of the University of California (University)    */
/*   for the operation of UC LLNL.  Copyright is reserved to the           */
/*   University for purposes of controlled dissemination,                  */
/*   commercialization through formal licensing, or other disposition      */
/*   under terms of Contract 48; DOE policies, regulations and orders;     */
/*   and U.S. statutes.  The rights of the Federal Government are          */
/*   reserved under Contract 48 subject to the restrictions agreed upon    */
/*   by the DOE and University.                                            */
/*                                                                         */
/*                                                                         */
/*                              DISCLAIMER                                 */
/*                                                                         */
/*   This software was prepared as an account of work sponsored by an      */
/*   agency of the United States Government.  Neither the United States    */
/*   Government nor the University of California nor any of their          */
/*   employees, makes any warranty, express or implied, or assumes any     */
/*   liability or responsibility for the accuracy, completeness, or        */
/*   usefulness of any information, apparatus, product, or process         */
/*   disclosed, or represents that its specific commercial products,       */
/*   process, or service by trade name, trademark, manufacturer, or        */
/*   otherwise, does not necessarily constitute or imply its               */
/*   endorsement, recommendation, or favoring by the United States         */
/*   Government or the University of California. The views and opinions    */
/*   of the authors expressed herein do not necessarily state or reflect   */
/*   those of the United States Government or the University of            */
/*   California, and shall not be used for advertising or product          */
/*   endorsement purposes.                                                 */
/*                                                                         */
/*   Permission to use, copy, modify and distribute this software and its  */
/*   documentation for any non-commercial purpose, without fee, is         */
/*   hereby granted, provided that the above copyright notice and this     */
/*   permission notice appear in all copies of the software and            */
/*   supporting documentation, and that all UC LLNL identification in      */
/*   the user interface remain unchanged.  The title to copyright LLNL     */
/*   XDIR shall at all times remain with The Regents of the University     */
/*   of California and users agree to preserve same. Users seeking the     */
/*   right to make derivative works with LLNL XDIR for commercial          */
/*   purposes may obtain a license from the Lawrence Livermore National    */
/*   Laboratory's Technology Transfer Office, P.O. Box 808, L-795,         */
/*   Livermore, CA 94550.                                                  */
/*                                                                         */
/***************************************************************************/
/***************************************************************************/

#include <Xm/SelectioB.h>
#include <Xm/LabelG.h>
#include <Xm/Form.h>
#include "xdir.h"
#include "list.h"
#include "str.h"

static struct {
    int recursive;                      /* Requires initialization */
    int level;                          /* Requires initialization */
    struct dirwin_st *dirwin;           /* Requires initialization */
    struct entry_link *head[MAXLEVELS]; /* Requires initialization */
	int error;							/* Requires initialization */
	int asked_user;						/* Requires initialization */
    char *rel_path;
    char *full_path;
} dc;

static char *del_question = "You are attempting to delete a (possibly nonempty)\ndirectory, but the general preference DELETE MODE\nis set to NONRECURSIVE.\n\nDelete nonempty directories anyway?";

static char *msg1 = "Unable to redisplay directory.\n\nDirectory window might be out of date.";

extern struct st_host_info hinfo[];
extern int beep_when_ops_done;
extern Widget w_toplev;
extern int diagnostics;
extern int inquire_on_delete;
extern XtAppContext app;
extern int rdelete_mode;

char *merge_paths();
char *links_to_path();
int cb_delete_entries();
char **path_to_links();


/*
 * cb_delete - Callback that deletes selected file(s).
 */
void
cb_delete(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
	struct dirwin_st *dirwin = (struct dirwin_st *)client_data;
    struct entry_link *head;
	struct entry_link *tail;
    int i;
	int retval;

	/* Start operation */
	if (!start_op(True))
		return;

    /* Clear error flag */
    raise_okflag();

    /* Ask the user if okay to delete? */
    if (inquire_on_delete) {
		if (!verify_selection(dirwin, dirwin,
                "Do you really want to delete these entries?")) {
			end_op();
            return;
		}
    }

    /* Make operation interruptable */
	show_stop_button(dirwin);

    /* This might take some time */
    use_busy_cursor();

	/* Make sure connection is still good */
	if (dirwin->host != LOCAL) {
		retval = check_connection(dirwin->host, dirwin);
		if (retval < 0) {
			restore_prev_cursor();
			switch (retval) {
			case -6:
				record_abort("Delete Entries");
				break;
			case -1:
				record_and_alert("Unable to delete entries.", dirwin->w_shell);
			}
			hide_stop_button();
			end_op();
			return;
		}
	}

	/* Form list of selected items to delete */
	head = NULL;
	tail = NULL;
    for (i=0; i<dirwin->nentries; i++)
        if (dirwin->entries[i].level == 0)
            postorder_selected_items(&dirwin->entries[i], &head, &tail);

    /* Set up deletion control block */
    dc.recursive = rdelete_mode;
    dc.level = 0;
    dc.dirwin = dirwin;
    dc.head[0] = head;
	dc.error = False;
	dc.asked_user = False;

    /* Perform deletion */
	show_mp_monitor(dirwin, "Now Deleting:");
    XtAppAddWorkProc(app, (XtWorkProc)cb_delete_entries, NULL);
}


/*
 * cb_delete_entries - Work procedure for executing deletion request.
 *                     State information is kept in "dc", the
 *                     deletion control block data structure.
 */
cb_delete_entries()
{
	static char *del_error_msg =
		"Unable to delete entry(s).  Can't get directory list.";
	struct entry_link *ptr;
	struct sl_struct *list;
	int retval;
	int len;
	int i;
	int is_a_directory;
	char msg[MAXPATHLEN+40];
	int already_handled_dir = False;
	char **rel_path_links;
	int nlinks;
	char **link_ptr;
	int indx;
	char **first_path_links;
	char **p;
	char *dir;

	dc.full_path = NULL;
	dc.rel_path = NULL;
		
	/* Did user push stop button? */
	if (stop())
		goto abort;

	/* Is there more to do? */
	if (dc.head[dc.level] == NULL) {
		if (dc.level == 0) {
			if (dc.error)
				record_and_alert("At least one deletion failed.",
					dc.dirwin->w_shell);
			goto done;
		} else {
			dc.level--;
			already_handled_dir = True;
		}
	}

	/* Build relative path name */
	first_path_links = path_to_links(hinfo[dc.dirwin->host].system,
		dc.head[0]->entry);
	nlinks = 0;
	link_ptr = first_path_links;
	while (*link_ptr++)
		nlinks++;
	nlinks += dc.level;
	rel_path_links = (char **)XtMalloc(sizeof(char *)*(nlinks+1));
	indx = 0;
	p = first_path_links;
	while (*p) {
		rel_path_links[indx++] = XtNewString(*p);
		p++;
	}
	release_path_links(first_path_links);
	for (i=1; i<=dc.level; i++)
		rel_path_links[indx++] = XtNewString(dc.head[i]->entry);
	rel_path_links[nlinks] = NULL;
	dc.rel_path = links_to_path(hinfo[dc.dirwin->host].system, rel_path_links,
		nlinks);
	release_path_links(rel_path_links);

	/* Build full path name */
	dc.full_path = merge_paths(hinfo[dc.dirwin->host].system,
		dc.dirwin->dirname, dc.rel_path);

	/* Handle recursion */
	if (!already_handled_dir) {
		if (dc.recursive || !dc.asked_user) {
			/* Test for directory by trying to cd to it */
			is_a_directory = False;
			if (dc.dirwin->host == LOCAL) {
				if (local_cd(dc.full_path, False) == 0)
					is_a_directory = True;
			} else
				switch (remote_cd(dc.dirwin->host, dc.full_path, False)) {
				case -6:
					goto abort;
				case -3:
					goto lost;
				case 0:
					is_a_directory = True;
				}
			if (is_a_directory) {
				if (!dc.recursive) {
					beep();
					if (question_dialog(del_question, dc.dirwin->w_shell))
						dc.recursive = True;
					dc.asked_user = True;
				}
				if (dc.recursive) {
					/* Get directory list */
					switch (get_dirlist(dc.dirwin->host, dc.full_path, TABULAR,
						True, False, False, &list)) {
					case -6:
						goto abort;
					case -3:
						goto lost;
					case -1:
						record_and_alert(del_error_msg, dc.dirwin->w_shell);
						goto done;
					}
					/* Add directory list to new level */
					dc.level++;
					if (dc.level == MAXLEVELS) {
						record_and_alert(
							"Deletion(s) aborted.  Recursion too deep.",
							dc.dirwin->w_shell);
						goto done;
					}
					dc.head[dc.level] = NULL;
					for (i=list->nentries-1; i>=0; i--) {
						ptr = XtNew(struct entry_link);
						ptr->entry = XtNewString(list->entries[i]);
						ptr->next = dc.head[dc.level];
						dc.head[dc.level] = ptr;
					}
					release_array_list(list);
				    XtFree(dc.full_path);
				    XtFree(dc.rel_path);
					return False;
				}
			}
		}
	}

	/* Delete next directory entry */
	update_mp_monitor(dc.rel_path);
	if (dc.dirwin->host == LOCAL)
		retval = local_delete(dc.full_path);
	else {
		flush_cache_directory(dc.dirwin->host, dc.full_path);
		parse_path(hinfo[dc.dirwin->host].system, dc.full_path, &dir, NULL);
		flush_cache_directory(dc.dirwin->host, dir);
		XtFree(dir);
		len = strlen(dc.full_path);
		if ((hinfo[dc.dirwin->host].system == SYS_VMS)
				&& (dc.full_path[len-1] == ']'))
			retval = remote_rmdir(dc.dirwin->host, dc.full_path);
		else if (hinfo[dc.dirwin->host].server == SERVER_MAC_FTPD ||
				hinfo[dc.dirwin->host].server == SERVER_WINDOWS_WFTPD ||
				hinfo[dc.dirwin->host].server == SERVER_NT)
			switch (remote_cd(dc.dirwin->host, dc.full_path, False)) {
			case -6:
				goto abort;
			case -3:
				goto lost;
			case 0:
				retval = remote_rmdir(dc.dirwin->host, dc.full_path);
				break;
			default:
				retval = remote_delete(dc.dirwin->host, dc.full_path);
			}
		else
			retval = remote_delete(dc.dirwin->host, dc.full_path);
	}
    switch (retval) {
	case -6:
		goto abort;
    case -3:
		goto lost;
    case -1:
        sprintf(msg, "Unable to delete %s.", dc.rel_path);
        record_warning(msg);
		dc.error = True;
		break;
	case 0:
		if (diagnostics >= NORMAL) {
        	sprintf(msg, "*** Successfully deleted:  %s\n", dc.rel_path);
        	write_log(msg);
		}
    }
    XtFree(dc.full_path);
    XtFree(dc.rel_path);
    ptr = dc.head[dc.level];
    dc.head[dc.level] = ptr->next;
    XtFree(ptr->entry);
    XtFree((char *)ptr);
    return False;

abort:
	
	hide_mp_monitor();
	record_abort("Delete Entries");
	write_log("*** Deletion(s) aborted.");
	dirwin_out_of_date_alert(dc.dirwin);
	goto final;

done:
	
	hide_mp_monitor();
	retval = display_dir(dc.dirwin->host, dc.dirwin, dc.dirwin->dirname, True,
		False, dc.dirwin->cache_mode, False);
	switch (retval) {
	case -6:
		record_abort("Delete Entries");
		write_log("*** Deletion(s) aborted.");
		dirwin_out_of_date_alert(dc.dirwin);
		break;
	case -3:
		restore_lost_connection(dc.dirwin->host, dc.dirwin);
		break;
	case -1:
		record_and_alert(msg1, dc.dirwin->w_shell);
	}
	goto final;

lost:

	hide_mp_monitor();
	restore_lost_connection(dc.dirwin->host, dc.dirwin);

final:

	/* Clean up the deletion control block data structure */
	XtFree(dc.rel_path);
	dc.rel_path = NULL;

	XtFree(dc.full_path);
	dc.full_path = NULL;

	for(i=0; i<=dc.level; i++)
		release_linked_list(&dc.head[i]);

	/* Miscellaneous cleanup */
	clear_selected_entries();
	update_dir_controls();
	if (beep_when_ops_done)
		beep();
	restore_prev_cursor();

	/* Signal end of operation */
	hide_stop_button();
	end_op();
	return True;
}



syntax highlighted by Code2HTML, v. 0.9.1