/***************************************************************************/ /***************************************************************************/ /* */ /* (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 #include #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; inentries; 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; inentries; 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 (inentries) { 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++; inentries; i++) if (src_dirwin->entries[i].level <= level) break; continue; } for (j=i+1; jnentries; 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; inentries; 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); } } } }