/***************************************************************************/
/***************************************************************************/
/* */
/* (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/Xm.h>
#include <string.h>
#include "xdir.h"
#include "list.h"
static struct {
int host;
struct dirwin_st *src_dirwin;
struct dirwin_st *snk_dirwin;
char *snk_dir;
struct entry_link *head;
struct entry_link *head_src_dirs;
int error;
} mc;
static char *not_implemented_msg = "Moving entry(s) from a host to another host not allowed.\nConsider copying entry(s) instead.";
static char *msg1 = "Unable to redisplay source directory.\n\nSource directory window might be out of date.";
static char *msg2 = "Unable to redisplay sink directory.\n\nSink directory window might be out of date.";
extern int inquire_on_move;
extern XtAppContext app;
extern int beep_when_ops_done;
extern int diagnostics;
extern struct st_host_info hinfo[];
int cb_move_entries();
char *entry_to_rel_path();
struct entry_info *rel_path_to_entry();
struct ref_st *create_reference_subtree();
char *entry_to_full_path();
char *merge_paths();
char *equivalent_file_path();
char **path_to_links();
void update_move_displays();
/*
* init_move - Initialize the move of selected entries in directory
* window "src_dirwin" to directory window "snk_dirwin". If
* "einfo" is non-NULL then move the entries into the
* directory represented by "einfo".
*/
void
init_move(src_dirwin, snk_dirwin, einfo)
struct dirwin_st *src_dirwin;
struct dirwin_st *snk_dirwin;
struct entry_info *einfo;
{
struct entry_link *head;
struct entry_link *tail;
struct entry_link *ptr;
char *temp_snk_dir;
char *snk_dir;
int retval;
int i;
int j;
int level;
int need_to_update_entire_source;
/* Start operation */
if (!start_op(True))
return;
/* Sanity check */
if (src_dirwin == snk_dirwin && einfo == NULL)
fatal_error("Bug in init_move()");
/* Clear error flag */
raise_okflag();
/* Is operation implemented */
if (src_dirwin->host != snk_dirwin->host) {
warn(not_implemented_msg, snk_dirwin->w_shell);
end_op();
return;
}
/* Ask the user if okay to move */
if (inquire_on_move) {
if (!verify_selection(src_dirwin, snk_dirwin,
"Do you really want to move these items?")) {
end_op();
return;
}
}
/* Make operation interruptable */
show_stop_button(snk_dirwin);
/* This might take some time */
use_busy_cursor();
/* Make sure connection is still good */
if (snk_dirwin->host != LOCAL) {
retval = check_connection(snk_dirwin->host, snk_dirwin);
if (retval < 0) {
restore_prev_cursor();
switch (retval) {
case -6:
record_abort("Move Entries");
break;
case -1:
record_and_alert("Unable to move entry(s).",
snk_dirwin->w_shell);
}
hide_stop_button();
end_op();
return;
}
}
/* Determine true sink directory path */
if (einfo) {
temp_snk_dir = entry_to_full_path(einfo);
} else
temp_snk_dir = XtNewString(snk_dirwin->dirname);
retval = determine_true_path(snk_dirwin->host, temp_snk_dir, True, False,
False, &snk_dir);
XtFree(temp_snk_dir);
if (retval < 0) {
switch (retval) {
case -1:
record_and_alert("Unable to move entry(s).", snk_dirwin->w_shell);
break;
case -3:
restore_lost_connection(snk_dirwin->host, snk_dirwin);
break;
case -6:
record_abort("Move Entries");
}
restore_prev_cursor();
hide_stop_button();
end_op();
return;
}
/* Form list of selected items to move */
head = NULL;
tail = NULL;
for (i=0; i<src_dirwin->nentries; i++)
if (src_dirwin->entries[i].level == 0)
postorder_selected_items(&src_dirwin->entries[i], &head, &tail);
/* Set up move control block */
mc.host = src_dirwin->host;
mc.src_dirwin = src_dirwin;
mc.snk_dirwin = snk_dirwin;
mc.snk_dir = snk_dir;
mc.head = head;
mc.head_src_dirs = NULL;
mc.error = False;
/* Make list of src dirs to update after move. NULL path means update all */
if (src_dirwin->layout == TREE) {
need_to_update_entire_source = False;
for (i=0; i<src_dirwin->nentries; i++)
if (src_dirwin->entries[i].level == 0
&& src_dirwin->entries[i].state == SELECTED) {
need_to_update_entire_source = True;
break;
}
if (snk_dirwin == src_dirwin && einfo == NULL)
need_to_update_entire_source = True;
if (need_to_update_entire_source == False) {
i = 0;
while (i<src_dirwin->nentries) {
if (src_dirwin->entries[i].type == DIRECTORY_TYPE) {
level = src_dirwin->entries[i].level;
if (einfo == &src_dirwin->entries[i] && einfo->expanded) {
ptr = XtNew(struct entry_link);
ptr->entry = entry_to_rel_path(einfo);
ptr->next = mc.head_src_dirs;
mc.head_src_dirs = ptr;
for (i++; i<src_dirwin->nentries; i++)
if (src_dirwin->entries[i].level <= level)
break;
continue;
}
for (j=i+1; j<src_dirwin->nentries; j++) {
if (src_dirwin->entries[j].level <= level)
break;
if (src_dirwin->entries[j].level == level+1
&& src_dirwin->entries[j].state == SELECTED) {
ptr = XtNew(struct entry_link);
ptr->entry =
entry_to_rel_path(&src_dirwin->entries[i]);
ptr->next = mc.head_src_dirs;
mc.head_src_dirs = ptr;
for (i=j+1; i<src_dirwin->nentries; i++)
if (src_dirwin->entries[i].level <= level) {
i--;
break;
}
break;
}
}
}
i++;
}
}
}
/* Perform move */
show_mp_monitor(snk_dirwin, "Now Moving:");
XtAppAddWorkProc(app, (XtWorkProc)cb_move_entries, NULL);
}
/*
* cb_move_entries - Work proc to actually move directory entries.
*/
cb_move_entries()
{
struct entry_link *ptr;
char *src_path;
char *snk_path;
int retval;
char msg[MAXPATHLEN+40];
char *temp_path;
char **links;
char **link_ptr;
int nlinks;
char *dir;
/* Did user push stop button? */
if (stop())
goto abort;
/* Are we done? */
if (mc.head == NULL) {
if (mc.error)
record_and_alert("At least one move failed.",
mc.snk_dirwin->w_shell);
goto done;
}
/* Let user know where we are */
update_mp_monitor(mc.head->entry);
/* Create source path */
temp_path = merge_paths(hinfo[mc.src_dirwin->host].system,
mc.src_dirwin->dirname, mc.head->entry);
if (mc.host != LOCAL) {
flush_cache_directory(mc.src_dirwin->host, temp_path);
parse_path(hinfo[mc.src_dirwin->host].system, temp_path, &dir, NULL);
flush_cache_directory(mc.src_dirwin->host, dir);
XtFree(dir);
}
src_path = equivalent_file_path(hinfo[mc.src_dirwin->host].system,
temp_path);
XtFree(temp_path);
/* Create sink path */
links = path_to_links(hinfo[mc.snk_dirwin->host].system, mc.head->entry);
nlinks = 0;
link_ptr = links;
while (*link_ptr++)
nlinks++;
temp_path = merge_paths(hinfo[mc.snk_dirwin->host].system, mc.snk_dir,
links[nlinks-1]);
release_path_links(links);
if (mc.host != LOCAL) {
flush_cache_directory(mc.snk_dirwin->host, temp_path);
parse_path(hinfo[mc.snk_dirwin->host].system, temp_path, &dir, NULL);
flush_cache_directory(mc.snk_dirwin->host, dir);
XtFree(dir);
}
snk_path = equivalent_file_path(hinfo[mc.snk_dirwin->host].system,
temp_path);
XtFree(temp_path);
/* Move entry */
if (mc.host == LOCAL)
retval = local_rename(src_path, snk_path);
else
retval = remote_rename(mc.host, src_path, snk_path);
XtFree(src_path);
XtFree(snk_path);
switch (retval) {
case -6:
goto abort;
case -3:
goto lost;
case -1:
sprintf(msg, "Unable to move %s", mc.head->entry);
record_warning(msg);
mc.error = True;
break;
case 0:
if (diagnostics >= NORMAL) {
sprintf(msg, "*** Successfully moved: %s\n",mc.head->entry);
write_log(msg);
}
}
ptr = mc.head;
mc.head = mc.head->next;
XtFree(ptr->entry);
XtFree((char *)ptr);
return False;
abort:
hide_mp_monitor();
record_abort("Move Entries");
dirwins_out_of_date_alert(mc.snk_dirwin);
goto final;
done:
hide_mp_monitor();
update_move_displays();
goto final;
lost:
hide_mp_monitor();
restore_prev_cursor();
restore_lost_connection(mc.host, mc.snk_dirwin);
use_busy_cursor();
final:
/* Clean up move control block data structure */
release_linked_list(&mc.head);
release_linked_list(&mc.head_src_dirs);
XtFree(mc.snk_dir);
/* 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;
}
/*
* update_move_displays - Call after move operation is complete to update
* source and sink directory displays.
*/
void
update_move_displays()
{
struct entry_info *einfo;
struct ref_st *ref_tree;
struct entry_link *ptr;
struct dirwin_st *snk_dirwin;
int indx;
char *anchor_rel_path;
int retval;
/* Update source display */
if ((mc.src_dirwin->layout == TREE) && mc.head_src_dirs) {
indx = mc.src_dirwin->first_visible_row;
anchor_rel_path = entry_to_rel_path(&mc.src_dirwin->entries[indx]);
ptr = mc.head_src_dirs;
while (ptr) {
einfo = rel_path_to_entry(mc.src_dirwin, ptr->entry);
if (einfo) {
ref_tree = create_reference_subtree(einfo);
collapse_subtree(&einfo, False);
retval = re_expand_subtree(&einfo, ref_tree,
mc.src_dirwin->cache_mode, False);
release_reference_subtree(ref_tree);
switch (retval) {
case -6:
record_abort("Move Entries");
dirwins_out_of_date_alert( mc.snk_dirwin);
XtFree(anchor_rel_path);
return;
case -1:
record_and_alert(msg1, mc.snk_dirwin);
break;
case -3:
XtFree(anchor_rel_path);
restore_lost_connection(mc.src_dirwin->host, mc.snk_dirwin);
goto sink;
}
}
ptr = ptr->next;
}
calc_dirwin_geometry(mc.src_dirwin);
set_first_visible_entry(mc.src_dirwin, anchor_rel_path);
XtFree(anchor_rel_path);
} else {
retval = display_dir(mc.src_dirwin->host, mc.src_dirwin,
mc.src_dirwin->dirname, True, False, mc.src_dirwin->cache_mode,
False);
switch (retval) {
case -6:
record_abort("Move Entries");
dirwins_out_of_date_alert( mc.snk_dirwin);
return;
case -1:
record_and_alert(msg1, mc.snk_dirwin);
break;
case -3:
restore_lost_connection(mc.src_dirwin->host, mc.snk_dirwin);
}
}
sink:
/* Update sink display */
if (is_dir_displayed(mc.host, mc.snk_dir, &snk_dirwin, &einfo)
&& (snk_dirwin != mc.src_dirwin)) {
if (einfo) {
indx = snk_dirwin->first_visible_row;
anchor_rel_path = entry_to_rel_path(&snk_dirwin->entries[indx]);
ref_tree = create_reference_subtree(einfo);
collapse_subtree(&einfo, False);
retval = re_expand_subtree(&einfo, ref_tree, snk_dirwin->cache_mode,
False);
release_reference_subtree(ref_tree);
switch (retval) {
case -6:
record_abort("Move Entries");
dirwin_out_of_date_alert(mc.snk_dirwin);
XtFree(anchor_rel_path);
return;
case -1:
record_and_alert(msg2, mc.snk_dirwin);
break;
case -3:
restore_lost_connection(mc.snk_dirwin->host, mc.snk_dirwin);
XtFree(anchor_rel_path);
return;
}
calc_dirwin_geometry(snk_dirwin);
set_first_visible_entry(snk_dirwin, anchor_rel_path);
XtFree(anchor_rel_path);
} else {
retval = display_dir(snk_dirwin->host, mc.snk_dirwin, mc.snk_dir,
True, False, snk_dirwin->cache_mode, False);
switch (retval) {
case -6:
record_abort("Move Entries");
dirwin_out_of_date_alert(mc.snk_dirwin);
return;
case -1:
record_and_alert(msg2, mc.snk_dirwin);
break;
case -3:
restore_lost_connection(mc.snk_dirwin->host, mc.snk_dirwin);
}
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1