home *** CD-ROM | disk | FTP | other *** search
/ Carousel / CAROUSEL.cdr / mactosh / hc / openands.sit / FileName.p next >
Text File  |  1987-10-31  |  7KB  |  266 lines

  1. {$R-              }
  2. {$S FileName }
  3.  
  4. (*** Filename
  5.  
  6. This HyperCard XFunction will present the user with the standard
  7. SFGetFile dialog box and return the users responce to the caller
  8. as either a full path name of the new file or empty if canceled.
  9.  
  10. I have departed from the human interface guidelines for dialog
  11. boxes as the SFGetFile dialog will be centered in the hypercard
  12. window and not the screen.  My reson for this is that HyperCard 
  13. has only one window (ignoring message box, &c) within which many
  14. of the rules are broken so by placing the dialog centered on the
  15. window it clearly indicates the dialog has been presented do to 
  16. pressing a button.
  17.     
  18. Much of the code is a taken from the FileName XFunction by
  19.     
  20.     Steve Maller
  21.     Apple Computer Training Support
  22.     Copyright ⌐ 1987 Apple Computer
  23.     AppleLink: MALLER1
  24.  
  25. To compile and link with MPW and MPW Pascal
  26.     
  27.     pascal -w FileName.p
  28.     
  29.     link -m ENTRYPOINT 
  30.          -rt XFCN=1 
  31.          -sn Main=FileName 
  32.          -o HyperCommands
  33.          FileName.p.o
  34.          Interface.o             
  35.          Paslib.o
  36.  
  37. A typical HyperTalk script calling NewFileName would be
  38.  
  39.     -- function FileName( [ <type> ] ): <filename>
  40.  
  41.     on mouseUp
  42.         put FileName( "TEXT" ) into filename
  43.             
  44.         if filename is not empty then
  45.             open file filename
  46.             read from file filename until return
  47.             put it into field x
  48.             close file filename
  49.         end if
  50.     end mouseDown
  51.     
  52. Written by
  53.     
  54.     Andrew Gilmartin
  55.     Academic & User Service, Box 1885
  56.     Brown University
  57.     Providence, Rhode Island 02912
  58.     Copyright ⌐ 1987 Brown University
  59.     bitnet:  ANDREW@BROWNVM
  60.         
  61.     October 31, 1987 ***)
  62.  
  63.  
  64. unit filenameUnit;
  65.  
  66.     interface
  67.  
  68.         uses memtypes, quickdraw, osintf, toolintf, packintf, hyperxcmd;
  69.  
  70.         procedure entrypoint(paramptr: xcmdptr);
  71.  
  72.     implementation
  73.  
  74.         procedure filename(paramptr: xcmdptr); forward;
  75.  
  76.         procedure entrypoint(paramptr: xcmdptr);
  77.         begin
  78.             filename(paramptr);
  79.         end(* entry point *);
  80.         
  81.         procedure filename;
  82.  
  83.             var fullpathname: str255;
  84.                 filename    : str255;
  85.                 prompt        : str255;
  86.                 reply        : sfreply;
  87.                 numtypes    : integer;
  88.                 typelist    : sftypelist;
  89.  
  90.             {$I xcmdglue.inc }
  91.  
  92.  
  93.             (**    Param To Num
  94.         
  95.             This function returns a long integer interpretation of 
  96.             a zero terminated string (c-string). **)
  97.             
  98.             function paramtonum( param: handle ): longInt;
  99.                 var Str: Str255;
  100.             begin
  101.                 zerotopas( param^, str );
  102.                 paramtonum := strtonum( str )
  103.             end(* ParamToNum *);
  104.             
  105.  
  106.             (**  CenterRect
  107.             
  108.             This function will return the point where the top left corner
  109.             of inside rectange should be placed inorder for it to be
  110.             centered within outside rectangle.
  111.                 
  112.             It is not checked that inside is indeed wholely inside of
  113.             outside **)
  114.             
  115.             function centerrect( outr, inr: rect ): point;
  116.                 var p: point;
  117.             begin
  118.                 p.v := outr.top  + (((outr.bottom - outr.top) - (inr.bottom  - inr.top)) div 2);
  119.                 p.h := outr.left + (((outr.right - outr.left) - (inr.right  - inr.left)) div 2);
  120.                 centerrect := p
  121.             end(* center rect *);
  122.  
  123.             
  124.             (**    Card Rect
  125.             
  126.             This function will return a rectangle that specifies where
  127.             the HyperCard window (aka this card) is upon the screen.
  128.             It should be noted that the position is determined by asking
  129.             HyperCard rather than calling toolbox routines. **)
  130.             
  131.             function cardrect: rect;
  132.                 var card: rect;
  133.             begin
  134.                 card.top    := ParamToNum( evalexpr( 'item two of loc of card window' ) );
  135.                 card.left   := ParamToNum( evalexpr( 'item one of loc of card window' ) );
  136.                 card.bottom := card.top  + 342;
  137.                 card.right  := card.left + 512;
  138.                 cardrect    := card
  139.             end(* card rect *);
  140.             
  141.             
  142.             (**    Dialog Rect
  143.             
  144.             This function returns a rectangle that specifies where the
  145.             SFGetFile dialog whould be placed upon the screen. **)
  146.             
  147.             function dialogrect: rect;
  148.                 var dialog: dialogthndl;
  149.             begin
  150.                 dialog       := dialogthndl( getresource( 'DLOG', getdlgid ) );
  151.                 dialogrect := dialog^^.boundsrect
  152.             end(* dialog rect *);
  153.             
  154.             
  155.             (**    Build Pathname
  156.             
  157.             This function will return the full pathname from the volume
  158.             reference number and filename.  This code is a taken from
  159.             Steve Maller's original XFunction "FileName". **)
  160.             
  161.             function buildpathname( volume:integer; filename: str255): Str255;
  162.                 var fullpathname: str255;
  163.                     name        : str255;
  164.                     err            : integer;
  165.                     mywdpb        : wdpbptr;
  166.                     mycpb        : cinfopbptr;
  167.                     mypb        : hparmblkptr;
  168.             begin
  169.             
  170.                 buildpathname := '';
  171.                 
  172.                 { 
  173.                 first we allocate some memory in the heap for the 
  174.                 parameter block. this could in theory work on the stack, 
  175.                 but in reality it makes no difference as we're entirely 
  176.                 modal (ugh) here...
  177.                 }
  178.                 mycpb  := cinfopbptr(newptr(sizeof(hparamblockrec)));
  179.                 if ord4(mycpb) <= 0 then
  180.                     exit(buildpathname);            { rats! bill didn't leave enough room }
  181.                 mywdpb := wdpbptr(mycpb);            { icky pascal type coercions follow }
  182.                 mypb   := hparmblkptr(mycpb);
  183.  
  184.  
  185.                 name := '';                         { start with an empty name }
  186.                 mypb^.ionameptr := @name;            { we want the volume name }
  187.                 mypb^.iocompletion := pointer(0);
  188.                 mypb^.iovrefnum := volume;            { returned from sfgetfile }
  189.                 mypb^.iovolindex := 0;                { use the vrefnum and name }
  190.                 err := pbhgetvinfo(mypb, false);    { fill in the volume info }
  191.                 if err <> noerr then
  192.                     exit(buildpathname);
  193.  
  194.                 {     
  195.                 now we need the working directory (wd) information 
  196.                 because we're going to step backwards from the file 
  197.                 through all of the the folders until we reach the 
  198.                 root directory
  199.                 }
  200.                 mywdpb^.iovrefnum := volume;        { this got set to 0 above }                    mywdpb^.iowdprocid := 0;                            { use the vrefnum }
  201.                 mywdpb^.iowdindex := 0;                { we want all directories }
  202.                 err := pbgetwdinfo(mywdpb, false);    { do it }
  203.                 if err <> noerr then
  204.                     exit(buildpathname);
  205.  
  206.                 mycpb^.iofdirindex := - 1;                { use the iodirid field only }
  207.                 mycpb^.iodrdirid := mywdpb^.iowddirid;    { info returned above }
  208.                 err := pbgetcatinfo(mycpb, false);        { do it }
  209.                 if err <> noerr then
  210.                     exit(buildpathname);
  211.  
  212.                 {
  213.                 here starts the real work - start to climb the tree by 
  214.                 continually    looking in the iodrparid field for the next 
  215.                 directory above until we fail... 
  216.                 }
  217.                 mycpb^.iodrdirid := mycpb^.iodrparid;    { the first folder}
  218.                 fullpathname      := concat(mycpb^.ionameptr^, ':', filename);
  219.                 
  220.                 repeat
  221.                     mycpb^.iodrdirid := mycpb^.iodrparid;
  222.                     err := pbgetcatinfo(mycpb, false);    { the next level }
  223.  
  224.                     { 
  225.                     be careful of an error returned here - it means the user 
  226.                     chose a file on the desktop level of this volume. if this 
  227.                     is the case, just stop here and return "volumename:filename", 
  228.                     otherwise loop until failure 
  229.                     }
  230.                     
  231.                     if err = noerr then
  232.                         fullpathname := concat(mycpb^.ionameptr^, ':', fullpathname);
  233.  
  234.                 until err <> noerr;
  235.                 
  236.                 disposptr(pointer(mycpb));    { clean up your heap! }
  237.  
  238.                 buildpathname := fullpathname
  239.                 
  240.             end(* build path name *);
  241.             
  242.         begin
  243.         
  244.             with paramptr^ do
  245.                 begin    
  246.                     if paramcount <> 1 then { filename() }
  247.                         numtypes := -1
  248.                     else                     { filename( "TEXT" ) }
  249.                         begin
  250.                             numtypes := 1;
  251.                             blockmove( params[ 1 ]^, @typelist[ 0 ], 4 )
  252.                         end;
  253.                             
  254.                     sfgetfile( centerrect( cardrect, dialogrect ), 
  255.                                '', nil, numtypes, typelist, nil, reply );
  256.  
  257.                     if reply.good then
  258.                         fullpathname := buildpathname( reply.vrefnum, 
  259.                                                        reply.fname );
  260.                                                     
  261.                     returnvalue := pastozero(fullpathname)
  262.                 end
  263.  
  264.         end(* filename *);
  265.  
  266. end.