2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $XConsortium: SharedProcs.c /main/7 1996/10/03 14:01:42 drk $ */
24 /************************************<+>*************************************
25 ****************************************************************************
29 * COMPONENT_NAME: Desktop File Manager (dtfile)
31 * Description: Contains the set of functions which are of general
32 * use to all DT clients.
34 * FUNCTIONS: BuildBufferFileName
37 * RetrieveAndUseNameTemplateInfo
40 * _DtBuildActionArgsWithDroppedBuffers
41 * _DtBuildActionArgsWithDroppedFiles
42 * _DtBuildActionArgsWithSelectedFiles
43 * _DtBuildActionArgsWithDTSelectedFiles
46 * _DtChangeTildeToHome
47 * _DtCheckAndFreePixmapData
48 * _DtCheckForDataTypeProperty
49 * _DtCompileActionVector
50 * _DtCopyDroppedFileInfo
52 * _DtDestroySubdialogArray
53 * _DtDuplicateDialogNameList
56 * _DtFreeDroppedBufferInfo
57 * _DtFreeDroppedFileInfo
60 * _DtGenericUpdateWindowPosition
61 * _DtGetSelectedFilePath
63 * _DtIsBufferExecutable
64 * _DtLoadSubdialogArray
68 * _DtResolveAppManPath
69 * _DtRetrieveDefaultAction
70 * _DtRetrievePixmapData
71 * _DtSaveSubdialogArray
72 * _DtSetDroppedBufferInfo
73 * _DtSetDroppedFileInfo
74 * _DtSpacesInFileNames
75 * _DtStringsAreEquivalent
77 * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
78 * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
79 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
80 * (c) Copyright 1993, 1994, 1995 Novell, Inc.
82 ****************************************************************************
83 ************************************<+>*************************************/
85 #include <sys/types.h>
97 #include <Xm/VendorSEP.h>
98 #include <Xm/MessageB.h>
99 #include <Xm/RowColumn.h>
100 #include <Xm/MwmUtil.h>
101 #include <Xm/Protocols.h>
102 #include <X11/ShellP.h>
103 #include <X11/Shell.h>
104 #include <X11/Xatom.h>
105 /* Copied from Xm/BaseClassI.h */
106 extern XmWidgetExtData _XmGetWidgetExtData(
108 #if NeedWidePrototypes
109 unsigned int extType) ;
111 unsigned char extType) ;
112 #endif /* NeedWidePrototypes */
115 #include <Dt/Connect.h>
116 #include <Dt/DtNlUtils.h>
119 #include <Dt/IconP.h>
120 #include <Dt/IconFile.h>
121 #include <Dt/Action.h>
131 #include "SharedProcs.h"
133 extern char *pathcollapse();
137 #define RW_ALL S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
140 /* Global controlling whether auto-positioning is enabled */
141 Boolean disableDialogAutoPlacement = False;
144 /******** Static Function Declarations ********/
146 static void SetBufferFileNames (
148 DtDndBuffer *buffers,
149 int num_of_buffers) ;
150 static char * BuildBufferFileName (
155 static char * RetrieveAndUseNameTemplateInfo(
158 char *template_input) ;
159 static void RenameEntry(
161 unsigned int addIndex) ;
162 static void RenameCollisions(
166 /******** End Static Function Declarations ********/
169 /************************************************************************
172 * Returns the parent directory of its argument.
173 * Does this by looking for the last "/" in the name, and
176 ************************************************************************/
180 register char *name )
184 static char pnam[MAXPATHLEN];
185 static char dot[] = ".";
188 q = strrchr(pnam, '/');
192 else if ((q == pnam) &&
194 (mblen(q, MB_CUR_MAX) == 1) &&
203 return(pnam[0] ? pnam : dot);
208 * Given a filename, follow it to the end of its link. Returns NULL if
209 * a recursive symbolic link is found.
211 * Note, the path returned is a static buffer, and should not be freed by
212 * the calling function.
219 char link_path[MAXPATHLEN];
220 static char file[MAXPATHLEN];
228 /* Used to check for symbolic link loops */
231 history = (char **)XtMalloc(sizeof(char *) * history_size);
235 while ((link_len = readlink(file, link_path, MAXPATHLEN)) > 0)
237 link_path[link_len] = '\0';
239 /* Force the link to be an absolute path, if necessary */
240 if (link_path[0] != '/')
242 /* Relative paths are relative to the current directory */
243 end = strrchr(file, '/') + 1;
245 strcat(file, link_path);
248 strcpy(file, link_path);
250 /* Check for a recursive loop; abort if found */
251 for (i = 0; i < history_count; i++)
253 if (strcmp(file, history[i]) == 0)
255 for (i = 0; i < history_count; i++)
257 XtFree((char *)history);
263 /* Add to the history list */
264 if (history_count >= history_size)
267 history = (char **)XtRealloc((char *)history,
268 sizeof(char *) * history_size);
270 history[history_count++] = XtNewString(file);
273 /* Free up the history list */
274 for (i = 0; i < history_count; i++)
276 XtFree((char *)history);
283 /************************************************************************
285 * _DtStringsAreEquivalent
286 * Compare two strings and return true if equal.
287 * The comparison is on lower cased strings. It is the callers
288 * responsibility to ensure that test_str is already lower cased.
290 ************************************************************************/
293 _DtStringsAreEquivalent(
294 register char *in_str,
295 register char *test_str )
310 /* Convert each character from multibyte to wide format */
311 c1size = mbtowc(&c1, in_str, MB_CUR_MAX);
312 c2size = mbtowc(&c2, test_str, MB_CUR_MAX);
314 /* No match, if the two characters have different byte counts */
315 if (c1size != c2size)
318 /* Do case conversion only for single byte characters */
321 if (isupper((int) c1))
322 c1 = tolower((int) c1);
325 /* See if the two wide characters match */
329 /* Are we at the end of the string? */
346 if (isupper (i)) i = tolower (i);
347 if (i != j) return (False);
348 if (i == 0) return (True);
359 _DtDuplicateDialogNameList (
368 /* Get a copy of the name list to be used to build new name lists. */
370 while (nameList[*nameCount] != NULL)
372 newNameList[*nameCount] = nameList[*nameCount];
376 /* NULL out any remaining array entries */
377 for (i = (*nameCount); i < newNameListSize; i++)
378 newNameList[i] = NULL;
383 _DtLoadSubdialogArray (
386 DialogData *** dialogArray,
389 XrmDatabase dataBase,
396 /* Load sub-dialogs */
397 nameList[nameCount] = number;
398 nameList[nameCount + 1] = NULL;
400 /* Get text annotation dialogs */
401 *dialogArray = (DialogData **) XtMalloc(sizeof(DialogData *) * dialogCount);
403 for (i = 0; i < dialogCount; i++)
405 sprintf(number, "%d", firstId);
406 (*dialogArray)[i] = _DtGetResourceDialogData(dialogId, dataBase, nameList);
414 _DtSaveSubdialogArray (
417 DialogData ** dialogArray,
426 nameList[nameCount] = number;
427 nameList[nameCount + 1] = NULL;
429 for (i = 0; i < dialogCount; i++)
431 sprintf(number, "%d", firstId);
432 _DtWriteDialogData(dialogArray[i], fd, nameList);
439 _DtDestroySubdialogArray (
440 DialogData ** dialogArray,
446 for (i = 0; i < dialogCount; i++)
448 if (_DtIsDialogShowing(dialogArray[i]))
449 _DtHideDialog(dialogArray[i], False);
451 _DtFreeDialogData(dialogArray[i]);
453 XtFree((char *)dialogArray);
458 _DtDestroySubdialog (
459 DialogData * dialogData )
464 if (_DtIsDialogShowing(dialogData))
465 _DtHideDialog(dialogData, False);
466 _DtFreeDialogData(dialogData);
472 _DtHideOneSubdialog (
473 DialogData * dialogData,
474 DialogData *** dialogArray,
475 int * dialogCountPtr )
480 for (i = 0; i < *dialogCountPtr; i++)
482 if (dialogData == (*dialogArray)[i])
484 for (j = i; j < (*dialogCountPtr) - 1; j++)
485 (*dialogArray)[j] = (*dialogArray)[j + 1];
490 /* Free or decrease the size of the dialog data list */
492 if (*dialogCountPtr == 0)
494 XtFree((char *)*dialogArray);
499 *dialogArray = (DialogData **)
500 XtRealloc((char *)*dialogArray,
501 sizeof(DialogData *) * (*dialogCountPtr));
508 DialogData * dialogData,
509 DialogData *** dialogArray,
510 int * dialogCountPtr )
515 count = *dialogCountPtr;
517 (*dialogArray) = (DialogData **) XtRealloc((char *)(*dialogArray),
518 sizeof(DialogData *) * (*dialogCountPtr));
519 (*dialogArray)[count] = dialogData;
524 * This function acts as a frontend to the encapsulator's map callback
525 * function. If we are in the middle of a restore session, then we don't
526 * want the map callback to alter the placement of the dialog, so we will
527 * not call the encapsulator's function.
533 XtPointer client_data,
534 XtPointer call_data )
536 if (!disableDialogAutoPlacement)
537 _DtmapCB(w,client_data,call_data);
539 XtRemoveCallback(w, XmNpopupCallback, (XtCallbackProc)_DtMappedCB, client_data);
544 * This is the generic function for registering the map callback.
548 _DtGenericMapWindow (
552 GenericRecord * genericRecord = (GenericRecord *) recordPtr;
554 XtAddCallback (genericRecord->shell, XmNpopupCallback,
555 (XtCallbackProc)_DtMappedCB, (XtPointer) parent);
560 * This is the generic function for destroying a dialog widget hierarchy.
565 XtPointer recordPtr )
568 GenericRecord * genericRecord = (GenericRecord *) recordPtr;
570 XtDestroyWidget(genericRecord->shell);
571 XtFree((char *) genericRecord);
576 * This is the generic function for updating the shell's x and y, to
577 * take the window manager border into consideration.
581 _DtGenericUpdateWindowPosition(
582 DialogData * dataPtr )
585 DialogInstanceData * genericData = (DialogInstanceData *) dataPtr->data;
586 GenericRecord * genericRecord;
588 /* Do nothing, if the dialog is not displayed */
589 if (genericData->displayed == True)
591 XmVendorShellExtObject vendorExt;
592 XmWidgetExtData extData;
597 genericRecord = (GenericRecord *)_DtGetDialogInstance(dataPtr);
599 XtSetArg(args[0], XmNwidth, &genericData->width);
600 XtSetArg(args[1], XmNheight, &genericData->height);
601 XtGetValues(genericRecord->shell, args, 2);
603 XTranslateCoordinates(XtDisplay(genericRecord->shell),
604 XtWindow(genericRecord->shell),
605 RootWindowOfScreen(XtScreen(genericRecord->shell)),
608 genericData->x = (Position) t_x;
609 genericData->y = (Position) t_y;
611 /* Modify x & y to take into account window mgr frames */
612 extData=_XmGetWidgetExtData(genericRecord->shell, XmSHELL_EXTENSION);
613 vendorExt = (XmVendorShellExtObject)extData->widget;
614 genericData->x -= vendorExt->vendor.xOffset;
615 genericData->y -= vendorExt->vendor.yOffset;
621 * This is a function for building a path from directory and filename
635 sprintf(path, "%s/%s", directory, fileName);
637 sprintf(path, "%s", directory);
642 sprintf(path, "%s", fileName);
644 sprintf(path, "%s", "");
650 * This is a function for retrieving the pixmap data for a data type.
654 _DtRetrievePixmapData(
662 PixmapData *pixmapData;
663 char path[MAXPATHLEN];
666 pixmapData = (PixmapData *) XtMalloc(sizeof(PixmapData));
671 _DtBuildPath(path, directory, fileName);
673 pixmapData->size = size;
675 /* retrieve host name */
676 pixmapData->hostPrefix = DtDtsDataTypeToAttributeValue(dataType,
681 retrieve instance icon name if one exists; otherwise, retrieve class
686 pixmapData->instanceIconName = DtDtsDataTypeToAttributeValue(dataType,
687 DtDTS_DA_INSTANCE_ICON,
691 pixmapData->instanceIconName = NULL;
693 if (pixmapData->instanceIconName == NULL)
695 pixmapData->iconName = DtDtsDataTypeToAttributeValue( dataType,
696 DtDTS_DA_ICON, NULL);
697 if( pixmapData->iconName == NULL )
699 if( strcmp( dataType, LT_DIRECTORY ) == 0 )
700 pixmapData->iconName = XtNewString( "DtdirB" );
702 pixmapData->iconName = XtNewString( "Dtdeflt" );
707 pixmapData->iconName = NULL;
710 /* retrieve icon file name */
711 if (pixmapData->size == LARGE)
712 pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
713 pixmapData->instanceIconName,
714 pixmapData->iconName,
715 pixmapData->hostPrefix,
718 pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
719 pixmapData->instanceIconName,
720 pixmapData->iconName,
721 pixmapData->hostPrefix,
724 /* return pixmap data */
730 * This is a function for checking the size, etc of an icon pixmap and
731 * freeing the pixmap data for an icon.
735 _DtCheckAndFreePixmapData(
738 DtIconGadget iconGadget,
739 PixmapData *pixmapData)
748 if there was an instance icon name; verify that the pixmap parameters
749 do not exceed system limits; if system limits are exceeded, retrieve
750 class icon name and set icon gadget image resource to this value
752 if (pixmapData->instanceIconName)
755 if(! pixmapData->iconFileName && iconGadget->icon.pixmap == NULL)
756 { /* Try to get pixmap name
760 tmp = XtNewString( pixmapData->instanceIconName );
761 if( ptr = strrchr( tmp,'/' ) )
763 XmeFlushIconFileCache( tmp );
765 if (pixmapData->iconFileName != NULL)
766 XtFree(pixmapData->iconFileName);
767 if (pixmapData->size == LARGE)
768 pixmapData->iconFileName = _DtGetIconFileName( XtScreen(shell),
769 pixmapData->instanceIconName,
771 pixmapData->hostPrefix,
774 pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
775 pixmapData->instanceIconName,
777 pixmapData->hostPrefix,
782 XtSetArg(args[0], XmNimageName, pixmapData->iconFileName);
783 XtSetValues((Widget) iconGadget, args, 1);
790 DtDtsFreeAttributeValue(pixmapData->instanceIconName);
792 if (iconGadget->icon.pixmap == NULL ||
793 iconGadget->icon.pixmap_width == NULL ||
794 iconGadget->icon.pixmap_height == NULL ||
795 (Dimension)iconGadget->icon.pixmap_width > (Dimension)instanceWidth ||
796 (Dimension)iconGadget->icon.pixmap_height > (Dimension)instanceHeight)
799 pixmapData->iconName = DtDtsDataTypeToAttributeValue(
801 DtDTS_DA_ICON, NULL);
803 /* retrieve icon file name */
804 if (pixmapData->iconFileName != NULL)
806 XtFree(pixmapData->iconFileName);
807 pixmapData->iconFileName = NULL;
810 if (pixmapData->size == LARGE)
811 pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
812 pixmapData->instanceIconName,
813 pixmapData->iconName,
814 pixmapData->hostPrefix,
817 pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
818 pixmapData->instanceIconName,
819 pixmapData->iconName,
820 pixmapData->hostPrefix,
825 XtSetArg(args[0], XmNimageName, pixmapData->iconFileName);
826 XtSetValues((Widget) iconGadget, args, 1);
828 DtDtsFreeAttributeValue(pixmapData->iconName);
833 DtDtsFreeAttributeValue(pixmapData->iconName);
836 DtDtsFreeAttributeValue(pixmapData->hostPrefix);
837 if (pixmapData->iconFileName)
838 XtFree(pixmapData->iconFileName);
840 XtFree((char *) pixmapData);
845 * This is a function for checking for a datatype property.
849 _DtCheckForDataTypeProperty(
857 Boolean found = False;
860 properties = DtDtsDataTypeToAttributeValue(dataType,
868 while (props = DtStrchr(props, ','))
871 if (strcmp(prop, property) == 0)
883 if (strcmp(prop, property) == 0)
887 DtDtsFreeAttributeValue(properties);
895 * This is a function for compiling a vectorized action list for a data type.
899 _DtCompileActionVector(
904 char **vector = NULL;
906 actions = DtDtsDataTypeToAttributeValue(dataType,
907 DtDTS_DA_ACTION_LIST,
910 vector = (char **) _DtVectorizeInPlace(actions, ',');
917 * This is a generic function for retrieving the default action for a data
922 _DtRetrieveDefaultAction(
928 char *default_action = NULL;
930 actions = DtDtsDataTypeToAttributeValue(dataType,
931 DtDTS_DA_ACTION_LIST,
935 if (acts = DtStrchr(actions, ','))
937 default_action = XtNewString(actions);
939 DtDtsFreeAttributeValue(actions);
942 return(default_action);
947 * This is a function for building a title for a File Manager view.
952 FileMgrData *file_mgr_data )
955 char *title, *ptr, *fileLabel, *fileName;
957 if (fileLabel = DtDtsFileToAttributeValue(file_mgr_data->current_directory,
960 else if (fileName = strrchr(file_mgr_data->current_directory, '/'))
965 if (file_mgr_data->title)
967 if (file_mgr_data->toolbox &&
968 strcmp(file_mgr_data->current_directory,
969 file_mgr_data->restricted_directory) != 0)
971 title = (char *)XtMalloc(strlen(file_mgr_data->title) +
973 4); /* Need for blank dash blank NULL */
974 sprintf(title, "%s - %s", file_mgr_data->title, ptr);
978 title = XtNewString(file_mgr_data->title);
983 if (strcmp(file_mgr_data->current_directory, "/") == 0 && !fileLabel)
985 title = (char *)XtMalloc(strlen((GETMESSAGE(12, 7, "File Manager"))) +
986 strlen(file_mgr_data->host) +
988 5); /* Need for blank dash blank colon NULL */
989 sprintf( title, "%s - %s:%s", (GETMESSAGE(12, 7, "File Manager")),
995 title = (char *)XtMalloc(strlen((GETMESSAGE(12, 7, "File Manager"))) +
997 4); /* Need for blank dash blank NULL */
998 sprintf( title, "%s - %s", (GETMESSAGE(12, 7, "File Manager")), ptr);
1002 DtDtsFreeAttributeValue(fileLabel);
1008 * This is a function for building a path from the directory name
1009 * and file name pieces of a FileViewData structure.
1013 _DtGetSelectedFilePath(
1014 FileViewData *selected_file )
1021 directory = ((DirectorySet *)selected_file->directory_set)->name;
1022 file = selected_file->file_data->file_name;
1024 if (strcmp(directory, "/") == 0)
1026 path = XtMalloc(strlen(directory) + strlen(file) + 1);
1027 sprintf(path, "%s%s", directory, file);
1031 path = XtMalloc(strlen(directory) + strlen(file) + 2);
1032 sprintf(path, "%s/%s", directory, file);
1040 * This is a generic function for building action parameters from an array of
1041 * file view data structures.
1045 _DtBuildActionArgsWithSelectedFiles(
1046 FileViewData **selection_list,
1048 DtActionArg **action_args,
1054 *action_args = (DtActionArg *)
1055 XtCalloc(1, sizeof(DtActionArg) * selected_count);
1061 for(i = 0; i < selected_count; i++)
1063 ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1064 ((*action_args)[(*arg_count)++]).u.file.name =
1065 _DtGetSelectedFilePath(selection_list[i]);
1072 _DtBuildActionArgsWithDTSelectedFiles(
1073 DesktopRec **selection_list,
1075 DtActionArg **action_args,
1081 *action_args = (DtActionArg *)
1082 XtCalloc(1, sizeof(DtActionArg) * selected_count);
1088 for(i = 0; i < selected_count; i++)
1090 ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1091 ((*action_args)[(*arg_count)++]).u.file.name =
1092 _DtGetSelectedFilePath(selection_list[i]->file_view_data);
1099 * This is a generic function for building action parameters from drag and drop
1104 _DtBuildActionArgsWithDroppedFiles(
1105 FileViewData *dropped_on_obj,
1106 DtDndDropCallbackStruct *drop_parameters,
1107 DtActionArg **action_args,
1114 *action_args = (DtActionArg *) XtCalloc
1115 (1, sizeof(DtActionArg) * (drop_parameters->dropData->numItems + 1));
1117 *action_args = (DtActionArg *) XtCalloc
1118 (1, sizeof(DtActionArg) * drop_parameters->dropData->numItems);
1126 ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1127 ((*action_args)[(*arg_count)++]).u.file.name =
1128 _DtGetSelectedFilePath(dropped_on_obj);
1131 for(i = 0; i < drop_parameters->dropData->numItems; i++)
1133 ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1134 ((*action_args)[(*arg_count)++]).u.file.name =
1135 XtNewString(drop_parameters->dropData->data.files[i]);
1142 * This is a generic function for building action parameters from drag and drop
1143 * buffer information.
1148 _DtBuildActionArgsWithDroppedBuffers(
1149 FileViewData *dropped_on_obj,
1150 DtDndDropCallbackStruct *drop_parameters,
1151 DtActionArg **action_args,
1158 *action_args = (DtActionArg *) XtCalloc
1159 (1, sizeof(DtActionArg) * (drop_parameters->dropData->numItems + 1));
1161 *action_args = (DtActionArg *) XtCalloc
1162 (1, sizeof(DtActionArg) * drop_parameters->dropData->numItems);
1167 DtActionBuffer buffer_arg = {NULL, 0, NULL, NULL, False};
1171 ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1172 ((*action_args)[(*arg_count)++]).u.file.name =
1173 _DtGetSelectedFilePath(dropped_on_obj);
1176 for(i = 0; i < drop_parameters->dropData->numItems; i++)
1178 buffer_arg.bp = drop_parameters->dropData->data.buffers[i].bp;
1179 buffer_arg.size = drop_parameters->dropData->data.buffers[i].size;
1180 buffer_arg.name = drop_parameters->dropData->data.buffers[i].name;
1182 ((*action_args)[(*arg_count)]).argClass = DtACTION_BUFFER;
1183 ((*action_args)[(*arg_count)++]).u.buffer = buffer_arg;
1190 * This is a generic function for freeing action parameters.
1195 DtActionArg *action_args,
1201 for (i = 0; i < arg_count; i++)
1203 if (action_args[i].argClass == DtACTION_FILE)
1205 XtFree(action_args[i].u.file.name);
1206 action_args[i].u.file.name = NULL;
1210 XtFree((char *) action_args);
1214 /************************************************************************
1215 * The following functions deal with Buffer Manipulation and Naming
1216 ************************************************************************/
1219 * This is a generic function for extracting buffer information from
1224 _DtSetDroppedBufferInfo(char **file_set,
1225 BufferInfo *buffer_set,
1227 DtDndDropCallbackStruct *drop_parameters)
1231 int num_of_buffers = drop_parameters->dropData->numItems;
1233 DtDndBuffer *buffers = drop_parameters->dropData->data.buffers;
1236 DPRINTF (("Executing..._DtSetDroppedBufferInfo\n"));
1238 /* Initialize file_set and ensure of unique file names for unamed buffers*/
1239 SetBufferFileNames(file_set, buffers, num_of_buffers);
1241 for (i= 0; i < num_of_buffers; i++)
1244 (buffer_set[i]).buf_ptr = buffers[i].bp;
1245 (buffer_set[i]).size = buffers[i].size;
1247 host_set[i] = XtNewString(home_host_name);
1249 DPRINTF(("_DtSetDroppedBufferInfo:\n host_set[%d]=%s,\
1250 buffer_set[%d].buf_ptr=%p, buffer_set[%d].size=%d\n",
1251 i, host_set[i], i, buffer_set[i].buf_ptr, i, buffer_set[i].size));
1257 * This is a function for creating file names for a set of buffers.
1261 SetBufferFileNames (char **file_set,
1262 DtDndBuffer *buffers,
1265 int null_filenames_count = 0;
1267 int first_nullfile_index = 0;
1268 Boolean NULL_FILENAMES=FALSE;
1270 DPRINTF (("Executing...SetBufferFileNames\n"));
1272 for (i = 0; i < num_of_buffers; i++)
1274 if (buffers[i].name == NULL)
1276 /* generate buffer name using Untitled as a base name */
1277 file_set[i]=BuildBufferFileName(DEFAULT_BUFFER_FILENAME,
1284 /* file name is supplied by the drag initiator */
1285 file_set[i] = XtNewString(buffers[i].name);
1288 DPRINTF(("file_set[%d]=%s\n", i, file_set[i]));
1290 } /* end for loop */
1293 /* Rename any collisions to unique names */
1294 RenameCollisions(file_set, num_of_buffers);
1301 * This is a generic function for generating a name for an untitled buffer.
1302 * A default name (Untitled) is used in conjunction with the name template
1303 * information from the types database.
1307 BuildBufferFileName (char *file_name,
1312 const char delim = '_';
1313 char *new_file_name;
1316 DPRINTF (("Executing....BuildBufferFileName\n"));
1318 /* Malloc memory and contruct the new file name */
1319 new_file_name = (char *) XtMalloc (strlen(file_name) + 1 +
1320 MAX_POSTFIX_LENGTH + 1);
1322 DPRINTF (("BuildBufferFileName: Old file name is %s\n", file_name));
1324 /* determine whether to append post fix name */
1325 if (postfix_index == -1)
1326 strcpy(new_file_name, file_name);
1328 sprintf(new_file_name,"%s%c%d", file_name, delim, postfix_index);
1330 /* Retrieve the name template if it exists and use it in the filename */
1331 new_file_name = RetrieveAndUseNameTemplateInfo(buffer,
1335 DPRINTF(("BuildBufferFileName: Returning new_file_name=%s\n", new_file_name));
1337 /* return new file name */
1338 return (new_file_name);
1344 * This is a function for building a buffer name using predfined input
1345 * and name template information from the types database.
1346 * WARNING: template_input will be freed. It must point to a char *.
1350 RetrieveAndUseNameTemplateInfo(
1353 char *template_input)
1356 char *name_template;
1357 char *buffer_name = NULL;
1359 name_template = DtDtsBufferToAttributeValue(buffer,
1361 DtDTS_DA_NAME_TEMPLATE,
1364 buffer_name = (char *) XtMalloc(strlen(name_template) +
1365 strlen(template_input) +
1369 sprintf(buffer_name, name_template, template_input);
1370 DtDtsFreeAttributeValue(name_template);
1371 XtFree(template_input);
1372 return(buffer_name);
1376 return(template_input);
1382 * This is a function for resolving collisions in a list of buffer names.
1386 RenameCollisions( char ** list, int count )
1388 register int i, j, k, l;
1389 char flg = 0, flg2 = 0;
1391 for( i = 0; i < count; ++i )
1393 unsigned int addIndex = 1;
1395 if( *(list[i]) == 0x0 )
1401 for( j = i+1; j < count; ++j )
1403 if( strcmp( list[i], list[j] ) == 0 )
1405 RenameEntry( &(list[j]), ++addIndex );
1413 RenameEntry( &(list[l]), 1 );
1419 list[k] = (char *)malloc( strlen( DEFAULT_BUFFER_FILENAME ) + 1 );
1420 sprintf( list[k], "%s", DEFAULT_BUFFER_FILENAME );
1426 * This is a function for adding an index to a buffer name which has
1431 RenameEntry( char ** name, unsigned int addIndex )
1434 #define MAX_INT_SIZE 15
1436 char * tmpPtr, * newName;
1440 else if( **name == 0x0 )
1442 newName = (char *)XtCalloc(1,strlen(DEFAULT_BUFFER_FILENAME)+ MAX_INT_SIZE);
1443 sprintf( newName, "%s_%d", DEFAULT_BUFFER_FILENAME, addIndex );
1447 tmpPtr = strrchr( *name, '.' );
1449 newName = (char *)XtCalloc( 1, strlen( *name ) + MAX_INT_SIZE );
1451 if( tmpPtr == NULL )
1452 sprintf( newName, "%s_%d", *name, addIndex );
1453 else if( tmpPtr == *name )
1454 sprintf( newName, "%d%s", addIndex, *name );
1458 sprintf( newName, "%s_%d.%s", *name, addIndex, ++tmpPtr);
1467 * This is a generic function for freeing buffer information extracted from
1472 _DtFreeDroppedBufferInfo(char **file_set,
1473 BufferInfo *buffer_set,
1479 DPRINTF (("Executing..._DtFreeDroppedBufferInfo\n"));
1481 /* Check for Null pointers */
1482 if (file_set && buffer_set && host_set )
1484 for (i=0; i< num_of_buffers; i++ )
1486 XtFree(file_set[i]);
1487 XtFree(host_set[i]);
1490 XtFree((char *)file_set);
1491 XtFree((char *)host_set);
1492 XtFree((char *)buffer_set);
1498 * This is a generic function for determining if a buffer is executable.
1502 _DtIsBufferExecutable(
1507 char *exe_attribute;
1508 Boolean is_exe = False;
1510 exe_attribute = DtDtsBufferToAttributeValue(buffer,
1516 if (DtDtsIsTrue(exe_attribute))
1519 DtDtsFreeAttributeValue(exe_attribute);
1527 * This is a generic function for extracting file information from drop input.
1531 _DtSetDroppedFileInfo(
1532 DtDndDropCallbackStruct *drop_parameters,
1538 numFiles = drop_parameters->dropData->numItems;
1540 *file_set = (char **)XtMalloc(sizeof(char *) * numFiles);
1541 *host_set = (char **)XtMalloc(sizeof(char *) * numFiles);
1542 for(i = 0; i < numFiles; i++)
1544 (*file_set)[i] = XtNewString(drop_parameters->dropData->data.files[i]);
1545 (*host_set)[i] = home_host_name;
1547 DPRINTF(("ProcessMoveCopyLink:\n host_set[%d]=%s, file_set[%d]=%s\n",
1548 i, (*host_set)[i], i, (*file_set)[i]));
1554 * This is a generic function for copying file info extracted from drop input.
1558 _DtCopyDroppedFileInfo(
1560 char **orig_file_set,
1561 char **orig_host_set,
1562 char ***new_file_set,
1563 char ***new_host_set)
1567 *new_file_set = (char **)XtMalloc(sizeof(char *) * num_files);
1568 *new_host_set = (char **)XtMalloc(sizeof(char *) * num_files);
1569 for(i = 0; i < num_files; i++)
1571 (*new_file_set)[i] = XtNewString(orig_file_set[i]);
1572 (*new_host_set)[i] = XtNewString(orig_host_set[i]);
1578 * This is a generic function for freeing file info extracted from drop input.
1582 _DtFreeDroppedFileInfo(
1589 for(i = 0; i < num_files; i++)
1590 XtFree(file_set[i]);
1592 XtFree((char *)file_set);
1593 XtFree((char *)host_set);
1598 * This is a generic function for resolving a cannonical path from user input.
1610 char *tmp_path = NULL;
1611 char *true_path = NULL;
1612 Tt_status tt_status;
1616 *host = XtNewString(home_host_name);
1618 /* find relative path */
1619 tmp_path = path = XtNewString(input_string);
1621 /* Strip any spaces from name -- input is overwritten */
1622 path = (char *) _DtStripSpaces(path);
1624 /* Resolve, if there're any, environment variables */
1627 char command[MAXPATHLEN];
1629 sprintf(command,"echo %s",path);
1631 if((pfp=popen(command,"r")) != NULL)
1635 if (NULL == (fgets(command,MAXPATHLEN,pfp)))
1638 * Try a few more reads and if the read still fails,
1639 * just use the path as is.
1642 for (i=0; i < 5; i++)
1645 if (NULL != (fgets(command,MAXPATHLEN,pfp)))
1654 command[strlen(command)-1] = '\0';
1656 path = XtNewString(command);
1662 /* Resolve '~' -- new memory is allocated, old memory is freed */
1664 path = _DtChangeTildeToHome(path);
1666 /* If current dir provided, check for relative path */
1667 if (path && current_dir)
1671 /* file is relative path i.e. xyz/abc */
1672 if (strcmp(current_dir, "/") == 0)
1674 tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 1);
1675 sprintf(tmp_path, "%s%s", current_dir, path);
1679 tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 2);
1680 sprintf(tmp_path, "%s/%s", current_dir, path);
1695 /* Resolve '.' or '..' -- input is overwritten, output may be NULL! */
1696 /* Save pointer to path to free if output is NULL. */
1698 path = (char *) DtEliminateDots(path);
1702 /* Resolve to local pathname */
1703 true_path = ResolveLocalPathName(*host,
1710 /* Strip off trailing '/' */
1711 dir_len = strlen(true_path);
1712 if (dir_len > 1 && *(true_path + dir_len - 1) == '/')
1713 *(true_path + dir_len - 1) = NULL;
1721 *rel_path = true_path;
1726 * This function takes a path name, and resolves any leading '~' to refer
1727 * to one of the following:
1729 * 1) if ~ or ~/path, then it resolves to the user's home directory on
1732 * 2) if ~user or ~user/path, then it resolves to the specified user's
1733 * home directory on the home host.
1735 * This function never resolves to any host but the home host, since we
1736 * have no way of determining a user's home directory on any system other
1737 * than the home system.
1741 _DtChangeTildeToHome (
1746 struct passwd * pwInfo;
1748 if ((input_string[1] != '\0') && (input_string[1] != '/'))
1752 /* ~user or ~user/path format */
1754 /* is there a path? */
1755 path = DtStrchr(input_string, '/');
1760 if ((pwInfo = getpwnam(input_string + 1)) == NULL)
1762 /* user doesn't exist */
1770 /* ~user/path format */
1774 if (strcmp(pwInfo->pw_dir, "/") == 0)
1776 /* We don't want to end up with double '/' in the path */
1777 full_path = (char *) XtMalloc(strlen(path) + 1);
1778 strcpy(full_path, path);
1782 full_path = (char *) XtMalloc(strlen(pwInfo->pw_dir) +
1784 sprintf(full_path, "%s%s", pwInfo->pw_dir, path);
1791 full_path = XtMalloc(strlen(pwInfo->pw_dir) + 1);
1792 strcpy(full_path, pwInfo->pw_dir);
1795 else if (input_string[1])
1799 /* NOTE: users_home_dir has trailing '/' */
1800 full_path = XtMalloc(strlen(users_home_dir) + strlen(input_string+2) + 1);
1801 sprintf(full_path, "%s%s", users_home_dir, (input_string + 2));
1807 full_path = XtMalloc(strlen(users_home_dir) + 1);
1808 strcpy(full_path, users_home_dir);
1811 XtFree(input_string);
1817 * This function checks for spaces in filenames.
1819 #ifdef _CHECK_FOR_SPACES
1822 _DtSpacesInFileNames(
1828 for (i = 0; i < fileCount; i++)
1830 fileNames[i] = (char *) _DtStripSpaces(fileNames[i]);
1832 if (DtStrchr (fileNames[i], ' ') != NULL ||
1833 DtStrchr (fileNames[i], '\t') != NULL)
1843 * This resolves the path for an appmanager object to its true path.
1847 _DtResolveAppManPath(
1849 char *restricted_dir )
1851 if (strlen(path) > strlen(restricted_dir))
1853 char *linkDir, *ptr, *tmpPath;
1855 linkDir = path + strlen(restricted_dir) + 1;
1856 ptr = DtStrchr(linkDir, '/');
1860 linkDir = _DtFollowLink(path);
1862 tmpPath = XtMalloc(strlen(linkDir) + strlen(ptr) + 1);
1863 sprintf(tmpPath, "%s%s", linkDir, ptr);
1869 linkDir = _DtFollowLink(path);
1871 path = XtNewString(linkDir);