/* * 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: SharedProcs.c /main/7 1996/10/03 14:01:42 drk $ */ /************************************<+>************************************* **************************************************************************** * * FILE: SharedProcs.c * * COMPONENT_NAME: Desktop File Manager (dtfile) * * Description: Contains the set of functions which are of general * use to all DT clients. * * FUNCTIONS: BuildBufferFileName * RenameCollisions * RenameEntry * RetrieveAndUseNameTemplateInfo * SetBufferFileNames * _DtAddOneSubdialog * _DtBuildActionArgsWithDroppedBuffers * _DtBuildActionArgsWithDroppedFiles * _DtBuildActionArgsWithSelectedFiles * _DtBuildActionArgsWithDTSelectedFiles * _DtBuildFMTitle * _DtBuildPath * _DtChangeTildeToHome * _DtCheckAndFreePixmapData * _DtCheckForDataTypeProperty * _DtCompileActionVector * _DtCopyDroppedFileInfo * _DtDestroySubdialog * _DtDestroySubdialogArray * _DtDuplicateDialogNameList * _DtFollowLink * _DtFreeActionArgs * _DtFreeDroppedBufferInfo * _DtFreeDroppedFileInfo * _DtGenericDestroy * _DtGenericMapWindow * _DtGenericUpdateWindowPosition * _DtGetSelectedFilePath * _DtHideOneSubdialog * _DtIsBufferExecutable * _DtLoadSubdialogArray * _DtMappedCB * _DtPName * _DtPathFromInput * _DtResolveAppManPath * _DtRetrieveDefaultAction * _DtRetrievePixmapData * _DtSaveSubdialogArray * _DtSetDroppedBufferInfo * _DtSetDroppedFileInfo * _DtSpacesInFileNames * _DtStringsAreEquivalent * * (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 /* Copied from Xm/BaseClassI.h */ extern XmWidgetExtData _XmGetWidgetExtData( Widget widget, #if NeedWidePrototypes unsigned int extType) ; #else unsigned char extType) ; #endif /* NeedWidePrototypes */ #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include #include "Encaps.h" #include "FileMgr.h" #include "Desktop.h" #include "Common.h" #include "Main.h" #include "SharedProcs.h" extern char *pathcollapse(); /* Defines */ #define RW_ALL S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH /* Global controlling whether auto-positioning is enabled */ Boolean disableDialogAutoPlacement = False; /******** Static Function Declarations ********/ static void SetBufferFileNames ( char **file_set, DtDndBuffer *buffers, int num_of_buffers) ; static char * BuildBufferFileName ( char *file_name, int postfix_index, void *buffer, int buffer_size) ; static char * RetrieveAndUseNameTemplateInfo( void *buffer, int buffer_size, char *template_input) ; static void RenameEntry( char **name, unsigned int addIndex) ; static void RenameCollisions( char **list, int count) ; /******** End Static Function Declarations ********/ /************************************************************************ * * _DtPName * Returns the parent directory of its argument. * Does this by looking for the last "/" in the name, and * NULL'ing it out. * ************************************************************************/ char * _DtPName( char *name ) { char * q; static char pnam[MAXPATHLEN]; static char dot[] = "."; strcpy(pnam, name); q = strrchr(pnam, '/'); if (q == NULL) q = pnam; else if ((q == pnam) && #ifdef NLS16 (mblen(q, MB_CUR_MAX) == 1) && #endif (*q == '/')) { q++; } *q = '\0'; return(pnam[0] ? pnam : dot); } /* * Given a filename, follow it to the end of its link. Returns NULL if * a recursive symbolic link is found. * * Note, the path returned is a static buffer, and should not be freed by * the calling function. */ char * _DtFollowLink ( char * path) { char link_path[MAXPATHLEN]; static char file[MAXPATHLEN]; int link_len; char * end; int history_count; int history_size; char ** history; int i; /* Used to check for symbolic link loops */ history_count = 0; history_size = 100; history = (char **)XtMalloc(sizeof(char *) * history_size); strcpy(file, path); while ((link_len = readlink(file, link_path, MAXPATHLEN - 1)) > 0) { link_path[link_len] = 0; /* Force the link to be an absolute path, if necessary */ if (link_path[0] != '/') { /* Relative paths are relative to the current directory */ end = strrchr(file, '/') + 1; *end = '\0'; strcat(file, link_path); } else strcpy(file, link_path); /* Check for a recursive loop; abort if found */ for (i = 0; i < history_count; i++) { if (strcmp(file, history[i]) == 0) { for (i = 0; i < history_count; i++) XtFree(history[i]); XtFree((char *)history); history = NULL; return(NULL); } } /* Add to the history list */ if (history_count >= history_size) { history_size += 100; history = (char **)XtRealloc((char *)history, sizeof(char *) * history_size); } history[history_count++] = XtNewString(file); } /* Free up the history list */ for (i = 0; i < history_count; i++) XtFree(history[i]); XtFree((char *)history); history = NULL; return(file); } /************************************************************************ * * _DtStringsAreEquivalent * Compare two strings and return true if equal. * The comparison is on lower cased strings. It is the callers * responsibility to ensure that test_str is already lower cased. * ************************************************************************/ Boolean _DtStringsAreEquivalent( char *in_str, char *test_str ) { #ifdef NLS16 wchar_t c1; wchar_t c2; int c1size, c2size; #endif int i; int j; #ifdef NLS16 if (is_multibyte) { for (;;) { /* Convert each character from multibyte to wide format */ c1size = mbtowc(&c1, in_str, MB_CUR_MAX); c2size = mbtowc(&c2, test_str, MB_CUR_MAX); /* No match, if the two characters have different byte counts */ if (c1size != c2size) return(False); /* Do case conversion only for single byte characters */ if (c1size == 1) { if (isupper((int) c1)) c1 = tolower((int) c1); } /* See if the two wide characters match */ if (c1 != c2) return(False); /* Are we at the end of the string? */ if (c1 == '\0') return(True); /* Keep comparing */ in_str += c1size; test_str += c2size; } } else #endif { for (;;) { i = *in_str; j = *test_str; if (isupper (i)) i = tolower (i); if (i != j) return (False); if (i == 0) return (True); in_str++; test_str++; } } } void _DtDuplicateDialogNameList ( char ** nameList, char ** newNameList, int newNameListSize, int * nameCount ) { int i; /* Get a copy of the name list to be used to build new name lists. */ *nameCount = 0; while (nameList[*nameCount] != NULL) { newNameList[*nameCount] = nameList[*nameCount]; (*nameCount)++; } /* NULL out any remaining array entries */ for (i = (*nameCount); i < newNameListSize; i++) newNameList[i] = NULL; } void _DtLoadSubdialogArray ( char ** nameList, int nameCount, DialogData *** dialogArray, int dialogCount, int dialogId, XrmDatabase dataBase, int firstId ) { int i; static char number[10]; /* Load sub-dialogs */ nameList[nameCount] = number; nameList[nameCount + 1] = NULL; /* Get text annotation dialogs */ *dialogArray = (DialogData **) XtMalloc(sizeof(DialogData *) * dialogCount); for (i = 0; i < dialogCount; i++) { snprintf(number, 10, "%d", firstId); (*dialogArray)[i] = _DtGetResourceDialogData(dialogId, dataBase, nameList); firstId++; } } void _DtSaveSubdialogArray ( char ** nameList, int nameCount, DialogData ** dialogArray, int dialogCount, int fd, int firstId ) { int i; static char number[10]; nameList[nameCount] = number; nameList[nameCount + 1] = NULL; for (i = 0; i < dialogCount; i++) { snprintf(number, 10, "%d", firstId); _DtWriteDialogData(dialogArray[i], fd, nameList); firstId++; } } void _DtDestroySubdialogArray ( DialogData ** dialogArray, int dialogCount ) { int i; for (i = 0; i < dialogCount; i++) { if (_DtIsDialogShowing(dialogArray[i])) _DtHideDialog(dialogArray[i], False); _DtFreeDialogData(dialogArray[i]); } XtFree((char *)dialogArray); } void _DtDestroySubdialog ( DialogData * dialogData ) { if (dialogData) { if (_DtIsDialogShowing(dialogData)) _DtHideDialog(dialogData, False); _DtFreeDialogData(dialogData); } } void _DtHideOneSubdialog ( DialogData * dialogData, DialogData *** dialogArray, int * dialogCountPtr ) { int i, j; for (i = 0; i < *dialogCountPtr; i++) { if (dialogData == (*dialogArray)[i]) { for (j = i; j < (*dialogCountPtr) - 1; j++) (*dialogArray)[j] = (*dialogArray)[j + 1]; break; } } /* Free or decrease the size of the dialog data list */ (*dialogCountPtr)--; if (*dialogCountPtr == 0) { XtFree((char *)*dialogArray); *dialogArray = NULL; } else { *dialogArray = (DialogData **) XtRealloc((char *)*dialogArray, sizeof(DialogData *) * (*dialogCountPtr)); } } void _DtAddOneSubdialog ( DialogData * dialogData, DialogData *** dialogArray, int * dialogCountPtr ) { int count; count = *dialogCountPtr; (*dialogCountPtr)++; (*dialogArray) = (DialogData **) XtRealloc((char *)(*dialogArray), sizeof(DialogData *) * (*dialogCountPtr)); (*dialogArray)[count] = dialogData; } /* * This function acts as a frontend to the encapsulator's map callback * function. If we are in the middle of a restore session, then we don't * want the map callback to alter the placement of the dialog, so we will * not call the encapsulator's function. */ void _DtMappedCB( Widget w, XtPointer client_data, XtPointer call_data ) { if (!disableDialogAutoPlacement) _DtmapCB(w,client_data,call_data); XtRemoveCallback(w, XmNpopupCallback, (XtCallbackProc)_DtMappedCB, client_data); } /* * This is the generic function for registering the map callback. */ void _DtGenericMapWindow ( Widget parent, XtPointer recordPtr) { GenericRecord * genericRecord = (GenericRecord *) recordPtr; XtAddCallback (genericRecord->shell, XmNpopupCallback, (XtCallbackProc)_DtMappedCB, (XtPointer) parent); } /* * This is the generic function for destroying a dialog widget hierarchy. */ void _DtGenericDestroy( XtPointer recordPtr ) { GenericRecord * genericRecord = (GenericRecord *) recordPtr; XtDestroyWidget(genericRecord->shell); XtFree((char *) genericRecord); } /* * This is the generic function for updating the shell's x and y, to * take the window manager border into consideration. */ void _DtGenericUpdateWindowPosition( DialogData * dataPtr ) { DialogInstanceData * genericData = (DialogInstanceData *) dataPtr->data; GenericRecord * genericRecord; /* Do nothing, if the dialog is not displayed */ if (genericData->displayed == True) { XmVendorShellExtObject vendorExt; XmWidgetExtData extData; Window junkWindow; int t_x, t_y; Arg args[5]; genericRecord = (GenericRecord *)_DtGetDialogInstance(dataPtr); XtSetArg(args[0], XmNwidth, &genericData->width); XtSetArg(args[1], XmNheight, &genericData->height); XtGetValues(genericRecord->shell, args, 2); XTranslateCoordinates(XtDisplay(genericRecord->shell), XtWindow(genericRecord->shell), RootWindowOfScreen(XtScreen(genericRecord->shell)), 0, 0, &t_x, &t_y, &junkWindow); genericData->x = (Position) t_x; genericData->y = (Position) t_y; /* Modify x & y to take into account window mgr frames */ extData=_XmGetWidgetExtData(genericRecord->shell, XmSHELL_EXTENSION); vendorExt = (XmVendorShellExtObject)extData->widget; genericData->x -= vendorExt->vendor.xOffset; genericData->y -= vendorExt->vendor.yOffset; } } /* * This is a function for building a path from directory and filename * parameters. */ void _DtBuildPath( char *path, char *directory, char *fileName) { if (directory) { if (fileName) sprintf(path, "%s/%s", directory, fileName); else sprintf(path, "%s", directory); } else { if (fileName) sprintf(path, "%s", fileName); else sprintf(path, "%s", ""); } } /* * This is a function for retrieving the pixmap data for a data type. */ PixmapData * _DtRetrievePixmapData( char *dataType, char *fileName, char *directory, Widget shell, int size) { PixmapData *pixmapData; char path[MAXPATHLEN]; char *iconName; pixmapData = (PixmapData *) XtMalloc(sizeof(PixmapData)); if (!pixmapData) return NULL; path[0] = 0x0; _DtBuildPath(path, directory, fileName); pixmapData->size = size; /* retrieve host name */ pixmapData->hostPrefix = DtDtsDataTypeToAttributeValue(dataType, DtDTS_DA_DATA_HOST, NULL); /* retrieve instance icon name if one exists; otherwise, retrieve class icon name */ if (path[0] != 0x0) { pixmapData->instanceIconName = DtDtsDataTypeToAttributeValue(dataType, DtDTS_DA_INSTANCE_ICON, path); } else pixmapData->instanceIconName = NULL; if (pixmapData->instanceIconName == NULL) { pixmapData->iconName = DtDtsDataTypeToAttributeValue( dataType, DtDTS_DA_ICON, NULL); if( pixmapData->iconName == NULL ) { if( strcmp( dataType, LT_DIRECTORY ) == 0 ) pixmapData->iconName = XtNewString( "DtdirB" ); else pixmapData->iconName = XtNewString( "Dtdeflt" ); } } else { pixmapData->iconName = NULL; } /* retrieve icon file name */ if (pixmapData->size == LARGE) pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell), pixmapData->instanceIconName, pixmapData->iconName, pixmapData->hostPrefix, DtMEDIUM); else pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell), pixmapData->instanceIconName, pixmapData->iconName, pixmapData->hostPrefix, DtTINY); /* return pixmap data */ return(pixmapData); } /* * This is a function for checking the size, etc of an icon pixmap and * freeing the pixmap data for an icon. */ void _DtCheckAndFreePixmapData( char *dataType, Widget shell, DtIconGadget iconGadget, PixmapData *pixmapData) { Arg args[1]; if (!pixmapData) return; /* if there was an instance icon name; verify that the pixmap parameters do not exceed system limits; if system limits are exceeded, retrieve class icon name and set icon gadget image resource to this value */ if (pixmapData->instanceIconName) { if(! pixmapData->iconFileName && iconGadget->icon.pixmap == 0) { /* Try to get pixmap name */ char * tmp, * ptr; tmp = XtNewString( pixmapData->instanceIconName ); if( ptr = strrchr( tmp,'/' ) ) *(ptr) = 0; XmeFlushIconFileCache( tmp ); if (pixmapData->iconFileName != NULL) XtFree(pixmapData->iconFileName); if (pixmapData->size == LARGE) pixmapData->iconFileName = _DtGetIconFileName( XtScreen(shell), pixmapData->instanceIconName, NULL, pixmapData->hostPrefix, DtMEDIUM ); else pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell), pixmapData->instanceIconName, NULL, pixmapData->hostPrefix, DtTINY); XtSetArg(args[0], XmNimageName, pixmapData->iconFileName); XtSetValues((Widget) iconGadget, args, 1); XtFree( tmp ); } DtDtsFreeAttributeValue(pixmapData->instanceIconName); pixmapData->instanceIconName = NULL; if (iconGadget->icon.pixmap == 0 || iconGadget->icon.pixmap_width == 0 || iconGadget->icon.pixmap_height == 0 || (Dimension)iconGadget->icon.pixmap_width > (Dimension)instanceWidth || (Dimension)iconGadget->icon.pixmap_height > (Dimension)instanceHeight) { pixmapData->iconName = DtDtsDataTypeToAttributeValue( dataType, DtDTS_DA_ICON, NULL); /* retrieve icon file name */ if (pixmapData->iconFileName != NULL) { XtFree(pixmapData->iconFileName); pixmapData->iconFileName = NULL; } if (pixmapData->size == LARGE) pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell), pixmapData->instanceIconName, pixmapData->iconName, pixmapData->hostPrefix, DtMEDIUM); else pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell), pixmapData->instanceIconName, pixmapData->iconName, pixmapData->hostPrefix, DtTINY); XtSetArg(args[0], XmNimageName, pixmapData->iconFileName); XtSetValues((Widget) iconGadget, args, 1); DtDtsFreeAttributeValue(pixmapData->iconName); pixmapData->iconName = NULL; } } else { DtDtsFreeAttributeValue(pixmapData->iconName); pixmapData->iconName = NULL; } DtDtsFreeAttributeValue(pixmapData->hostPrefix); if (pixmapData->iconFileName) XtFree(pixmapData->iconFileName); XtFree((char *) pixmapData); } /* * This is a function for checking for a datatype property. */ Boolean _DtCheckForDataTypeProperty( char *dataType, char *property) { char *properties; char *prop; char *props; Boolean found = False; properties = DtDtsDataTypeToAttributeValue(dataType, DtDTS_DA_PROPERTIES, NULL); if (properties) { props = properties; prop = props; while (props = DtStrchr(props, ',')) { *props = '\0'; if (strcmp(prop, property) == 0) { found = True; break; } *props = ','; props++; prop = props; } if (!props) { if (strcmp(prop, property) == 0) found = True; } DtDtsFreeAttributeValue(properties); } return found; } /* * This is a function for compiling a vectorized action list for a data type. */ char ** _DtCompileActionVector( char *dataType) { char *actions; char **vector = NULL; actions = DtDtsDataTypeToAttributeValue(dataType, DtDTS_DA_ACTION_LIST, NULL); if (actions) vector = (char **) _DtVectorizeInPlace(actions, ','); return(vector); } /* * This is a generic function for retrieving the default action for a data * type. */ char * _DtRetrieveDefaultAction( char *dataType) { char *actions; char *acts; char *default_action = NULL; actions = DtDtsDataTypeToAttributeValue(dataType, DtDTS_DA_ACTION_LIST, NULL); if (actions) { if (acts = DtStrchr(actions, ',')) *acts = '\0'; default_action = XtNewString(actions); DtDtsFreeAttributeValue(actions); } return(default_action); } /* * This is a function for building a title for a File Manager view. */ char * _DtBuildFMTitle( FileMgrData *file_mgr_data ) { char *title, *ptr, *fileLabel, *fileName; if (fileLabel = DtDtsFileToAttributeValue(file_mgr_data->current_directory, DtDTS_DA_LABEL)) ptr = fileLabel; else if (fileName = strrchr(file_mgr_data->current_directory, '/')) ptr = fileName + 1; else ptr = ""; if (file_mgr_data->title) { if (file_mgr_data->toolbox && strcmp(file_mgr_data->current_directory, file_mgr_data->restricted_directory) != 0) { title = (char *)XtMalloc(strlen(file_mgr_data->title) + strlen(ptr) + 4); /* Need for blank dash blank NULL */ sprintf(title, "%s - %s", file_mgr_data->title, ptr); } else { title = XtNewString(file_mgr_data->title); } } else { if (strcmp(file_mgr_data->current_directory, "/") == 0 && !fileLabel) { title = (char *)XtMalloc(strlen((GETMESSAGE(12, 7, "File Manager"))) + strlen(file_mgr_data->host) + strlen(root_title) + 5); /* Need for blank dash blank colon NULL */ sprintf( title, "%s - %s:%s", (GETMESSAGE(12, 7, "File Manager")), file_mgr_data->host, root_title ); } else { title = (char *)XtMalloc(strlen((GETMESSAGE(12, 7, "File Manager"))) + strlen(ptr) + 4); /* Need for blank dash blank NULL */ sprintf( title, "%s - %s", (GETMESSAGE(12, 7, "File Manager")), ptr); } } DtDtsFreeAttributeValue(fileLabel); return(title); } /* * This is a function for building a path from the directory name * and file name pieces of a FileViewData structure. */ char * _DtGetSelectedFilePath( FileViewData *selected_file ) { char *directory; char *file; char *path; directory = ((DirectorySet *)selected_file->directory_set)->name; file = selected_file->file_data->file_name; if (strcmp(directory, "/") == 0) { path = XtMalloc(strlen(directory) + strlen(file) + 1); sprintf(path, "%s%s", directory, file); } else { path = XtMalloc(strlen(directory) + strlen(file) + 2); sprintf(path, "%s/%s", directory, file); } return(path); } /* * This is a generic function for building action parameters from an array of * file view data structures. */ void _DtBuildActionArgsWithSelectedFiles( FileViewData **selection_list, int selected_count, DtActionArg **action_args, int *arg_count ) { *arg_count = 0; *action_args = (DtActionArg *) XtCalloc(1, sizeof(DtActionArg) * selected_count); if (*action_args) { int i; for(i = 0; i < selected_count; i++) { ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE; ((*action_args)[(*arg_count)++]).u.file.name = _DtGetSelectedFilePath(selection_list[i]); } } } void _DtBuildActionArgsWithDTSelectedFiles( DesktopRec **selection_list, int selected_count, DtActionArg **action_args, int *arg_count ) { *arg_count = 0; *action_args = (DtActionArg *) XtCalloc(1, sizeof(DtActionArg) * selected_count); if (*action_args) { int i; for(i = 0; i < selected_count; i++) { ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE; ((*action_args)[(*arg_count)++]).u.file.name = _DtGetSelectedFilePath(selection_list[i]->file_view_data); } } } /* * This is a generic function for building action parameters from drag and drop * file information. */ void _DtBuildActionArgsWithDroppedFiles( FileViewData *dropped_on_obj, DtDndDropCallbackStruct *drop_parameters, DtActionArg **action_args, int *arg_count ) { *arg_count = 0; if (dropped_on_obj) *action_args = (DtActionArg *) XtCalloc (1, sizeof(DtActionArg) * (drop_parameters->dropData->numItems + 1)); else *action_args = (DtActionArg *) XtCalloc (1, sizeof(DtActionArg) * drop_parameters->dropData->numItems); if (*action_args) { int i; if (dropped_on_obj) { ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE; ((*action_args)[(*arg_count)++]).u.file.name = _DtGetSelectedFilePath(dropped_on_obj); } for(i = 0; i < drop_parameters->dropData->numItems; i++) { ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE; ((*action_args)[(*arg_count)++]).u.file.name = XtNewString(drop_parameters->dropData->data.files[i]); } } } /* * This is a generic function for building action parameters from drag and drop * buffer information. */ void _DtBuildActionArgsWithDroppedBuffers( FileViewData *dropped_on_obj, DtDndDropCallbackStruct *drop_parameters, DtActionArg **action_args, int *arg_count ) { *arg_count = 0; if (dropped_on_obj) *action_args = (DtActionArg *) XtCalloc (1, sizeof(DtActionArg) * (drop_parameters->dropData->numItems + 1)); else *action_args = (DtActionArg *) XtCalloc (1, sizeof(DtActionArg) * drop_parameters->dropData->numItems); if (*action_args) { int i; DtActionBuffer buffer_arg = {NULL, 0, NULL, NULL, False}; if (dropped_on_obj) { ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE; ((*action_args)[(*arg_count)++]).u.file.name = _DtGetSelectedFilePath(dropped_on_obj); } for(i = 0; i < drop_parameters->dropData->numItems; i++) { buffer_arg.bp = drop_parameters->dropData->data.buffers[i].bp; buffer_arg.size = drop_parameters->dropData->data.buffers[i].size; buffer_arg.name = drop_parameters->dropData->data.buffers[i].name; ((*action_args)[(*arg_count)]).argClass = DtACTION_BUFFER; ((*action_args)[(*arg_count)++]).u.buffer = buffer_arg; } } } /* * This is a generic function for freeing action parameters. */ void _DtFreeActionArgs( DtActionArg *action_args, int arg_count ) { int i; for (i = 0; i < arg_count; i++) { if (action_args[i].argClass == DtACTION_FILE) { XtFree(action_args[i].u.file.name); action_args[i].u.file.name = NULL; } } XtFree((char *) action_args); } /************************************************************************ * The following functions deal with Buffer Manipulation and Naming ************************************************************************/ /* * This is a generic function for extracting buffer information from * drop input. */ void _DtSetDroppedBufferInfo(char **file_set, BufferInfo *buffer_set, char **host_set, DtDndDropCallbackStruct *drop_parameters) { int num_of_buffers = drop_parameters->dropData->numItems; int i; DtDndBuffer *buffers = drop_parameters->dropData->data.buffers; DPRINTF (("Executing..._DtSetDroppedBufferInfo\n")); /* Initialize file_set and ensure of unique file names for unamed buffers*/ SetBufferFileNames(file_set, buffers, num_of_buffers); for (i= 0; i < num_of_buffers; i++) { (buffer_set[i]).buf_ptr = buffers[i].bp; (buffer_set[i]).size = buffers[i].size; host_set[i] = XtNewString(home_host_name); DPRINTF(("_DtSetDroppedBufferInfo:\n host_set[%d]=%s,\ buffer_set[%d].buf_ptr=%p, buffer_set[%d].size=%d\n", i, host_set[i], i, buffer_set[i].buf_ptr, i, buffer_set[i].size)); } } /* * This is a function for creating file names for a set of buffers. */ static void SetBufferFileNames (char **file_set, DtDndBuffer *buffers, int num_of_buffers) { int null_filenames_count = 0; int i; int first_nullfile_index = 0; Boolean NULL_FILENAMES=FALSE; DPRINTF (("Executing...SetBufferFileNames\n")); for (i = 0; i < num_of_buffers; i++) { if (buffers[i].name == NULL) { /* generate buffer name using Untitled as a base name */ file_set[i]=BuildBufferFileName(DEFAULT_BUFFER_FILENAME, -1, buffers[i].bp, buffers[i].size); } else { /* file name is supplied by the drag initiator */ file_set[i] = XtNewString(buffers[i].name); } DPRINTF(("file_set[%d]=%s\n", i, file_set[i])); } /* end for loop */ /* Rename any collisions to unique names */ RenameCollisions(file_set, num_of_buffers); return; } /* * This is a generic function for generating a name for an untitled buffer. * A default name (Untitled) is used in conjunction with the name template * information from the types database. */ static char * BuildBufferFileName (char *file_name, int postfix_index, void *buffer, int buffer_size) { const char delim = '_'; char *new_file_name; DPRINTF (("Executing....BuildBufferFileName\n")); /* Malloc memory and contruct the new file name */ new_file_name = (char *) XtMalloc (strlen(file_name) + 1 + MAX_POSTFIX_LENGTH + 1); DPRINTF (("BuildBufferFileName: Old file name is %s\n", file_name)); /* determine whether to append post fix name */ if (postfix_index == -1) strcpy(new_file_name, file_name); else sprintf(new_file_name,"%s%c%d", file_name, delim, postfix_index); /* Retrieve the name template if it exists and use it in the filename */ new_file_name = RetrieveAndUseNameTemplateInfo(buffer, buffer_size, new_file_name); DPRINTF(("BuildBufferFileName: Returning new_file_name=%s\n", new_file_name)); /* return new file name */ return (new_file_name); } /* * This is a function for building a buffer name using predfined input * and name template information from the types database. * WARNING: template_input MAY be freed. It must point to a char *. */ static char * RetrieveAndUseNameTemplateInfo( void *buffer, int buffer_size, char *template_input) { char *name_template; char *buffer_name = NULL; name_template = DtDtsBufferToAttributeValue(buffer, buffer_size, DtDTS_DA_NAME_TEMPLATE, NULL); if (name_template) buffer_name = (char *) XtMalloc(strlen(name_template) + strlen(template_input) + 1); if (buffer_name) { sprintf(buffer_name, name_template, template_input); DtDtsFreeAttributeValue(name_template); XtFree(template_input); return(buffer_name); } else { DtDtsFreeAttributeValue(name_template); return(template_input); } } /* * This is a function for resolving collisions in a list of buffer names. */ static void RenameCollisions( char ** list, int count ) { int i, j, k, l; char flg = 0, flg2 = 0; for( i = 0; i < count; ++i ) { unsigned int addIndex = 1; if( *(list[i]) == 0x0 ) { k = i; flg = 1; } for( j = i+1; j < count; ++j ) { if( strcmp( list[i], list[j] ) == 0 ) { RenameEntry( &(list[j]), ++addIndex ); l = i; flg2 = 1; } } if( flg2 ) { flg2 = 0; RenameEntry( &(list[l]), 1 ); } } if( flg ) { free( list[k] ); list[k] = (char *)malloc( strlen( DEFAULT_BUFFER_FILENAME ) + 1 ); sprintf( list[k], "%s", DEFAULT_BUFFER_FILENAME ); } } /* * This is a function for adding an index to a buffer name which has * collided. */ static void RenameEntry( char ** name, unsigned int addIndex ) { #define MAX_INT_SIZE 15 char * tmpPtr, * newName; if( *name == 0x0 ) return; else if( **name == 0x0 ) { newName = (char *)XtCalloc(1,strlen(DEFAULT_BUFFER_FILENAME)+ MAX_INT_SIZE); sprintf( newName, "%s_%d", DEFAULT_BUFFER_FILENAME, addIndex ); } else { tmpPtr = strrchr( *name, '.' ); newName = (char *)XtCalloc( 1, strlen( *name ) + MAX_INT_SIZE ); if( tmpPtr == NULL ) sprintf( newName, "%s_%d", *name, addIndex ); else if( tmpPtr == *name ) sprintf( newName, "%d%s", addIndex, *name ); else { *tmpPtr = 0x0; sprintf( newName, "%s_%d.%s", *name, addIndex, ++tmpPtr); } } free( *name ); *name = newName; } /* * This is a generic function for freeing buffer information extracted from * drop input. */ void _DtFreeDroppedBufferInfo(char **file_set, BufferInfo *buffer_set, char **host_set, int num_of_buffers) { int i; DPRINTF (("Executing..._DtFreeDroppedBufferInfo\n")); /* Check for Null pointers */ if (file_set && buffer_set && host_set ) { for (i=0; i< num_of_buffers; i++ ) { XtFree(file_set[i]); XtFree(host_set[i]); } XtFree((char *)file_set); XtFree((char *)host_set); XtFree((char *)buffer_set); } } /* * This is a generic function for determining if a buffer is executable. */ Boolean _DtIsBufferExecutable( void *buffer, int buffer_size) { char *exe_attribute; Boolean is_exe = False; exe_attribute = DtDtsBufferToAttributeValue(buffer, buffer_size, "IS_EXECUTABLE", NULL); if (exe_attribute) { if (DtDtsIsTrue(exe_attribute)) is_exe = True; DtDtsFreeAttributeValue(exe_attribute); } return(is_exe); } /* * This is a generic function for extracting file information from drop input. */ void _DtSetDroppedFileInfo( DtDndDropCallbackStruct *drop_parameters, char ***file_set, char ***host_set) { int numFiles, i; numFiles = drop_parameters->dropData->numItems; *file_set = (char **)XtMalloc(sizeof(char *) * numFiles); *host_set = (char **)XtMalloc(sizeof(char *) * numFiles); for(i = 0; i < numFiles; i++) { (*file_set)[i] = XtNewString(drop_parameters->dropData->data.files[i]); (*host_set)[i] = home_host_name; DPRINTF(("ProcessMoveCopyLink:\n host_set[%d]=%s, file_set[%d]=%s\n", i, (*host_set)[i], i, (*file_set)[i])); } } /* * This is a generic function for copying file info extracted from drop input. */ void _DtCopyDroppedFileInfo( int num_files, char **orig_file_set, char **orig_host_set, char ***new_file_set, char ***new_host_set) { int i; *new_file_set = (char **)XtMalloc(sizeof(char *) * num_files); *new_host_set = (char **)XtMalloc(sizeof(char *) * num_files); for(i = 0; i < num_files; i++) { (*new_file_set)[i] = XtNewString(orig_file_set[i]); (*new_host_set)[i] = XtNewString(orig_host_set[i]); } } /* * This is a generic function for freeing file info extracted from drop input. */ void _DtFreeDroppedFileInfo( int num_files, char **file_set, char **host_set) { int i; for(i = 0; i < num_files; i++) XtFree(file_set[i]); XtFree((char *)file_set); XtFree((char *)host_set); } /* * This is a generic function for resolving a cannonical path from user input. */ void _DtPathFromInput( char *input_string, char *current_dir, char **host, char **rel_path) { char *path; char *tmp_path = NULL; char *true_path = NULL; Tt_status tt_status; int dir_len; /* find host */ *host = XtNewString(home_host_name); /* find relative path */ tmp_path = path = XtNewString(input_string); /* Strip any spaces from name -- input is overwritten */ path = (char *) _DtStripSpaces(path); /* Resolve, if there're any, environment variables */ { FILE *pfp = NULL; char command[MAXPATHLEN]; memset(command, 0, sizeof(command)); sprintf(command,"echo %s",path); if((pfp=popen(command,"r")) != NULL) { int read_ok = 1; if (NULL == (fgets(command,MAXPATHLEN,pfp))) { /* * Try a few more reads and if the read still fails, * just use the path as is. */ int i; for (i=0; i < 5; i++) { sleep (1); if (NULL != (fgets(command,MAXPATHLEN,pfp))) break; } if (i >= 5) read_ok = 0; } if (read_ok) { int slen = strlen(command); /* need to remove the trailing newline safely*/ if (slen >= 1) command[slen-1] = '\0'; XtFree(path); path = XtNewString(command); pclose(pfp); pfp = NULL; } } if (pfp) { pclose(pfp); pfp = NULL; } } /* Resolve '~' -- new memory is allocated, old memory is freed */ if (*path == '~') path = _DtChangeTildeToHome(path); /* If current dir provided, check for relative path */ if (path && current_dir) { if (*path != '/') { /* file is relative path i.e. xyz/abc */ if (strcmp(current_dir, "/") == 0) { tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 1); sprintf(tmp_path, "%s%s", current_dir, path); } else { tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 2); sprintf(tmp_path, "%s/%s", current_dir, path); } XtFree(path); path = tmp_path; tmp_path = NULL; } } else if (!path) { *rel_path = NULL; XtFree(tmp_path); return; } /* Resolve '.' or '..' -- input is overwritten, output may be NULL! */ /* Save pointer to path to free if output is NULL. */ tmp_path = path; path = (char *) DtEliminateDots(path); if (path) { /* Resolve to local pathname */ true_path = ResolveLocalPathName(*host, path, NULL, home_host_name, &tt_status); XtFree(path); /* Strip off trailing '/' */ dir_len = strlen(true_path); if (dir_len > 1 && *(true_path + dir_len - 1) == '/') *(true_path + dir_len - 1) = '\0'; } else { true_path = NULL; XtFree(tmp_path); } *rel_path = true_path; } /* * This function takes a path name, and resolves any leading '~' to refer * to one of the following: * * 1) if ~ or ~/path, then it resolves to the user's home directory on * their home host. * * 2) if ~user or ~user/path, then it resolves to the specified user's * home directory on the home host. * * This function never resolves to any host but the home host, since we * have no way of determining a user's home directory on any system other * than the home system. */ char * _DtChangeTildeToHome ( char *input_string) { char *path; char *full_path; struct passwd * pwInfo; if ((input_string[1] != '\0') && (input_string[1] != '/')) { char *path; /* ~user or ~user/path format */ /* is there a path? */ path = DtStrchr(input_string, '/'); /* find user */ if (path) *path = '\0'; if ((pwInfo = getpwnam(input_string + 1)) == NULL) { /* user doesn't exist */ if (path) *path = '/'; return NULL; } if (path) { /* ~user/path format */ *path = '/'; if (strcmp(pwInfo->pw_dir, "/") == 0) { /* We don't want to end up with double '/' in the path */ full_path = (char *) XtMalloc(strlen(path) + 1); strcpy(full_path, path); } else { full_path = (char *) XtMalloc(strlen(pwInfo->pw_dir) + strlen(path) + 1); sprintf(full_path, "%s%s", pwInfo->pw_dir, path); } } else { /* ~user format */ full_path = XtMalloc(strlen(pwInfo->pw_dir) + 1); strcpy(full_path, pwInfo->pw_dir); } } else if (input_string[1]) { /* ~/path format */ /* NOTE: users_home_dir has trailing '/' */ full_path = XtMalloc(strlen(users_home_dir) + strlen(input_string+2) + 1); sprintf(full_path, "%s%s", users_home_dir, (input_string + 2)); } else { /* ~ format */ full_path = XtMalloc(strlen(users_home_dir) + 1); strcpy(full_path, users_home_dir); } XtFree(input_string); return(full_path); } /* * This function checks for spaces in filenames. */ #ifdef _CHECK_FOR_SPACES Boolean _DtSpacesInFileNames( char **fileNames, int fileCount ) { int i; for (i = 0; i < fileCount; i++) { fileNames[i] = (char *) _DtStripSpaces(fileNames[i]); if (DtStrchr (fileNames[i], ' ') != NULL || DtStrchr (fileNames[i], '\t') != NULL) return(TRUE); } return(FALSE); } #endif /* * This resolves the path for an appmanager object to its true path. */ char * _DtResolveAppManPath( char *path, char *restricted_dir ) { if (strlen(path) > strlen(restricted_dir)) { char *linkDir, *ptr, *tmpPath; linkDir = path + strlen(restricted_dir) + 1; ptr = DtStrchr(linkDir, '/'); if (ptr) { *ptr = '\0'; linkDir = _DtFollowLink(path); *ptr = '/'; tmpPath = XtMalloc(strlen(linkDir) + strlen(ptr) + 1); sprintf(tmpPath, "%s%s", linkDir, ptr); XtFree(path); path = tmpPath; } else { linkDir = _DtFollowLink(path); XtFree(path); path = XtNewString(linkDir); } } return(path); }