home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / central / ufilemgr.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  33.0 KB  |  1,183 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. // ===========================================================================
  20. // ufilemgr.cp
  21. // Created by atotic, June 15th, 1994
  22. // File utility routines for:
  23. // Creating a temporary file name
  24. // Bookkeeping of the temporary files
  25. // ===========================================================================
  26.  
  27. // Front End
  28. #include "ufilemgr.h"
  29. #include "uprefd.h"
  30. #include "BufferStream.h"
  31. #include "uerrmgr.h"
  32. #include "macutil.h"
  33. #include "resgui.h"
  34. #include "ulaunch.h"
  35. #include "libmime.h"
  36. #include "uerrmgr.h"
  37. #include "FullPath.h"
  38. #include "FileCopy.h"        //in MoreFiles
  39.  
  40. // XP
  41. #ifndef _XP_H_
  42. #include "xp.h"
  43. #endif
  44.  
  45. #include "PascalString.h"
  46.  
  47. // MacOS
  48. #include <AppleEvents.h>
  49. #include <Folders.h>
  50. #include <Errors.h>
  51. #include <Finder.h>
  52. //#include <UAEGizmos.h>
  53.  
  54. #define MAX_FILENAME_LEN        31
  55. #define MAX_ALT_DIGIT_LEN        5
  56. #define MAX_ALT_NAME_LEN        (MAX_FILENAME_LEN - (MAX_ALT_DIGIT_LEN + 1) )
  57.  
  58. /*****************************************************************************
  59.  * class CFileMgr
  60.  *****************************************************************************/
  61.  
  62. CFileMgr CFileMgr::sFileManager;        // The manager
  63. unsigned int CFileMgr::sMungeNum = 1;
  64.  
  65. extern "C" OSErr FSSpecFromPathname_CWrapper(char * path, FSSpec * outSpec);
  66.  
  67. // ÑÑ constructors/destructors
  68.  
  69. // Tries to delete all the files.
  70. // It will not be able to delete all the files, since users might have
  71. // moved them, deleted them, etc.
  72. CFileMgr::~CFileMgr()
  73. {
  74.     Boolean allDeleted = TRUE;
  75.     LFile * aFile;
  76.     for (int i =1; i <= fFiles.GetCount(); i++)        // Loop through
  77.     {
  78.         fFiles.FetchItemAt(i, &aFile);
  79.         Try_ {
  80.             FSSpec fileSpec;
  81.             aFile->GetSpecifier(fileSpec);
  82.             FSpDelete(&fileSpec);
  83.             delete aFile;
  84.         }
  85.         Catch_(inErr)    {
  86.             allDeleted = FALSE;
  87.         } EndCatch_
  88.     }
  89.     fFiles.RemoveItemsAt(fFiles.GetCount(), 1);
  90. }
  91.  
  92. // ÑÑ file management interface
  93.  
  94. // Register a file
  95. void CFileMgr::RegisterFile(LFileBufferStream * inFile)
  96. {
  97.     fFiles.InsertItemsAt(1, LArray::index_Last, &inFile);
  98. }
  99.  
  100. // Cancel file registration. Just deletes it from the queue
  101. void CFileMgr::CancelRegister(LFileBufferStream * inFile)
  102. {
  103.     fFiles.Remove(&inFile);
  104. }
  105.  
  106. // Cancels registration, and deletes the file from disk, and its file object
  107. void CFileMgr::CancelAndDelete(LFileBufferStream * inFile)
  108. {
  109.     fFiles.Remove(&inFile);            // Remove it from the queue
  110.  
  111.     FSSpec fileSpec;
  112.     inFile->GetSpecifier(fileSpec);
  113.     OSErr err = FSpDelete(&fileSpec);    // Delete disk file
  114.     delete inFile;                        // Delete the object
  115. }
  116.  
  117. // FindURL occurs when we have launched an external file
  118. void CFileMgr::HandleFindURLEvent(
  119.     const AppleEvent    &inAppleEvent,
  120.     AppleEvent            &outAEReply,
  121.     AEDesc                &/*outResult*/,
  122.     long                /*inAENumber*/)
  123. {
  124.     FSSpec lookingFor;
  125.     Size actualSize;
  126.     DescType realType;
  127.  
  128.     OSErr err = ::AEGetParamPtr(&inAppleEvent, keyDirectObject,
  129.                             typeFSS, &realType,
  130.                             &lookingFor, 
  131.                             sizeof(lookingFor), &actualSize);
  132.     ThrowIfOSErr_(err);
  133.     // Have the file spec, now look for the same one
  134.     LFileBufferStream *file;
  135.     LArrayIterator iter(fFiles);
  136.     while (iter.Next(&file))
  137.     {
  138.         FSSpec macSpec;
  139.         file->GetSpecifier(macSpec);
  140.         if ((macSpec.vRefNum == lookingFor.vRefNum) &&
  141.             (macSpec.parID == lookingFor.parID) &&
  142.             (CStr32(macSpec.name) == CStr32(lookingFor.name)))
  143.         {
  144.             char * url = file->GetURL();
  145.             if (url)
  146.             {
  147.                 err = ::AEPutParamPtr(&outAEReply, keyAEResult, typeChar, url, strlen(url));
  148.                 return;
  149.             }
  150.             else
  151.                 Throw_(errAEDescNotFound);
  152.         }
  153.     }
  154.     Throw_(errAEDescNotFound);
  155. }
  156.  
  157. /*
  158.     Turning an URL into a filename
  159.     Returns a file name that works on a Mac
  160.     
  161.     Requirements:
  162.         Length < 32 characters
  163.         No colons
  164.         Name should look similar to URL (which is closer to the URN than the anchor)
  165.     
  166.     Input:
  167.         URLs match this expression: <host>:<top><paths><name><crud>
  168.         Top can be a /
  169.         Paths end with a /
  170.         Crud begins with a # or ?
  171.         Host ends with a :
  172.     
  173.     Method:
  174.         Start at the end of the paths - after last /
  175.         Or at the end of the hostname - after first :
  176.         Go until a # or ?
  177.  
  178.     Notes:
  179.         This does not guarantee that the filename will work. We may still need to
  180.         munge it later (if for example such a filename already existed)
  181. */
  182.  
  183. CStr31 CFileMgr::FileNameFromURL( const char* url )
  184. {
  185.     CStr255        newName;
  186.     Byte        size = 0;
  187.     
  188.     if ( !url )
  189.         return CStr31(::GetCString(FILE_NAME_NONE));
  190.  
  191.     const char* urlString = url;    
  192.     
  193.     // Ñ get the starting point
  194.     const char* nameStart = strrchr( urlString, '/' );
  195.     
  196.     // Ñ╩filename starts *after* the colon
  197.     if ( nameStart && ( strlen( nameStart ) > 1) )
  198.         nameStart++;
  199.  
  200.     // Ñ no colon, must be simple path, go after the hostname
  201.     else
  202.     {
  203.         nameStart = strchr( urlString, ':' );
  204.         // Ñ╩filename starts *after* the colon
  205.         if ( nameStart )
  206.             nameStart++;
  207.         // Ñ╩no host, assume it's a simple local URL
  208.         else 
  209.             nameStart = urlString;
  210.     }
  211.     
  212.     // Ñ╩copy it until we hit the crud (# or ?) or max out
  213.     size = 0;        
  214.     while ( size < MAX_FILENAME_LEN )
  215.     {
  216.         // 0 indexed
  217.         char current = nameStart[ size ];
  218.         if ( current == '#' || current == '?' || !current )
  219.             break;
  220.         // Ñ╩take out any : characters as well
  221.         if ( current == ':' )
  222.             current = 'Ñ';
  223.         
  224.         size++;
  225.         
  226.         newName[ size ] = current;
  227.         newName.Length() = size;
  228.     }
  229.  
  230.     // If size was 0 then we have a problem. Make a temp filename.
  231.     // A reasonable convention would be to have names like "Untitled 1", "Untitled 2", etc
  232.     // since we really don't have any other information. We'll leave off the number
  233.     // here and let the arbitrator add it on later. We don't have an english file kind
  234.     // either, which the arbitrator might have, so this could get folded in later (just
  235.     // have a "Untitled" hack in here now)
  236.     if ( size == 0 )
  237.          newName = (char*)GetCString( UNTITLED_RESID );
  238.     return newName;
  239. }
  240.  
  241. // Creates a FSSpec of a file that does not exist, given the template
  242. OSErr CFileMgr::UniqueFileSpec(const FSSpec& inSpec, const CStr31& genericName,
  243.                                 FSSpec & outSpec)
  244. {
  245.     CStr255            goodName = genericName;
  246.     OSErr            err;
  247.     
  248.     err = FSMakeFSSpec( inSpec.vRefNum, inSpec.parID, goodName, &outSpec );
  249.     if (err == fnfErr)
  250.         return noErr;
  251.     if (err)
  252.         return err;
  253.  
  254.     // If the filename exists (noErr) then we have a problem!
  255.     
  256.     // Argh. We can do this: filename.gif-2
  257.     // Or this: #2 filename.gif
  258.     // One messes with the extension (which some people care about) and the other
  259.     // with the "proper" name.
  260.         
  261. #define USE_RANDOM 0
  262. #if USE_RANDOM
  263.     long index = 0;
  264. #else
  265.     static short    index = 1;
  266. #endif
  267.     CStr31            indexStr;
  268.     Boolean            done = FALSE;
  269.     CStr255            altName;
  270.     
  271.     do {
  272.         index++;                // start with "Picture 2" after "Picture" exists
  273.         if ( index > 999 )        // something's very wrong
  274.             return ioErr;
  275.         altName = goodName;
  276.         if ( altName.Length() > MAX_ALT_NAME_LEN )
  277.             altName.Length() = MAX_ALT_NAME_LEN;
  278. #if USE_RANDOM
  279.         long randomNum = abs(::Random())*9999/32767;
  280.         NumToString( randomNum, indexStr );
  281. #else
  282.         NumToString( index, indexStr );
  283. #endif
  284.         altName += "-";
  285.         altName += indexStr;
  286.         err = FSMakeFSSpec( inSpec.vRefNum, inSpec.parID, altName, &outSpec );
  287.         if ( err == fnfErr )
  288.             return noErr;
  289.     } while ( err == noErr );
  290.     return noErr;
  291. }
  292.  
  293. /*
  294.     Turning an URL into a fileSpec of a new file.
  295.     A file spec for non-existent file is created.
  296.     
  297.     Requirements:
  298.         Ñ Preserve filename as much as possible, including extension, if any (even though
  299.         this doesn't quite make sense on the Mac).
  300.         Ñ Make the new filename look "nice". Provide as much information as possible to the
  301.         user (they might want to keep the file) and don't use random numbers or the date.
  302.         Well, the date might be OK. Something like "Picture 1", "Picture 2" might do,
  303.         or "#2 madonna.gif".
  304.         
  305.     Method:
  306.         For file name generation see FileNameFromURL
  307.         If file with default name already exists, munge the name by appending
  308.         it a number.
  309. */
  310.  
  311. OSErr CFileMgr::NewFileSpecFromURLStruct (const char * location,
  312.                             const FSSpec& inSpec,
  313.                             FSSpec &outSpec)
  314. {
  315.     CStr31 goodName = FileNameFromURL(location);
  316.     return UniqueFileSpec( inSpec, goodName, outSpec );
  317. }
  318.  
  319.  
  320. /*
  321.     FL_SetComment
  322. */
  323.  
  324. void CFileMgr::FileSetComment (const FSSpec& file, const CStr255& comment)
  325. {
  326.     // Set GetInfo box in Finder to the URL. Not really  necessary, but a neat hack
  327.     Boolean hasDesktop;
  328.     FSSpec tempSpec = CPrefs::GetFolderSpec(CPrefs::DownloadFolder);
  329.     OSErr err = VolHasDesktopDB(tempSpec.vRefNum, hasDesktop);
  330.     if (err || !hasDesktop)
  331.         return;
  332.     DTPBRec pb;
  333.     pb.ioCompletion = NULL;
  334.     pb.ioVRefNum = tempSpec.vRefNum;
  335.     pb.ioNamePtr = NULL;
  336.     err = PBDTGetPath(&pb);
  337.     if (err)
  338.         return;
  339.     short refNum = pb.ioDTRefNum;
  340.     pb.ioNamePtr = (StringPtr)&file.name;    // A pointer to a file or directory name.    
  341.     char *ccomment = comment;
  342.     pb.ioDTBuffer = ccomment;    
  343.     pb.ioDTReqCount = strlen(ccomment);
  344.     pb.ioDirID = file.parID;    // The parent directory of the file or directory.    
  345.     err = ::PBDTSetCommentSync(&pb);
  346. }
  347.  
  348. /*
  349.     FL_VolumeHasDesktopDB
  350. */
  351.  
  352. OSErr CFileMgr::VolHasDesktopDB(short vRefNum, Boolean& hasDesktop)
  353. {
  354.     HParamBlockRec pb;
  355.     GetVolParmsInfoBuffer info;
  356.  
  357.     pb.ioParam.ioCompletion = NULL;
  358.     pb.ioParam.ioVRefNum = vRefNum;
  359.     pb.ioParam.ioNamePtr = NULL;
  360.     pb.ioParam.ioBuffer = (Ptr) & info;
  361.     pb.ioParam.ioReqCount = sizeof(GetVolParmsInfoBuffer);
  362.  
  363.     OSErr err = ::PBHGetVolParmsSync(&pb);
  364.  
  365.     hasDesktop = (err == noErr) && ((info.vMAttrib & (1L << bHasDesktopMgr)) != 0);
  366.  
  367.     return err;
  368.     
  369. } // VolHasDesktopDB 
  370.  
  371. // From MacApp
  372. // Get the vRefNum of an indexed on-line volume
  373. OSErr CFileMgr::GetIndVolume(short index,
  374.                    short& vRefNum)
  375. {
  376.     ParamBlockRec pb;
  377.     OSErr err;
  378.  
  379.     pb.volumeParam.ioCompletion = NULL;
  380.     pb.volumeParam.ioNamePtr = NULL;
  381.     pb.volumeParam.ioVolIndex = index;
  382.  
  383.     err = PBGetVInfoSync(&pb);
  384.  
  385.     vRefNum = pb.volumeParam.ioVRefNum;
  386.     return err;
  387. } // GetIndVolume 
  388.  
  389. // Copied from MacApp
  390. // Get the vRefNum of the system (boot) volume
  391. OSErr CFileMgr::GetSysVolume(short& vRefNum)
  392. {
  393.     OSErr theErr;
  394.     long dir;
  395.     theErr = FindFolder(kOnSystemDisk, kSystemFolderType, false, &vRefNum, &dir);
  396.     return theErr;
  397. }
  398.  
  399. // Finds a folder inside a folder.
  400. // The folder must be writeable
  401. // Signals error if folder cannot be found
  402. // Success: returns noErr and the location of the found folder in foundRefNum, foundDirID
  403. // Failure: returns  PBGetCatInfo error, and undefined foundRefNum, foundDirID
  404. OSErr CFileMgr::FindWFolderInFolder(short refNum,         // Directory/folder to be searched
  405.                                     long dirID,
  406.                                     const CStr255& folderName,    // Name of the folder to search for
  407.                                     short * outRefNum,// Location of the found folder
  408.                                     long * outDirID)
  409. {
  410.     CInfoPBRec cipb;
  411.     DirInfo    *dipb=(DirInfo *)&cipb;        // Typecast to what we need
  412.     OSErr err;
  413.  
  414.     dipb->ioNamePtr     = (unsigned char *) &folderName;
  415.     dipb->ioFDirIndex     = 0;
  416.     dipb->ioVRefNum        = refNum;
  417.     dipb->ioDrDirID     = dirID;
  418.     
  419.     err = PBGetCatInfoSync(&cipb);
  420.     
  421.     if (err != noErr)
  422.         return err;
  423.         
  424.     if ( ( dipb->ioFlAttrib & 0x0010 ) )// && !(cipb.ioACUser && 2))    // Is it a directory and writable?
  425.     {
  426.         *outRefNum     = dipb->ioVRefNum;
  427.         *outDirID     = dipb->ioDrDirID;
  428.         return noErr;
  429.     }
  430.     
  431.     return fnfErr;
  432. }    // FindWFolderInFolder
  433.  
  434. // Creates a folder named 'folderName' inside a folder.
  435. // The errors returned are same as PBDirCreate
  436. OSErr CFileMgr::CreateFolderInFolder(short refNum,         // Parent directory/volume
  437.                                     long dirID,
  438.                                     const CStr255 &folderName,    // Name of the new folder
  439.                                     short * outRefNum,    // Volume of the created folder
  440.                                     long * outDirID)    // 
  441. {
  442.     HFileParam hpb;
  443.     
  444.     hpb.ioVRefNum = refNum;
  445.     hpb.ioDirID = dirID;
  446.     hpb.ioNamePtr = (StringPtr)&folderName;
  447.     OSErr err = PBDirCreateSync((HParmBlkPtr)&hpb);
  448.     if (err == noErr)    {
  449.         *outRefNum = hpb.ioVRefNum;
  450.         *outDirID = hpb.ioDirID;
  451.     }    else    {
  452.         *outRefNum = 0;
  453.         *outDirID = 0;
  454.     }
  455.     return err;
  456. }
  457.  
  458. // Creates a folder spec from folder id;
  459. OSErr CFileMgr::FolderSpecFromFolderID(short vRefNum, long dirID, FSSpec& folderSpec)
  460. {
  461.     folderSpec.vRefNum = 0;    // Initialize them to 0
  462.     folderSpec.parID = 0;
  463.     CInfoPBRec cinfo;
  464.     DirInfo    *dipb=(DirInfo *)&cinfo;
  465.     dipb->ioNamePtr = (StringPtr)&folderSpec.name;
  466.     dipb->ioVRefNum = vRefNum;
  467.     dipb->ioFDirIndex = -1;
  468.     dipb->ioDrDirID = dirID;
  469.     OSErr err = PBGetCatInfoSync(&cinfo);
  470.     
  471.     if (err == noErr)
  472.     {
  473.         folderSpec.vRefNum = dipb->ioVRefNum;
  474.         folderSpec.parID = dipb->ioDrParID;
  475.     }
  476.     return err;
  477. }
  478.  
  479. //-----------------------------------
  480. char* CFileMgr::PathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeafName )
  481. // Returns a full pathname to the given file
  482. // Returned value is allocated with XP_ALLOC, and must be freed with XP_FREE
  483. // This is taken from FSpGetFullPath in MoreFiles, except that we need to tolerate
  484. // fnfErr.
  485. //-----------------------------------
  486. {    
  487.     char* result = nil;
  488.     FSSpec tempSpec;
  489.     OSErr err = noErr;
  490.     
  491.     short fullPathLength = 0;
  492.     Handle fullPath = NULL;
  493.     
  494.     /* Make a copy of the input FSSpec that can be modified */
  495.     BlockMoveData(&inSpec, &tempSpec, sizeof(FSSpec));
  496.     
  497.     if ( tempSpec.parID == fsRtParID )
  498.     {
  499.         /* The object is a volume */
  500.         
  501.         /* Add a colon to make it a full pathname */
  502.         ++tempSpec.name[0];
  503.         tempSpec.name[tempSpec.name[0]] = ':';
  504.         
  505.         /* We're done */
  506.         err = PtrToHand(&tempSpec.name[1], &fullPath, tempSpec.name[0]);
  507.     }
  508.     else
  509.     {
  510.         /* The object isn't a volume */
  511.         
  512.         CInfoPBRec    pb;
  513.  
  514.         /* Is the object a file or a directory? */
  515.         pb.dirInfo.ioNamePtr = tempSpec.name;
  516.         pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
  517.         pb.dirInfo.ioDrDirID = tempSpec.parID;
  518.         pb.dirInfo.ioFDirIndex = 0;
  519.         err = PBGetCatInfoSync(&pb);
  520.         if ( err == noErr || err == fnfErr)
  521.         {
  522.             // if the object is a directory, append a colon so full pathname ends with colon
  523.             // Beware of the "illegal spec" case that Netscape uses (empty name string). In
  524.             // this case, we don't want the colon.
  525.             if ( err == noErr && tempSpec.name[0] && (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
  526.             {
  527.                 ++tempSpec.name[0];
  528.                 tempSpec.name[tempSpec.name[0]] = ':';
  529.             }
  530.             
  531.             /* Put the object name in first */
  532.             err = PtrToHand(&tempSpec.name[1], &fullPath, tempSpec.name[0]);
  533.             if ( err == noErr )
  534.             {
  535.                 /* Get the ancestor directory names */
  536.                 pb.dirInfo.ioNamePtr = tempSpec.name;
  537.                 pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
  538.                 pb.dirInfo.ioDrParID = tempSpec.parID;
  539.                 do    /* loop until we have an error or find the root directory */
  540.                 {
  541.                     pb.dirInfo.ioFDirIndex = -1;
  542.                     pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
  543.                     err = PBGetCatInfoSync(&pb);
  544.                     if ( err == noErr )
  545.                     {
  546.                         /* Append colon to directory name */
  547.                         ++tempSpec.name[0];
  548.                         tempSpec.name[tempSpec.name[0]] = ':';
  549.                         
  550.                         /* Add directory name to beginning of fullPath */
  551.                         (void) Munger(fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
  552.                         err = MemError();
  553.                     }
  554.                 } while ( err == noErr && pb.dirInfo.ioDrDirID != fsRtDirID );
  555.             }
  556.         }
  557.     }
  558.     if ( err != noErr && err != fnfErr)
  559.         goto Clean;
  560.  
  561.     fullPathLength = GetHandleSize(fullPath);
  562.     err = noErr;    
  563.     int allocSize = 1 + fullPathLength;
  564.     // We only want the leaf name if it's the root directory or wantLeafName is true.
  565.     if (inSpec.parID != fsRtParID && !wantLeafName)
  566.         allocSize -= inSpec.name[0];
  567.     result = (char*)XP_ALLOC(allocSize);
  568.     if (!result)
  569.         goto Clean;
  570.     memcpy(result, *fullPath, allocSize - 1);
  571.     result[ allocSize - 1 ] = 0;
  572. Clean:
  573.     if (fullPath)
  574.         DisposeHandle(fullPath);
  575.     Assert_(result); // OOPS! very bad.
  576.     return result;
  577. } // CFileMgr::PathNameFromFSSpec
  578.  
  579. // PathNameFromFSSpec + hex encoding
  580. // pass this in to netlib when specifying filesToPost, etch
  581. char* CFileMgr::EncodedPathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeafName )
  582. {
  583.     char* path = CFileMgr::PathNameFromFSSpec( inSpec, wantLeafName );
  584.     path = CFileMgr::EncodeMacPath( path );
  585.     return path;
  586. }
  587.  
  588. // GetElement is a routine used by FSSpecFromPathname, routine adopted from ParseFullPathName.c on dev disk
  589. // I am not sure how does it work.
  590. static Boolean GetElement(StringPtr Result,char * PathNamePtr,short ElementNumber);
  591. static Boolean GetElement(StringPtr Result,char *PathNamePtr,short ElementNumber)
  592. {
  593.     char             *eStart, *eEnd;
  594.     
  595.     eStart = eEnd = PathNamePtr;
  596.     while (ElementNumber) {                    // Search for the element
  597.         if (*eEnd == ':' || !(*eEnd)) {        //   if we see colon or a null , we're at the end of element
  598.             --ElementNumber;                //   one down, n-1 to go
  599.             if (ElementNumber == 1)            //   are we at the second to last element??
  600.                 eStart = eEnd + 1;            //        mark it.
  601.         }
  602.         if (!(*eEnd)) break;
  603.         ++eEnd;                                //   always increment 
  604.     }
  605.     
  606.     if (ElementNumber || (eEnd - eStart > 32) || (eEnd - eStart == 0))    // If n > 0 or the element is too big or there is no element
  607.         return false;                                                     //  then croak.
  608.  
  609.     Result[0] = (char)(eEnd - eStart);        // Move the substring into the Result
  610.     BlockMove ((Ptr) eStart, (Ptr) (Result + 1),Result[0]);            
  611.         return true;
  612. }
  613.  
  614. //-----------------------------------
  615. OSErr CFileMgr::FSSpecFromPathname(char* inPathNamePtr, FSSpec* outSpec)
  616. // FSSpecFromPathname reverses PathNameFromFSSpec.
  617. // It returns a FSSpec given a c string which is a mac pathname.
  618. //-----------------------------------
  619. {
  620.     // Simplify this routine to use FSMakeFSSpec if length < 255. Otherwise use the MoreFiles
  621.     // routine FSpLocationFromFullPath, which allocates memory, to handle longer pathnames. 
  622.     if (strlen(inPathNamePtr) < 255)
  623.         return ::FSMakeFSSpec(0, 0, CStr255(inPathNamePtr), outSpec);
  624.     return FSpLocationFromFullPath(strlen(inPathNamePtr), inPathNamePtr, outSpec);
  625. } // CFileMgr::FSSpecFromPathname
  626.  
  627. // Changes the creator/file 
  628. OSErr CFileMgr::SetFileTypeCreator(OSType creator, OSType type, const FSSpec * fileSpec)
  629. {
  630.     FInfo info;
  631.     OSErr err = ::FSpGetFInfo (fileSpec, &info);
  632.     if (err != noErr)
  633.         return err;
  634.     info.fdCreator = creator;
  635.     info.fdType = type;
  636.     err = ::FSpSetFInfo (fileSpec, &info);
  637.     return err;
  638. }
  639.  
  640. // Set or clear a Finder flag
  641. OSErr CFileMgr::SetFileFinderFlag(const FSSpec& fileSpec, Uint16 flagMask, Uint8 value)
  642. {
  643.     FInfo info;
  644.     OSErr err = ::FSpGetFInfo (&fileSpec, &info);
  645.     if (err != noErr)
  646.         return err;
  647.         
  648.     if (value)        //set the bit
  649.         info.fdFlags |= flagMask;
  650.     else             //clear the bit
  651.         info.fdFlags &= ~flagMask;
  652.     
  653.     err = ::FSpSetFInfo (&fileSpec, &info);
  654.     return err;
  655. }
  656.  
  657.  
  658. //-----------------------------------
  659. Boolean CFileMgr::IsFolder(const FSSpec& spec)
  660. //-----------------------------------
  661. {
  662.     CStr31 name = spec.name;
  663.     CInfoPBRec pb;
  664.     DirInfo    *dipb=(DirInfo *)&pb;
  665.     pb.hFileInfo.ioNamePtr = name;
  666.     pb.hFileInfo.ioVRefNum = spec.vRefNum;
  667.     pb.hFileInfo.ioDirID = spec.parID;
  668.     pb.hFileInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
  669.     OSErr err = PBGetCatInfoSync(&pb);
  670.     if (err != noErr)
  671.         return FALSE;
  672.     if (dipb->ioFlAttrib & 0x10)
  673.         return TRUE;
  674.     // else
  675.         return FALSE;
  676. }
  677.  
  678. //-----------------------------------
  679. OSErr CFileMgr::FindAppOnVolume(OSType sig,
  680.                       short vRefNum,
  681.                       FSSpec& thefile)
  682. // Copied from MacApp. It did not have any docs in MacApp eithere
  683. // Ask vol's desktop db for application
  684. //-----------------------------------
  685. {
  686.     DTPBRec pb;
  687.     OSErr err;
  688.  
  689.     pb.ioCompletion = NULL;
  690.     pb.ioVRefNum = vRefNum;
  691.     pb.ioNamePtr = NULL;
  692.     if ((err = PBDTGetPath(&pb)) != noErr)
  693.         return err;                                    // Puts DT refnum into pb.ioDTRefNum
  694.     short refNum = pb.ioDTRefNum;
  695.  
  696.     pb.ioCompletion = NULL;
  697.     pb.ioDTRefNum = refNum;
  698.     pb.ioIndex = 0;
  699.     pb.ioFileCreator = sig;
  700.     pb.ioNamePtr = (StringPtr) thefile.name;
  701.     err = PBDTGetAPPLSync(&pb);                        // Find it!
  702.  
  703.     if( err == fnfErr )
  704.         err = afpItemNotFound;                        // Bug in PBDTGetAPPL
  705.     if( err )
  706.         return err;                                    // Returns afpItemNotFound if app wasn't found.
  707.  
  708.     thefile.vRefNum = vRefNum;
  709.     thefile.parID = pb.ioAPPLParID;
  710.     return err;
  711. }
  712.  
  713. //-----------------------------------
  714. OSErr CFileMgr::FindApplication(OSType sig, FSSpec& file)    
  715. // Finds application info given a file, based on file's creator
  716. // Copied almost exactly from LaunchBySignature volume search
  717. //-----------------------------------
  718. {
  719.     short sysVRefNum;
  720.  
  721.     OSErr err = CFileMgr::GetSysVolume(sysVRefNum);
  722.     if (err)
  723.         return err;                                    // Find boot volume
  724.  
  725.     short vRefNum = sysVRefNum;                        // Start search with boot volume
  726.     short index = 0;
  727.     do    {
  728.         if (index == 0 || vRefNum != sysVRefNum)        {
  729.             Boolean hasDesktopDB;
  730.             err = CFileMgr::VolHasDesktopDB(vRefNum, hasDesktopDB);
  731.             if (err)
  732.                 return err;
  733.             if (hasDesktopDB)            {
  734.                 // If volume has a desktop DB,
  735.                 err = FindAppOnVolume(sig, vRefNum, file);    // ask it to find app
  736.                 if (err == noErr)
  737.                     return err;
  738. //                else if (err != afpItemNotFound) on broken file systems, the error returned might be spurious
  739. //                    return err;
  740.             }
  741.         }
  742.         err = CFileMgr::GetIndVolume(++index, vRefNum);    // Else go to next volume
  743.     } while (err != nsvErr);                        // Keep going until we run out of vols
  744.     if( err==nsvErr || err==afpItemNotFound )
  745.         err= fnfErr;                                    // File not found on any volume
  746.     return err;
  747. }
  748.  
  749. //-----------------------------------
  750. inline void  SwapSlashColon(char * s)
  751. // Swaps ':' with '/'
  752. //-----------------------------------
  753. {
  754.     while ( *s != 0)
  755.     {
  756.         if (*s == '/')
  757.             *s++ = ':';
  758.         else if (*s == ':')
  759.             *s++ = '/';
  760.         else
  761.             *s++;
  762.     }
  763. }
  764.  
  765. //-----------------------------------
  766. char* CFileMgr::EncodeMacPath( char* inPath, Boolean prependSlash )
  767. //    Transforms Macintosh style path into Unix one
  768. //    Method: Swap ':' and '/', hex escape the result
  769. //-----------------------------------
  770. {
  771.     if (inPath == NULL)
  772.         return NULL;
  773.     int pathSize = XP_STRLEN(inPath);
  774.     
  775.     // XP code sometimes chokes if there's a final slash in the unix path.
  776.     // Since correct mac paths to folders and volumes will end in ':', strip this
  777.     // first.
  778.     char* c = inPath + pathSize - 1;
  779.     if (*c == ':')
  780.     {
  781.         *c = 0;
  782.         pathSize--;
  783.     }
  784.  
  785.     char * newPath = NULL;
  786.     char * finalPath = NULL;
  787.     
  788.     if (prependSlash)
  789.     {
  790.         newPath = (char*) XP_ALLOC(pathSize + 2);
  791.         newPath[0] = ':';    // It will be converted to '/'
  792.         XP_MEMCPY(&newPath[1], inPath, pathSize + 1);
  793.     }
  794.     else
  795.         newPath = XP_STRDUP(inPath);
  796.  
  797.     if (newPath)
  798.     {
  799.         SwapSlashColon( newPath );
  800.         finalPath = NET_Escape(newPath, URL_PATH);
  801.         XP_FREE(newPath);        
  802.     }
  803.  
  804.     XP_FREE( inPath );
  805.     return finalPath;
  806. } // CFileMgr::EncodeMacPath
  807.  
  808. //-----------------------------------
  809. char * CFileMgr::GetURLFromFileSpec(const FSSpec& inSpec)
  810. //-----------------------------------
  811. /* GetURLFromFileSpec generates a local file URL given a file spec.
  812.      Requirements:
  813.         Unix-style file name (':' is replaced with '/')
  814.         url looks like file:///<path>
  815.         <path> is mac path, where all reserved characters (= | ; | / | # | ? | space)
  816.         have been escaped. (except :).
  817.         ':' is then changed to '/' for compatibility with UNIX style file names.
  818.     
  819.     Input:
  820.         Valid FSSpec
  821.         
  822.     Method:
  823.         Generate a full path name
  824.     Notes:
  825.         This does not guarantee that the filename will work. We may still need to
  826.         munge it later (if for example such a filename already existed)
  827. */
  828. {
  829.     char * path = PathNameFromFSSpec( inSpec, TRUE );
  830.     char * unixPath = EncodeMacPath(path);
  831.     char * finalPath = (char*)XP_ALLOC(strlen(unixPath) + 8 + 1);    //  file:///<path>0
  832.     if ( finalPath == NULL )
  833.         return NULL;
  834.     finalPath[0] = 0;
  835.     if ( unixPath == NULL )
  836.         return NULL;
  837.     strcat(finalPath, "file://");
  838.     strcat(finalPath, unixPath);
  839.     XP_FREE(unixPath);
  840.     return finalPath;
  841. }
  842.  
  843. //-----------------------------------
  844. char*  CFileMgr::MacPathFromUnixPath(const char* unixPath)
  845. //-----------------------------------
  846. {
  847.     // Relying on the fact that the unix path is always longer than the mac path:
  848.     size_t len = XP_STRLEN(unixPath);
  849.     char* result = (char*)XP_ALLOC(len + 2); // ... but allow for the initial colon in a partial name
  850.     if (result)
  851.     {
  852.         char* dst = result;
  853.         const char* src = unixPath;
  854.         if (*src == '/')             // Ñ full path
  855.             src++;
  856.         else if (strchr(src, '/'))    // Ñ partial path, and not just a leaf name
  857.             *dst++ = ':';
  858.         XP_STRCPY(dst, src);
  859.         NET_UnEscape(dst);    // Hex Decode
  860.         SwapSlashColon(dst);
  861.     }
  862.     return result;
  863. } // CFileMgr::MacPathFromUnixPath
  864.  
  865. //-----------------------------------
  866. OSErr CFileMgr::FSSpecFromLocalUnixPath(
  867.     const char * unixPath,
  868.     FSSpec * inOutSpec,
  869.     Boolean resolveAlias)
  870. // File spec from URL. Reverses GetURLFromFileSpec 
  871. // Its input is only the <path> part of the URL
  872. // JRM 97/01/08 changed this so that if it's a partial path (doesn't start with '/'),
  873. // then it is combined with inOutSpec's vRefNum and parID to form a new spec.
  874. //-----------------------------------
  875. {
  876.     if (unixPath == NULL)
  877.         return badFidErr;
  878.     char* macPath = MacPathFromUnixPath(unixPath);
  879.     if (!macPath)
  880.         return memFullErr;
  881.  
  882.     OSErr err = noErr;
  883.     if (*unixPath == '/' /*full path*/)
  884.         err = FSSpecFromPathname(macPath, inOutSpec);
  885.     else
  886.         err = ::FSMakeFSSpec(inOutSpec->vRefNum, inOutSpec->parID, CStr255(macPath), inOutSpec);
  887.     if (err == fnfErr)
  888.         err = noErr;
  889.     Boolean dummy, dummy2;    
  890.     if (err == noErr && resolveAlias)    // Added 
  891.         err = ::ResolveAliasFile(inOutSpec,TRUE,&dummy,&dummy2);
  892.     XP_FREE(macPath);
  893.     Assert_(err==noErr||err==fnfErr);
  894.     return err;
  895. } // CFileMgr::FSSpecFromLocalUnixPath
  896.  
  897. Boolean CFileMgr::FileExists( const FSSpec& fsSpec )
  898. {    
  899.     FSSpec        temp;
  900.     OSErr        err;
  901.     
  902.     err = FSMakeFSSpec( fsSpec.vRefNum, fsSpec.parID, fsSpec.name, &temp );
  903.     
  904.     return ( err == noErr );
  905. }
  906.  
  907. Boolean    CFileMgr::FileHasDataFork(const FSSpec& fsSpec )
  908. {
  909.     CStr31 name = fsSpec.name;
  910.     CInfoPBRec pb;
  911.     pb.hFileInfo.ioNamePtr = name;
  912.     pb.hFileInfo.ioVRefNum = fsSpec.vRefNum;
  913.     pb.hFileInfo.ioDirID = fsSpec.parID;
  914.     pb.hFileInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
  915.     OSErr err = PBGetCatInfoSync(&pb);
  916.     if (err != noErr)
  917.         return FALSE;
  918.     else if (pb.hFileInfo.ioFlLgLen <= 0)
  919.         return FALSE;
  920.     else
  921.         return TRUE;
  922. }
  923. // Does the file have resource fork?
  924. Boolean    CFileMgr::FileHasResourceFork(const FSSpec& fsSpec )
  925. {
  926.     CStr31 name = fsSpec.name;
  927.     CInfoPBRec pb;
  928.     pb.hFileInfo.ioNamePtr = name;
  929.     pb.hFileInfo.ioVRefNum = fsSpec.vRefNum;
  930.     pb.hFileInfo.ioDirID = fsSpec.parID;
  931.     pb.hFileInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
  932.     OSErr err = PBGetCatInfoSync(&pb);
  933.     if (err != noErr)
  934.         return FALSE;
  935.     else if (pb.hFileInfo.ioFlRLgLen <= 0)
  936.         return FALSE;
  937.     else
  938.         return TRUE;
  939.     
  940. }
  941.  
  942. void CFileMgr::CopyFSSpec(const FSSpec & srcSpec, FSSpec & destSpec)
  943. {
  944.     destSpec.vRefNum = srcSpec.vRefNum;
  945.     destSpec.parID = srcSpec.parID;
  946.     *(CStr31*)&destSpec.name = srcSpec.name;
  947. }
  948.  
  949. OSErr CFileMgr::GetFolderID(FSSpec& folderSpec, long& dirID)
  950. {
  951.     CInfoPBRec pb;
  952.     pb.hFileInfo.ioNamePtr = folderSpec.name;
  953.     pb.hFileInfo.ioVRefNum = folderSpec.vRefNum;
  954.     pb.hFileInfo.ioDirID = folderSpec.parID;
  955.     pb.hFileInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
  956.     OSErr err = PBGetCatInfoSync(&pb);
  957.     if (err == noErr)
  958.         dirID = pb.dirInfo.ioDrDirID;
  959.     return err;
  960. }
  961.  
  962. OSErr CFileMgr::DeleteFolder(const FSSpec& folderSpec)
  963. {
  964.     CFileIter iter(folderSpec);
  965.     FSSpec    nextFile;
  966.     FInfo finderInfo;
  967.     Boolean isFolder;
  968.     OSErr err = noErr;
  969.     OSErr storedErr = noErr;
  970.     
  971.     if (FileExists(folderSpec) == false)
  972.         return noErr;
  973. // Delete all the items in the folder
  974.     while ( iter.Next(nextFile, finderInfo, isFolder) )
  975.     {
  976.         if (isFolder)
  977.             err = DeleteFolder(nextFile);
  978.         else
  979.             err = ::FSpDelete(&nextFile);
  980.         if (err != noErr)
  981.             storedErr = err;
  982.     }
  983. // Delete the folder
  984.     err = FSpDelete(&folderSpec);
  985.     if (err != noErr)
  986.         storedErr = err;
  987.     return storedErr;
  988. }
  989.  
  990. CFileIter::CFileIter(const FSSpec &folderSpec)
  991. {    
  992.     fDir = folderSpec;
  993.     fIndex = 0;
  994.  
  995.     CInfoPBRec pb;
  996.     pb.hFileInfo.ioNamePtr = (unsigned char*)folderSpec.name; // cast avoids warning
  997.     pb.hFileInfo.ioVRefNum = folderSpec.vRefNum;
  998.     pb.hFileInfo.ioDirID = folderSpec.parID;
  999.     pb.hFileInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
  1000.     OSErr err = PBGetCatInfoSync(&pb);
  1001.     if (err == noErr)
  1002.     {
  1003.         fIndex = pb.dirInfo.ioDrNmFls;
  1004.         fDir.parID = pb.dirInfo.ioDrDirID;
  1005.     }
  1006. }
  1007.  
  1008. Boolean CFileIter::Next(FSSpec &nextFile, FInfo& finderInfo, Boolean& folder)
  1009. {
  1010. tryagain:
  1011.     if (fIndex <= 0)
  1012.         return FALSE;
  1013.  
  1014.     CInfoPBRec cipb;
  1015.     DirInfo    *dipb=(DirInfo *)&cipb;
  1016.     dipb->ioCompletion = NULL;
  1017.     dipb->ioFDirIndex = fIndex--;
  1018.     dipb->ioVRefNum = fDir.vRefNum;
  1019.     dipb->ioDrDirID = fDir.parID;
  1020.     dipb->ioNamePtr = (StringPtr)&nextFile.name;
  1021.     OSErr err = PBGetCatInfoSync (&cipb);
  1022.     if (err != noErr)
  1023.         goto tryagain;    // Go backwards, skip the directories
  1024.     if ((dipb->ioFlAttrib & 0x10) != 0)
  1025.         folder = TRUE;
  1026.     else
  1027.         folder = FALSE;
  1028.     nextFile.vRefNum = fDir.vRefNum;
  1029.     nextFile.parID = fDir.parID;
  1030.     Boolean dummy,wasAliased;
  1031.     err = ::ResolveAliasFile(&nextFile,TRUE,&dummy,&wasAliased);
  1032.     if ((err == noErr) && wasAliased)
  1033.     {    // Need to get info again
  1034.         CInfoPBRec pb;
  1035.  
  1036.         pb.hFileInfo.ioNamePtr = (StringPtr)&nextFile.name;
  1037.         pb.hFileInfo.ioVRefNum = nextFile.vRefNum;
  1038.         pb.hFileInfo.ioDirID = nextFile.parID;
  1039.         pb.hFileInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
  1040.         err = PBGetCatInfoSync(&pb);
  1041.         finderInfo = pb.hFileInfo.ioFlFndrInfo;
  1042.         if ((pb.hFileInfo.ioFlAttrib & 0x10) != 0)
  1043.             folder = TRUE;
  1044.         else
  1045.             folder = FALSE;
  1046.     }
  1047.     else
  1048.         finderInfo = cipb.hFileInfo.ioFlFndrInfo;
  1049.     return TRUE;
  1050. }
  1051.  
  1052.  
  1053. OSErr CFileMgr::UpdateFinderDisplay(const FSSpec& inSpec)
  1054. {
  1055.     AppleEvent theEvent;
  1056.     AliasHandle    theAlias = NULL;
  1057.     OSErr        theErr = noErr;
  1058.     
  1059.     try
  1060.         {
  1061.         theErr = ::NewAlias(NULL, &inSpec, &theAlias);
  1062.         ThrowIfOSErr_(theErr);
  1063.  
  1064.         FSSpec theFinderSpec;
  1065.         ProcessSerialNumber theFinderPSN;
  1066.         theErr = FindProcessBySignature('MACS', 'FNDR', theFinderPSN, &theFinderSpec);
  1067.         ThrowIfOSErr_(theErr);
  1068.  
  1069.         StHandleLocker theAliasLocker((Handle)theAlias);
  1070.         //LAEStream theEventStream('fndr', 'fupd', typeProcessSerialNumber, &theFinderPSN, sizeof( ProcessSerialNumber ));
  1071.         //theEventStream.WriteKeyDesc(keyDirectObject, typeAlias, *theAlias, ::GetHandleSize((Handle)theAlias));
  1072.         //theEventStream.Close(&theEvent);
  1073.         //UAppleEventsMgr::SendAppleEvent(theEvent);
  1074.         }
  1075.     catch(...)
  1076.         {
  1077.         if (theAlias != NULL)
  1078.             ::DisposeHandle((Handle)theAlias);
  1079.         }
  1080.     
  1081.     return theErr;
  1082. }
  1083.  
  1084. void CFileMgr::MakeAliasFile(const FSSpec& aliasSpec, const FSSpec& target)
  1085. {
  1086.     AliasHandle alias;
  1087.     OSErr err = NewAlias( nil, &target, &alias );
  1088.     ThrowIfOSErr_(err);
  1089.     
  1090.     LFile aliasFile(aliasSpec);
  1091.     aliasFile.CreateNewFile('MACS', kContainerFolderAliasType);
  1092.     aliasFile.OpenResourceFork(fsRdWrPerm);
  1093.  
  1094.     AddResource((Handle) alias, 'alis', 0, nil);
  1095.         
  1096.     FInfo info;
  1097.     err = ::FSpGetFInfo(&aliasSpec, &info);
  1098.     ThrowIfOSErr_(err);
  1099.     
  1100.     info.fdFlags |= kIsAlias;
  1101.     err = ::FSpSetFInfo(&aliasSpec, &info);
  1102.     ThrowIfOSErr_(err);
  1103. }
  1104.  
  1105. OSErr CFileMgr::CopyFile(const FSSpec& srcSpec, const FSSpec &dstDirSpec, const CStr255 ©Name)
  1106. {
  1107.  
  1108.     return FSpFileCopy(&srcSpec, &dstDirSpec, (StringPtr)©Name, nil, 0, true);
  1109.  
  1110. }
  1111.  
  1112.  
  1113. //-----------------------------------------------------------------------------
  1114. // More Utilities
  1115. //-----------------------------------------------------------------------------
  1116.  
  1117. void  WriteCString (LStream * s, const char * c)
  1118. {
  1119.     s->WriteData (c, strlen(c));
  1120. }
  1121.  
  1122. void 
  1123. WriteChar (LStream * s, char c)
  1124. {
  1125.     s->WriteData (&c, 1);
  1126. }
  1127.  
  1128. //
  1129. // fe_FileNameFromContext
  1130. //
  1131. // Suggest a name for this document based on its title or it's URL content type. If there
  1132. // are colons, be sure to swa[ them with /
  1133. //
  1134.  
  1135. void fe_FileNameFromContext( MWContext* context, const char* url, CStr31& defaultName )
  1136. {
  1137. #ifdef MOZ_MAIL_NEWS
  1138.     char*        urlString;
  1139.     
  1140.     urlString = MimeGuessURLContentName( context, url );
  1141.     if ( urlString )
  1142.     {
  1143.         SwapSlashColon( urlString );
  1144.         defaultName = urlString;
  1145.         XP_FREE( urlString );
  1146.     }
  1147.     else
  1148. #endif // MOZ_MAIL_NEWS
  1149.     {
  1150.         // If we have a context title and it's not an ftp URL
  1151.         if (context && context->title && context->title[0] &&
  1152.             strncasecomp(url, "ftp://", 6))
  1153.         {
  1154.             defaultName = context->title;
  1155.         }
  1156.         else
  1157.         {
  1158.             defaultName = CFileMgr::FileNameFromURL( url );
  1159.         }
  1160.     }
  1161.     
  1162.     // now make sure the resulting name doesn't have any colons.
  1163.     char buffer[50];
  1164.     short nextInsertPos = 0;
  1165.     for ( short loop = 1; loop <= defaultName.Length(); loop++ )
  1166.     {
  1167.         char currChar = defaultName[loop];
  1168.         if ( currChar != ':' ) 
  1169.         {
  1170.             buffer[nextInsertPos] = currChar;
  1171.             nextInsertPos++;
  1172.         }
  1173.     } // for each character
  1174.     buffer[nextInsertPos] = NULL;        // null terminate the new name
  1175.     defaultName = buffer;                // make the string w/out colons the default
  1176.     
  1177. } // fe_FileNameFromContext
  1178.  
  1179. OSErr FSSpecFromPathname_CWrapper(char * path, FSSpec * outSpec)
  1180. {
  1181.     return (CFileMgr::FSSpecFromPathname(path, outSpec));
  1182. }
  1183.