dthelp: Change to ANSI function definitions
[oweals/cde.git] / cde / programs / dtfile / SharedProcs.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: SharedProcs.c /main/7 1996/10/03 14:01:42 drk $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  *
27  *   FILE:           SharedProcs.c
28  *
29  *   COMPONENT_NAME: Desktop File Manager (dtfile)
30  *
31  *   Description:    Contains the set of functions which are of general
32  *                   use to all DT clients.
33  *
34  *   FUNCTIONS: BuildBufferFileName
35  *              RenameCollisions
36  *              RenameEntry
37  *              RetrieveAndUseNameTemplateInfo
38  *              SetBufferFileNames
39  *              _DtAddOneSubdialog
40  *              _DtBuildActionArgsWithDroppedBuffers
41  *              _DtBuildActionArgsWithDroppedFiles
42  *              _DtBuildActionArgsWithSelectedFiles
43  *              _DtBuildActionArgsWithDTSelectedFiles
44  *              _DtBuildFMTitle
45  *              _DtBuildPath
46  *              _DtChangeTildeToHome
47  *              _DtCheckAndFreePixmapData
48  *              _DtCheckForDataTypeProperty
49  *              _DtCompileActionVector
50  *              _DtCopyDroppedFileInfo
51  *              _DtDestroySubdialog
52  *              _DtDestroySubdialogArray
53  *              _DtDuplicateDialogNameList
54  *              _DtFollowLink
55  *              _DtFreeActionArgs
56  *              _DtFreeDroppedBufferInfo
57  *              _DtFreeDroppedFileInfo
58  *              _DtGenericDestroy
59  *              _DtGenericMapWindow
60  *              _DtGenericUpdateWindowPosition
61  *              _DtGetSelectedFilePath
62  *              _DtHideOneSubdialog
63  *              _DtIsBufferExecutable
64  *              _DtLoadSubdialogArray
65  *              _DtMappedCB
66  *              _DtPName
67  *              _DtPathFromInput
68  *              _DtResolveAppManPath
69  *              _DtRetrieveDefaultAction
70  *              _DtRetrievePixmapData
71  *              _DtSaveSubdialogArray
72  *              _DtSetDroppedBufferInfo
73  *              _DtSetDroppedFileInfo
74  *              _DtSpacesInFileNames
75  *              _DtStringsAreEquivalent
76  *
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.
81  *
82  ****************************************************************************
83  ************************************<+>*************************************/
84
85 #include <sys/types.h>
86 #include <sys/stat.h>
87 #include <errno.h>
88 #include <fcntl.h>
89 #include <limits.h>
90 #include <stdio.h>
91 #include <time.h>
92 #include <pwd.h>
93 #include <ctype.h>
94
95 #include <Xm/Xm.h>
96 #include <Xm/XmP.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( 
107                         Widget widget,
108 #if NeedWidePrototypes
109                         unsigned int extType) ;
110 #else
111                         unsigned char extType) ;
112 #endif /* NeedWidePrototypes */
113
114 #include <Dt/DtP.h>
115 #include <Dt/Connect.h>
116 #include <Dt/DtNlUtils.h>
117 #include <Dt/Dts.h>
118 #include <Dt/Icon.h>
119 #include <Dt/IconP.h>
120 #include <Dt/IconFile.h>
121 #include <Dt/Action.h>
122 #include <Dt/Dnd.h>
123 #include <Dt/Utility.h>
124 #include <Dt/SharedProcs.h>
125
126 #include <Tt/tttk.h>
127
128 #include "Encaps.h"
129 #include "FileMgr.h"
130 #include "Desktop.h"
131 #include "Common.h"
132 #include "Main.h"
133 #include "SharedProcs.h"
134
135 extern char *pathcollapse();
136
137
138 /* Defines */
139 #define RW_ALL S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
140
141
142 /* Global controlling whether auto-positioning is enabled */
143 Boolean disableDialogAutoPlacement = False;
144
145
146 /********    Static Function Declarations    ********/
147
148 static void SetBufferFileNames (
149                         char **file_set,
150                         DtDndBuffer *buffers,
151                         int num_of_buffers) ;
152 static char * BuildBufferFileName (
153                         char *file_name,
154                         int postfix_index,
155                         void *buffer,
156                         int buffer_size) ;
157 static char * RetrieveAndUseNameTemplateInfo(
158                         void *buffer,
159                         int buffer_size,
160                         char *template_input) ;
161 static void RenameEntry(
162                         char **name,
163                         unsigned int addIndex) ;
164 static void RenameCollisions(
165                         char **list,
166                         int count) ;
167
168 /********    End Static Function Declarations    ********/
169
170
171 /************************************************************************
172  *
173  *  _DtPName
174  *      Returns the parent directory of its argument.
175  *      Does this by looking for the last "/" in the name, and
176  *      NULL'ing it out.
177  *
178  ************************************************************************/
179
180 char *
181 _DtPName(
182         register char *name )
183
184 {
185    register char * q;
186    static char pnam[MAXPATHLEN];
187    static char dot[] = ".";
188
189    strcpy(pnam, name);
190    q = strrchr(pnam, '/');
191
192    if (q == NULL)
193       q = pnam;
194    else if ((q == pnam) &&
195 #ifdef NLS16
196             (mblen(q, MB_CUR_MAX) == 1) &&
197 #endif
198             (*q == '/'))
199    {
200       q++;
201    }
202
203    *q = '\0';
204
205    return(pnam[0] ? pnam : dot);
206 }
207
208
209 /*
210  * Given a filename, follow it to the end of its link.  Returns NULL if
211  * a recursive symbolic link is found.
212  *
213  * Note, the path returned is a static buffer, and should not be freed by
214  * the calling function.
215  */
216
217 char *
218 _DtFollowLink (
219    char * path)
220 {
221    char link_path[MAXPATHLEN];
222    static char file[MAXPATHLEN];
223    int link_len;
224    char * end;
225    int history_count;
226    int history_size;
227    char ** history;
228    int i;
229
230    /* Used to check for symbolic link loops */
231    history_count = 0;
232    history_size = 100;
233    history = (char **)XtMalloc(sizeof(char *) * history_size);
234
235    strcpy(file, path);
236
237    while ((link_len = readlink(file, link_path, MAXPATHLEN - 1)) > 0)
238    {
239       link_path[link_len] = 0;
240
241       /* Force the link to be an absolute path, if necessary */
242       if (link_path[0] != '/')
243       {
244          /* Relative paths are relative to the current directory */
245          end = strrchr(file, '/') + 1;
246          *end = '\0';
247          strcat(file, link_path);
248       }
249       else
250          strcpy(file, link_path);
251
252       /* Check for a recursive loop; abort if found */
253       for (i = 0; i < history_count; i++)
254       {
255          if (strcmp(file, history[i]) == 0)
256          {
257             for (i = 0; i < history_count; i++)
258                XtFree(history[i]);
259             XtFree((char *)history);
260             history = NULL;
261             return(NULL);
262          }
263       }
264
265       /* Add to the history list */
266       if (history_count >= history_size)
267       {
268          history_size += 100;
269          history = (char **)XtRealloc((char *)history,
270                                       sizeof(char *) * history_size);
271       }
272       history[history_count++] = XtNewString(file);
273    }
274
275    /* Free up the history list */
276    for (i = 0; i < history_count; i++)
277       XtFree(history[i]);
278    XtFree((char *)history);
279    history = NULL;
280
281    return(file);
282 }
283
284
285 /************************************************************************
286  *
287  *  _DtStringsAreEquivalent
288  *      Compare two strings and return true if equal.
289  *      The comparison is on lower cased strings.  It is the callers
290  *      responsibility to ensure that test_str is already lower cased.
291  *
292  ************************************************************************/
293
294 Boolean
295 _DtStringsAreEquivalent(
296         register char *in_str,
297         register char *test_str )
298 {
299 #ifdef NLS16
300    wchar_t c1;
301    wchar_t c2;
302    int c1size, c2size;
303 #endif
304    register int i;
305    register int j;
306
307 #ifdef NLS16
308    if (is_multibyte)
309    {
310       for (;;)
311       {
312          /* Convert each character from multibyte to wide format */
313          c1size = mbtowc(&c1, in_str, MB_CUR_MAX);
314          c2size = mbtowc(&c2, test_str, MB_CUR_MAX);
315
316          /* No match, if the two characters have different byte counts */
317          if (c1size != c2size)
318             return(False);
319
320          /* Do case conversion only for single byte characters */
321          if (c1size == 1)
322          {
323             if (isupper((int) c1))
324                c1 = tolower((int) c1);
325          }
326
327          /* See if the two wide characters match */
328          if (c1 != c2)
329             return(False);
330
331          /* Are we at the end of the string? */
332          if (c1 == '\0')
333             return(True);
334
335          /* Keep comparing */
336          in_str += c1size;
337          test_str += c2size;
338       }
339    }
340    else
341 #endif
342    {
343       for (;;)
344       {
345          i = *in_str;
346          j = *test_str;
347
348          if (isupper (i)) i = tolower (i);
349          if (i != j) return (False);
350          if (i == 0) return (True);
351
352          in_str++;
353          test_str++;
354       }
355    }
356 }
357
358
359
360 void
361 _DtDuplicateDialogNameList (
362         char ** nameList,
363         char ** newNameList,
364         int newNameListSize,
365         int * nameCount )
366
367 {
368    int i;
369
370    /*  Get a copy of the name list to be used to build new name lists.  */
371    *nameCount = 0;
372    while (nameList[*nameCount] != NULL)
373    {
374       newNameList[*nameCount] = nameList[*nameCount];
375       (*nameCount)++;
376    }
377
378    /* NULL out any remaining array entries */
379    for (i = (*nameCount); i < newNameListSize; i++)
380       newNameList[i] = NULL;
381 }
382
383
384 void
385 _DtLoadSubdialogArray (
386         char ** nameList,
387         int    nameCount,
388         DialogData *** dialogArray,
389         int    dialogCount,
390         int    dialogId,
391         XrmDatabase dataBase,
392         int    firstId )
393
394 {
395    int i;
396    static char number[10];
397
398    /* Load sub-dialogs */
399    nameList[nameCount] = number;
400    nameList[nameCount + 1] = NULL;
401
402    /* Get text annotation dialogs */
403    *dialogArray = (DialogData **) XtMalloc(sizeof(DialogData *) * dialogCount);
404
405    for (i = 0; i < dialogCount; i++)
406    {
407       snprintf(number, 10, "%d", firstId);
408       (*dialogArray)[i] = _DtGetResourceDialogData(dialogId, dataBase, nameList);
409       firstId++;
410    }
411 }
412
413
414
415 void
416 _DtSaveSubdialogArray (
417         char ** nameList,
418         int    nameCount,
419         DialogData ** dialogArray,
420         int    dialogCount,
421         int    fd,
422         int    firstId )
423
424 {
425    int i;
426    static char number[10];
427
428    nameList[nameCount] = number;
429    nameList[nameCount + 1] = NULL;
430
431    for (i = 0; i < dialogCount; i++)
432    {
433       snprintf(number, 10, "%d", firstId);
434       _DtWriteDialogData(dialogArray[i], fd, nameList);
435       firstId++;
436    }
437 }
438
439
440 void
441 _DtDestroySubdialogArray (
442         DialogData ** dialogArray,
443         int    dialogCount )
444
445 {
446    int i;
447
448    for (i = 0; i < dialogCount; i++)
449    {
450       if (_DtIsDialogShowing(dialogArray[i]))
451          _DtHideDialog(dialogArray[i], False);
452
453       _DtFreeDialogData(dialogArray[i]);
454    }
455    XtFree((char *)dialogArray);
456 }
457
458
459 void
460 _DtDestroySubdialog (
461         DialogData * dialogData )
462
463 {
464    if (dialogData)
465    {
466       if (_DtIsDialogShowing(dialogData))
467          _DtHideDialog(dialogData, False);
468       _DtFreeDialogData(dialogData);
469    }
470 }
471
472
473 void
474 _DtHideOneSubdialog (
475         DialogData * dialogData,
476         DialogData *** dialogArray,
477         int         * dialogCountPtr )
478
479 {
480    int i, j;
481
482    for (i = 0; i < *dialogCountPtr; i++)
483    {
484       if (dialogData == (*dialogArray)[i])
485       {
486          for (j = i; j < (*dialogCountPtr) - 1; j++)
487             (*dialogArray)[j] = (*dialogArray)[j + 1];
488          break;
489       }
490    }
491
492    /*  Free or decrease the size of the dialog data list  */
493    (*dialogCountPtr)--;
494    if (*dialogCountPtr == 0)
495    {
496       XtFree((char *)*dialogArray);
497       *dialogArray = NULL;
498    }
499    else
500    {
501       *dialogArray = (DialogData **)
502          XtRealloc((char *)*dialogArray,
503                    sizeof(DialogData *) * (*dialogCountPtr));
504    }
505 }
506
507
508 void
509 _DtAddOneSubdialog (
510         DialogData * dialogData,
511         DialogData *** dialogArray,
512         int         * dialogCountPtr )
513
514 {
515    int count;
516
517    count = *dialogCountPtr;
518    (*dialogCountPtr)++;
519    (*dialogArray) = (DialogData **) XtRealloc((char *)(*dialogArray),
520                                   sizeof(DialogData *) * (*dialogCountPtr));
521    (*dialogArray)[count] = dialogData;
522 }
523
524
525 /*
526  * This function acts as a frontend to the encapsulator's map callback
527  * function.  If we are in the middle of a restore session, then we don't
528  * want the map callback to alter the placement of the dialog, so we will
529  * not call the encapsulator's function.
530  */
531
532 void
533 _DtMappedCB(
534          Widget w,
535          XtPointer client_data,
536          XtPointer call_data )
537 {
538    if (!disableDialogAutoPlacement)
539       _DtmapCB(w,client_data,call_data);
540
541    XtRemoveCallback(w, XmNpopupCallback, (XtCallbackProc)_DtMappedCB, client_data);
542 }
543
544
545 /*
546  * This is the generic function for registering the map callback.
547  */
548
549 void
550 _DtGenericMapWindow (
551      Widget parent,
552      XtPointer recordPtr)
553 {
554    GenericRecord * genericRecord = (GenericRecord *) recordPtr;
555
556    XtAddCallback (genericRecord->shell, XmNpopupCallback,
557                   (XtCallbackProc)_DtMappedCB, (XtPointer) parent);
558 }
559
560
561 /*
562  * This is the generic function for destroying a dialog widget hierarchy.
563  */
564
565 void
566 _DtGenericDestroy(
567         XtPointer recordPtr )
568
569 {
570    GenericRecord * genericRecord = (GenericRecord *) recordPtr;
571
572    XtDestroyWidget(genericRecord->shell);
573    XtFree((char *) genericRecord);
574 }
575
576
577 /*
578  * This is the generic function for updating the shell's x and y, to
579  * take the window manager border into consideration.
580  */
581
582 void
583 _DtGenericUpdateWindowPosition(
584         DialogData * dataPtr )
585
586 {
587    DialogInstanceData * genericData = (DialogInstanceData *) dataPtr->data;
588    GenericRecord * genericRecord;
589
590    /* Do nothing, if the dialog is not displayed */
591    if (genericData->displayed == True)
592    {
593       XmVendorShellExtObject vendorExt;
594       XmWidgetExtData        extData;
595       Window                 junkWindow;
596       int                    t_x, t_y;
597       Arg                    args[5];
598
599       genericRecord = (GenericRecord *)_DtGetDialogInstance(dataPtr);
600
601       XtSetArg(args[0], XmNwidth, &genericData->width);
602       XtSetArg(args[1], XmNheight, &genericData->height);
603       XtGetValues(genericRecord->shell, args, 2);
604
605       XTranslateCoordinates(XtDisplay(genericRecord->shell),
606                        XtWindow(genericRecord->shell),
607                        RootWindowOfScreen(XtScreen(genericRecord->shell)),
608                        0, 0, &t_x, &t_y,
609                        &junkWindow);
610       genericData->x = (Position) t_x;
611       genericData->y = (Position) t_y;
612
613       /* Modify x & y to take into account window mgr frames */
614       extData=_XmGetWidgetExtData(genericRecord->shell, XmSHELL_EXTENSION);
615       vendorExt = (XmVendorShellExtObject)extData->widget;
616       genericData->x -= vendorExt->vendor.xOffset;
617       genericData->y -= vendorExt->vendor.yOffset;
618    }
619 }
620
621
622 /*
623  * This is a function for building a path from directory and filename
624  * parameters.
625  */
626
627 void
628 _DtBuildPath(
629         char         *path,
630         char         *directory,
631         char         *fileName)
632
633 {
634   if (directory)
635   {
636     if (fileName)
637       sprintf(path, "%s/%s", directory, fileName);
638     else
639       sprintf(path, "%s", directory);
640   }
641   else
642   {
643     if (fileName)
644       sprintf(path, "%s", fileName);
645     else
646       sprintf(path, "%s", "");
647   }
648 }
649
650
651 /*
652  * This is a function for retrieving the pixmap data for a data type.
653  */
654
655 PixmapData *
656 _DtRetrievePixmapData(
657         char         *dataType,
658         char         *fileName,
659         char         *directory,
660         Widget        shell,
661         int           size)
662
663 {
664   PixmapData *pixmapData;
665   char path[MAXPATHLEN];
666   char *iconName;
667
668   pixmapData = (PixmapData *) XtMalloc(sizeof(PixmapData));
669   if (!pixmapData)
670     return NULL;
671
672   path[0] = 0x0;
673   _DtBuildPath(path, directory, fileName);
674
675   pixmapData->size = size;
676
677   /* retrieve host name */
678   pixmapData->hostPrefix = DtDtsDataTypeToAttributeValue(dataType,
679                                                          DtDTS_DA_DATA_HOST,
680                                                          NULL);
681
682   /*
683      retrieve instance icon name if one exists; otherwise, retrieve class
684      icon name
685   */
686   if (path[0] != 0x0)
687   {
688     pixmapData->instanceIconName = DtDtsDataTypeToAttributeValue(dataType,
689                                             DtDTS_DA_INSTANCE_ICON,
690                                             path);
691   }
692   else
693     pixmapData->instanceIconName = NULL;
694
695   if (pixmapData->instanceIconName == NULL)
696   {
697     pixmapData->iconName = DtDtsDataTypeToAttributeValue( dataType, 
698                                                           DtDTS_DA_ICON, NULL);
699     if( pixmapData->iconName == NULL )
700     {
701       if( strcmp( dataType, LT_DIRECTORY ) == 0 )
702         pixmapData->iconName = XtNewString( "DtdirB" );
703       else
704         pixmapData->iconName = XtNewString( "Dtdeflt" );
705     }
706   }
707   else
708   {
709     pixmapData->iconName = NULL;
710   }
711
712   /* retrieve icon file name */
713   if (pixmapData->size == LARGE)
714      pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
715                                                pixmapData->instanceIconName,
716                                                pixmapData->iconName,
717                                                pixmapData->hostPrefix,
718                                                DtMEDIUM);
719   else
720      pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
721                                                pixmapData->instanceIconName,
722                                                pixmapData->iconName,
723                                                pixmapData->hostPrefix,
724                                                DtTINY);
725
726   /* return pixmap data */
727   return(pixmapData);
728 }
729
730
731 /*
732  * This is a function for checking the size, etc of an icon pixmap and
733  * freeing the pixmap data for an icon.
734  */
735
736 void
737 _DtCheckAndFreePixmapData(
738         char         *dataType,
739         Widget        shell,
740         DtIconGadget  iconGadget,
741         PixmapData   *pixmapData)
742
743 {
744   Arg   args[1];
745
746   if (!pixmapData)
747     return;
748
749   /*
750      if there was an instance icon name; verify that the pixmap parameters
751      do not exceed system limits; if system limits are exceeded, retrieve
752      class icon name and set icon gadget image resource to this value
753   */
754   if (pixmapData->instanceIconName)
755   {
756
757     if(! pixmapData->iconFileName && iconGadget->icon.pixmap == 0)
758     { /* Try to get pixmap name
759       */
760       char * tmp, * ptr;
761
762       tmp = XtNewString( pixmapData->instanceIconName );
763       if( ptr = strrchr( tmp,'/' ) )
764         *(ptr) = 0;
765       XmeFlushIconFileCache( tmp );
766
767       if (pixmapData->iconFileName != NULL)
768          XtFree(pixmapData->iconFileName);
769       if (pixmapData->size == LARGE)
770         pixmapData->iconFileName = _DtGetIconFileName( XtScreen(shell),
771                                               pixmapData->instanceIconName,
772                                               NULL,
773                                               pixmapData->hostPrefix,
774                                               DtMEDIUM );
775       else
776         pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
777                                               pixmapData->instanceIconName,
778                                               NULL,
779                                               pixmapData->hostPrefix,
780                                               DtTINY);
781
782
783
784       XtSetArg(args[0], XmNimageName, pixmapData->iconFileName);
785       XtSetValues((Widget) iconGadget, args, 1);
786
787       XtFree( tmp );
788     }
789
790
791
792     DtDtsFreeAttributeValue(pixmapData->instanceIconName);
793     pixmapData->instanceIconName = NULL;
794
795     if (iconGadget->icon.pixmap == 0                     ||
796         iconGadget->icon.pixmap_width == 0               ||
797         iconGadget->icon.pixmap_height == 0              ||
798         (Dimension)iconGadget->icon.pixmap_width > (Dimension)instanceWidth    ||
799         (Dimension)iconGadget->icon.pixmap_height > (Dimension)instanceHeight)
800     {
801
802       pixmapData->iconName = DtDtsDataTypeToAttributeValue(
803                                              dataType, 
804                                              DtDTS_DA_ICON, NULL);
805
806       /* retrieve icon file name */
807       if (pixmapData->iconFileName != NULL)
808       {
809          XtFree(pixmapData->iconFileName);
810          pixmapData->iconFileName = NULL;
811       }
812
813       if (pixmapData->size == LARGE)
814             pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
815                                              pixmapData->instanceIconName,
816                                              pixmapData->iconName,
817                                              pixmapData->hostPrefix,
818                                              DtMEDIUM);
819       else
820             pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
821                                              pixmapData->instanceIconName,
822                                              pixmapData->iconName,
823                                              pixmapData->hostPrefix,
824                                              DtTINY);
825
826
827
828       XtSetArg(args[0], XmNimageName, pixmapData->iconFileName);
829       XtSetValues((Widget) iconGadget, args, 1);
830
831       DtDtsFreeAttributeValue(pixmapData->iconName);
832       pixmapData->iconName = NULL;
833     }
834   }
835   else
836   {
837      DtDtsFreeAttributeValue(pixmapData->iconName);
838      pixmapData->iconName = NULL;
839   }
840
841   DtDtsFreeAttributeValue(pixmapData->hostPrefix);
842   if (pixmapData->iconFileName)
843      XtFree(pixmapData->iconFileName);
844
845   XtFree((char *) pixmapData);
846 }
847
848
849 /*
850  * This is a function for checking for a datatype property.
851  */
852
853 Boolean
854 _DtCheckForDataTypeProperty(
855         char *dataType,
856         char *property)
857
858 {
859    char *properties;
860    char *prop;
861    char *props;
862    Boolean found = False;
863
864
865    properties = DtDtsDataTypeToAttributeValue(dataType,
866                                               DtDTS_DA_PROPERTIES,
867                                               NULL);
868
869    if (properties)
870    {
871      props = properties;
872      prop = props;
873      while (props = DtStrchr(props, ','))
874      {
875        *props = '\0';
876        if (strcmp(prop, property) == 0)
877        {
878          found = True;
879          break;
880        }
881        *props = ','; 
882        props++;
883        prop = props;
884      }
885
886      if (!props)
887      {
888        if (strcmp(prop, property) == 0)
889          found = True;
890      }
891
892      DtDtsFreeAttributeValue(properties);
893    }
894
895    return found;
896 }
897
898
899 /*
900  * This is a function for compiling a vectorized action list for a data type.
901  */
902
903 char **
904 _DtCompileActionVector(
905         char *dataType)
906
907 {
908    char *actions;
909    char **vector = NULL;
910
911    actions = DtDtsDataTypeToAttributeValue(dataType,
912                                            DtDTS_DA_ACTION_LIST,
913                                            NULL);
914    if (actions)
915      vector = (char **) _DtVectorizeInPlace(actions, ',');
916
917    return(vector);
918 }
919
920
921 /*
922  * This is a generic function for retrieving the default action for a data
923  * type.
924  */
925
926 char *
927 _DtRetrieveDefaultAction(
928         char *dataType)
929
930 {
931    char *actions;
932    char *acts;
933    char *default_action = NULL;
934
935    actions = DtDtsDataTypeToAttributeValue(dataType,
936                                            DtDTS_DA_ACTION_LIST,
937                                            NULL);
938    if (actions)
939    {
940      if (acts = DtStrchr(actions, ','))
941        *acts = '\0';
942      default_action = XtNewString(actions);
943
944      DtDtsFreeAttributeValue(actions);
945    }
946
947    return(default_action);
948 }
949
950
951 /*
952  * This is a function for building a title for a File Manager view.
953  */
954
955 char *
956 _DtBuildFMTitle(
957         FileMgrData *file_mgr_data )
958
959 {
960    char *title, *ptr, *fileLabel, *fileName;
961
962    if (fileLabel = DtDtsFileToAttributeValue(file_mgr_data->current_directory,
963                                              DtDTS_DA_LABEL))
964       ptr = fileLabel;
965    else if (fileName = strrchr(file_mgr_data->current_directory, '/'))
966       ptr = fileName + 1;
967    else
968       ptr = "";
969
970    if (file_mgr_data->title)
971    {
972       if (file_mgr_data->toolbox &&
973           strcmp(file_mgr_data->current_directory,
974                  file_mgr_data->restricted_directory) != 0)
975       {
976          title = (char *)XtMalloc(strlen(file_mgr_data->title) +
977                                   strlen(ptr) +
978                                   4); /* Need for blank dash blank NULL */
979          sprintf(title, "%s - %s", file_mgr_data->title, ptr);
980       }
981       else
982       {
983          title = XtNewString(file_mgr_data->title);
984       }
985    }
986    else
987    {
988       if (strcmp(file_mgr_data->current_directory, "/") == 0 && !fileLabel)
989       {
990          title = (char *)XtMalloc(strlen((GETMESSAGE(12, 7, "File Manager"))) +
991                                   strlen(file_mgr_data->host) +
992                                   strlen(root_title) +
993                                   5); /* Need for blank dash blank colon NULL */
994          sprintf( title, "%s - %s:%s", (GETMESSAGE(12, 7, "File Manager")),
995                                        file_mgr_data->host,
996                                        root_title );
997       }
998       else
999       {
1000          title = (char *)XtMalloc(strlen((GETMESSAGE(12, 7, "File Manager"))) +
1001                                   strlen(ptr) +
1002                                   4); /* Need for blank dash blank NULL */
1003          sprintf( title, "%s - %s", (GETMESSAGE(12, 7, "File Manager")), ptr);
1004       }
1005    }
1006
1007    DtDtsFreeAttributeValue(fileLabel);
1008    return(title);
1009 }
1010
1011
1012 /*
1013  * This is a function for building a path from the directory name
1014  * and file name pieces of a FileViewData structure.
1015  */
1016
1017 char *
1018 _DtGetSelectedFilePath(
1019         FileViewData *selected_file )
1020
1021 {
1022    char *directory;
1023    char *file;
1024    char *path;
1025
1026    directory = ((DirectorySet *)selected_file->directory_set)->name;
1027    file = selected_file->file_data->file_name;
1028
1029    if (strcmp(directory, "/") == 0)
1030    {
1031       path = XtMalloc(strlen(directory) + strlen(file) + 1);
1032       sprintf(path, "%s%s", directory, file);
1033    }
1034    else
1035    {
1036       path = XtMalloc(strlen(directory) + strlen(file) + 2);
1037       sprintf(path, "%s/%s", directory, file);
1038    }
1039
1040    return(path);
1041 }
1042
1043
1044 /*
1045  * This is a generic function for building action parameters from an array of
1046  * file view data structures.
1047  */
1048
1049 void
1050 _DtBuildActionArgsWithSelectedFiles(
1051         FileViewData **selection_list,
1052         int selected_count,
1053         DtActionArg **action_args,
1054         int *arg_count )
1055
1056 {
1057    *arg_count = 0;
1058
1059    *action_args = (DtActionArg *)
1060                      XtCalloc(1, sizeof(DtActionArg) * selected_count);
1061
1062    if (*action_args)
1063    {
1064       int i;
1065
1066       for(i = 0; i < selected_count; i++)
1067       {
1068          ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1069          ((*action_args)[(*arg_count)++]).u.file.name =
1070                          _DtGetSelectedFilePath(selection_list[i]);
1071       }
1072    }
1073 }
1074
1075
1076 void
1077 _DtBuildActionArgsWithDTSelectedFiles(
1078         DesktopRec **selection_list,
1079         int selected_count,
1080         DtActionArg **action_args,
1081         int *arg_count )
1082
1083 {
1084    *arg_count = 0;
1085
1086    *action_args = (DtActionArg *)
1087                      XtCalloc(1, sizeof(DtActionArg) * selected_count);
1088
1089    if (*action_args)
1090    {
1091       int i;
1092
1093       for(i = 0; i < selected_count; i++)
1094       {
1095          ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1096          ((*action_args)[(*arg_count)++]).u.file.name =
1097                   _DtGetSelectedFilePath(selection_list[i]->file_view_data);
1098       }
1099    }
1100 }
1101
1102
1103 /*
1104  * This is a generic function for building action parameters from drag and drop
1105  * file information.
1106  */
1107
1108 void
1109 _DtBuildActionArgsWithDroppedFiles(
1110         FileViewData *dropped_on_obj,
1111         DtDndDropCallbackStruct *drop_parameters,
1112         DtActionArg **action_args,
1113         int *arg_count )
1114
1115 {
1116    *arg_count = 0;
1117
1118    if (dropped_on_obj)
1119       *action_args = (DtActionArg *) XtCalloc
1120         (1, sizeof(DtActionArg) * (drop_parameters->dropData->numItems + 1));
1121    else
1122       *action_args = (DtActionArg *) XtCalloc
1123         (1, sizeof(DtActionArg) * drop_parameters->dropData->numItems);
1124
1125    if (*action_args)
1126    {
1127       int i;
1128
1129       if (dropped_on_obj)
1130       {
1131          ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1132          ((*action_args)[(*arg_count)++]).u.file.name =
1133                          _DtGetSelectedFilePath(dropped_on_obj);
1134       }
1135
1136       for(i = 0; i < drop_parameters->dropData->numItems; i++)
1137       {
1138          ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1139          ((*action_args)[(*arg_count)++]).u.file.name =
1140                          XtNewString(drop_parameters->dropData->data.files[i]);
1141       }
1142    }
1143 }
1144
1145
1146 /*
1147  * This is a generic function for building action parameters from drag and drop
1148  * buffer information.
1149  */
1150
1151
1152 void
1153 _DtBuildActionArgsWithDroppedBuffers(
1154         FileViewData *dropped_on_obj,
1155         DtDndDropCallbackStruct *drop_parameters,
1156         DtActionArg **action_args,
1157         int *arg_count )
1158
1159 {
1160    *arg_count = 0;
1161
1162    if (dropped_on_obj)
1163       *action_args = (DtActionArg *) XtCalloc
1164         (1, sizeof(DtActionArg) * (drop_parameters->dropData->numItems + 1));
1165    else
1166       *action_args = (DtActionArg *) XtCalloc
1167         (1, sizeof(DtActionArg) * drop_parameters->dropData->numItems);
1168
1169    if (*action_args)
1170    {
1171       int i;
1172       DtActionBuffer buffer_arg = {NULL, 0, NULL, NULL, False};
1173
1174       if (dropped_on_obj)
1175       {
1176          ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1177          ((*action_args)[(*arg_count)++]).u.file.name =
1178                          _DtGetSelectedFilePath(dropped_on_obj);
1179       }
1180
1181       for(i = 0; i < drop_parameters->dropData->numItems; i++)
1182       {
1183          buffer_arg.bp = drop_parameters->dropData->data.buffers[i].bp;
1184          buffer_arg.size = drop_parameters->dropData->data.buffers[i].size;
1185          buffer_arg.name = drop_parameters->dropData->data.buffers[i].name;
1186
1187          ((*action_args)[(*arg_count)]).argClass = DtACTION_BUFFER;
1188          ((*action_args)[(*arg_count)++]).u.buffer = buffer_arg;
1189       }
1190    }
1191 }
1192
1193
1194 /*
1195  * This is a generic function for freeing action parameters.
1196  */
1197
1198 void
1199 _DtFreeActionArgs(
1200         DtActionArg *action_args,
1201         int arg_count )
1202
1203 {
1204    int i;
1205
1206    for (i = 0; i < arg_count; i++)
1207    {
1208       if (action_args[i].argClass == DtACTION_FILE)
1209       {
1210          XtFree(action_args[i].u.file.name);
1211          action_args[i].u.file.name = NULL;
1212       }
1213    }
1214    
1215    XtFree((char *) action_args);
1216 }
1217
1218
1219 /************************************************************************
1220  * The following functions deal with Buffer Manipulation and Naming
1221  ************************************************************************/
1222
1223 /*
1224  * This is a generic function for extracting buffer information from
1225  * drop input.
1226  */
1227
1228 void
1229 _DtSetDroppedBufferInfo(char **file_set,
1230               BufferInfo *buffer_set,
1231               char **host_set,
1232               DtDndDropCallbackStruct *drop_parameters)
1233
1234 {
1235
1236  int num_of_buffers = drop_parameters->dropData->numItems;
1237  int i;
1238  DtDndBuffer *buffers = drop_parameters->dropData->data.buffers;
1239
1240
1241  DPRINTF (("Executing..._DtSetDroppedBufferInfo\n"));
1242
1243  /* Initialize file_set and ensure of unique file names for unamed buffers*/
1244  SetBufferFileNames(file_set, buffers, num_of_buffers);
1245
1246  for (i= 0; i < num_of_buffers; i++)
1247   {
1248
1249      (buffer_set[i]).buf_ptr = buffers[i].bp;
1250      (buffer_set[i]).size    = buffers[i].size;
1251
1252      host_set[i] = XtNewString(home_host_name);
1253
1254      DPRINTF(("_DtSetDroppedBufferInfo:\n host_set[%d]=%s,\
1255               buffer_set[%d].buf_ptr=%p, buffer_set[%d].size=%d\n",
1256               i, host_set[i], i, buffer_set[i].buf_ptr, i, buffer_set[i].size));
1257   }
1258 }
1259
1260
1261 /*
1262  * This is a function for creating file names for a set of buffers.
1263  */
1264
1265 static void
1266 SetBufferFileNames (char **file_set,
1267                     DtDndBuffer *buffers,
1268                     int num_of_buffers)
1269 {
1270  int null_filenames_count = 0;
1271  int i;
1272  int first_nullfile_index = 0;
1273  Boolean NULL_FILENAMES=FALSE;
1274
1275  DPRINTF (("Executing...SetBufferFileNames\n"));
1276
1277  for (i = 0; i < num_of_buffers; i++)
1278  {
1279      if (buffers[i].name == NULL)
1280      {
1281        /* generate buffer name using Untitled as a base name */
1282        file_set[i]=BuildBufferFileName(DEFAULT_BUFFER_FILENAME,
1283                                        -1,
1284                                        buffers[i].bp,
1285                                        buffers[i].size);
1286      }
1287      else
1288      {
1289         /* file name is supplied by the drag initiator */
1290        file_set[i] = XtNewString(buffers[i].name);
1291      }
1292
1293      DPRINTF(("file_set[%d]=%s\n", i, file_set[i]));
1294
1295  } /* end for loop */
1296
1297
1298  /* Rename any collisions to unique names  */
1299  RenameCollisions(file_set, num_of_buffers);
1300
1301  return;
1302 }
1303
1304
1305 /*
1306  * This is a generic function for generating a name for an untitled buffer.
1307  * A default name (Untitled) is used in conjunction with the name template
1308  * information from the types database.
1309  */
1310
1311 static char *
1312 BuildBufferFileName (char   *file_name,
1313                      int     postfix_index,
1314                      void   *buffer,
1315                      int     buffer_size)
1316 {
1317   const char delim = '_';
1318   char *new_file_name;
1319
1320
1321   DPRINTF (("Executing....BuildBufferFileName\n"));
1322
1323   /* Malloc memory and contruct the new file name */
1324   new_file_name = (char *) XtMalloc (strlen(file_name) + 1 +
1325                                      MAX_POSTFIX_LENGTH  + 1);
1326
1327   DPRINTF (("BuildBufferFileName: Old file name is %s\n", file_name));
1328
1329   /* determine whether to append post fix name */
1330   if (postfix_index == -1)
1331      strcpy(new_file_name, file_name);
1332   else
1333      sprintf(new_file_name,"%s%c%d", file_name, delim, postfix_index);
1334
1335   /* Retrieve the name template if it exists and use it in the filename */
1336   new_file_name = RetrieveAndUseNameTemplateInfo(buffer,
1337                                                  buffer_size,
1338                                                  new_file_name);
1339
1340   DPRINTF(("BuildBufferFileName: Returning new_file_name=%s\n", new_file_name));
1341
1342   /* return new file name */
1343   return (new_file_name);
1344 }
1345
1346
1347
1348 /*
1349  * This is a function for building a buffer name using predfined input
1350  * and name template information from the types database.
1351  * WARNING: template_input MAY be freed. It must point to a char *.
1352  */
1353
1354 static char *
1355 RetrieveAndUseNameTemplateInfo(
1356         void *buffer,
1357         int buffer_size,
1358         char *template_input)
1359
1360 {
1361    char *name_template;
1362    char *buffer_name = NULL;
1363
1364    name_template = DtDtsBufferToAttributeValue(buffer,
1365                                                buffer_size,
1366                                                DtDTS_DA_NAME_TEMPLATE,
1367                                                NULL);
1368    if (name_template)
1369       buffer_name = (char *) XtMalloc(strlen(name_template) +
1370                                       strlen(template_input) +
1371                                        1);
1372    if (buffer_name)
1373    {
1374       sprintf(buffer_name, name_template, template_input);
1375       DtDtsFreeAttributeValue(name_template);
1376       XtFree(template_input);
1377       return(buffer_name);
1378    }
1379    else
1380    {
1381       DtDtsFreeAttributeValue(name_template);
1382       return(template_input);
1383    }
1384 }
1385
1386
1387 /*
1388  * This is a function for resolving collisions in a list of buffer names.
1389  */
1390
1391 static void
1392 RenameCollisions( char ** list, int count )
1393 {
1394   register int i, j, k, l;
1395   char flg = 0, flg2 = 0;
1396
1397   for( i = 0; i < count; ++i )
1398   {
1399     unsigned int addIndex = 1;
1400
1401     if( *(list[i]) == 0x0 )
1402     {
1403       k = i;
1404       flg = 1;
1405     }
1406
1407     for( j = i+1; j < count; ++j )
1408     {
1409       if( strcmp( list[i], list[j] ) == 0 )
1410       {
1411         RenameEntry( &(list[j]), ++addIndex );
1412         l = i;
1413         flg2 = 1;
1414       }
1415     }
1416     if( flg2 )
1417     {
1418       flg2 = 0;
1419       RenameEntry( &(list[l]), 1 );
1420     }
1421   }
1422   if( flg )
1423   {
1424     free( list[k] );
1425     list[k] = (char *)malloc( strlen( DEFAULT_BUFFER_FILENAME ) + 1 );
1426     sprintf( list[k], "%s", DEFAULT_BUFFER_FILENAME );
1427   }
1428 }
1429
1430
1431 /*
1432  * This is a function for adding an index to a buffer name which has
1433  * collided.
1434  */
1435
1436 static void
1437 RenameEntry( char ** name, unsigned int addIndex )
1438 {
1439
1440 #define MAX_INT_SIZE 15
1441
1442 char * tmpPtr, * newName;
1443
1444   if( *name == 0x0 )
1445     return;
1446   else if( **name == 0x0 )
1447   {
1448     newName = (char *)XtCalloc(1,strlen(DEFAULT_BUFFER_FILENAME)+ MAX_INT_SIZE);
1449     sprintf( newName, "%s_%d", DEFAULT_BUFFER_FILENAME, addIndex );
1450   }
1451   else
1452   {
1453     tmpPtr = strrchr( *name, '.' );
1454
1455     newName = (char *)XtCalloc( 1, strlen( *name ) + MAX_INT_SIZE );
1456
1457     if( tmpPtr == NULL )
1458       sprintf( newName, "%s_%d", *name, addIndex );
1459     else if( tmpPtr == *name )
1460       sprintf( newName, "%d%s", addIndex, *name );
1461     else
1462     {
1463       *tmpPtr = 0x0;
1464       sprintf( newName, "%s_%d.%s", *name, addIndex, ++tmpPtr);
1465     }
1466   }
1467   free( *name );
1468   *name = newName;
1469 }
1470
1471
1472 /*
1473  * This is a generic function for freeing buffer information extracted from
1474  * drop input.
1475  */
1476
1477 void
1478 _DtFreeDroppedBufferInfo(char **file_set,
1479               BufferInfo *buffer_set,
1480               char **host_set,
1481               int num_of_buffers)
1482 {
1483   int i;
1484
1485   DPRINTF (("Executing..._DtFreeDroppedBufferInfo\n"));
1486
1487   /* Check for Null pointers */
1488   if (file_set && buffer_set && host_set )
1489   {
1490      for (i=0; i< num_of_buffers; i++ )
1491      {
1492        XtFree(file_set[i]);
1493        XtFree(host_set[i]);
1494      }
1495
1496      XtFree((char *)file_set);
1497      XtFree((char *)host_set);
1498      XtFree((char *)buffer_set);
1499   }
1500 }
1501
1502
1503 /*
1504  * This is a generic function for determining if a buffer is executable.
1505  */
1506
1507 Boolean
1508 _DtIsBufferExecutable(
1509         void *buffer,
1510         int buffer_size)
1511
1512 {
1513    char *exe_attribute;
1514    Boolean is_exe = False;
1515
1516    exe_attribute = DtDtsBufferToAttributeValue(buffer,
1517                                                buffer_size,
1518                                                "IS_EXECUTABLE",
1519                                                NULL);
1520    if (exe_attribute)
1521    {
1522       if (DtDtsIsTrue(exe_attribute))
1523          is_exe = True;
1524
1525       DtDtsFreeAttributeValue(exe_attribute);
1526    }
1527
1528    return(is_exe);
1529 }
1530
1531
1532 /*
1533  * This is a generic function for extracting file information from drop input.
1534  */
1535
1536 void
1537 _DtSetDroppedFileInfo(
1538         DtDndDropCallbackStruct *drop_parameters,
1539         char ***file_set,
1540         char ***host_set)
1541 {
1542    int numFiles, i;
1543
1544    numFiles = drop_parameters->dropData->numItems;
1545
1546    *file_set = (char **)XtMalloc(sizeof(char *) * numFiles);
1547    *host_set = (char **)XtMalloc(sizeof(char *) * numFiles);
1548    for(i = 0; i < numFiles; i++)
1549    {
1550       (*file_set)[i] = XtNewString(drop_parameters->dropData->data.files[i]);
1551       (*host_set)[i] = home_host_name;
1552
1553       DPRINTF(("ProcessMoveCopyLink:\n host_set[%d]=%s, file_set[%d]=%s\n",
1554                i, (*host_set)[i], i, (*file_set)[i]));
1555    }
1556 }
1557
1558
1559 /*
1560  * This is a generic function for copying file info extracted from drop input.
1561  */
1562
1563 void
1564 _DtCopyDroppedFileInfo(
1565         int num_files,
1566         char **orig_file_set,
1567         char **orig_host_set,
1568         char ***new_file_set,
1569         char ***new_host_set)
1570 {
1571    int i;
1572
1573    *new_file_set = (char **)XtMalloc(sizeof(char *) * num_files);
1574    *new_host_set = (char **)XtMalloc(sizeof(char *) * num_files);
1575    for(i = 0; i < num_files; i++)
1576    {
1577       (*new_file_set)[i] = XtNewString(orig_file_set[i]);
1578       (*new_host_set)[i] = XtNewString(orig_host_set[i]);
1579    }
1580 }
1581
1582
1583 /*
1584  * This is a generic function for freeing file info extracted from drop input.
1585  */
1586
1587 void
1588 _DtFreeDroppedFileInfo(
1589         int num_files,
1590         char **file_set,
1591         char **host_set)
1592 {
1593    int i;
1594
1595    for(i = 0; i < num_files; i++)
1596       XtFree(file_set[i]);
1597
1598    XtFree((char *)file_set);
1599    XtFree((char *)host_set);
1600 }
1601
1602
1603 /*
1604  * This is a generic function for resolving a cannonical path from user input.
1605  */
1606
1607 void
1608 _DtPathFromInput(
1609         char *input_string,
1610         char *current_dir,
1611         char **host,
1612         char **rel_path)
1613
1614 {
1615    char *path;
1616    char *tmp_path = NULL;
1617    char *true_path = NULL;
1618    Tt_status tt_status;
1619    int dir_len;
1620
1621    /* find host */
1622    *host = XtNewString(home_host_name);
1623
1624    /* find relative path */
1625    tmp_path = path = XtNewString(input_string);
1626
1627    /* Strip any spaces from name -- input is overwritten */
1628    path = (char *) _DtStripSpaces(path);
1629
1630    /* Resolve, if there're any, environment variables */
1631    {
1632       FILE *pfp = NULL;
1633       char command[MAXPATHLEN];
1634
1635       memset(command, 0, sizeof(command));
1636       sprintf(command,"echo %s",path);
1637
1638       if((pfp=popen(command,"r")) != NULL)
1639       {
1640           int read_ok = 1;
1641
1642           if (NULL == (fgets(command,MAXPATHLEN,pfp))) 
1643           {
1644               /*
1645                * Try a few more reads and if the read still fails, 
1646                * just use the path as is.
1647                */
1648               int i;
1649               for (i=0; i < 5; i++) 
1650               {
1651                   sleep (1);
1652                   if (NULL != (fgets(command,MAXPATHLEN,pfp))) 
1653                       break;
1654               }
1655              if (i >= 5)
1656                  read_ok = 0;
1657          }
1658
1659          if (read_ok)
1660          {
1661              int slen = strlen(command);
1662              /* need to remove the trailing newline safely*/
1663              if (slen >= 1)
1664                  command[slen-1] = '\0';
1665
1666              XtFree(path);
1667              path = XtNewString(command);
1668              pclose(pfp);
1669              pfp = NULL;
1670          }
1671       }
1672       if (pfp)
1673       {
1674           pclose(pfp);
1675           pfp = NULL;
1676       }
1677    }
1678
1679    /* Resolve '~' -- new memory is allocated, old memory is freed */
1680    if (*path == '~')
1681       path = _DtChangeTildeToHome(path);
1682
1683    /* If current dir provided, check for relative path */
1684    if (path && current_dir)
1685    {
1686       if (*path != '/')
1687       {
1688          /* file is relative path i.e.      xyz/abc */
1689          if (strcmp(current_dir, "/") == 0)
1690          {
1691             tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 1);
1692             sprintf(tmp_path, "%s%s", current_dir, path);
1693          }
1694          else
1695          {
1696             tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 2);
1697             sprintf(tmp_path, "%s/%s", current_dir, path);
1698          }
1699
1700          XtFree(path);
1701          path = tmp_path;
1702          tmp_path = NULL;
1703       }
1704    }
1705    else if (!path)
1706    {
1707      *rel_path = NULL;
1708      XtFree(tmp_path);
1709      return;
1710    }
1711
1712    /* Resolve '.' or '..' -- input is overwritten, output may be NULL! */
1713    /* Save pointer to path to free if output is NULL.                  */
1714    tmp_path = path;
1715    path = (char *) DtEliminateDots(path);
1716
1717    if (path)
1718    {
1719       /* Resolve to local pathname */
1720       true_path = ResolveLocalPathName(*host,
1721                                        path,
1722                                        NULL,
1723                                        home_host_name,
1724                                        &tt_status);
1725       XtFree(path);
1726
1727       /* Strip off trailing '/' */
1728       dir_len = strlen(true_path);
1729       if (dir_len > 1 && *(true_path + dir_len - 1) == '/')
1730          *(true_path + dir_len - 1) = '\0';
1731    }
1732    else
1733    {
1734       true_path = NULL;
1735       XtFree(tmp_path);
1736    }
1737
1738    *rel_path = true_path;
1739 }
1740
1741
1742 /*
1743  * This function takes a path name, and resolves any leading '~' to refer
1744  * to one of the following:
1745  *
1746  *   1) if ~ or ~/path, then it resolves to the user's home directory on
1747  *      their home host.
1748  *
1749  *   2) if ~user or ~user/path, then it resolves to the specified user's
1750  *      home directory on the home host.
1751  *
1752  * This function never resolves to any host but the home host, since we
1753  * have no way of determining a user's home directory on any system other
1754  * than the home system.
1755  */
1756
1757 char *
1758 _DtChangeTildeToHome (
1759         char *input_string)
1760 {
1761    char *path;
1762    char *full_path;
1763    struct passwd * pwInfo;
1764
1765    if ((input_string[1] != '\0') && (input_string[1] != '/'))
1766    {
1767       char *path;
1768
1769       /* ~user or ~user/path format */
1770
1771       /* is there a path? */
1772       path = DtStrchr(input_string, '/');
1773
1774       /* find user */
1775       if (path)
1776          *path = '\0';
1777       if ((pwInfo = getpwnam(input_string + 1)) == NULL)
1778       {
1779          /* user doesn't exist */
1780          if (path)
1781             *path = '/';
1782          return NULL;
1783       }
1784
1785       if (path)
1786       {
1787          /* ~user/path format */
1788
1789          *path = '/';
1790
1791          if (strcmp(pwInfo->pw_dir, "/") == 0)
1792          {
1793             /* We don't want to end up with double '/' in the path */
1794             full_path = (char *) XtMalloc(strlen(path) + 1);
1795             strcpy(full_path, path);
1796          }
1797          else
1798          {
1799             full_path = (char *) XtMalloc(strlen(pwInfo->pw_dir) +
1800                                           strlen(path) + 1);
1801             sprintf(full_path, "%s%s", pwInfo->pw_dir, path);
1802          }
1803       }
1804       else
1805       {
1806          /* ~user format */
1807
1808          full_path = XtMalloc(strlen(pwInfo->pw_dir) + 1);
1809          strcpy(full_path, pwInfo->pw_dir);
1810       }
1811    }
1812    else if (input_string[1])
1813    {
1814       /* ~/path format */
1815
1816       /* NOTE: users_home_dir has trailing '/' */
1817       full_path = XtMalloc(strlen(users_home_dir) + strlen(input_string+2) + 1);
1818       sprintf(full_path, "%s%s", users_home_dir, (input_string + 2));
1819    }
1820    else
1821    {
1822       /* ~ format */
1823
1824       full_path = XtMalloc(strlen(users_home_dir) + 1);
1825       strcpy(full_path, users_home_dir);
1826    }
1827
1828    XtFree(input_string);
1829    return(full_path);
1830 }
1831
1832
1833 /*
1834  * This function checks for spaces in filenames.
1835  */
1836 #ifdef _CHECK_FOR_SPACES
1837
1838 Boolean
1839 _DtSpacesInFileNames(
1840          char **fileNames, 
1841          int  fileCount )
1842 {
1843   int i;
1844
1845   for (i = 0; i < fileCount; i++)
1846   {
1847      fileNames[i] = (char *) _DtStripSpaces(fileNames[i]);
1848
1849      if (DtStrchr (fileNames[i], ' ') != NULL ||
1850          DtStrchr (fileNames[i], '\t') != NULL)
1851         return(TRUE);
1852   }
1853
1854   return(FALSE);
1855 }
1856
1857 #endif
1858
1859 /*
1860  * This resolves the path for an appmanager object to its true path.
1861  */
1862
1863 char *
1864 _DtResolveAppManPath(
1865          char *path,
1866          char *restricted_dir )
1867 {
1868    if (strlen(path) > strlen(restricted_dir))
1869    {
1870       char *linkDir, *ptr, *tmpPath;
1871
1872       linkDir = path + strlen(restricted_dir) + 1;
1873       ptr = DtStrchr(linkDir, '/');
1874       if (ptr)
1875       {
1876          *ptr = '\0';
1877          linkDir = _DtFollowLink(path);
1878          *ptr = '/';
1879          tmpPath = XtMalloc(strlen(linkDir) + strlen(ptr) + 1);
1880          sprintf(tmpPath, "%s%s", linkDir, ptr);
1881          XtFree(path);
1882          path = tmpPath;
1883       }
1884       else
1885       {
1886          linkDir = _DtFollowLink(path);
1887          XtFree(path);
1888          path = XtNewString(linkDir);
1889       }
1890    }
1891
1892    return(path);
1893 }