Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!efi!tim From: tim@efi.com (Tim Maroney) Newsgroups: comp.sys.mac.programmer Subject: Re: Full Path Names (Was: Launching application returned in an SFReply record.) Message-ID: <1990Aug23.154101.12931@efi.com> Date: 23 Aug 90 15:41:01 GMT References: <25810@cs.yale.edu> <2079@cod.NOSC.MIL> Organization: Electronics For Imaging, Inc. Lines: 79 In article <2079@cod.NOSC.MIL> sampson@cod.nosc.mil.UUCP (Charles H. Sampson) writes: >In article <25810@cs.yale.edu> braun-eric@CS.YALE.EDU (Eric E. Braun) writes: >> ... Is there any function hidden in IM somplace that returns a full >>path name given an SFReply? > > At least two respondents have given routines that generate the full path >name. I haven't analyzed them to see if they work (they probably do), but one >problem with this approach is that the generated path name could theoretically >be longer than 255 characters (the maximum size of Str255). I doubt that such >a case would ever arise in the real world. Does anyone know of a case where >where it did? Well, no, but folders can nest to any depth. This could happen very quickly if someone is fond of giving folders names like "The Unbearable Lightness of Being". I wrote a C routine that at least won't crash in this case, and with a little work to parse long file names, could cope with it cleanly: FullFileName(StringPtr outname, StringPtr tail, short volume, long dirID) { StringHandle name; Str255 text, volname; HVolumeParam hvp; CInfoPBRec di; long size; short err; /* extract the volume name */ hvp.ioNamePtr = volname; hvp.ioVRefNum = volume; hvp.ioVolIndex = 0; PBHGetVInfo((HParmBlkPtr)&hvp, false); if (hvp.ioVSigWord == 0xd2d7) { outname[0] = 0; return noHFSerr; } /* create and initialize the name handle */ if (tail) { if (err = PtrToHand(tail + 1, &name, tail[0])) return err; size = tail[0]; } else { if ((name = NewHandle(0)) == 0) return MemError(); size = 0; } /* now start extracting the dirs and prepending them to * the handle */ for ( ; dirID != 2; dirID = di.dirInfo.ioDrParID) { text[0] = 0; di.dirInfo.ioNamePtr = text; di.dirInfo.ioVRefNum = volume; di.dirInfo.ioFDirIndex = -1; di.dirInfo.ioDrDirID = dirID; PBGetCatInfo(&di, false); text[++text[0]] = ':'; SetHandleSize(name, size += text[0]); BlockMove((Ptr)*name, (Ptr)(*name) + text[0], size - text[0]); BlockMove((Ptr)text + 1, (Ptr)*name, text[0]); } /* prepend the volume name onto the handle */ volname[++volname[0]] = ':'; SetHandleSize(name, size += volname[0]); BlockMove((Ptr)*name, (Ptr)(*name) + volname[0], size - volname[0]); BlockMove((Ptr)volname + 1, (Ptr)*name, volname[0]); /* copy and delete the handle */ if (size > 255) { DisposHandle(name); SysBeep(12); outname[0] = 0; return tooBigErr; } outname[0] = size; BlockMove((Ptr)*name, (Ptr)outname + 1, size); DisposHandle(name); return noErr; } If you want to work with longer names, then you make the return value the handle instead of a Str255. To use it, write a fairly easy routine that first takes off the volume name and turns it to a vRefNum, then pulls off each folder name and turns it to a directory id, then pulls off the file name, so you wind up with the vRefNum, dirID, fName triplet you need.