Link with C++ linker
[oweals/cde.git] / cde / programs / dtfile / Command.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: Command.c /main/9 1996/10/30 11:09:42 drk $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  *
27  *   FILE:           Command.c
28  *
29  *   COMPONENT_NAME: Desktop File Manager (dtfile)
30  *
31  *   Description:    Command processing functions used by the File Browser.
32  *
33  *   FUNCTIONS: ActionCallback
34  *              InvalidTrashDragDrop
35  *              ProcessAction
36  *              ProcessBufferDropOnFolder
37  *              ProcessMoveCopyLink
38  *              ProcessNewView
39  *              RunCommand
40  *              TimerEvent
41  *              UpdateActionMenuPane
42  *
43  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
44  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
45  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
46  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
47  *
48  ****************************************************************************
49  ************************************<+>*************************************/
50
51
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <Xm/PushBG.h>
55 #include <Xm/RowColumn.h>
56 #include <Xm/SeparatoG.h>
57 #include <Xm/XmP.h>
58 #include <X11/Shell.h>
59 #include <X11/Intrinsic.h>
60
61 #include <Dt/Action.h>
62 #include <Dt/ActionP.h>
63 #include <Dt/Connect.h>
64 #include <Dt/DtNlUtils.h>
65 #include <Dt/HourGlass.h>
66 #include <Dt/Dnd.h>
67
68 #include "Encaps.h"
69 #include "SharedProcs.h"
70 #include "FileMgr.h"
71 #include "Desktop.h"
72 #include "Main.h"
73 #include "Help.h"
74 #include "SharedMsgs.h"
75 #include "Prefs.h"
76
77 /********    Static Function Declarations    ********/
78
79 static void ActionCallback( Widget w,
80                             XtPointer client_data,
81                             XtPointer call_data) ;
82 static void TimerEvent(
83                         Widget widget,
84                         XtIntervalId *id) ;
85 void ProcessBufferDropOnFolder (
86                                 char *command,
87                                 FileMgrData *file_mgr_data,
88                                 FileViewData *file_view_data,
89                                 DtDndDropCallbackStruct *drop_parameters,
90                                 Widget drop_window);
91
92
93 /********    End Static Function Declarations    ********/
94
95 extern int G_dropx,G_dropy;
96
97 /************************************************************************
98  *
99  *  UpdateActionMenuPane
100  *      Build up a set of menu panes for the provided file manager rec
101  *      that contains as items each of the commands for each file type.
102  *
103  ************************************************************************/
104
105 void
106 UpdateActionMenuPane(
107         XtPointer client_data,
108         FileMgrRec *file_mgr_rec,
109         char *file_type,
110         int type,
111         int number,
112         Widget widget,
113         unsigned char physical_type)
114 {
115    XmManagerWidget action_pane;
116    FileMgrData *file_mgr_data = NULL;
117    DialogData * dialog_data;
118    FileViewData *file_view_data;
119    DesktopRec *desktopWindow;
120    Widget child;
121    register int i, menu_offset;
122    register int action_count;
123    int count, del_count;
124    int num_children;
125    char ** command_list;
126    XmString string;
127    char *action_label;
128
129    Arg args[2];
130
131
132    if(type == DESKTOP)
133       desktopWindow = (DesktopRec *)client_data;
134    else if(type == FM_POPUP)
135       file_view_data = (FileViewData *)client_data;
136
137    if (file_mgr_rec)
138    {
139       dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
140       file_mgr_data = (FileMgrData *) dialog_data->data;
141    }
142
143    /*  Count the number of actions defined for the the file type  */
144
145    action_count = 0;
146    command_list = _DtCompileActionVector(file_type);
147
148    if(command_list != NULL)
149       while (command_list[action_count] != NULL &&
150                                     strlen (command_list[action_count]) != 0)
151          action_count++;
152
153    if (physical_type == DtDIRECTORY && type == DESKTOP)
154        ++action_count;
155
156
157    /*  If the menu pane is already set up for the file type then return.  */
158
159    if(type == NOT_DESKTOP)
160    {
161       XtFree(file_mgr_rec->action_pane_file_type);
162       file_mgr_rec->action_pane_file_type = XtNewString(file_type);
163
164       action_pane = (XmManagerWidget) file_mgr_rec->action_pane;
165       menu_offset = number + SELECTED_MENU_MAX;
166    }
167    else
168    {
169       action_pane = (XmManagerWidget) widget;
170       menu_offset = number;
171    }
172
173    num_children = action_pane->composite.num_children;
174
175    /*
176     * This is so that we can determine which icon was responsible for
177     * posting the menu, or requesting help.
178     */
179    if (type == FM_POPUP)
180       file_mgr_data->popup_menu_icon = file_view_data;
181 /*
182    else if (file_mgr_data)
183       file_mgr_data->popup_menu_icon = NULL;
184 */
185
186    if (action_count + menu_offset > num_children)
187    {
188       if(type == FM_POPUP)
189          for (i = number; i < num_children; i++)
190             XtManageChild (action_pane->composite.children[i]);
191       for (i = num_children; i < action_count + menu_offset; i++)
192       {
193          child = XmCreatePushButtonGadget ((Widget)action_pane,
194                                             "action_button", args, 0);
195          if(type == DESKTOP)
196          {
197             XtAddCallback (child, XmNactivateCallback, DTActionCallback,
198                                                     (XtPointer)desktopWindow);
199             XtAddCallback(child, XmNhelpCallback,
200                           (XtCallbackProc)DTHelpRequestCB, NULL);
201          }
202          else if(type == FM_POPUP)
203          {
204             XtAddCallback (child, XmNactivateCallback, ActionCallback, NULL);
205             XtAddCallback(child, XmNhelpCallback,
206                           (XtCallbackProc)HelpRequestCB, NULL);
207          }
208          else
209          {
210             XtAddCallback (child, XmNactivateCallback, ActionCallback,
211                                                     (XtPointer)file_mgr_rec);
212             XtAddCallback(child, XmNhelpCallback,
213                           (XtCallbackProc)HelpRequestCB, NULL);
214          }
215          XtManageChild (child);
216       }
217    }
218    else
219    {
220      for (i = menu_offset; i < num_children; i++)
221      {
222        if (i < action_count + menu_offset)
223        {
224           XtRemoveAllCallbacks(action_pane->composite.children[i],
225                                                    XmNactivateCallback);
226           if(type == DESKTOP)
227              XtAddCallback (action_pane->composite.children[i],
228                                      XmNactivateCallback, DTActionCallback,
229                                      (XtPointer)desktopWindow);
230           else if(type == FM_POPUP)
231              XtAddCallback (action_pane->composite.children[i],
232                                   XmNactivateCallback, ActionCallback, NULL);
233           else
234              XtAddCallback (action_pane->composite.children[i],
235                                         XmNactivateCallback, ActionCallback,
236                                         (XtPointer)file_mgr_rec);
237           XtManageChild (action_pane->composite.children[i]);
238         }
239         else
240           XtUnmanageChild (action_pane->composite.children[i]);
241      }
242    }
243
244    /*  For each action, set the label of the menu button  */
245    /*  and the user data.                                 */
246
247    num_children =  menu_offset + action_count;
248    del_count = 0;
249    for (i = 0; i < action_count; i++)
250    {
251       char *oldCommand;
252       Arg argsTmp[2];
253
254       if(type != DESKTOP)
255       {
256          char* strp;
257
258          strp = XtNewString(command_list[i]);
259          XtSetArg (args[1], XmNuserData, strp);
260
261          action_label = DtActionLabel(command_list[i]);
262
263          if(action_label != NULL)
264              string = XmStringCreateLocalized(action_label);
265          else
266              string = XmStringCreateLocalized(command_list[i]);
267
268          count = i + menu_offset;
269       }
270       else
271       {
272          if (physical_type == DtDIRECTORY && i == 0)
273          {
274             if((action_label = DtActionLabel(openNewView)) != NULL)
275                 string = XmStringCreateLocalized(action_label);
276             else
277                 string = XmStringCreateLocalized(openNewView);
278             XtSetArg (args[1], XmNuserData, openNewView);
279             count = i + number;
280          }
281          else
282          {
283             if (physical_type == DtDIRECTORY)
284             {
285                if(strcmp(command_list[i - 1], openNewView) == 0  ||
286                   strcmp(command_list[i - 1], openInPlace) == 0)
287                {
288                   del_count++;
289                   XtUnmanageChild (action_pane->composite.children[
290                                               num_children - del_count]);
291                   continue;
292                }
293                action_label = DtActionLabel(command_list[i - 1]);
294
295                if(action_label != NULL)
296                    string = XmStringCreateLocalized(action_label);
297                else
298                    string = XmStringCreateLocalized(command_list[i-1]);
299
300                XtSetArg (args[1], XmNuserData, XtNewString
301                                                  (command_list[i - 1]));
302                count = i + number - del_count;
303             }
304             else
305             {
306                action_label = DtActionLabel(command_list[i]);
307
308                if(action_label != NULL)
309                    string = XmStringCreateLocalized(action_label);
310                else
311                    string = XmStringCreateLocalized(command_list[i]);
312
313                XtSetArg (args[1], XmNuserData, XtNewString(command_list[i]));
314                count = i + number;
315             }
316          }
317       }
318
319       /* first we need to get the userData from the push button and
320          free it up */
321       XtSetArg (argsTmp[0], XmNuserData, &oldCommand);
322       XtGetValues (action_pane->composite.children[count], argsTmp, 1);
323
324       if(oldCommand != NULL && strcmp(oldCommand, openNewView) != 0)
325          XtFree(oldCommand);
326
327
328       XtSetArg (args[0], XmNlabelString, string);
329       XtSetValues (action_pane->composite.children[count], args, 2);
330       if(type != NOT_DESKTOP)
331       {
332          XtRemoveAllCallbacks(action_pane->composite.children[count],
333                                                    XmNactivateCallback);
334
335          if(type == DESKTOP)
336          {
337             XtAddCallback (action_pane->composite.children[count],
338                            XmNactivateCallback, DTActionCallback,
339                            (XtPointer)desktopWindow);
340          }
341          else
342             XtAddCallback (action_pane->composite.children[count],
343                            XmNactivateCallback, ActionCallback,
344                            (XtPointer)NULL);
345       }
346       XmStringFree (string);
347       XtFree(action_label);
348    }
349
350    _DtFreeStringVector(command_list);
351 }
352
353
354
355
356 /************************************************************************
357  *
358  *  ActionCallback
359  *      Callback function invoked upon the an actions menu button
360  *      being selected.
361  *
362  ************************************************************************/
363
364 static void
365 ActionCallback(
366         Widget w,
367         XtPointer client_data,
368         XtPointer call_data )
369 {
370    FileMgrRec   * file_mgr_rec;
371    DialogData   * dialog_data;
372    FileMgrData  * file_mgr_data;
373    FileViewData  * file_view_data;
374    char * command;
375    Arg args[1];
376    Widget mbar;
377    Boolean popup = False;
378    XmAnyCallbackStruct * callback;
379
380
381    XmUpdateDisplay (w);
382    mbar = XtParent(w);
383
384    callback = (XmAnyCallbackStruct *) call_data;
385    if(client_data == NULL)
386    {
387       popup = True;
388       XtSetArg(args[0], XmNuserData, &file_mgr_rec);
389       XtGetValues(mbar, args, 1);
390       dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
391       file_mgr_data = (FileMgrData *) dialog_data->data;
392       file_view_data = file_mgr_data->popup_menu_icon;
393       if(!file_view_data) /* The object would have probably been delete */
394          return;
395       file_mgr_data->popup_menu_icon = NULL;  /* Just to make it unuseful */
396    }
397    else
398    {
399       file_mgr_rec = (FileMgrRec *) client_data;
400       dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec);
401       file_mgr_data = (FileMgrData *) dialog_data->data;
402    }
403
404
405
406    /*  Find the file data for the file that is selected  */
407
408    XtSetArg (args[0], XmNuserData, (XtPointer) &command);
409    XtGetValues (w, args, 1);
410
411    if(strcmp(command, openNewView) == 0)
412    {
413       XButtonEvent *event = (XButtonEvent *)callback->event;
414       unsigned int modifiers;
415
416       modifiers = event->state;
417       if(popup)
418          RunCommand (command, file_mgr_data, file_view_data, NULL, NULL, NULL);
419       else
420          RunCommand (command, file_mgr_data, file_mgr_data->selection_list[0],
421                      NULL, NULL, NULL);
422
423       if((modifiers != 0) && ((modifiers & ControlMask) != 0))
424       {
425          DialogData  *dialog_data;
426
427          dialog_data = _DtGetInstanceData(file_mgr_data->file_mgr_rec);
428          CloseView(dialog_data);
429       }
430    }
431    else
432    {
433       if(popup)
434          RunCommand (command, file_mgr_data, file_view_data, NULL, NULL, NULL);
435       else
436          RunCommand (command, file_mgr_data, file_mgr_data->selection_list[0],
437                      NULL, NULL, NULL);
438    }
439 }
440
441
442 /************************************************************************
443  *
444  *  RunCommand
445  *
446  *    WARNING: when desktop links are passed in, this function will NOT
447  *             expect the links to have already been mapped to their
448  *             real files.
449  *
450  ************************************************************************/
451
452 void
453 RunCommand(
454         char *command,
455         FileMgrData *file_mgr_data,
456         FileViewData *file_view_data,
457         WindowPosition *position,
458         DtDndDropCallbackStruct *drop_parameters,
459         Widget drop_window )
460
461 {
462    if ((strcmp (command, openInPlace) == 0) ||
463        (strcmp (command, openNewView) == 0))
464    {
465       /* If the folder is locked, don't allow user to go into it */
466       if( strcmp( file_view_data->file_data->logical_type, LT_FOLDER_LOCK ) == 0 )
467       {
468         char *tmpStr, *title, *msg;
469
470         tmpStr = GETMESSAGE(9, 6, "Action Error");
471         title = XtNewString(tmpStr);
472         msg = (char *)XtMalloc(
473                    strlen( GETMESSAGE(30, 1, "Cannot read from %s") )
474                  + strlen( file_view_data->file_data->file_name )
475                  + 1 );
476         sprintf( msg, GETMESSAGE(30, 1, "Cannot read from %s"),
477                  file_view_data->file_data->file_name );
478         _DtMessage(((FileMgrRec*)file_mgr_data->file_mgr_rec)->file_window,
479                    title, msg, NULL, HelpRequestCB );
480         XtFree(title);
481         XtFree(msg);
482         return;
483       }
484
485       /* this statement applies to the case where a user traverses down the *
486        * part of the directory tree containing the application manager      *
487        * directories or the trash directory                                 */
488       if( ((strcmp(file_view_data->file_data->logical_type, LT_AGROUP) == 0) &&
489            (!(file_mgr_data->toolbox)))
490           ||
491           (strcmp(file_view_data->file_data->logical_type, LT_TRASH) == 0) )
492       {
493          ProcessAction(command,
494                        file_view_data,
495                        drop_parameters,
496                        file_mgr_data->host,
497                        file_mgr_data->current_directory,
498                        file_mgr_data->restricted_directory,
499                        ((FileMgrRec *) file_mgr_data->file_mgr_rec)->shell);
500       }
501       else
502       {
503          ProcessNewView(command, file_mgr_data, file_view_data, position);
504       }
505    }
506
507    else if ((strcmp (command, "FILESYSTEM_MOVE") == 0) ||
508             (strcmp (command, "FILESYSTEM_COPY") == 0) ||
509             (strcmp (command, "FILESYSTEM_LINK") == 0))
510    {
511       /* Check to see what was dropped (files or buffers) */
512       /* Call the appropriate routine to handle the drop  */
513       if (drop_parameters->dropData->protocol == DtDND_FILENAME_TRANSFER)
514          ProcessMoveCopyLink(command,
515                              file_mgr_data,
516                              file_view_data,
517                              drop_parameters,
518                              drop_window);
519       else
520          if (drop_parameters->dropData->protocol == DtDND_BUFFER_TRANSFER)
521            ProcessBufferDropOnFolder(command,
522                                      file_mgr_data,
523                                      file_view_data,
524                                      drop_parameters,
525                                      drop_window);
526
527    }
528
529    else
530    {
531       ProcessAction(command,
532                     file_view_data,
533                     drop_parameters,
534                     file_mgr_data->host,
535                     file_mgr_data->current_directory,
536                     file_mgr_data->restricted_directory,
537                     ((FileMgrRec *) file_mgr_data->file_mgr_rec)->shell);
538    }
539 }
540
541
542 /************************************************************************
543  *
544  *  ProcessNewView
545  *
546  ************************************************************************/
547
548 void
549 ProcessNewView (
550      char *command,
551      FileMgrData *file_mgr_data,
552      FileViewData *file_view_data,
553      WindowPosition *position)
554 {
555    DirectorySet * directory_set;
556    char host_name[MAX_PATH];
557    char directory_name[MAX_PATH];
558    char *tmpStr, *title, *msg;
559
560    /* we don't want to execute the default action if in trash ...  */
561    if( trashFileMgrData != NULL
562        && file_mgr_data == trashFileMgrData)
563    {
564       tmpStr = GETMESSAGE(27, 3, "Trash Can Error");
565       title = XtNewString(tmpStr);
566       tmpStr = GETMESSAGE(27, 87, "Object in the Trash cannot be opened.\n\nTo open an object use 'Put Back' to return it to the\nFile Manager then open it there.");
567       msg = XtNewString(tmpStr);
568
569       _DtMessage( ((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window,
570                   title, msg, NULL, HelpRequestCB);
571       XtFree(title);
572       XtFree(msg);
573       return;
574    }
575
576    strcpy (host_name, file_mgr_data->host);
577
578    directory_set = (DirectorySet *) (file_view_data->directory_set);
579    strcpy (directory_name, directory_set->name);
580
581    if (strcmp (directory_name, "/") != 0)
582       strcat (directory_name, "/");
583
584    strcat (directory_name, file_view_data->file_data->file_name);
585    DtEliminateDots (directory_name);
586
587    if (strcmp (directory_name, "/..") == 0)
588       strcpy (directory_name, "/");
589
590    if (strcmp (command, openInPlace) == 0)
591    {
592       FileMgrRec *file_mgr_rec;
593       Arg args[1];
594       Widget vb;
595       int value, size, increment, page;
596
597       file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
598       ShowNewDirectory (file_mgr_data, host_name, directory_name);
599
600       XtSetArg (args[0], XmNverticalScrollBar, &vb);
601       XtGetValues (file_mgr_rec->scroll_window, args, 1);
602
603          /* get scroll bar values */
604       (void)XmScrollBarGetValues(vb, &value, &size, &increment, &page);
605
606          /* set scroll bar values changing its position */
607       if(value != 0)
608         (void)XmScrollBarSetValues(vb, (int)0, size, increment, page, True);
609
610       if(strcmp(file_mgr_data->current_directory,
611                 file_mgr_data->restricted_directory) == 0)
612       {
613          XtSetSensitive(*upBarBtn, False);
614          currentMenuStates &= ~(MOVE_UP);
615          file_mgr_rec->menuStates &= ~(MOVE_UP);
616       }
617       else
618       {
619          file_mgr_rec->menuStates |= MOVE_UP;
620          XtSetSensitive(*upBarBtn, True);
621          currentMenuStates &= ~(MOVE_UP);
622       }
623    }
624    else
625    {
626       initiating_view = (XtPointer) file_mgr_data;
627       if(file_mgr_data->restricted_directory == NULL)
628       {
629          GetNewView (host_name, directory_name, NULL, position, 0);
630       }
631       else
632       {
633          special_view = True;
634          special_treeType = file_mgr_data->show_type;
635          special_viewType = file_mgr_data->view;
636          special_orderType = file_mgr_data->order;
637          special_directionType = file_mgr_data->direction;
638          special_randomType = file_mgr_data->positionEnabled;
639          special_restricted =
640             XtNewString(file_mgr_data->restricted_directory);
641          if(file_mgr_data->title == NULL)
642             special_title = NULL;
643          else
644             special_title = XtNewString(file_mgr_data->title);
645          special_helpVol = XtNewString(file_mgr_data->helpVol);
646          if(file_mgr_data->toolbox)
647             GetNewView (file_mgr_data->host, directory_name,
648                         file_mgr_data->restricted_directory, position, 0);
649          else
650             GetNewView (file_mgr_data->host, directory_name, NULL, position, 0);
651       }
652
653       initiating_view = (XtPointer) NULL;
654    }
655 }
656
657
658 /************************************************************************
659  *
660  *  ProcessMoveCopyLink
661  *
662  ************************************************************************/
663
664 void
665 ProcessMoveCopyLink (
666      char *command,
667      FileMgrData *file_mgr_data,
668      FileViewData *file_view_data,
669      DtDndDropCallbackStruct *drop_parameters,
670      Widget drop_window)
671
672 {
673    unsigned int modifiers = NULL;
674    int numFiles, i;
675    char ** file_set = NULL;
676    char ** host_set = NULL;
677    Boolean trashFile;
678
679
680      /***************************************************/
681      /* if no drop_parameters, there is nothing to move */
682      /***************************************************/
683    if (!drop_parameters)
684      return;
685
686
687      /**************************/
688      /* are these trash files? */
689      /**************************/
690    trashFile = FileFromTrash(drop_parameters->dropData->data.files[0]);
691
692
693      /***********************************************/
694      /* if trying to copy or link from trash return */
695      /***********************************************/
696    if (trashFile)
697    {
698      if (file_mgr_data != trashFileMgrData)
699         if (InvalidTrashDragDrop(drop_parameters->operation,
700               FROM_TRASH,
701               ((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window))
702            return;
703    }
704
705
706      /***************************************************/
707      /* extract file and host sets from drop parameters */
708      /***************************************************/
709    numFiles = drop_parameters->dropData->numItems;
710    _DtSetDroppedFileInfo(drop_parameters, &file_set, &host_set);
711
712
713       /******************************/
714       /* set movement modifier mask */
715       /******************************/
716    if( (initiating_view != NULL) &&
717        (((FileMgrData *)initiating_view)->toolbox) )
718    {
719       /* if initiating_view is a toolbox, the transfer must be */
720       /* a copy                                                */
721       modifiers = ControlMask;
722    }
723    else
724    {
725       if (strcmp(command, "FILESYSTEM_COPY") == 0)
726          modifiers = ControlMask;
727       else if (strcmp(command, "FILESYSTEM_LINK") == 0)
728          modifiers = ShiftMask;
729       else
730          modifiers = NULL;
731    }
732
733
734       /*****************************/
735       /* Files dropped on a window */
736       /*****************************/
737    if (drop_window)
738    {
739         /****************************************************************/
740         /* Files dropped in the trash -- move files  to trash directory */
741         /****************************************************************/
742       if(file_mgr_data == trashFileMgrData && !trashFile)
743       {
744          DPRINTF(("DropOnFileWindow:Dragging File(s) to Trash Can from NonTrash Window\n"));
745
746          DropOnTrashCan(numFiles, host_set, file_set, drop_parameters);
747       }
748
749         /****************************************************************/
750         /* Files dragged in the trash -- do nothing                     */
751         /****************************************************************/
752       else if(file_mgr_data == trashFileMgrData && trashFile)
753       {
754          DPRINTF(("DropOnFileWindow: Drag from Within Trash Can\n"));
755       }
756
757         /****************************************************************/
758         /* Files dragged from the trash -- move the files to their new  */
759         /* location                                                     */
760         /****************************************************************/
761       else if(trashFile && file_mgr_data != trashFileMgrData)
762       {
763          DPRINTF(("DropOnFileWindow: Dragging from Trash to Folder Window\n"));
764
765          MoveOutOfTrashCan(file_mgr_data,
766                            (FileMgrRec *)file_mgr_data->file_mgr_rec,
767                            XtWindow(drop_window),  numFiles, host_set,
768                            file_set, drop_parameters->x, drop_parameters->y);
769       }
770
771
772         /****************************************************************/
773         /* Files dropped on a non-trash window -- move files to new     */
774         /* location.                                                    */
775         /*                                                              */
776         /* Droppable windows must be handled like the desktop; i.e.     */
777         /* positioning is supported.                                    */
778         /****************************************************************/
779       else
780       {
781          FileMgrRec *file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec;
782
783 /*
784          if ((file_mgr_data->show_type == SINGLE_DIRECTORY) &&
785              (file_mgr_data->view != BY_ATTRIBUTES))
786 */
787          {
788             if (file_mgr_data == (FileMgrData *) initiating_view)
789             {
790                DPRINTF(("DropOnFileWindow: Dragging and Dropping File within same window\n"));
791
792                   /* Simple reposition in the same window */
793                XmDropSiteStartUpdate(file_mgr_rec->file_window);
794                RepositionIcons(file_mgr_data,
795                                file_set,
796                                numFiles,
797                                drop_parameters->x, drop_parameters->y,
798                                False);
799                LayoutFileIcons(file_mgr_rec, file_mgr_data, False, True);
800                XmDropSiteEndUpdate(file_mgr_rec->file_window);
801             }
802             else
803             {
804                DPRINTF (("DropOnFileWindow: Dragging file(s) and dropping from other folders\n"));
805
806                CheckMoveType(file_mgr_data, (FileViewData *)NULL,
807                              (DirectorySet *)NULL, (DesktopRec *)NULL,
808                              file_set, host_set, modifiers,
809                              numFiles,
810                              drop_parameters->x, drop_parameters->y,
811                              NOT_DESKTOP);
812             }
813          }
814 /*
815          else
816          {
817             DPRINTF(("DropOnFileWindow: Not Single Directory View\n"));
818
819             if (FileMoveCopy (file_mgr_data,
820                               NULL, file_mgr_data->current_directory, file_mgr_data->host,
821                               host_set, file_set, numFiles,
822                               modifiers, NULL, NULL))
823             {
824                DirectorySet * directory_data;
825                char * directory_name;
826                FileViewData * file_view_data;
827                int j;
828
829                DeselectAllFiles (file_mgr_data);
830
831                directory_data = file_mgr_data->directory_set[0];
832                for (i = 0; i < numFiles; i++)
833                {
834                   directory_name = DName (file_set[i]);
835                   for (j = 0; j < directory_data->file_count; j++)
836                   {
837                      file_view_data = directory_data->file_view_data[j];
838                      if ( (file_view_data->filtered != True) &&
839                           (strcmp(directory_name,
840                                   file_view_data->file_data->file_name) == 0) )
841                      {
842                         SelectFile (file_mgr_data, file_view_data);
843                         break;
844                      }
845                   }
846                }
847
848                PositionFileView(file_view_data, file_mgr_data);
849             }
850          }
851 */
852
853          if (file_mgr_data->selected_file_count == 0)
854             ActivateNoSelect (file_mgr_rec);
855          else if (file_mgr_data->selected_file_count == 1)
856             ActivateSingleSelect
857                (file_mgr_rec,
858                 file_mgr_data->selection_list[0]->file_data->logical_type);
859          else
860             ActivateMultipleSelect (file_mgr_rec);
861       }
862    }
863
864       /*****************************/
865       /* Files dropped on an icon  */
866       /*****************************/
867    else
868    {
869       CheckMoveType(file_mgr_data, file_view_data,
870                     (DirectorySet *) file_view_data->directory_set,
871                     (DesktopRec *)NULL,
872                     file_set, host_set, modifiers,
873                     numFiles, drop_parameters->x, drop_parameters->y,
874                     NOT_DESKTOP_DIR);
875    }
876
877       /***************************/
878       /* free file and host sets */
879       /***************************/
880    _DtFreeDroppedFileInfo(numFiles, file_set, host_set);
881
882 }
883
884 /************************************************************************
885  *
886  * ProcessBufferDropOnFolder
887  *
888  ************************************************************************/
889
890 void
891 ProcessBufferDropOnFolder (
892      char *command,
893      FileMgrData *file_mgr_data,
894      FileViewData *file_view_data,
895      DtDndDropCallbackStruct *drop_parameters,
896      Widget drop_window)
897
898 {
899    unsigned int modifiers = NULL;
900    int num_of_buffers, i;
901    char ** file_set = NULL;
902    char ** host_set = NULL;
903    BufferInfo *buffer_set = NULL;
904    char  directory[MAX_PATH];
905
906
907
908
909    /***************************************************/
910    /* if no drop_parameters, or invalid params        */
911    /* then disallow the drop                          */
912    /***************************************************/
913    if (!drop_parameters)
914      return;
915
916    /* if dropped on file window and file_mgr_data is null */
917    if (drop_window && (file_mgr_data == NULL))
918      return;
919
920    /* if dropped on a folder icon and file_view_data */
921    /* is NULL, disallow the drop                     */
922    if (!drop_window && (file_view_data == NULL))
923      return;
924
925
926
927
928
929   /****************************************************/
930   /* extract file and host sets from drop parameters  */
931   /* @@@...need to check with Linda about how host_set*/
932   /* is being handled                                 */
933   /****************************************************/
934
935    num_of_buffers = drop_parameters->dropData->numItems;
936
937    /* Allocate memory for file and buffer structures */
938    file_set = (char **)XtMalloc(sizeof(char **) * num_of_buffers );
939    host_set = (char **)XtMalloc(sizeof(char **) * num_of_buffers);
940    buffer_set = (BufferInfo * )XtMalloc (sizeof (BufferInfo) * num_of_buffers);
941
942
943    _DtSetDroppedBufferInfo(file_set, buffer_set, host_set, drop_parameters);
944
945
946
947
948   /*****************************************************/
949   /* If buffers were dropped on the window, determine  */
950   /* which MODE (AS PLACED, GRID, TREE VIEW) and call  */
951   /* the appropriate routines to handle the creation   */
952   /* of the buffers into files. Assuming dropping      */
953   /* on non-trash windows.                             */
954   /*****************************************************/
955
956   if (drop_window)
957   {
958
959     /* Single directory view */
960     if ((file_mgr_data->show_type == SINGLE_DIRECTORY ) &&
961         (file_mgr_data->view != BY_ATTRIBUTES))
962
963     {
964
965       DPRINTF (("ProcessDropOnBufferFolder: Dropping buffers on single directory view: %s\n", file_mgr_data->current_directory));
966
967       G_dropx = drop_parameters->x;
968       G_dropy = drop_parameters->y;
969
970       /* Reposition Icons if in in "AS PLACED" Mode */
971       if (file_mgr_data -> positionEnabled == RANDOM_ON)
972       {
973 /*
974         RepositionIcons (file_mgr_data,
975                          file_set,
976                          num_of_buffers,
977                          drop_parameters->x, drop_parameters->y,
978                          True);
979 */
980       }
981
982       /* Call MakeFileFromBuffer */
983       MakeFilesFromBuffers(file_mgr_data, file_mgr_data->current_directory,
984                            file_mgr_data->host, file_set,
985                            host_set, buffer_set, num_of_buffers,
986                            NULL, NULL);
987
988     }
989     else
990     {
991       DPRINTF (("ProcessDropOnBufferFolder: Dropping buffers in Tree View\n"));
992
993       MakeFilesFromBuffers(file_mgr_data, file_mgr_data->current_directory,
994                            file_mgr_data->host, file_set,
995                            host_set, buffer_set, num_of_buffers,
996                            NULL, NULL);
997
998       /* Do Tree View Stuff      */
999       {
1000          DirectorySet * directory_data;
1001          char * directory_name;
1002          FileViewData * file_view_data;
1003          int j;
1004
1005          DeselectAllFiles (file_mgr_data);
1006
1007          directory_data = file_mgr_data->directory_set[0];
1008          for (i = 0; i < num_of_buffers; i++)
1009          {
1010             directory_name = DName (file_set[i]);
1011             for (j = 0; j < directory_data->file_count; j++)
1012             {
1013                file_view_data = directory_data->file_view_data[j];
1014                if ( (file_view_data->filtered != True) &&
1015                      (strcmp(directory_name,
1016                      file_view_data->file_data->file_name) == 0) )
1017                {
1018                   SelectFile (file_mgr_data, file_view_data);
1019                   break;
1020                }
1021             }
1022          }
1023          PositionFileView(file_view_data, file_mgr_data);
1024       }
1025    } /* endif for Tree View */
1026
1027   } /* endif drop buffers on window */
1028   else
1029   {
1030     /* Buffers were dropped on a Folder icon */
1031     /* Call MakeFileFromBuffer */
1032
1033
1034     DPRINTF(("ProcessBufferDropOnFolder...Buffers dropped on Folder icon %s\n",
1035              file_view_data ->file_data -> file_name));
1036
1037     if (file_mgr_data->show_type != SINGLE_DIRECTORY &&
1038         file_mgr_data->tree_root == file_view_data)
1039     {
1040         /* dropped on the top level folder in the tree view */
1041         sprintf (directory,"%s",file_mgr_data->current_directory);
1042     }
1043     else
1044         sprintf (directory,"%s/%s",file_mgr_data->current_directory,
1045                  file_view_data->file_data->file_name);
1046     DtEliminateDots(directory);
1047
1048     DPRINTF (("Copying buffer to %s\n", directory));
1049     MakeFilesFromBuffers(file_mgr_data, directory,
1050                          file_mgr_data->host, file_set,
1051                          host_set, buffer_set, num_of_buffers,
1052                          NULL, NULL);
1053
1054   }
1055
1056
1057   /***********************************/
1058   /* free file_set + buffer_set      */
1059   /***********************************/
1060   _DtFreeDroppedBufferInfo (file_set, buffer_set, host_set, num_of_buffers);
1061
1062
1063 }
1064
1065
1066 /************************************************************************
1067  *
1068  *  InvalidTrashDragDrop
1069  *
1070  ************************************************************************/
1071
1072 Boolean
1073 InvalidTrashDragDrop (
1074      int drag_op,
1075      int trash_context,
1076      Widget w)
1077 {
1078    Boolean rc = False;
1079
1080    if ( (drag_op == XmDROP_COPY) ||
1081         (drag_op == XmDROP_LINK) )
1082    {
1083       char *tmpStr, *title, *msg;
1084
1085       tmpStr = GETMESSAGE(18, 22, "Drag Error");
1086       title = XtNewString(tmpStr);
1087
1088       switch(trash_context)
1089       {
1090          case TO_TRASH:
1091          case WITHIN_TRASH:
1092             tmpStr = (GETMESSAGE(18,36, "You can't copy or link a file or folder out of the Trash Can.\nMove the object out of the Trash and put it into the File Manager.\nYou can then copy or link it from there."));
1093             break;
1094          case FROM_TRASH:
1095             tmpStr = (GETMESSAGE(18,37, "You can't copy or link a file or folder out of the Trash Can.\nMove the object out of the Trash and put it into the File Manager.\nYou can then copy or link it from there."));
1096             break;
1097          default:
1098             tmpStr = NULL;
1099             break;
1100       }
1101
1102       if (tmpStr)
1103       {
1104          msg = XtNewString(tmpStr);
1105          _DtMessage (w, title, msg, NULL, HelpRequestCB);
1106          XtFree(msg);
1107       }
1108
1109       XtFree(title);
1110
1111       rc = True;
1112    }
1113
1114    return(rc);
1115 }
1116
1117
1118 /************************************************************************
1119  *
1120  *  ProcessAction
1121  *
1122  ************************************************************************/
1123
1124 void
1125 ProcessAction (
1126      char *action,
1127      FileViewData *file_view_data,
1128      DtDndDropCallbackStruct *drop_parameters,
1129      char *cur_host,
1130      char *cur_dir,
1131      char *restricted_dir,
1132      Widget w)
1133
1134 {
1135    FileViewData *first_arg = NULL;
1136    DtActionArg * action_args = NULL;
1137    int arg_count = 0;
1138    char * pwd_host = NULL;
1139    char * pwd_dir = NULL;
1140    DirectorySet *directory_set;
1141    FileMgrData *file_mgr_data;
1142
1143    /* We don't want to execute the default action if in trash ...  */
1144    directory_set = (DirectorySet *) file_view_data->directory_set;
1145    file_mgr_data = (FileMgrData *) directory_set->file_mgr_data;
1146    if( trashFileMgrData != NULL
1147        && file_mgr_data == trashFileMgrData)
1148    {
1149       char *tmpStr, *title, *msg;
1150
1151       /* we don't want to execute the default action if in trash ...  */
1152       tmpStr = GETMESSAGE(27, 3, "Trash Can Error");
1153       title = XtNewString(tmpStr);
1154       tmpStr = GETMESSAGE(27, 105, "Default action of a trash object will not be executed.\n\nTo execute the default action of this object\n use 'Put Back' to return it to the File Manager\nthen execute it there.");
1155       msg = XtNewString(tmpStr);
1156
1157       _DtMessage(((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window,
1158                  title, msg, NULL, HelpRequestCB);
1159       XtFree(title);
1160       XtFree(msg);
1161       return;
1162    }
1163
1164    /* Build action arguments:
1165     *   First, test for redundant action information --
1166     *   file_view_data contains information for the object that the user
1167     *       a) dropped files on
1168     *       b) activated a popup menu over (note that the Actions piece
1169     *          of both the Selected and popup menus is only active when
1170     *          a single file is selected; therefore, this function doesn't
1171     *          deal with cases where multiple files are selected and a
1172     *          popup menu is activated
1173     *       c) doubled-clicked
1174     *
1175     *   If file_view_data contains information for the action that we
1176     *   are processing, then this information is not included as an
1177     *   argument to DtActionInvoke; otherwise, the information is
1178     *   included as the first argument to DtActionInvoke.
1179     */
1180    if ( !DtDtsDataTypeIsAction(file_view_data->file_data->logical_type) ||
1181         (strcmp(action, file_view_data->file_data->logical_type) != 0) ||
1182         (strcmp(action, file_view_data->file_data->file_name)    != 0) )
1183       first_arg = file_view_data;
1184
1185    if (drop_parameters)
1186    {
1187       if (drop_parameters->dropData->protocol == DtDND_FILENAME_TRANSFER)
1188          _DtBuildActionArgsWithDroppedFiles(first_arg, drop_parameters,
1189                                             &action_args, &arg_count);
1190       else
1191          _DtBuildActionArgsWithDroppedBuffers(first_arg, drop_parameters,
1192                                               &action_args, &arg_count);
1193    }
1194    else
1195    {
1196       if (first_arg)
1197          _DtBuildActionArgsWithSelectedFiles(&first_arg, 1,
1198                                              &action_args, &arg_count);
1199    }
1200
1201
1202    /* Retrieve context dir for action -- in the case of toolboxes, the
1203       root toolbox */
1204    SetPWD(cur_host, cur_dir, &pwd_host, &pwd_dir, restricted_dir);
1205
1206
1207    /* Turn on hour glass */
1208    _DtTurnOnHourGlass(w);
1209
1210
1211    /* Invoke action */
1212    DtActionInvoke(w, action, action_args, arg_count,
1213                   NULL, NULL, pwd_dir, True, NULL, NULL);
1214
1215
1216    /* Add timer event to turn off hour glass */
1217    XtAppAddTimeOut(XtWidgetToApplicationContext(w), 1500,
1218                    (XtTimerCallbackProc) TimerEvent, (XtPointer) w);
1219
1220
1221    XtFree(pwd_host);
1222    XtFree(pwd_dir);
1223    _DtFreeActionArgs(action_args, arg_count);
1224 }
1225
1226
1227 /************************************************************************
1228  *
1229  *  TimerEvent
1230  *      This function is called when dtfile does an _DtActionInvoke. All
1231  *      it does is turn off the Hourglass cursor.
1232  *
1233  ************************************************************************/
1234
1235 static void
1236 TimerEvent(
1237         Widget widget,
1238         XtIntervalId *id )
1239 {
1240    _DtTurnOffHourGlass (widget);
1241 }
1242
1243 /************************************************************************
1244  *
1245  * This Handle's the FILESYSTEM_MOVE, FILESYSTEM_COPY, or FILESYSTEM_LINK
1246  * ToolTalk messages.  The operation type is passed in via opType. It is
1247  * either MOVE_FILE, COPY_FILE, or LINK_FILE.  Arg 0 of the ToolTalk message
1248  * contains the folder the operation is taking place TO and arg 1 contains
1249  * the files that the operation  is happening to.
1250  *
1251  ************************************************************************/
1252
1253 void
1254 MoveCopyLinkHandler(
1255                     Tt_message ttMsg,
1256                     int opType)
1257 {
1258    struct stat fileInfo;
1259    char title[256];
1260    int numArgs, i;
1261    char *ptr, *toName, *fileNames = NULL, *type = NULL, *fileList;
1262    char *files = NULL;
1263    char ** file_set = NULL;
1264    char ** host_set = NULL;
1265    unsigned int modifiers = NULL;
1266    int file_count = 0;
1267    int file_set_size = 0;
1268    int errorCount = 0;
1269
1270    toName = tt_message_file( ttMsg );
1271    fileNames = fileList = tt_message_arg_val( ttMsg, 1 );
1272
1273    if( tt_is_err( tt_ptr_error( toName ) ) )
1274    { /* No file name */
1275       tt_message_reply( ttMsg );
1276       tttk_message_destroy( ttMsg );
1277       return;
1278    }
1279
1280    /* let's loop through the fileName passed to get the files which the
1281     * operation is to happen on.  The file's are separated by spaces.  What
1282     * happens if a file has a space in it: We parse on the spaces and if the
1283     * next char after a space is a '/' then we assume that is the end of the
1284     * file name.  What this implies is that this won't work for files with
1285     * spaces at the end of the name
1286     */
1287    while(1)
1288    {
1289       /* build the arrary of char pointer's */
1290       if (file_count == file_set_size)
1291       {
1292          file_set_size += 10;
1293          file_set =
1294            (char **) XtRealloc ((char *)file_set,
1295                                 sizeof (char **) * file_set_size);
1296       }
1297
1298       /* find the next space */
1299       ptr = DtStrchr(fileList, ' ');
1300
1301       /* if ptr is NULL, we have our last file name (no spaces found) */
1302       if(ptr == NULL)
1303       {
1304          file_set[file_count] = XtNewString(fileList);
1305          file_count++;
1306          break;
1307       }
1308       else
1309       {
1310          /* Let's check if the next char is a '/'. If it is then we know it's
1311           * the next file name, else the space found is part of a filename.
1312           */
1313          if(ptr[1] == '/')
1314          {
1315             *ptr = '\0';
1316             file_set[file_count] = XtNewString(fileList);
1317             file_count++;
1318          }
1319          fileList = ptr+1;
1320       }
1321    }
1322
1323
1324   /* go clean up all the '.' and '..' */
1325    for(i = 0; i < file_count; i++)
1326       DtEliminateDots( file_set[i] );
1327    DtEliminateDots( toName );
1328
1329   /* Set up the modifier key's */
1330    if( opType == MOVE_FILE)
1331       modifiers = NULL;
1332    else if ( opType == COPY_FILE)
1333       modifiers = ControlMask;
1334    else
1335       modifiers = ShiftMask;
1336
1337
1338    /*
1339     * Let's check make sure the Folder the operation is happening to exists.
1340     */
1341    if( stat( toName, &fileInfo ) != 0
1342        && lstat( toName, &fileInfo ) != 0 )
1343    { /* to directory does not exist */
1344       char *dialogTitle;
1345
1346       if(opType == MOVE_FILE)
1347       {
1348          dialogTitle = XtNewString(GETMESSAGE(33, 3, "Move Object Error"));
1349          sprintf(title, GETMESSAGE(33, 6, "The location you are trying to Move to:\n\n   %s\n\ndoes not exist in the file system."), toName);
1350       }
1351       else if(opType == COPY_FILE)
1352       {
1353          dialogTitle = XtNewString(GETMESSAGE(33, 4, "Copy Object Error"));
1354          sprintf(title, GETMESSAGE(33, 7, "The location you are trying to Copy to:\n\n   %s\n\ndoes not exist in the file system."), toName);
1355       }
1356       else
1357       {
1358          dialogTitle = XtNewString(GETMESSAGE(33, 5, "Link Object Error"));
1359          sprintf(title, GETMESSAGE(33, 8, "The location you are trying to Link to:\n\n   %s\n\ndoes not exist in the file system."), toName);
1360       }
1361       _DtMessage( toplevel, dialogTitle, title, NULL, HelpRequestCB );
1362
1363       tt_free( toName );
1364       tt_message_reply( ttMsg );
1365       tttk_message_destroy( ttMsg );
1366       return;
1367    }
1368
1369
1370    /*
1371     * Let's check make sure the object the operation is happening to is a
1372     * Folder.
1373     */
1374    if ((fileInfo.st_mode & S_IFMT) != S_IFDIR)     /* target not directory */
1375    { /* File that the user is doing the operation to is not a directory */
1376       char *dialogTitle;
1377
1378       if(opType == MOVE_FILE)
1379       {
1380          dialogTitle = XtNewString(GETMESSAGE(33, 3, "Move Object Error"));
1381          sprintf(title, GETMESSAGE(33, 9, "The location you are trying to Move to:\n\n   %s\n\nis not a folder."), toName);
1382       }
1383       else if(opType == COPY_FILE)
1384       {
1385          dialogTitle = XtNewString(GETMESSAGE(33, 4, "Copy Object Error"));
1386          sprintf(title, GETMESSAGE(33, 10, "The location you are trying to Copy to:\n\n   %s\n\nis not a folder."), toName);
1387       }
1388       else
1389       {
1390          dialogTitle = XtNewString(GETMESSAGE(33, 5, "Link Object Error"));
1391          sprintf(title, GETMESSAGE(33, 11,"The location you are trying to Link to:\n\n   %s\n\nis not a folder."), toName);
1392       }
1393       _DtMessage( toplevel, dialogTitle, title, NULL, HelpRequestCB );
1394
1395       tt_free( toName );
1396       tt_message_reply( ttMsg );
1397       tttk_message_destroy( ttMsg );
1398       return;
1399    }
1400
1401    /*
1402     *
1403     *
1404     */
1405    for(i = 0; i < file_count; i++)
1406    {
1407       if( stat( file_set[i], &fileInfo ) != 0
1408           && lstat( file_set[i], &fileInfo ) != 0 )
1409       { /* File does not exist */
1410          char *dialogTitle;
1411
1412          if(opType == MOVE_FILE)
1413          {
1414             dialogTitle = XtNewString(GETMESSAGE(33, 3, "Move Object Error"));
1415             if(file_count == 1)
1416                sprintf(title, GETMESSAGE(33, 12, "The object you are trying to Move:\n\n   %s\n\ndoes not exist in the file system."), file_set[i]);
1417             else
1418                sprintf(title, GETMESSAGE(33, 13, "One of the objects you are trying to Move:\n\n   %s\n\ndoes not exist in the file system.\nNot Moving any of them."), file_set[i]);
1419          }
1420          else if(opType == COPY_FILE)
1421          {
1422             dialogTitle = XtNewString(GETMESSAGE(33, 4, "Copy Object Error"));
1423             if(file_count == 1)
1424                sprintf(title, GETMESSAGE(33, 14, "The object you are trying to Copy:\n\n   %s\n\ndoes not exist in the file system."), file_set[i]);
1425             else
1426                sprintf(title, GETMESSAGE(33, 15, "One of the objects you are trying to Copy:\n\n   %s\n\ndoes not exist in the file system.\nNot Copying any of them."), file_set[i]);
1427          }
1428          else
1429          {
1430             dialogTitle = XtNewString(GETMESSAGE(33, 5, "Link Object Error"));
1431             if(file_count == 1)
1432                sprintf(title, GETMESSAGE(33, 16, "The object you are trying to Link:\n\n   %s\n\ndoes not exist in the file system."), file_set[i]);
1433             else
1434                sprintf(title, GETMESSAGE(33, 17, "One of the objects you are trying to Link:\n\n   %s\n\ndoes not exist in the file system.\nNot Linking any of them."), file_set[i]);
1435          }
1436          _DtMessage( toplevel, dialogTitle, title, NULL, HelpRequestCB );
1437
1438          tt_free( toName );
1439          tt_message_reply( ttMsg );
1440          tttk_message_destroy( ttMsg );
1441          return;
1442       }
1443    }
1444
1445
1446    /* set all the hosts to the home host name since ToolTalk messages pass
1447     * the filenames in host relative paths (Is this correct?)
1448     */
1449    host_set = (char **)XtMalloc(sizeof(char *) * file_count);
1450    for(i = 0; i < file_count; i++)
1451       host_set[i] = home_host_name;
1452
1453    /* Go do the Move/Copy/Link... this function will do proper error checking */
1454    FileMoveCopy(NULL, NULL, toName, home_host_name,
1455                 host_set, file_set, file_count,
1456                 modifiers, NULL, NULL);
1457
1458    tt_free( toName );
1459    tt_message_reply( ttMsg );
1460    tttk_message_destroy( ttMsg );
1461    return;
1462 }
1463