home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-03-04 | 6.7 KB | 214 lines | [TEXT/TPAS] |
- program filename;
-
- {
- Name: ╥FileName╙ -- a HyperCard "XFCN" (External Function) resource
-
- Written By: Steve Maller
- Apple Computer Training Support
- Copyright ⌐ 1987 Apple Computer
- AppleLink: MALLER1
- Saturday, August 22, 1987
-
- Modified for Turbo Pascal by Stephen Kurtzman
-
- Very slightly modified by Brian Liebowitz...Steve Kurtzman got it right
- for the DHDR's that he was using, so if it doesn't work it's my fault.
-
- You must install the DHDR resources called PasXFCN and PasXCMD
- into your copy of Turbo before compiling this XCMD. You must also
- have compiled the unit HyperXCMD and moved it into the Turbo progam,
- and the file XCMDGlue.inc must be accessible. After compiling,use
- ResEdit to change the ID from 300, and to copy the XCMD or XFCN into
- your stack or Hypercard.
-
-
- Language: Turbo Pascal
-
- Usage: FileName("fileType") -- "fileType" is optional
-
- Examples: FileName("STAK") -- limits list to HyperCard Stacks
- FileName("TEXT") -- limits list to text files
- FileName("APPL") -- limits list to applications
- FileName() -- lists ALL files
-
- Result: The full pathname of the selected file.
- For example, if you selected the file "Address Stack" which is
- in the folder "My Stacks" in the folder "HyperCard" on the
- disk "HD" the result is:
- HD:HyperCard:My Stacks:Address Stack
- If the user clicks ╥Cancel╙ an empty string is returned.
-
- Warning: A word of caution: the Mac's file system can NOT accept
- pathnames longer than 255 characters. Be careful...
-
- Script
- Example: on mouseUp
- put FileName("TEXT") into theFile
- if theFile is not empty then
- open file theFile
- read from file theFile for 2000
- put it into bkgnd field 1
- close file theFile
- end if
- end mouseUp
-
- Why? You must access files in HyperCard by their full pathname.
- Unfortunately, HyperCard offers you no clear way of finding
- out what that full name is. If files are on a hard disk, it
- can be a real pain to remember the entire pathname. This
- function simplifies that task for both the stackware developer
- and the end user.
-
- Thanks to: Ted Kaehler, Dan Winkler, and Bill Atkinson - my hero!
-
- }
-
- {$R-}
- {$U-}
- {$D PasXFCN}
-
- USES MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf, HyperXCmd;
-
- PROCEDURE PasXFCN(paramPtr: XCmdPtr);
-
- VAR
- myWDPB: WDPBPtr; { some variants of the same animal }
- myCPB: CInfoPBPtr;
- myPB: HParmBlkPtr;
- fullPathName: Str255;
- numTypes: Integer;
- reply: SFReply;
- typeList: SFTypeList;
-
- PROCEDURE DoJsr(addr: ProcPtr); INLINE $205F,$4E90;
-
- FUNCTION PasToZero(str: Str255): Handle;
- { Convert a Pascal string to a zero-terminated string. Returns a handle
- to a new zero-terminated string. The caller must dispose the handle.
- You'll need to do this for any result or argument you send from
- your XCMD to HyperTalk. }
- BEGIN
- WITH paramPtr^ DO
- BEGIN
- inArgs[1] := ORD(@str);
- request := xreqPasToZero;
- DoJsr(entryPoint);
- PasToZero := Handle(outArgs[1]);
- END;
- END;
-
-
- FUNCTION TheyChoseAFile: Boolean;
-
- VAR
- pt: Point;
-
- BEGIN
- TheyChoseAFile := FALSE;
- pt.v := 60;
- pt.h := 82;
- SFGetFile(pt, '', NIL, numTypes, typeList, NIL, reply);
- { have 'em pick a file }
- IF reply.good THEN { if they didn't choose Cancel }
- BEGIN
- TheyChoseAFile := TRUE;
- fullPathName := reply.fName; { start the ball rolling }
- END;
- END;
-
- PROCEDURE BuildThePathName;
-
- VAR
- name: Str255;
- err: Integer;
-
- BEGIN
- name := ''; { start with an empty name }
- myPB^.ioNamePtr := @name; { we want the Volume name }
- myPB^.ioCompletion := pointer(0);
- myPB^.ioVRefNum := reply.vRefNum; { returned from SFGetFile }
- myPB^.ioVolIndex := 0; { use the vRefNum and name }
- err := PBHGetVInfo(myPB, FALSE); { fill in the Volume info }
- IF err <> noErr THEN
- Exit;
-
- { Now we need the Working Directory (WD) information because we're going
- to step backwards from the file through all of the the folders until
- we reach the root directory }
-
- myWDPB^.ioVRefNum := reply.vRefNum; { this got set to 0 above }
- myWDPB^.ioWDProcID := 0; { use the vRefNum }
- myWDPB^.ioWDIndex := 0; { we want ALL directories }
- err := PBGetWDInfo(myWDPB, FALSE); { do it }
- IF err <> noErr THEN
- Exit;
-
- myCPB^.ioFDirIndex := - 1; { use the ioDirID field only }
- myCPB^.ioDrDirID := myWDPB^.ioWDDirID;{ info returned above }
- err := PBGetCatInfo(myCPB, FALSE); { do it }
- IF err <> noErr THEN
- Exit;
-
- { Here starts the real work - start to climb the tree by continually
- looking in the ioDrParId field for the next directory above until we
- fail... }
-
- myCPB^.ioDrDirID := myCPB^.ioDrParId; { the first folder}
- fullPathName := Concat(myCPB^.ioNamePtr^, ':', reply.fName);
- REPEAT
- myCPB^.ioDrDirID := myCPB^.ioDrParId;
- err := PBGetCatInfo(myCPB, FALSE); { the next level }
-
- { Be careful of an error returned here - it means the user chose a file
- on the desktop level of this volume. If this is the case, just stop
- here and return "VolumeName:FileName", otherwise loop until failure }
- IF err = noErr THEN
- fullPathName := Concat(myCPB^.ioNamePtr^, ':', fullPathName);
-
- UNTIL err <> noErr;
-
- END; { PROCEDURE BuildThePathName }
-
- BEGIN { PROCEDURE FileName }
-
- { First we allocate some memory in the heap for the parameter block. This
- could in theory work on the stack, but in reality it makes no difference
- as we're entirely modal (ugh) here... }
-
- fullPathName := '';
-
- myCPB := CInfoPBPtr(NewPtr(SizeOf(HParamBlockRec)));
- IF ord4(myCPB) <= 0 THEN
- Exit; { Rats! Bill didn't leave enough room }
- myWDPB := WDPBPtr(myCPB); { icky Pascal type coercions follow }
- myPB := HParmBlkPtr(myCPB);
-
- numTypes := 1; { for SFGetFile }
- WITH paramPtr^ DO
- BEGIN
- IF paramCount = 0 THEN
- numTypes := - 1 { FileName() - get all files }
- ELSE
- BlockMove(params[1]^, @typeList[0], 4);
- { FileName("TYPE") }
-
- IF TheyChoseAFile THEN
- BuildThePathName;
-
- { PasToZero is very interesting - it is a HyperTalk command
- that you can actually call from OUTSIDE of HyperCard.
- You need it because HyperCard uses C format strings with
- no length byte; they are terminated by a null byte. They are
- actually HANDLES to C format strings. Nice work, Dan! }
-
- returnValue := PasToZero(fullPathName);
-
- END; { WITH paramPtr^ DO }
-
- DisposPtr(pointer(myCPB)); { Clean Up Your Heap! }
-
- END; { PROCEDURE FileName }
-
- BEGIN
- END.
-