[comp.sys.mac.programmer] filedata from SFGetFile

arenberg@earthquake.Berkeley.EDU (Jeff Arenberg) (01/17/90)

I'm working on a program that opens a number of different file types.
I want to display the filetype currently selected in the SFPGetFile
dialog box.  Can anyone please tell me how to acieve this?  I'm sure I
can do it if I can find the handle to the list used by the dialog.
Please respond my e-mail, I can't readnews very often.  Thanks,

Jeff Arenberg
arenberg@ocf.berkeley.edu

robert@polari.UUCP (robert) (01/23/90)

 
> I'm working on a program that opens a number of different file types.
> I want to display the filetype currently selected in the SFPGetFile
> dialog box.  Can anyone please tell me how to acieve this?  I'm sure I
> can do it if I can find the handle to the list used by the dialog.
> Please respond my e-mail, I can't readnews very often.  Thanks,


Jeff,

I wrote a program recently that does this. It's easy. I used a Filter
function to grab the ParamBlockPtr (and, specifically, to get the 
current directory ID number). Then I called PBHGetFInfo in my DlgHook
function, passing the current directory ID number and the file name of
the currently selected file. Below are some code fragments (in Pascal) 
with comments. If you want the whole program, send me Email and I'll 
mail it to you. It's fairly short and displays the type and creator
in the SFPGetFile box.

  1) Call SFPGetFile specifying a DlgHook function "GetHook" and
     a Filter function "FFilter" as follows:

   -----------------------------------------------------------
    SFPGetFile(where, prompt, @FFilter, numTypes, typeList, 
                      @GetHook, myreply, 1002, nil);
   -----------------------------------------------------------

  2) Define a Filter function "FFilter". The whole purpose of this Filter 
     function is to make a global copy of the ParmBlkPtr so I can use 
     it in procedure GetHook above. The pointer myParmBlkPtr:ParmBlkPtr
     is declared globally. This Filter function must always returns the
     value FALSE so that all files will be shown in the dialog.

     NOTE: The information I use later out of myParmBlkPtr is just the 
     directory ID number and the Volume ref number. The file type is not 
     for the correct file.

   -----------------------------------------------------------
	function FFilter (aParmBlkPtr: ParmBlkPtr): Boolean;

	begin  
		FFilter := FALSE;
		myParmBlkPtr := aParmBlkPtr;
	end;
   ------------------------------------------------------------

  3) In the DlgHook function "GetHook", call PBHGetFInfo whenever an
     event occurs that changes the file choice (see code below).

     NOTE: The SFReply record "myreply" is declared globally. It's
     passed to SFPGetFile and contains the name of the currently
     selected file when GetHook is called.

     NOTE: doitem:Boolean must be declared globally.

   -----------------------------------------------------------
    function GetHook (TheItem: integer; theDialog: DialogPtr): integer;

    var
      err: Integer;

    begin

      GetHook := TheItem;

      if (TheItem in [-1, 4, 5, 6, 102, 103]) then
         begin
          { theItem = -1  for first time GetHook is called,     }
          { TheItem = 4   command-Up Arrow triggers this event }
          { TheItem = 5   for Disk Eject event   }
          { TheItem = 6   for click in Drive button or hit Tab }
          { TheItem = 102 for click in pop-up to change directory }
          { TheItem = 103 for a double-click on a folder OR select}
                    {     a Folder and hit Return OR Select a }
                    {     Folder and hit Open button. }
           doitem := TRUE; { This flag is set so that the File info  }
              { will be updated the NEXT time GetHook is called.   }
              { If I update it now, the file info in myParmBlkPtr^ }
              { is wrong. }
         end

      else if (TheItem = $1000 + 30) or (TheItem = $1000 + 31) then
         begin { theItem = $1000 + 30 when Up Arrow is pressed and  }
               { theItem = $1000 + 31 when Down Arrow is pressed.   }
           doitem := TRUE; { This flag is set so that the File info  }
              { will be updated the NEXT time GetHook is called.   }
              { If I update it now, the file info in myParmBlkPtr^ }
              { is wrong. }
         end

      else if (theItem = 7) or (doitem) then
         begin { theItem=7 when a file or folder is clicked on. }

   { Now call PBHGetFInfo. }
   { We already have the Volume ref number in myParmBlkPtr^.ioVRefNum   }
   { and the Directory ID number in myParmBlkPtr^.ioFlNum. The type and }
   { creator are returned in myHParmBlkPtr^.ioFlFndrInfo. The File ID   }
   { number is returned in myHParmBlkPtr^.ioDirID, if you want it.      }

            myHParmBlkPtr^.ioCompletion := nil;
            myHParmBlkPtr^.ioNamePtr := @myreply.fName;
            myHParmBlkPtr^.ioVRefNum := myParmBlkPtr^.ioVRefNum;
            myHParmBlkPtr^.ioFDirIndex := 0;
            myHParmBlkPtr^.ioDirID := myParmBlkPtr^.ioFlNum;
            err := PBHGetFInfo(myHParmBlkPtr, FALSE);

            if (err = 0) then { a plain file was selected }
               begin   { At this point,  }
      {   myHParmBlkPtr^.ioFlFndrInfo.fdType contains the File Type       }
      {   myHParmBlkPtr^.ioFlFndrInfo.fdCreator contains the File Creator,}
                 doitem := FALSE;
               end

            else if (err <> 0) then
               begin
               { a folder was selected OR something else went wrong }
               end;

         end;
    end;   { End of GetHook  }
   -----------------------------------------------------------

  4) Don't forget to allocate space for the ParamBlockPtr's:

   -----------------------------------------------------------
    myParmBlkPtr := ParmBlkPtr(NewPtr(sizeof(ParamBlockRec)));
    myHParmBlkPtr := HParmBlkPtr(NewPtr(sizeof(HParamBlockRec)));
   -----------------------------------------------------------

  5) Here are the variables that I declared globally:

   -----------------------------------------------------------
   var
      doitem: Boolean;
      myreply: SFReply;
      myParmBlkPtr: ParmBlkPtr;
      myHParmBlkPtr: HParmBlkPtr;
   -----------------------------------------------------------

