/* * 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 */ /* $XConsortium: Command.c /main/9 1996/10/30 11:09:42 drk $ */ /************************************<+>************************************* **************************************************************************** * * FILE: Command.c * * COMPONENT_NAME: Desktop File Manager (dtfile) * * Description: Command processing functions used by the File Browser. * * FUNCTIONS: ActionCallback * InvalidTrashDragDrop * ProcessAction * ProcessBufferDropOnFolder * ProcessMoveCopyLink * ProcessNewView * RunCommand * TimerEvent * UpdateActionMenuPane * * (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
#include
#include
#include
#include
#include
#include
#include
#include
#include "Encaps.h" #include "SharedProcs.h" #include "FileMgr.h" #include "Desktop.h" #include "Main.h" #include "Help.h" #include "SharedMsgs.h" #include "Prefs.h" /******** Static Function Declarations ********/ static void ActionCallback( Widget w, XtPointer client_data, XtPointer call_data) ; static void TimerEvent( Widget widget, XtIntervalId *id) ; void ProcessBufferDropOnFolder ( char *command, FileMgrData *file_mgr_data, FileViewData *file_view_data, DtDndDropCallbackStruct *drop_parameters, Widget drop_window); /******** End Static Function Declarations ********/ extern int G_dropx,G_dropy; /************************************************************************ * * UpdateActionMenuPane * Build up a set of menu panes for the provided file manager rec * that contains as items each of the commands for each file type. * ************************************************************************/ void UpdateActionMenuPane( XtPointer client_data, FileMgrRec *file_mgr_rec, char *file_type, int type, int number, Widget widget, unsigned char physical_type) { XmManagerWidget action_pane; FileMgrData *file_mgr_data = NULL; DialogData * dialog_data; FileViewData *file_view_data; DesktopRec *desktopWindow; Widget child; int i, menu_offset; int action_count; int count, del_count; int num_children; char ** command_list; XmString string; char *action_label; Arg args[2]; if(type == DESKTOP) desktopWindow = (DesktopRec *)client_data; else if(type == FM_POPUP) file_view_data = (FileViewData *)client_data; if (file_mgr_rec) { dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec); file_mgr_data = (FileMgrData *) dialog_data->data; } /* Count the number of actions defined for the the file type */ action_count = 0; command_list = _DtCompileActionVector(file_type); if(command_list != NULL) while (command_list[action_count] != NULL && strlen (command_list[action_count]) != 0) action_count++; if (physical_type == DtDIRECTORY && type == DESKTOP) ++action_count; /* If the menu pane is already set up for the file type then return. */ if(type == NOT_DESKTOP) { XtFree(file_mgr_rec->action_pane_file_type); file_mgr_rec->action_pane_file_type = XtNewString(file_type); action_pane = (XmManagerWidget) file_mgr_rec->action_pane; menu_offset = number + SELECTED_MENU_MAX; } else { action_pane = (XmManagerWidget) widget; menu_offset = number; } num_children = action_pane->composite.num_children; /* * This is so that we can determine which icon was responsible for * posting the menu, or requesting help. */ if (type == FM_POPUP) file_mgr_data->popup_menu_icon = file_view_data; /* else if (file_mgr_data) file_mgr_data->popup_menu_icon = NULL; */ if (action_count + menu_offset > num_children) { if(type == FM_POPUP) for (i = number; i < num_children; i++) XtManageChild (action_pane->composite.children[i]); for (i = num_children; i < action_count + menu_offset; i++) { child = XmCreatePushButtonGadget ((Widget)action_pane, "action_button", args, 0); if(type == DESKTOP) { XtAddCallback (child, XmNactivateCallback, DTActionCallback, (XtPointer)desktopWindow); XtAddCallback(child, XmNhelpCallback, (XtCallbackProc)DTHelpRequestCB, NULL); } else if(type == FM_POPUP) { XtAddCallback (child, XmNactivateCallback, ActionCallback, NULL); XtAddCallback(child, XmNhelpCallback, (XtCallbackProc)HelpRequestCB, NULL); } else { XtAddCallback (child, XmNactivateCallback, ActionCallback, (XtPointer)file_mgr_rec); XtAddCallback(child, XmNhelpCallback, (XtCallbackProc)HelpRequestCB, NULL); } XtManageChild (child); } } else { for (i = menu_offset; i < num_children; i++) { if (i < action_count + menu_offset) { XtRemoveAllCallbacks(action_pane->composite.children[i], XmNactivateCallback); if(type == DESKTOP) XtAddCallback (action_pane->composite.children[i], XmNactivateCallback, DTActionCallback, (XtPointer)desktopWindow); else if(type == FM_POPUP) XtAddCallback (action_pane->composite.children[i], XmNactivateCallback, ActionCallback, NULL); else XtAddCallback (action_pane->composite.children[i], XmNactivateCallback, ActionCallback, (XtPointer)file_mgr_rec); XtManageChild (action_pane->composite.children[i]); } else XtUnmanageChild (action_pane->composite.children[i]); } } /* For each action, set the label of the menu button */ /* and the user data. */ num_children = menu_offset + action_count; del_count = 0; for (i = 0; i < action_count; i++) { char *oldCommand; Arg argsTmp[2]; if(type != DESKTOP) { char* strp; strp = XtNewString(command_list[i]); XtSetArg (args[1], XmNuserData, strp); action_label = DtActionLabel(command_list[i]); if(action_label != NULL) string = XmStringCreateLocalized(action_label); else string = XmStringCreateLocalized(command_list[i]); count = i + menu_offset; } else { if (physical_type == DtDIRECTORY && i == 0) { if((action_label = DtActionLabel(openNewView)) != NULL) string = XmStringCreateLocalized(action_label); else string = XmStringCreateLocalized(openNewView); XtSetArg (args[1], XmNuserData, openNewView); count = i + number; } else { if (physical_type == DtDIRECTORY) { if(strcmp(command_list[i - 1], openNewView) == 0 || strcmp(command_list[i - 1], openInPlace) == 0) { del_count++; XtUnmanageChild (action_pane->composite.children[ num_children - del_count]); continue; } action_label = DtActionLabel(command_list[i - 1]); if(action_label != NULL) string = XmStringCreateLocalized(action_label); else string = XmStringCreateLocalized(command_list[i-1]); XtSetArg (args[1], XmNuserData, XtNewString (command_list[i - 1])); count = i + number - del_count; } else { action_label = DtActionLabel(command_list[i]); if(action_label != NULL) string = XmStringCreateLocalized(action_label); else string = XmStringCreateLocalized(command_list[i]); XtSetArg (args[1], XmNuserData, XtNewString(command_list[i])); count = i + number; } } } /* first we need to get the userData from the push button and free it up */ XtSetArg (argsTmp[0], XmNuserData, &oldCommand); XtGetValues (action_pane->composite.children[count], argsTmp, 1); if(oldCommand != NULL && strcmp(oldCommand, openNewView) != 0) XtFree(oldCommand); XtSetArg (args[0], XmNlabelString, string); XtSetValues (action_pane->composite.children[count], args, 2); if(type != NOT_DESKTOP) { XtRemoveAllCallbacks(action_pane->composite.children[count], XmNactivateCallback); if(type == DESKTOP) { XtAddCallback (action_pane->composite.children[count], XmNactivateCallback, DTActionCallback, (XtPointer)desktopWindow); } else XtAddCallback (action_pane->composite.children[count], XmNactivateCallback, ActionCallback, (XtPointer)NULL); } XmStringFree (string); XtFree(action_label); } _DtFreeStringVector(command_list); } /************************************************************************ * * ActionCallback * Callback function invoked upon the an actions menu button * being selected. * ************************************************************************/ static void ActionCallback( Widget w, XtPointer client_data, XtPointer call_data ) { FileMgrRec * file_mgr_rec; DialogData * dialog_data; FileMgrData * file_mgr_data; FileViewData * file_view_data; char * command; Arg args[1]; Widget mbar; Boolean popup = False; XmAnyCallbackStruct * callback; XmUpdateDisplay (w); mbar = XtParent(w); callback = (XmAnyCallbackStruct *) call_data; if(client_data == NULL) { popup = True; XtSetArg(args[0], XmNuserData, &file_mgr_rec); XtGetValues(mbar, args, 1); dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec); file_mgr_data = (FileMgrData *) dialog_data->data; file_view_data = file_mgr_data->popup_menu_icon; if(!file_view_data) /* The object would have probably been delete */ return; file_mgr_data->popup_menu_icon = NULL; /* Just to make it unuseful */ } else { file_mgr_rec = (FileMgrRec *) client_data; dialog_data = _DtGetInstanceData ((XtPointer)file_mgr_rec); file_mgr_data = (FileMgrData *) dialog_data->data; } /* Find the file data for the file that is selected */ XtSetArg (args[0], XmNuserData, (XtPointer) &command); XtGetValues (w, args, 1); if(strcmp(command, openNewView) == 0) { XButtonEvent *event = (XButtonEvent *)callback->event; unsigned int modifiers; modifiers = event->state; if(popup) RunCommand (command, file_mgr_data, file_view_data, NULL, NULL, NULL); else RunCommand (command, file_mgr_data, file_mgr_data->selection_list[0], NULL, NULL, NULL); if((modifiers != 0) && ((modifiers & ControlMask) != 0)) { DialogData *dialog_data; dialog_data = _DtGetInstanceData(file_mgr_data->file_mgr_rec); CloseView(dialog_data); } } else { if(popup) RunCommand (command, file_mgr_data, file_view_data, NULL, NULL, NULL); else RunCommand (command, file_mgr_data, file_mgr_data->selection_list[0], NULL, NULL, NULL); } } /************************************************************************ * * RunCommand * * WARNING: when desktop links are passed in, this function will NOT * expect the links to have already been mapped to their * real files. * ************************************************************************/ void RunCommand( char *command, FileMgrData *file_mgr_data, FileViewData *file_view_data, WindowPosition *position, DtDndDropCallbackStruct *drop_parameters, Widget drop_window ) { if ((strcmp (command, openInPlace) == 0) || (strcmp (command, openNewView) == 0)) { /* If the folder is locked, don't allow user to go into it */ if( strcmp( file_view_data->file_data->logical_type, LT_FOLDER_LOCK ) == 0 ) { char *tmpStr, *title, *msg; tmpStr = GETMESSAGE(9, 6, "Action Error"); title = XtNewString(tmpStr); msg = (char *)XtMalloc( strlen( GETMESSAGE(30, 1, "Cannot read from %s") ) + strlen( file_view_data->file_data->file_name ) + 1 ); sprintf( msg, GETMESSAGE(30, 1, "Cannot read from %s"), file_view_data->file_data->file_name ); _DtMessage(((FileMgrRec*)file_mgr_data->file_mgr_rec)->file_window, title, msg, NULL, HelpRequestCB ); XtFree(title); XtFree(msg); return; } /* this statement applies to the case where a user traverses down the * * part of the directory tree containing the application manager * * directories or the trash directory */ if( ((strcmp(file_view_data->file_data->logical_type, LT_AGROUP) == 0) && (!(file_mgr_data->toolbox))) || (strcmp(file_view_data->file_data->logical_type, LT_TRASH) == 0) ) { ProcessAction(command, file_view_data, drop_parameters, file_mgr_data->host, file_mgr_data->current_directory, file_mgr_data->restricted_directory, ((FileMgrRec *) file_mgr_data->file_mgr_rec)->shell); } else { ProcessNewView(command, file_mgr_data, file_view_data, position); } } else if ((strcmp (command, "FILESYSTEM_MOVE") == 0) || (strcmp (command, "FILESYSTEM_COPY") == 0) || (strcmp (command, "FILESYSTEM_LINK") == 0)) { /* Check to see what was dropped (files or buffers) */ /* Call the appropriate routine to handle the drop */ if (drop_parameters->dropData->protocol == DtDND_FILENAME_TRANSFER) ProcessMoveCopyLink(command, file_mgr_data, file_view_data, drop_parameters, drop_window); else if (drop_parameters->dropData->protocol == DtDND_BUFFER_TRANSFER) ProcessBufferDropOnFolder(command, file_mgr_data, file_view_data, drop_parameters, drop_window); } else { ProcessAction(command, file_view_data, drop_parameters, file_mgr_data->host, file_mgr_data->current_directory, file_mgr_data->restricted_directory, ((FileMgrRec *) file_mgr_data->file_mgr_rec)->shell); } } /************************************************************************ * * ProcessNewView * ************************************************************************/ void ProcessNewView ( char *command, FileMgrData *file_mgr_data, FileViewData *file_view_data, WindowPosition *position) { DirectorySet * directory_set; char host_name[MAX_PATH]; char directory_name[MAX_PATH]; char *tmpStr, *title, *msg; /* we don't want to execute the default action if in trash ... */ if( trashFileMgrData != NULL && file_mgr_data == trashFileMgrData) { tmpStr = GETMESSAGE(27, 3, "Trash Can Error"); title = XtNewString(tmpStr); 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."); msg = XtNewString(tmpStr); _DtMessage( ((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window, title, msg, NULL, HelpRequestCB); XtFree(title); XtFree(msg); return; } strcpy (host_name, file_mgr_data->host); directory_set = (DirectorySet *) (file_view_data->directory_set); strcpy (directory_name, directory_set->name); if (strcmp (directory_name, "/") != 0) strcat (directory_name, "/"); strcat (directory_name, file_view_data->file_data->file_name); DtEliminateDots (directory_name); if (strcmp (directory_name, "/..") == 0) strcpy (directory_name, "/"); if (strcmp (command, openInPlace) == 0) { FileMgrRec *file_mgr_rec; Arg args[1]; Widget vb; int value, size, increment, page; file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec; ShowNewDirectory (file_mgr_data, host_name, directory_name); XtSetArg (args[0], XmNverticalScrollBar, &vb); XtGetValues (file_mgr_rec->scroll_window, args, 1); /* get scroll bar values */ (void)XmScrollBarGetValues(vb, &value, &size, &increment, &page); /* set scroll bar values changing its position */ if(value != 0) (void)XmScrollBarSetValues(vb, (int)0, size, increment, page, True); if(strcmp(file_mgr_data->current_directory, file_mgr_data->restricted_directory) == 0) { XtSetSensitive(*upBarBtn, False); currentMenuStates &= ~(MOVE_UP); file_mgr_rec->menuStates &= ~(MOVE_UP); } else { file_mgr_rec->menuStates |= MOVE_UP; XtSetSensitive(*upBarBtn, True); currentMenuStates &= ~(MOVE_UP); } } else { initiating_view = (XtPointer) file_mgr_data; if(file_mgr_data->restricted_directory == NULL) { GetNewView (host_name, directory_name, NULL, position, 0); } else { special_view = True; special_treeType = file_mgr_data->show_type; special_viewType = file_mgr_data->view; special_orderType = file_mgr_data->order; special_directionType = file_mgr_data->direction; special_randomType = file_mgr_data->positionEnabled; special_restricted = XtNewString(file_mgr_data->restricted_directory); if(file_mgr_data->title == NULL) special_title = NULL; else special_title = XtNewString(file_mgr_data->title); special_helpVol = XtNewString(file_mgr_data->helpVol); if(file_mgr_data->toolbox) GetNewView (file_mgr_data->host, directory_name, file_mgr_data->restricted_directory, position, 0); else GetNewView (file_mgr_data->host, directory_name, NULL, position, 0); } initiating_view = (XtPointer) NULL; } } /************************************************************************ * * ProcessMoveCopyLink * ************************************************************************/ void ProcessMoveCopyLink ( char *command, FileMgrData *file_mgr_data, FileViewData *file_view_data, DtDndDropCallbackStruct *drop_parameters, Widget drop_window) { unsigned int modifiers = 0; int numFiles, i; char ** file_set = NULL; char ** host_set = NULL; Boolean trashFile; /***************************************************/ /* if no drop_parameters, there is nothing to move */ /***************************************************/ if (!drop_parameters) return; /**************************/ /* are these trash files? */ /**************************/ trashFile = FileFromTrash(drop_parameters->dropData->data.files[0]); /***********************************************/ /* if trying to copy or link from trash return */ /***********************************************/ if (trashFile) { if (file_mgr_data != trashFileMgrData) if (InvalidTrashDragDrop(drop_parameters->operation, FROM_TRASH, ((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window)) return; } /***************************************************/ /* extract file and host sets from drop parameters */ /***************************************************/ numFiles = drop_parameters->dropData->numItems; _DtSetDroppedFileInfo(drop_parameters, &file_set, &host_set); /******************************/ /* set movement modifier mask */ /******************************/ if( (initiating_view != NULL) && (((FileMgrData *)initiating_view)->toolbox) ) { /* if initiating_view is a toolbox, the transfer must be */ /* a copy */ modifiers = ControlMask; } else { if (strcmp(command, "FILESYSTEM_COPY") == 0) modifiers = ControlMask; else if (strcmp(command, "FILESYSTEM_LINK") == 0) modifiers = ShiftMask; else modifiers = 0; } /*****************************/ /* Files dropped on a window */ /*****************************/ if (drop_window) { /****************************************************************/ /* Files dropped in the trash -- move files to trash directory */ /****************************************************************/ if(file_mgr_data == trashFileMgrData && !trashFile) { DPRINTF(("DropOnFileWindow:Dragging File(s) to Trash Can from NonTrash Window\n")); DropOnTrashCan(numFiles, host_set, file_set, drop_parameters); } /****************************************************************/ /* Files dragged in the trash -- do nothing */ /****************************************************************/ else if(file_mgr_data == trashFileMgrData && trashFile) { DPRINTF(("DropOnFileWindow: Drag from Within Trash Can\n")); } /****************************************************************/ /* Files dragged from the trash -- move the files to their new */ /* location */ /****************************************************************/ else if(trashFile && file_mgr_data != trashFileMgrData) { DPRINTF(("DropOnFileWindow: Dragging from Trash to Folder Window\n")); MoveOutOfTrashCan(file_mgr_data, (FileMgrRec *)file_mgr_data->file_mgr_rec, XtWindow(drop_window), numFiles, host_set, file_set, drop_parameters->x, drop_parameters->y); } /****************************************************************/ /* Files dropped on a non-trash window -- move files to new */ /* location. */ /* */ /* Droppable windows must be handled like the desktop; i.e. */ /* positioning is supported. */ /****************************************************************/ else { FileMgrRec *file_mgr_rec = (FileMgrRec *)file_mgr_data->file_mgr_rec; /* if ((file_mgr_data->show_type == SINGLE_DIRECTORY) && (file_mgr_data->view != BY_ATTRIBUTES)) */ { if (file_mgr_data == (FileMgrData *) initiating_view) { DPRINTF(("DropOnFileWindow: Dragging and Dropping File within same window\n")); /* Simple reposition in the same window */ XmDropSiteStartUpdate(file_mgr_rec->file_window); RepositionIcons(file_mgr_data, file_set, numFiles, drop_parameters->x, drop_parameters->y, False); LayoutFileIcons(file_mgr_rec, file_mgr_data, False, True); XmDropSiteEndUpdate(file_mgr_rec->file_window); } else { DPRINTF (("DropOnFileWindow: Dragging file(s) and dropping from other folders\n")); CheckMoveType(file_mgr_data, (FileViewData *)NULL, (DirectorySet *)NULL, (DesktopRec *)NULL, file_set, host_set, modifiers, numFiles, drop_parameters->x, drop_parameters->y, NOT_DESKTOP); } } /* else { DPRINTF(("DropOnFileWindow: Not Single Directory View\n")); if (FileMoveCopy (file_mgr_data, NULL, file_mgr_data->current_directory, file_mgr_data->host, host_set, file_set, numFiles, modifiers, NULL, NULL)) { DirectorySet * directory_data; char * directory_name; FileViewData * file_view_data; int j; DeselectAllFiles (file_mgr_data); directory_data = file_mgr_data->directory_set[0]; for (i = 0; i < numFiles; i++) { directory_name = DName (file_set[i]); for (j = 0; j < directory_data->file_count; j++) { file_view_data = directory_data->file_view_data[j]; if ( (file_view_data->filtered != True) && (strcmp(directory_name, file_view_data->file_data->file_name) == 0) ) { SelectFile (file_mgr_data, file_view_data); break; } } } PositionFileView(file_view_data, file_mgr_data); } } */ if (file_mgr_data->selected_file_count == 0) ActivateNoSelect (file_mgr_rec); else if (file_mgr_data->selected_file_count == 1) ActivateSingleSelect (file_mgr_rec, file_mgr_data->selection_list[0]->file_data->logical_type); else ActivateMultipleSelect (file_mgr_rec); } } /*****************************/ /* Files dropped on an icon */ /*****************************/ else { CheckMoveType(file_mgr_data, file_view_data, (DirectorySet *) file_view_data->directory_set, (DesktopRec *)NULL, file_set, host_set, modifiers, numFiles, drop_parameters->x, drop_parameters->y, NOT_DESKTOP_DIR); } /***************************/ /* free file and host sets */ /***************************/ _DtFreeDroppedFileInfo(numFiles, file_set, host_set); } /************************************************************************ * * ProcessBufferDropOnFolder * ************************************************************************/ void ProcessBufferDropOnFolder ( char *command, FileMgrData *file_mgr_data, FileViewData *file_view_data, DtDndDropCallbackStruct *drop_parameters, Widget drop_window) { unsigned int modifiers = 0; int num_of_buffers, i; char ** file_set = NULL; char ** host_set = NULL; BufferInfo *buffer_set = NULL; char directory[MAX_PATH]; /***************************************************/ /* if no drop_parameters, or invalid params */ /* then disallow the drop */ /***************************************************/ if (!drop_parameters) return; /* if dropped on file window and file_mgr_data is null */ if (drop_window && (file_mgr_data == NULL)) return; /* if dropped on a folder icon and file_view_data */ /* is NULL, disallow the drop */ if (!drop_window && (file_view_data == NULL)) return; /****************************************************/ /* extract file and host sets from drop parameters */ /* @@@...need to check with Linda about how host_set*/ /* is being handled */ /****************************************************/ num_of_buffers = drop_parameters->dropData->numItems; /* Allocate memory for file and buffer structures */ file_set = (char **)XtMalloc(sizeof(char **) * num_of_buffers ); host_set = (char **)XtMalloc(sizeof(char **) * num_of_buffers); buffer_set = (BufferInfo * )XtMalloc (sizeof (BufferInfo) * num_of_buffers); _DtSetDroppedBufferInfo(file_set, buffer_set, host_set, drop_parameters); /*****************************************************/ /* If buffers were dropped on the window, determine */ /* which MODE (AS PLACED, GRID, TREE VIEW) and call */ /* the appropriate routines to handle the creation */ /* of the buffers into files. Assuming dropping */ /* on non-trash windows. */ /*****************************************************/ if (drop_window) { /* Single directory view */ if ((file_mgr_data->show_type == SINGLE_DIRECTORY ) && (file_mgr_data->view != BY_ATTRIBUTES)) { DPRINTF (("ProcessDropOnBufferFolder: Dropping buffers on single directory view: %s\n", file_mgr_data->current_directory)); G_dropx = drop_parameters->x; G_dropy = drop_parameters->y; /* Reposition Icons if in in "AS PLACED" Mode */ if (file_mgr_data -> positionEnabled == RANDOM_ON) { /* RepositionIcons (file_mgr_data, file_set, num_of_buffers, drop_parameters->x, drop_parameters->y, True); */ } /* Call MakeFileFromBuffer */ MakeFilesFromBuffers(file_mgr_data, file_mgr_data->current_directory, file_mgr_data->host, file_set, host_set, buffer_set, num_of_buffers, NULL, NULL); } else { DPRINTF (("ProcessDropOnBufferFolder: Dropping buffers in Tree View\n")); MakeFilesFromBuffers(file_mgr_data, file_mgr_data->current_directory, file_mgr_data->host, file_set, host_set, buffer_set, num_of_buffers, NULL, NULL); /* Do Tree View Stuff */ { DirectorySet * directory_data; char * directory_name; FileViewData * file_view_data = NULL; int j; DeselectAllFiles (file_mgr_data); directory_data = file_mgr_data->directory_set[0]; for (i = 0; i < num_of_buffers; i++) { directory_name = DName (file_set[i]); for (j = 0; j < directory_data->file_count; j++) { file_view_data = directory_data->file_view_data[j]; if ( (file_view_data->filtered != True) && (strcmp(directory_name, file_view_data->file_data->file_name) == 0) ) { SelectFile (file_mgr_data, file_view_data); break; } } } if (file_view_data) PositionFileView(file_view_data, file_mgr_data); } } /* endif for Tree View */ } /* endif drop buffers on window */ else { /* Buffers were dropped on a Folder icon */ /* Call MakeFileFromBuffer */ DPRINTF(("ProcessBufferDropOnFolder...Buffers dropped on Folder icon %s\n", file_view_data ->file_data -> file_name)); if (file_mgr_data->show_type != SINGLE_DIRECTORY && file_mgr_data->tree_root == file_view_data) { /* dropped on the top level folder in the tree view */ sprintf (directory,"%s",file_mgr_data->current_directory); } else sprintf (directory,"%s/%s",file_mgr_data->current_directory, file_view_data->file_data->file_name); DtEliminateDots(directory); DPRINTF (("Copying buffer to %s\n", directory)); MakeFilesFromBuffers(file_mgr_data, directory, file_mgr_data->host, file_set, host_set, buffer_set, num_of_buffers, NULL, NULL); } /***********************************/ /* free file_set + buffer_set */ /***********************************/ _DtFreeDroppedBufferInfo (file_set, buffer_set, host_set, num_of_buffers); } /************************************************************************ * * InvalidTrashDragDrop * ************************************************************************/ Boolean InvalidTrashDragDrop ( int drag_op, int trash_context, Widget w) { Boolean rc = False; if ( (drag_op == XmDROP_COPY) || (drag_op == XmDROP_LINK) ) { char *tmpStr, *title, *msg; tmpStr = GETMESSAGE(18, 22, "Drag Error"); title = XtNewString(tmpStr); switch(trash_context) { case TO_TRASH: case WITHIN_TRASH: 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.")); break; case FROM_TRASH: 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.")); break; default: tmpStr = NULL; break; } if (tmpStr) { msg = XtNewString(tmpStr); _DtMessage (w, title, msg, NULL, HelpRequestCB); XtFree(msg); } XtFree(title); rc = True; } return(rc); } /************************************************************************ * * ProcessAction * ************************************************************************/ void ProcessAction ( char *action, FileViewData *file_view_data, DtDndDropCallbackStruct *drop_parameters, char *cur_host, char *cur_dir, char *restricted_dir, Widget w) { FileViewData *first_arg = NULL; DtActionArg * action_args = NULL; int arg_count = 0; char * pwd_host = NULL; char * pwd_dir = NULL; DirectorySet *directory_set; FileMgrData *file_mgr_data; /* We don't want to execute the default action if in trash ... */ directory_set = (DirectorySet *) file_view_data->directory_set; file_mgr_data = (FileMgrData *) directory_set->file_mgr_data; if( trashFileMgrData != NULL && file_mgr_data == trashFileMgrData) { char *tmpStr, *title, *msg; /* we don't want to execute the default action if in trash ... */ tmpStr = GETMESSAGE(27, 3, "Trash Can Error"); title = XtNewString(tmpStr); 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."); msg = XtNewString(tmpStr); _DtMessage(((FileMgrRec *)file_mgr_data->file_mgr_rec)->file_window, title, msg, NULL, HelpRequestCB); XtFree(title); XtFree(msg); return; } /* Build action arguments: * First, test for redundant action information -- * file_view_data contains information for the object that the user * a) dropped files on * b) activated a popup menu over (note that the Actions piece * of both the Selected and popup menus is only active when * a single file is selected; therefore, this function doesn't * deal with cases where multiple files are selected and a * popup menu is activated * c) doubled-clicked * * If file_view_data contains information for the action that we * are processing, then this information is not included as an * argument to DtActionInvoke; otherwise, the information is * included as the first argument to DtActionInvoke. */ if ( !DtDtsDataTypeIsAction(file_view_data->file_data->logical_type) || (strcmp(action, file_view_data->file_data->logical_type) != 0) || (strcmp(action, file_view_data->file_data->file_name) != 0) ) first_arg = file_view_data; if (drop_parameters) { if (drop_parameters->dropData->protocol == DtDND_FILENAME_TRANSFER) _DtBuildActionArgsWithDroppedFiles(first_arg, drop_parameters, &action_args, &arg_count); else _DtBuildActionArgsWithDroppedBuffers(first_arg, drop_parameters, &action_args, &arg_count); } else { if (first_arg) _DtBuildActionArgsWithSelectedFiles(&first_arg, 1, &action_args, &arg_count); } /* Retrieve context dir for action -- in the case of toolboxes, the root toolbox */ SetPWD(cur_host, cur_dir, &pwd_host, &pwd_dir, restricted_dir); /* Turn on hour glass */ _DtTurnOnHourGlass(w); /* Invoke action */ DtActionInvoke(w, action, action_args, arg_count, NULL, NULL, pwd_dir, True, NULL, NULL); /* Add timer event to turn off hour glass */ XtAppAddTimeOut(XtWidgetToApplicationContext(w), 1500, (XtTimerCallbackProc) TimerEvent, (XtPointer) w); XtFree(pwd_host); XtFree(pwd_dir); _DtFreeActionArgs(action_args, arg_count); } /************************************************************************ * * TimerEvent * This function is called when dtfile does an _DtActionInvoke. All * it does is turn off the Hourglass cursor. * ************************************************************************/ static void TimerEvent( Widget widget, XtIntervalId *id ) { _DtTurnOffHourGlass (widget); } /************************************************************************ * * This Handle's the FILESYSTEM_MOVE, FILESYSTEM_COPY, or FILESYSTEM_LINK * ToolTalk messages. The operation type is passed in via opType. It is * either MOVE_FILE, COPY_FILE, or LINK_FILE. Arg 0 of the ToolTalk message * contains the folder the operation is taking place TO and arg 1 contains * the files that the operation is happening to. * ************************************************************************/ void MoveCopyLinkHandler( Tt_message ttMsg, int opType) { struct stat fileInfo; char title[256]; int numArgs, i; char *ptr, *toName, *fileNames = NULL, *type = NULL, *fileList; char *files = NULL; char ** file_set = NULL; char ** host_set = NULL; unsigned int modifiers = 0; int file_count = 0; int file_set_size = 0; int errorCount = 0; toName = tt_message_file( ttMsg ); fileNames = fileList = tt_message_arg_val( ttMsg, 1 ); if( tt_is_err( tt_ptr_error( toName ) ) ) { /* No file name */ tt_message_reply( ttMsg ); tttk_message_destroy( ttMsg ); return; } /* let's loop through the fileName passed to get the files which the * operation is to happen on. The file's are separated by spaces. What * happens if a file has a space in it: We parse on the spaces and if the * next char after a space is a '/' then we assume that is the end of the * file name. What this implies is that this won't work for files with * spaces at the end of the name */ while(1) { /* build the arrary of char pointer's */ if (file_count == file_set_size) { file_set_size += 10; file_set = (char **) XtRealloc ((char *)file_set, sizeof (char **) * file_set_size); } /* find the next space */ ptr = DtStrchr(fileList, ' '); /* if ptr is NULL, we have our last file name (no spaces found) */ if(ptr == NULL) { file_set[file_count] = XtNewString(fileList); file_count++; break; } else { /* Let's check if the next char is a '/'. If it is then we know it's * the next file name, else the space found is part of a filename. */ if(ptr[1] == '/') { *ptr = '\0'; file_set[file_count] = XtNewString(fileList); file_count++; } fileList = ptr+1; } } /* go clean up all the '.' and '..' */ for(i = 0; i < file_count; i++) DtEliminateDots( file_set[i] ); DtEliminateDots( toName ); /* Set up the modifier key's */ if( opType == MOVE_FILE) modifiers = 0; else if ( opType == COPY_FILE) modifiers = ControlMask; else modifiers = ShiftMask; /* * Let's check make sure the Folder the operation is happening to exists. */ if( stat( toName, &fileInfo ) != 0 && lstat( toName, &fileInfo ) != 0 ) { /* to directory does not exist */ char *dialogTitle; if(opType == MOVE_FILE) { dialogTitle = XtNewString(GETMESSAGE(33, 3, "Move Object Error")); 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); } else if(opType == COPY_FILE) { dialogTitle = XtNewString(GETMESSAGE(33, 4, "Copy Object Error")); 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); } else { dialogTitle = XtNewString(GETMESSAGE(33, 5, "Link Object Error")); 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); } _DtMessage( toplevel, dialogTitle, title, NULL, HelpRequestCB ); tt_free( toName ); tt_message_reply( ttMsg ); tttk_message_destroy( ttMsg ); return; } /* * Let's check make sure the object the operation is happening to is a * Folder. */ if ((fileInfo.st_mode & S_IFMT) != S_IFDIR) /* target not directory */ { /* File that the user is doing the operation to is not a directory */ char *dialogTitle; if(opType == MOVE_FILE) { dialogTitle = XtNewString(GETMESSAGE(33, 3, "Move Object Error")); sprintf(title, GETMESSAGE(33, 9, "The location you are trying to Move to:\n\n %s\n\nis not a folder."), toName); } else if(opType == COPY_FILE) { dialogTitle = XtNewString(GETMESSAGE(33, 4, "Copy Object Error")); sprintf(title, GETMESSAGE(33, 10, "The location you are trying to Copy to:\n\n %s\n\nis not a folder."), toName); } else { dialogTitle = XtNewString(GETMESSAGE(33, 5, "Link Object Error")); sprintf(title, GETMESSAGE(33, 11,"The location you are trying to Link to:\n\n %s\n\nis not a folder."), toName); } _DtMessage( toplevel, dialogTitle, title, NULL, HelpRequestCB ); tt_free( toName ); tt_message_reply( ttMsg ); tttk_message_destroy( ttMsg ); return; } /* * * */ for(i = 0; i < file_count; i++) { if( stat( file_set[i], &fileInfo ) != 0 && lstat( file_set[i], &fileInfo ) != 0 ) { /* File does not exist */ char *dialogTitle; if(opType == MOVE_FILE) { dialogTitle = XtNewString(GETMESSAGE(33, 3, "Move Object Error")); if(file_count == 1) 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]); else 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]); } else if(opType == COPY_FILE) { dialogTitle = XtNewString(GETMESSAGE(33, 4, "Copy Object Error")); if(file_count == 1) 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]); else 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]); } else { dialogTitle = XtNewString(GETMESSAGE(33, 5, "Link Object Error")); if(file_count == 1) 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]); else 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]); } _DtMessage( toplevel, dialogTitle, title, NULL, HelpRequestCB ); tt_free( toName ); tt_message_reply( ttMsg ); tttk_message_destroy( ttMsg ); return; } } /* set all the hosts to the home host name since ToolTalk messages pass * the filenames in host relative paths (Is this correct?) */ host_set = (char **)XtMalloc(sizeof(char *) * file_count); for(i = 0; i < file_count; i++) host_set[i] = home_host_name; /* Go do the Move/Copy/Link... this function will do proper error checking */ FileMoveCopy(NULL, NULL, toName, home_host_name, host_set, file_set, file_count, modifiers, NULL, NULL); tt_free( toName ); tt_message_reply( ttMsg ); tttk_message_destroy( ttMsg ); return; }