/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* $TOG: main_dtcopy.c /main/10 1998/10/26 12:42:41 mgreess $ */ /************************************<+>************************************* **************************************************************************** * * FILE: main_dtcopy.c * * COMPONENT_NAME: dtcopy - Handles move/copy/link operations for 'dtfile' * * DESCRIPTION: Main program for dtfile_copy. * * * FUNCTIONS: AppendErrorMsg * CheckForMap * ConfirmHandler * ErrorHandler * EventCheck * InitNlsMessage * TimeoutHandler * UpdateErrorCount * UpdateStatus * UpdateSummary * get_command_line * main * moveDeleteCallback * moveErrorCallback * * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company * (c) Copyright 1993, 1994, 1995 International Business Machines Corp. * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc. * (c) Copyright 1993, 1994, 1995 Novell, Inc. * **************************************************************************** ************************************<+>*************************************/ #include #include #include #include #include #include #include #include #include /* #Include */ /* for editres debugging tool */ #include
#include
#include
#include "fsrtns.h" #include "dosync.h" #include "dtcopy.h" #include "sharedFuncs.h" /*-------------------------------------------------------------------- * Global Variables *------------------------------------------------------------------*/ extern Widget G_toplevel; Widget G_summary_text; Widget G_status_text; /* Widget G_status_text2; */ Widget G_error_count; Widget G_error_msgs; Widget G_copy_dialog; Widget G_error_dialog = NULL; Widget G_over_dialog = NULL; Widget G_over_confirm; Widget G_copy_action_area_pbuttons[4]; Widget G_help_dialog; Widget G_overwrite_radio; Widget G_rename_text; Widget G_toggle_main; Widget G_toggle_error; int G_overwrite_selection = G_OVERWRITE_EXISTING; int G_move = FALSE; int G_do_copy = TRUE; int G_pause_copy = FALSE; int G_user_pause_copy = FALSE; int G_wait_on_error = TRUE; int G_error_status = 0; int G_ignore_errors = FALSE; int G_overwrite_confirm = TRUE; int G_wait_on_input = TRUE; extern int G_dialog_closed; char G_rename_oldname[MAX_PATH]; char G_source_dir[MAX_PATH]; /* debugging flag */ #ifdef DEBUG int debug = 0; #endif static XtAppContext app_context; static Display *display; static Boolean is_mapped = False; static int nfiles = 0; static int ndirs = 0; static int nerr = 0; static char last_dir[MAX_PATH]; #define FILEOPNUM 14 static char *LongFileOpNames[FILEOPNUM]; static char *DefaultLongFileOpNames[] = { "processing", "opening", "opening", "opening", "reading link", "deleting", "copying", "creating directory", "copying link", "creating link", "working", "is a copy", "is a link", "renaming" }; /*-------------------------------------------------------------------- * application resource definitions *------------------------------------------------------------------*/ typedef struct { char *source_name; char *target_name; SyncParams sync; Boolean move; Boolean confirmreplace; Boolean confirmerrors; Boolean popdown; int delay; Boolean use_toggle_buttons; Boolean slow; Boolean checkPerms; } AppArgs, *AppArgsPtr; static AppArgs app_args; static XtResource resources[] = { /* source and target directories */ { "source", "Source", XmRString, sizeof (char *), XtOffset (AppArgsPtr, source_name), XmRImmediate, (XtPointer) NULL, }, { "target", "Target", XmRString, sizeof (char *), XtOffset (AppArgsPtr, target_name), XmRImmediate, (XtPointer) NULL, }, /* SyncParams */ { "verbose", "Verbose", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.verbose), XmRImmediate, (XtPointer) True, }, { "quiet", "Quiet", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.quiet), XmRImmediate, (XtPointer) False, }, { "dontDoIt", "DontDoIt", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.dontdoit), XmRImmediate, (XtPointer) False, }, { "keepNew", "KeepNew", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.keepnew), XmRImmediate, (XtPointer) False, }, { "keepOld", "KeepOld", XmRString, sizeof (char *), XtOffset (AppArgsPtr, sync.keepold), XmRImmediate, (XtPointer) NULL, }, { "dontDelete", "DontDelete", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.dontdelete), XmRImmediate, (XtPointer) False, }, { "dontAdd", "DontAdd", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.dontadd), XmRImmediate, (XtPointer) False, }, { "dontReplace", "DontReplace", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.dontreplace), XmRImmediate, (XtPointer) False, }, { "dontRecur", "DontRecur", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.dontrecur), XmRImmediate, (XtPointer) False, }, { "keepLinks", "KeepLinks", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.keeplinks), XmRImmediate, (XtPointer) False, }, { "keepCopies", "KeepCopies", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.keepcopies), XmRImmediate, (XtPointer) False, }, { "forceCopies", "ForceCopies", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.forcecopies), XmRImmediate, (XtPointer) False, }, { "listLinks", "ListLinks", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.listlinks), XmRImmediate, (XtPointer) False, }, { "listCopies", "ListCopies", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.listcopies), XmRImmediate, (XtPointer) False, }, { "linkFolders", "LinkFolders", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.linkdirs), XmRImmediate, (XtPointer) False, }, { "linkFiles", "LinkFiles", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.linkfiles), XmRImmediate, (XtPointer) False, }, { "copyFolders", "CopyFolders", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.copydirs), XmRImmediate, (XtPointer) False, }, { "copyFiles", "CopyFiles", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.copyfiles), XmRImmediate, (XtPointer) False, }, { "copyTop", "CopyTop", XmRBool, sizeof (int), XtOffset (AppArgsPtr, sync.copytop), XmRImmediate, (XtPointer) False, }, /* other options */ { "move", "Move", XmRBoolean, sizeof (Boolean), XtOffset (AppArgsPtr, move), XmRImmediate, (XtPointer) False, }, { "confirmReplace", "ConfirmReplace", XmRBoolean, sizeof (Boolean), XtOffset (AppArgsPtr, confirmreplace), XmRImmediate, (XtPointer) False, }, { "confirmErrors", "ConfirmErrors", XmRBoolean, sizeof (Boolean), XtOffset (AppArgsPtr, confirmerrors), XmRImmediate, (XtPointer) False, }, { "popDown", "PopDown", XmRBoolean, sizeof (Boolean), XtOffset (AppArgsPtr, popdown), XmRImmediate, (XtPointer) False, }, { "delay", "Delay", XmRInt, sizeof (int), XtOffset (AppArgsPtr, delay), XmRImmediate, (XtPointer) 5000, }, /* in milliseconds */ { "toggle", "Toggle", XmRBoolean, sizeof (Boolean), XtOffset (AppArgsPtr, use_toggle_buttons), XmRImmediate, (XtPointer) True, }, { "slow", "Slow", XmRBoolean, sizeof (Boolean), XtOffset (AppArgsPtr, slow), XmRImmediate, (XtPointer) False, }, { "checkPermissions", "CheckPermissions", XmRBoolean, sizeof (Boolean), XtOffset (AppArgsPtr, checkPerms), XmRImmediate, (XtPointer) False, }, }; static XrmOptionDescRec option_list[] = { { "-from", "source", XrmoptionSepArg, NULL }, { "-to", "target", XrmoptionSepArg, NULL }, { "-verbose", "verbose", XrmoptionNoArg, "True" }, { "-v", "verbose", XrmoptionNoArg, "True" }, { "-quiet", "quiet", XrmoptionNoArg, "True" }, { "-q", "quiet", XrmoptionNoArg, "True" }, { "-dontDoIt", "dontDoIt", XrmoptionNoArg, "True" }, { "-n", "dontDoIt", XrmoptionNoArg, "True" }, { "-keepNew", "keepNew", XrmoptionNoArg, "True" }, { "-kn", "keepNew", XrmoptionNoArg, "True" }, { "-keepOld", "keepOld", XrmoptionSepArg, NULL }, { "-ko", "keepOld", XrmoptionSepArg, NULL }, { "-dontDelete", "dontDelete", XrmoptionNoArg, "True" }, { "-nd", "dontDelete", XrmoptionNoArg, "True" }, { "-dontAdd", "dontAdd", XrmoptionNoArg, "True" }, { "-na", "dontAdd", XrmoptionNoArg, "True" }, { "-dontReplace", "dontReplace", XrmoptionNoArg, "True" }, { "-nr", "dontReplace", XrmoptionNoArg, "True" }, { "-dontRecur", "dontRecur", XrmoptionNoArg, "True" }, { "-nR", "dontRecur", XrmoptionNoArg, "True" }, { "-keepLinks", "keepLinks", XrmoptionNoArg, "True" }, { "-kl", "keepLinks", XrmoptionNoArg, "True" }, { "-keepCopies", "keepCopies", XrmoptionNoArg, "True" }, { "-kc", "keepCopies", XrmoptionNoArg, "True" }, { "-forceCopies", "forceCopies", XrmoptionNoArg, "True" }, { "-fc", "forceCopies", XrmoptionNoArg, "True" }, { "-listLinks", "listLinks", XrmoptionNoArg, "True" }, { "-ll", "listLinks", XrmoptionNoArg, "True" }, { "-listCopies", "listCopies", XrmoptionNoArg, "True" }, { "-lc", "listCopies", XrmoptionNoArg, "True" }, { "-linkFolders", "linkFolders", XrmoptionNoArg, "True" }, { "-ld", "linkFolders", XrmoptionNoArg, "True" }, { "-linkFiles", "linkFiles", XrmoptionNoArg, "True" }, { "-lf", "linkFiles", XrmoptionNoArg, "True" }, { "-copyFolders", "copyFolders", XrmoptionNoArg, "True" }, { "-cd", "copyFolders", XrmoptionNoArg, "True" }, { "-copyFiles", "copyFiles", XrmoptionNoArg, "True" }, { "-cf", "copyFiles", XrmoptionNoArg, "True" }, { "-copyTop", "copyTop", XrmoptionNoArg, "True" }, { "-ct", "copyTop", XrmoptionNoArg, "True" }, { "-move", "move", XrmoptionNoArg, "True" }, { "-mv", "move", XrmoptionNoArg, "True" }, { "-confirmReplace", "confirmReplace", XrmoptionNoArg, "True" }, { "-cr", "confirmReplace", XrmoptionNoArg, "True" }, { "-confirmErrors", "confirmErrors", XrmoptionNoArg, "True" }, { "-ce", "confirmErrors", XrmoptionNoArg, "True" }, { "-popDown", "popDown", XrmoptionNoArg, "True" }, { "-delay", "delay", XrmoptionSepArg, NULL }, { "-slow", "slow", XrmoptionNoArg, "True" }, { "-toggle", "toggle", XrmoptionNoArg, "True" }, { "-notoggle", "toggle", XrmoptionNoArg, "False" }, { "-checkPerms", "checkPermissions",XrmoptionNoArg, "True" }, }; /*-------------------------------------------------------------------- * display update functions *------------------------------------------------------------------*/ static void UpdateSummary(void) { XmString xs; char msg[1024]; char files[128]; char dirs[128]; int new_nfiles = nfiles, new_ndirs = ndirs; if (nfiles == 1) strcpy(files, GETMESSAGE(2, 3, "file")); else strcpy(files, GETMESSAGE(2, 4, "files")); if (ndirs == 1) strcpy(dirs, GETMESSAGE(2, 5, "subfolder")); else strcpy(dirs, GETMESSAGE(2, 6, "subfolders")); if ( nfiles < 0 ) new_nfiles = 0; if ( ndirs < 0 ) new_ndirs = 0; sprintf(msg, "%4d %s\n%4d %s", new_nfiles, files, new_ndirs, dirs); xs = XmStringCreateLocalized(msg); XtVaSetValues (G_summary_text, XmNlabelString, xs, NULL); XmStringFree(xs); } static void UpdateStatus( char *msg1, char *msg2) { String msg; String pad; const String ellipsis="..."; const int lenEllipsis = 3; int lenSourceDir, lenMsg, lenMsg2, numBlanks; static int maxMsg = -1; DPRINTF(("%s %s\n",msg1,msg2)); /* XtUnmanageChild(G_status_text2); XtVaSetValues (G_status_text, XmNvalue, msg1, XmNcursorPosition, 0, NULL); XtVaSetValues (G_status_text2, XmNvalue, msg2, NULL); XtManageChild(G_status_text2); XtVaSetValues (G_status_text2, XmNcursorPosition, strlen(msg2), NULL); */ /* The pathname is truncated, if possible, by replacing */ /* the name of the source directory with "...". Thus, */ /* when copying /u/joeuser/mydir/myfile, the pathanme */ /* is written as .../myfile */ lenSourceDir = strlen(G_source_dir); lenMsg2 = strlen(msg2); if ( (strncmp(G_source_dir,msg2,lenSourceDir) == 0) && (lenMsg2 > lenSourceDir) ) { msg = XtMalloc(strlen(msg1) + lenEllipsis + (lenMsg2 - lenSourceDir) + 2); sprintf(msg, "%s %s%s", msg1, ellipsis, msg2+lenSourceDir); } else { msg = XtMalloc(strlen(msg1) + lenMsg2 + 2); sprintf(msg, "%s %s", msg1, msg2); } /* In order to minimize re-sizing of the dialog, the */ /* length of the message is not allowed to decrease. */ /* Blanks are added to the end of shorter messages. */ lenMsg = strlen(msg); maxMsg = (maxMsg > lenMsg) ? maxMsg : lenMsg; /* MAX(maxMsg,lenMsg) */ if (lenMsg < maxMsg) { numBlanks = maxMsg - lenMsg; pad = XtMalloc(numBlanks+1); memset(pad,' ',numBlanks); pad[numBlanks] = '\0'; msg = XtRealloc(msg,maxMsg+1); strcat(msg,pad); XtFree(pad); } XmTextFieldSetString(G_status_text, msg); XtFree(msg); } static void UpdateErrorCount(void) { char msg[128]; if (nerr == 0) strcpy(msg, GETMESSAGE(2, 7, "Errors: none")); else sprintf(msg, GETMESSAGE(2, 8, "Errors: %d"), nerr); /* for the first error, manage the widgets used to display errors */ if (nerr == 1) { XtVaSetValues(G_status_text, XmNbottomAttachment, XmATTACH_NONE, NULL); /* XtVaSetValues(G_status_text2, XmNbottomAttachment, XmATTACH_NONE, NULL); */ XtManageChild(G_error_count); XtManageChild(G_error_msgs); XtManageChild(XtParent(G_error_msgs)); } XtVaSetValues (G_error_count, XmNvalue, msg, XmNcursorPosition, 0, NULL); } static void AppendErrorMsg(char *msg) { XmTextPosition pos; pos = XmTextGetLastPosition (G_error_msgs); XmTextInsert (G_error_msgs, pos, msg); XmTextSetInsertionPosition (G_error_msgs, pos); XmTextShowPosition (G_error_msgs, pos); } /*-------------------------------------------------------------------- * Callback functions *------------------------------------------------------------------*/ /* ARGSUSED */ static void CheckForMap( Widget w, XtPointer client_data, XEvent *event, Boolean *cont) /* set a flag when the main window is mapped */ { if (event->type == MapNotify) is_mapped = True; } static int EventCheck(void) /* process X events until there are no more pending events queued */ { XEvent event; unsigned long pend_result; for (;;) { if (!G_pause_copy) { /* check if there are any X events */ if (!(XtAppPending(app_context) & XtIMXEvent)) { /* maybe more events are "in the pipe" */ XSync(XtDisplay(G_toplevel), False); if (!(XtAppPending(app_context) & XtIMXEvent)) break; } } /* get the next event and process it */ XtAppNextEvent(app_context, &event); XtDispatchEvent(&event); } /* if the user clicked on the Cancel button and Warning 'yes' btn, abort the copy */ if (G_do_copy) return 0; else { return 1; } } static int ErrorHandler(FileOp op, char *fname, int errnum) { char msg[2048]; /* increment the error count */ nerr++; UpdateErrorCount(); /* don't count this file as one that has been copied */ nfiles--; UpdateSummary(); /* add error message to error_msgs */ sprintf(msg, "%s: %s\n", fname, strerror(errnum)); AppendErrorMsg(msg); XmUpdateDisplay(G_toplevel); /* Initialize the error status variable. It will be set if the user */ /* has chosen not to ignore errors */ G_error_status = 0; if (!G_ignore_errors) { create_error_dialog(G_toplevel, LongFileOpNames[op], fname, errnum); G_wait_on_input = TRUE; while (G_wait_on_input) EventCheck(); } return (G_error_status); } static int ConfirmHandler( FileOp op, char *sname, int stype, char *tname, int ttype, char *link) { char msg[1024]; Arg args[5]; Boolean is_overwrite = False; Boolean overwrite_dialog = False; /* was overwrite dialog invoked? */ char *fname; int rc = 0; SyncParams sync; /* update copy counts */ if (op == op_sync) { ndirs++; strcpy(last_dir, sname); UpdateSummary(); } else if (op == op_copy || op == op_cplink || op == op_mklink) { if (ttype != ft_noent) is_overwrite = True; if (!is_overwrite) { nfiles++; UpdateSummary(); } } /* display a message that tells the user what we are working on */ if (op == op_delete || op == op_mkdir) UpdateStatus(LongFileOpNames[op], tname); else UpdateStatus(LongFileOpNames[op], sname); XmUpdateDisplay(G_toplevel); if (is_overwrite) { /* target already exists and would be replaced */ /* if confirmation is turned on, ask the user */ /* set overwrite_dialog so we know if the user was prompted for this file */ /* Otherwise, G_overwrite_selection is either the default or was set */ /* by the user in a prior invocation of the overwrite dialog */ if (G_overwrite_confirm) { overwrite_dialog = TRUE; create_overwrite_dialog (G_toplevel, sname, tname, ttype & ft_isdir); G_wait_on_input = TRUE; while (G_wait_on_input) EventCheck(); } if (G_overwrite_selection != G_SKIP) { nfiles++; UpdateSummary(); XmUpdateDisplay(G_toplevel); } switch (G_overwrite_selection) { case G_OVERWRITE_EXISTING: rc = 0; break; case G_RENAME_EXISTING: /* i.e. move clashing target */ if (!overwrite_dialog) { if (auto_rename(tname) == 0) { touch(tname); /* SyncDirectory complains if the file is gone */ rc = 0; } else { ErrorHandler(op_rename, tname, errno); rc = 1; /* do not do the copy */ } } else { rc = 0; } break; case G_SKIP: rc = 1; break; } } if (app_args.slow) { XFlush(XtDisplay(G_toplevel)); XSync(XtDisplay(G_toplevel), False); sleep(1); } return (rc); } /* * moveDeleteCallback, moveErrorCallback: * called if "-move" option was given, when the * source directory is deleted after a successful copy. */ static int moveDeleteCallback(char *fname) { return ConfirmHandler(op_delete, "", ft_noent, fname, 0, ""); } static int moveErrorCallback(char *fname, int errnum) { return ErrorHandler(op_delete, fname, errnum); } /*-------------------------------------------------------------------- * Get command line arguments *------------------------------------------------------------------*/ static int get_command_line(int argc, char *argv[]) { int i = 1; #define USAGE \ "Usage: %s [options ...] source target\n" /* get source & target directory, if not yet set */ if (app_args.source_name == NULL && i < argc) app_args.source_name = argv[i++]; if (app_args.target_name == NULL && i < argc) app_args.target_name = argv[i++]; /* * There should be no more arguments left, and * source & target directory should be set */ if (i < argc || app_args.source_name == NULL || app_args.target_name == NULL) { fprintf(stderr, GETMESSAGE(2, 10, USAGE), argv[0]); exit(1); } return (0); } /*-------------------------------------------------------------------- * Initialize LongFileOpNames by message catalog. *------------------------------------------------------------------*/ static void InitNlsMessage(void) { int i; char *msg; for (i = 0; i < FILEOPNUM; i++) { msg = GETMESSAGE(2, i + 20, DefaultLongFileOpNames[i]); LongFileOpNames[i] = XtNewString(msg); } } /*-------------------------------------------------------------------- * Main *------------------------------------------------------------------*/ int main(int argc, char *argv[]) { char msg[1024]; XEvent event; Arg args[3]; int rc, n,perm_status=0; char * tmpStr; Boolean copy_status; _DtEnvControl(DT_ENV_SET); XtSetLanguageProc(NULL, NULL, NULL); /* initialize debugging flag */ #ifdef DEBUG if ((tmpStr = getenv("DTFILE_DEBUG")) != NULL) { debug = atoi(tmpStr); if (debug <= 0) debug = 1; } #endif /* Initialize the toolkit and Open the Display */ n=0; XtSetArg (args[n], XmNmappedWhenManaged, FALSE); n++; G_toplevel = XtAppInitialize(&app_context, "Dtfile", /* Dtcopy is considered part of Dtfile */ option_list, XtNumber(option_list), &argc, argv, NULL, args, n); InitNlsMessage(); XtGetApplicationResources(G_toplevel, &app_args, resources, XtNumber(resources), NULL, 0); /* add support for editres debugging tool */ /* XtAddEventHandler(G_toplevel, (EventMask) 0, True, _XEditResCheckMessages, NULL); */ /* Get the source and destination directories */ get_command_line(argc,argv); CheckDeleteAccess(app_context,app_args.delay,app_args.checkPerms, app_args.move,app_args.source_name); G_ignore_errors = !app_args.confirmerrors; G_overwrite_confirm = app_args.confirmreplace; G_move = app_args.move; /* Set resources for the shell */ n = 0; XtSetArg(args[n], XmNallowShellResize, TRUE); n++; if (G_move) { XtSetArg(args[n], XmNtitle, GETMESSAGE(2, 11, "File Manager - Folder Move")); n++; } else { XtSetArg(args[n], XmNtitle, GETMESSAGE(2, 12, "File Manager - Folder Copy")); n++; } XtSetValues(G_toplevel, args, n); /* Initialize images for error, warning, ... icons */ ImageInitialize(XtDisplay(G_toplevel)); /* Create The Copy Directory Dialog */ copy_status = create_copydir_dialog(G_toplevel, app_args.source_name, app_args.target_name); if(copy_status == False) { XtRealizeWidget(G_toplevel); XtAppAddTimeOut(app_context, app_args.delay, TimeoutHandler, NULL); /* wait for user to close the dialog before exiting */ while (!G_dialog_closed) { XtAppNextEvent(app_context, &event); XtDispatchEvent(&event); } exit (-1); } /* initialize status, error count, etc ... */ sensitize_copy_action_area(G_copy_action_area_pbuttons); nfiles = 0; ndirs = -1; /* -1 so the source folder does not get counted, only subfolders */ UpdateSummary(); nerr = 0; UpdateErrorCount(); /* Realize the top level Widget */ XtRealizeWidget(G_toplevel); XtMapWidget(G_toplevel); /* * Wait for the top level Widget to be mapped. * Reason: The routine for selecting a window position for popup windows * (error and overwrite warning dialogs) won't work until the main window * is mapped. Therefore, we don't want to start the actual copy operation * (which might generate error or warning messages) before the main window * is mapped. */ XtAddEventHandler(G_toplevel, StructureNotifyMask, False, CheckForMap, NULL); while (!is_mapped) EventCheck(); XtRemoveEventHandler(G_toplevel, XtAllEvents, True, CheckForMap, NULL); /* Set up the Callbacks for the copy operation */ periodicCallback = EventCheck; syncConfirmCallback = ConfirmHandler; syncErrorCallback = ErrorHandler; /* set up parameters for the copy operation */ app_args.sync.source = app_args.source_name; /* source directory */ app_args.sync.target = app_args.target_name; /* target directory */ app_args.sync.verbose++; strcpy(last_dir, app_args.sync.source); /* * Call the Copy Function. This copy function will look at the * even queue and see if there are any pending events. If so, * it will dispatch these events and then resume the copy * operation. The function will return after the copy operation * has completed or when the user aborts the operation by * clicking the "Cancel" button. */ SyncDirectory(&app_args.sync); /* if move was requested and the copy was successful, delete the source now */ if (G_move) { if (nerr > 0) { sprintf(msg, GETMESSAGE(2, 13, "%s not removed because of errors."), app_args.sync.source); AppendErrorMsg(msg); } else { /* arrange for callback's during recursive directory delete */ progressCallback = moveDeleteCallback; errorCallback = moveErrorCallback; /* delete the source directory */ fsErase(app_args.sync.source, &rc, True); } } /* display the result */ if (G_do_copy) UpdateStatus(GETMESSAGE(2, 14, "Completed."), ""); else UpdateStatus(GETMESSAGE(2, 15, "Cancelled in"), last_dir); XtVaSetValues (G_error_msgs, XmNcursorPosition, 0, XmNtopCharacter, 0, NULL); /* desensitize the copy area */ desensitize_copy_action_area(G_copy_action_area_pbuttons); /* if successful popdown the window after a delay */ if (app_args.popdown && nerr == 0) XtAppAddTimeOut(app_context, app_args.delay, TimeoutHandler, NULL); /* wait for user to close the dialog before exiting */ while (!G_dialog_closed) { XtAppNextEvent(app_context, &event); XtDispatchEvent(&event); } exit(nerr); }