NS_IMETHODIMP ValidityState::GetCustomError(bool* aCustomError) { *aCustomError = CustomError(); return NS_OK; }
intptr_t get_files(HANDLE hPlugin, struct PluginPanelItem *PanelItem, size_t ItemsNumber, int Move, UnicodeString& DestPath, OPERATION_MODES OpMode) { if ((ItemsNumber == 0) || (wcscmp(PanelItem[0].FileName, L"..") == 0)) return 1; PluginInstance* plugin = (PluginInstance*) hPlugin; bool show_dialog = (OpMode & (OPM_SILENT | OPM_FIND | OPM_VIEW | OPM_EDIT | OPM_QUICKVIEW)) == 0; bool show_error = (OpMode & (OPM_FIND | OPM_QUICKVIEW)) == 0; try { CopyFilesOptions options; options.show_dialog = show_dialog; options.show_error = show_error; options.dst_dir = DestPath; options.move_files = Move != 0; options.copy_shared = get_app_option(FSSF_SYSTEM, c_copy_opened_files_option, true); options.use_file_filters = false; options.use_tmp_files = (OpMode & (OPM_FIND | OPM_VIEW | OPM_QUICKVIEW)) != 0; if (show_dialog) { options.ignore_errors = g_plugin_options.ignore_errors; options.overwrite = g_plugin_options.overwrite; options.show_stats = g_plugin_options.show_stats; if (!show_copy_files_dlg(options, false)) BREAK; if (g_plugin_options.save_def_values) { g_plugin_options.ignore_errors = options.ignore_errors; g_plugin_options.overwrite = options.overwrite; g_plugin_options.show_stats = options.show_stats; save_def_option_values(g_plugin_options); } DestPath = options.dst_dir; } else { options.ignore_errors = false; options.overwrite = ooOverwrite; options.show_stats = ssoNever; } CopyFilesStats stats; Log log; { UiLink ui((OpMode & OPM_SILENT) != 0); if (ui.update_needed()) { draw_progress_msg(far_get_msg(MSG_PROGRESS_PREPARE)); } // source directory UnicodeString src_dir_path = plugin->current_dir; // distination directory and file name (if renaming) UnicodeString dst_dir_path, dst_new_name; FilePath dst_fp(options.dst_dir); bool dst_is_remote = !dst_fp.is_absolute || (dst_fp.root.size() == 0); if (dst_is_remote) { // ensure that file name case is correct in source and destinations paths // it will be used later in comparison FilePath src_dir_fp(src_dir_path); find_real_file_path(src_dir_fp, plugin->session); src_dir_path = src_dir_fp.get_full_path(); dst_fp = FilePath(plugin->current_dir).combine(dst_fp); find_real_file_path(dst_fp, plugin->session); } if ((dst_is_remote && dir_exists(dst_fp.get_full_path(), plugin->session)) || (!dst_is_remote && dir_exists(dst_fp.get_full_path()))) { dst_dir_path = dst_fp.get_full_path(); } else { if (ItemsNumber != 1) { dst_dir_path = dst_fp.get_full_path(); } else { dst_dir_path = dst_fp.get_dir_path(); dst_new_name = dst_fp.get_file_name(); } } UnicodeString src_file_name, dst_file_name; // store source / destination file names UnicodeString src_path, dst_path; // store source / destination file paths // list of selected files FileList panel_file_list; panel_items_to_file_list(PanelItem, ItemsNumber, panel_file_list); // verify that no file is copied into self if (dst_is_remote) { for (unsigned i = 0; i < ItemsNumber; i++) { src_file_name = panel_file_list[i].file_name; COMPOSE_PATH2(src_path, src_dir_path, src_file_name); if (dst_new_name.size() != 0) dst_file_name = dst_new_name; else dst_file_name = src_file_name; COMPOSE_PATH2(dst_path, dst_dir_path, dst_file_name); if (dst_path == src_path) FAIL(CustomError(far_get_msg(MSG_ERR_SELF_COPY), src_path)); } } // make sure destination path exists if (dst_is_remote) prepare_target_path(dst_dir_path, plugin->session, plugin); else prepare_target_path(dst_dir_path, plugin); Array<unsigned> finished_idx; // indices of processed files // try to move files remotely // mark files that were processed successfully if (options.move_files && dst_is_remote) { // prepare progress data CopyFilesProgress progress; QueryPerformanceCounter((PLARGE_INTEGER) &progress.start_time); ui.force_update(); // iterate through selected files for (unsigned i = 0; i < ItemsNumber; i++) { src_file_name = panel_file_list[i].file_name; // source file name COMPOSE_PATH2(src_path, src_dir_path, src_file_name); // source file path if (dst_new_name.size() != 0) dst_file_name = dst_new_name; else dst_file_name = src_file_name; // destination file name COMPOSE_PATH2(dst_path, dst_dir_path, dst_file_name); // destination file path // update progress bar if needed if (ui.update_needed()) { progress.src_path = src_path; progress.dst_path = dst_path; draw_move_remote_files_progress(progress, stats); } // try to move file remotely if (move_remote_file(src_path, dst_path, plugin->session)) { // update stats if (panel_file_list[i].is_dir()) stats.dirs++; else stats.files++; // add finished file to list finished_idx += i; } } } // scan source directories and prepare lists of files to process ObjectArray<FileList> file_lists; ui.force_update(); CreateListStats list_stats; CreateListOptions list_options; list_options.ignore_errors = options.ignore_errors; list_options.show_error = options.show_error; try { for (unsigned i = 0; i < ItemsNumber; i++) { if (finished_idx.bsearch(i) == -1) { file_lists += create_file_list(src_dir_path, panel_file_list[i].file_name, list_stats, list_options, ui, log, plugin->session, plugin); } else file_lists += FileList(); // skip already moved objects } } finally (stats.errors = list_stats.errors); // show file filters dialog if needed ObjectArray<FilterInterface> filters; if (options.use_file_filters && !dst_is_remote && show_dialog) { load_file_filters(); if (export_filter_list.size() != 0) { Array<FilterSelection> selection; if (!show_filters_dlg(export_filter_list, selection)) BREAK; for (unsigned i = 0; i < selection.size(); i++) { filters += FilterInterface(export_filter_list[selection[i].src_idx].src_ext, export_filter_list[selection[i].src_idx][selection[i].dst_idx].dst_ext, export_filter_list[selection[i].src_idx][selection[i].dst_idx].guid); } } } // perform copy CopyFilesProgress progress; progress.total_size = list_stats.size; progress.processed_total_size = progress.copied_total_size = 0; QueryPerformanceCounter((PLARGE_INTEGER) &progress.start_time); ui.force_update(); AutoBuffer buffer(g_plugin_options.copy_buf_size); for (unsigned i = 0; i < ItemsNumber; i++) { if (finished_idx.bsearch(i) == -1) { copy_files(true, src_dir_path, file_lists[i], dst_is_remote, dst_dir_path, dst_new_name, stats, progress, options, ui, buffer, log, filters, plugin->session, plugin); } PanelItem[i].Flags &= ~PPIF_SELECTED; } // delete source files if moving (only if no errors or skipped files to prevent data loss) if (options.move_files && (stats.errors == 0) && (stats.skipped == 0)) { DeleteFilesStats del_stats; DeleteFilesOptions del_options; del_options.ignore_errors = options.ignore_errors; del_options.show_stats = options.show_stats; del_options.show_error = options.show_error; del_options.show_dialog = options.show_dialog; DeleteFilesProgress del_progress; del_progress.objects = 0; del_progress.total_objects = list_stats.files + list_stats.dirs; QueryPerformanceCounter((PLARGE_INTEGER) &del_progress.start_time); ui.force_update(); try { for (unsigned i = 0; i < ItemsNumber; i++) { delete_files(true, src_dir_path, file_lists[i], del_stats, del_progress, del_options, ui, log, plugin->session, plugin); } } finally (stats.errors += del_stats.errors); } // set cursor to new file name after rename if (dst_is_remote && options.move_files && (src_dir_path == dst_dir_path)) { assert(dst_new_name.size() != 0); far_control_int(plugin, FCTL_UPDATEPANEL, 1); PanelInfo panel_info; far_control_ptr(plugin, FCTL_GETPANELINFO, &panel_info); PanelRedrawInfo redraw_info = { sizeof(PanelRedrawInfo) }; redraw_info.TopPanelItem = panel_info.TopPanelItem; redraw_info.CurrentItem = panel_info.CurrentItem; for (size_t i = 0; i < panel_info.ItemsNumber; i++) { PluginPanelItem* ppi = far_get_panel_item(plugin, i, panel_info); UnicodeString file_name = ppi->FileName; if (file_name == dst_new_name) { redraw_info.CurrentItem = i; break; } } far_control_ptr(INVALID_HANDLE_VALUE, FCTL_REDRAWPANEL, &redraw_info); } } if (show_dialog && ((options.show_stats == ssoAlways) || ((options.show_stats == ssoIfError) && (stats.errors != 0)))) show_copy_files_results_dlg(stats, log); return 1; }