That should do it. Send me Email if you have any questions.

|***********************************************************************|
|Robert Riebman                    |  robert@polari                     |
|Northwest Information Technology  |                                    |
|P.O. Box 3156                     |  "EXPERT ON EVERYTHING"            |
|Redmond, WA     98073             |     well, at least when I'm right. |
|***********************************************************************|
 

tim@hoptoad.uucp (Tim Maroney) (01/24/90)

OK.  I give up.  Limit your distribution all you want.  No one outside
North America really exists anyway.

In article <1201@polari.UUCP> robert@polari.UUCP (robert) writes:
>> I'm working on a program that opens a number of different file types.
>> I want to display the filetype currently selected in the SFPGetFile
>> dialog box.  Can anyone please tell me how to acieve this?
>
>I wrote a program recently that does this. It's easy. I used a Filter
>function to grab the ParamBlockPtr (and, specifically, to get the 
>current directory ID number). Then I called PBHGetFInfo in my DlgHook
>function, passing the current directory ID number and the file name of
>the currently selected file. Below are some code fragments (in Pascal) 
>with comments. If you want the whole program, send me Email and I'll 
>mail it to you. It's fairly short and displays the type and creator
>in the SFPGetFile box.

You're making it awfully hard on yourself.  All you're grabbing from
the file filter are the volume reference number and directory ID, which
are stored in the low-memory globals SFSaveDisk and CurDirStore
already.  Standard File tracks these as it goes from folder to folder
and disk to disk.  So all you have to do in your item filter procedure
is a PBHGetFInfo using reply.fName together with SFSaveDisk and
CurDirStore to find out what the type is; this elaborate snarfing of
volume and directory from a file filter procedure is unneccessary.
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"The government of the United States is not, in any sense, founded
 on the Christian religion." -- George Washington

d88-jwa@nada.kth.se (Jon Watte) (01/25/90)

In article <9821@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes:
>OK.  I give up.  Limit your distribution all you want.  No one outside
>North America really exists anyway.

>You're making it awfully hard on yourself.  All you're grabbing from
>the file filter are the volume reference number and directory ID, which
>are stored in the low-memory globals SFSaveDisk and CurDirStore

Just look at him ! _twice_ in a _row_ he's been wrong ! (Gloat :-)

Seriously, we aren't supposed to read low-memoty globals.
Wonder when they'll change MemErr 8)

>Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

h+
-- 
   ---  Stay alert !  -  Trust no one !  -  Keep your laser handy !  ---
             h+@nada.kth.se  ==  h+@proxxi.se  ==  Jon Watte
                    longer .sig available on request

ech@cbnewsk.ATT.COM (ned.horvath) (01/25/90)

From article <9821@hoptoad.uucp>, by tim@hoptoad.uucp (Tim Maroney):
> You're making it awfully hard on yourself.  All you're grabbing from
> the file filter are the volume reference number and directory ID, which
> are stored in the low-memory globals SFSaveDisk and CurDirStore
> already.  Standard File tracks these as it goes from folder to folder
> and disk to disk...

Uh.  While things may work this way today, the only committment
Inside Mac makes is that those globals will be used to initialize the
SFGet/SFPut, and that they'll be set at completion of SFGet/SFPut.  There's
no good reason they should "track," and no guarantee that they'll always
do so.  That, quite aside from the general caveat to use lo-mem globals
as little as possible.  Using the file filter sounds prudent to me.

=Ned Horvath=