home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / hc / turbopgl.sit / FileName.p < prev    next >
Encoding:
Text File  |  1988-03-04  |  6.7 KB  |  214 lines  |  [TEXT/TPAS]

  1. program filename;
  2.  
  3. Name:    ╥FileName╙ -- a HyperCard "XFCN" (External Function) resource
  4.  
  5. Written By: Steve Maller
  6.       Apple Computer Training Support
  7.       Copyright ⌐ 1987 Apple Computer
  8.       AppleLink: MALLER1
  9.       Saturday, August 22, 1987 
  10.  
  11. Modified for Turbo Pascal by Stephen Kurtzman
  12.  
  13. Very slightly modified by Brian Liebowitz...Steve Kurtzman got it right
  14. for the DHDR's that he was using, so if it doesn't work it's my fault.
  15.  
  16.     You must install the DHDR resources called PasXFCN and PasXCMD 
  17.     into your copy of Turbo before compiling this XCMD.  You must also 
  18.      have compiled the unit HyperXCMD and moved it into the Turbo progam,
  19.       and the file XCMDGlue.inc must be accessible.  After compiling,use
  20.      ResEdit to change the ID from 300, and to copy the XCMD or XFCN into 
  21.     your stack or Hypercard.
  22.  
  23.  
  24. Language:  Turbo Pascal
  25.  
  26. Usage:   FileName("fileType") -- "fileType" is optional
  27.  
  28. Examples:  FileName("STAK")   -- limits list to HyperCard Stacks
  29.       FileName("TEXT")   -- limits list to text files
  30.       FileName("APPL")   -- limits list to applications
  31.       FileName()       -- lists ALL files
  32.  
  33. Result:   The full pathname of the selected file.
  34.       For example, if you selected the file "Address Stack" which is
  35.       in the folder "My Stacks" in the folder "HyperCard" on the
  36.       disk "HD" the result is:
  37.          HD:HyperCard:My Stacks:Address Stack
  38.       If the user clicks ╥Cancel╙ an empty string is returned.
  39.       
  40. Warning:  A word of caution: the Mac's file system can NOT accept
  41.       pathnames longer than 255 characters. Be careful...
  42.       
  43. Script
  44. Example:  on mouseUp
  45.        put FileName("TEXT") into theFile
  46.        if theFile is not empty then
  47.         open file theFile
  48.         read from file theFile for 2000
  49.         put it into bkgnd field 1
  50.         close file theFile
  51.        end if
  52.       end mouseUp
  53.  
  54. Why?    You must access files in HyperCard by their full pathname.
  55.       Unfortunately, HyperCard offers you no clear way of finding
  56.       out what that full name is. If files are on a hard disk, it
  57.       can be a real pain to remember the entire pathname. This
  58.       function simplifies that task for both the stackware developer
  59.       and the end user.
  60.  
  61. Thanks to: Ted Kaehler, Dan Winkler, and Bill Atkinson - my hero!
  62.  
  63. }
  64.  
  65. {$R-}
  66. {$U-}
  67. {$D PasXFCN}
  68.  
  69. USES   MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf, HyperXCmd;
  70.  
  71.   PROCEDURE PasXFCN(paramPtr: XCmdPtr);
  72.  
  73.    VAR
  74.     myWDPB: WDPBPtr;       { some variants of the same animal }
  75.     myCPB: CInfoPBPtr;
  76.     myPB: HParmBlkPtr;
  77.     fullPathName: Str255;
  78.     numTypes: Integer;
  79.     reply: SFReply;
  80.     typeList: SFTypeList;
  81.  
  82.  PROCEDURE DoJsr(addr: ProcPtr); INLINE $205F,$4E90;
  83.  
  84. FUNCTION PasToZero(str: Str255): Handle;
  85. {  Convert a Pascal string to a zero-terminated string.  Returns a handle
  86.    to a new zero-terminated string.  The caller must dispose the handle.
  87.    You'll need to do this for any result or argument you send from 
  88.    your XCMD to HyperTalk. }
  89. BEGIN
  90.   WITH paramPtr^ DO
  91.     BEGIN
  92.       inArgs[1] := ORD(@str);
  93.       request := xreqPasToZero;
  94.       DoJsr(entryPoint);
  95.       PasToZero := Handle(outArgs[1]);
  96.     END;
  97. END;
  98.  
  99.  
  100.    FUNCTION TheyChoseAFile: Boolean;
  101.  
  102.     VAR
  103.      pt: Point;
  104.  
  105.     BEGIN
  106.      TheyChoseAFile := FALSE;
  107.      pt.v := 60;
  108.      pt.h := 82;
  109.      SFGetFile(pt, '', NIL, numTypes, typeList, NIL, reply);
  110.                         { have 'em pick a file }
  111.      IF reply.good THEN           { if they didn't choose Cancel }
  112.       BEGIN
  113.        TheyChoseAFile := TRUE;
  114.        fullPathName := reply.fName;    { start the ball rolling }
  115.       END;
  116.     END;
  117.  
  118.    PROCEDURE BuildThePathName;
  119.  
  120.     VAR
  121.      name: Str255;
  122.      err: Integer;
  123.  
  124.     BEGIN
  125.      name := '';              { start with an empty name }
  126.      myPB^.ioNamePtr := @name;       { we want the Volume name }
  127.       myPB^.ioCompletion := pointer(0);
  128.      myPB^.ioVRefNum := reply.vRefNum;   { returned from SFGetFile }
  129.      myPB^.ioVolIndex := 0;        { use the vRefNum and name }
  130.      err := PBHGetVInfo(myPB, FALSE);   { fill in the Volume info }
  131.      IF err <> noErr THEN
  132.       Exit;
  133.  
  134. { Now we need the Working Directory (WD) information because we're going 
  135.  to step backwards from the file through all of the the folders until
  136.  we reach the root directory }
  137.  
  138.      myWDPB^.ioVRefNum := reply.vRefNum;  { this got set to 0 above }
  139.      myWDPB^.ioWDProcID := 0;       { use the vRefNum }
  140.      myWDPB^.ioWDIndex := 0;        { we want ALL directories }
  141.      err := PBGetWDInfo(myWDPB, FALSE);  { do it }
  142.      IF err <> noErr THEN
  143.       Exit;
  144.  
  145.      myCPB^.ioFDirIndex := - 1;      { use the ioDirID field only }
  146.      myCPB^.ioDrDirID := myWDPB^.ioWDDirID;{ info returned above }
  147.      err := PBGetCatInfo(myCPB, FALSE);  { do it }
  148.      IF err <> noErr THEN
  149.       Exit;
  150.  
  151. { Here starts the real work - start to climb the tree by continually
  152.  looking in the ioDrParId field for the next directory above until we
  153.  fail... }
  154.  
  155.      myCPB^.ioDrDirID := myCPB^.ioDrParId; { the first folder}
  156.      fullPathName := Concat(myCPB^.ioNamePtr^, ':', reply.fName);
  157.      REPEAT
  158.       myCPB^.ioDrDirID := myCPB^.ioDrParId;
  159.       err := PBGetCatInfo(myCPB, FALSE); { the next level }
  160.  
  161. { Be careful of an error returned here - it means the user chose a file 
  162.  on the desktop level of this volume. If this is the case, just stop
  163.  here and return "VolumeName:FileName", otherwise loop until failure }
  164.       IF err = noErr THEN
  165.        fullPathName := Concat(myCPB^.ioNamePtr^, ':', fullPathName);
  166.  
  167.      UNTIL err <> noErr;
  168.      
  169.     END;  { PROCEDURE BuildThePathName }
  170.  
  171.    BEGIN  { PROCEDURE FileName }
  172.    
  173. { First we allocate some memory in the heap for the parameter block. This
  174.  could in theory work on the stack, but in reality it makes no difference
  175.  as we're entirely modal (ugh) here... }
  176.  
  177.     fullPathName := '';
  178.  
  179.     myCPB := CInfoPBPtr(NewPtr(SizeOf(HParamBlockRec)));
  180.     IF ord4(myCPB) <= 0 THEN
  181.      Exit;       { Rats! Bill didn't leave enough room }
  182.     myWDPB := WDPBPtr(myCPB);   { icky Pascal type coercions follow }
  183.     myPB := HParmBlkPtr(myCPB);
  184.  
  185.     numTypes := 1;        { for SFGetFile }
  186.     WITH paramPtr^ DO
  187.      BEGIN
  188.       IF paramCount = 0 THEN
  189.        numTypes := - 1     { FileName() - get all files }
  190.       ELSE
  191.        BlockMove(params[1]^, @typeList[0], 4);
  192.                    { FileName("TYPE") }
  193.  
  194.       IF TheyChoseAFile THEN
  195.        BuildThePathName;
  196.  
  197. { PasToZero is very interesting - it is a HyperTalk command
  198.  that you can actually call from OUTSIDE of HyperCard.
  199.  You need it because HyperCard uses C format strings with
  200.  no length byte; they are terminated by a null byte. They are
  201.  actually HANDLES to C format strings. Nice work, Dan! }
  202.  
  203.       returnValue := PasToZero(fullPathName);
  204.  
  205.      END;  { WITH paramPtr^ DO }
  206.  
  207.     DisposPtr(pointer(myCPB));    { Clean Up Your Heap! }
  208.  
  209.    END;  { PROCEDURE FileName }
  210.  
  211. BEGIN
  212. END.
  213.