SettingUpStdFile.c

/*
    File:       SettingUpStdFile.c
 
    Contains:   This snippet demonstrates how to make Standard File
                select an initial file under both System 6 and System 7.
                (In this example, the System file will be selected.)
    
                "An exhilirating snippet"
                             - Nitin Ganatra
 
    Written by:  Greg Robbins   
 
    Copyright:  Copyright © 1993-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                7/1/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                            sfScript is reset in the System 7 DialogHook (below) to work  
                            around a gotcha in Standard File that's incorrectly documented in  
                            a New Inside Macintosh: Files sample.  See the DialogHook() function 
                            for details.
                2/94        Nitin Ganatra   Compatible with the Universal Interfaces.
                
 
*/
 
#include <QuickDraw.h>
#include <StandardFile.h>
#include <Fonts.h>
#include <Menus.h>
#include <Dialogs.h>
#include <Events.h>
#include <GestaltEqu.h>
#include <TextEdit.h>
#include <Errors.h>
#include <OSEvents.h>
#include <Folders.h>
#include <Memory.h>
#include <Script.h>
#include <LowMem.h>
 
// prototypes
pascal short DialogHook(short, DialogPtr , void *);
pascal short OldDlgHook(short, DialogPtr);
OSErr GetSystemFileSpec(FSSpecPtr);
 
// global struct for System 7 Std File dialog hook
typedef struct {
    StandardFileReply *theSFR;
    FSSpec *itemSpec;
} HookRecord, *HookRecordPtr;
 
// globals for System 6 Std File stuff
StringPtr   gSelectFileName;
short       gSelectFileCounter;
 
 
 
 
void main(void)
{
    Point dialogPt;
    SFTypeList mySFTypeList;
    StandardFileReply mySFR;
    SFReply oldSFR;
    long procID;
    FSSpec systemSpec;
    HookRecord hookRec;
    Boolean hasNewStdFileCallsFlag;
    long gestResponse;
    
    OSErr retCode;
    DlgHookYDUPP    myDlgHookUPP;
 
 
    // initialize the toolbox
    InitGraf(&qd.thePort); InitFonts(); InitWindows(); InitMenus();
    TEInit(); InitDialogs(nil); InitCursor(); FlushEvents(everyEvent,0);
 
    // determine if the System 7 std file calls are available
    retCode = Gestalt(gestaltStandardFileAttr, &gestResponse);
    if (retCode == noErr && ((gestResponse >> gestaltStandardFile58) & 1) != 0)
        hasNewStdFileCallsFlag = true;
    else
        hasNewStdFileCallsFlag = false;
 
    SetPt(&dialogPt, -1, -1);
        
    // get the FSSpec of the system file
    retCode = GetSystemFileSpec(&systemSpec);
    if (retCode != noErr) DebugStr((StringPtr)"\p GetSystemFileSpec failed");
    
    if (hasNewStdFileCallsFlag) {
    
        // System 7 method
        
        // point my hook data record at the reply record and at
        // the file spec for the system file
        
        hookRec.itemSpec = &systemSpec;
        hookRec.theSFR = &mySFR;
 
 
        // Set up the universal proc pointer to your hook routine with this 
        // macro defined in StandardFile.h.  **NOTE** This is different
        // from the macro used for System 6 dialog hooks, and you should get
        // a compiler error if you try to use the wrong UPP with the wrong call.
        myDlgHookUPP = NewDlgHookYDProc(DialogHook);
        
        // call Std File
        CustomGetFile(nil, -1, mySFTypeList, &mySFR, 0, dialogPt, myDlgHookUPP,
            nil, nil, nil, &hookRec);
            
        // Dispose of the routine descriptor, since they do allocate memory..
        DisposeRoutineDescriptor(myDlgHookUPP);
 
 
    }
    
    else {
        // System 6 method
    
        // stuff low memory to display the proper initial directory; 
        // see Inside Mac:Files 3-31
        
        DlgHookUPP  myOldDlgHookUPP;
        
        // Throw out your SysEqu.h file and start using the low memory 
        // accessor functions provided in LowMem.h.
        LMSetSFSaveDisk(-systemSpec.vRefNum);
        LMSetCurDirStore(systemSpec.parID);
 
        // set up the string for the system file name
        gSelectFileName = systemSpec.name;
 
        // Set up the universal proc pointer to your hook routine with this 
        // macro defined in StandardFile.h.  **NOTE** This is different
        // from the macro used for System 7 dialog hooks, and you should get
        // a compiler error if you try to use the wrong UPP with the wrong call.
        myOldDlgHookUPP = NewDlgHookProc(OldDlgHook);
        
        // call Std File
        SFGetFile(dialogPt, nil, nil, -1, mySFTypeList, myOldDlgHookUPP, &oldSFR);
 
        // Dispose of the routine descriptor, since they do allocate memory..
        DisposeRoutineDescriptor(myOldDlgHookUPP);
        
        // store the result in a new reply record
        mySFR.sfGood = oldSFR.good;
        if (oldSFR.good) {
        
            // convert the WDRefNum and copy the name string
            retCode = GetWDInfo(oldSFR.vRefNum, 
                &mySFR.sfFile.vRefNum, &mySFR.sfFile.parID, &procID);
            BlockMove(oldSFR.fName, mySFR.sfFile.name, 1 + oldSFR.fName[0]);
        }
    }
}
 
// this dialog hook for System 7 std file selects
// the file specified by the hookRecord supplied as userData
 
pascal short DialogHook(short item, DialogPtr theDialog, 
    void *userData)
{
    HookRecordPtr hookRecPtr;
    
    hookRecPtr = (HookRecordPtr) userData;
    
    // hookRecPtr->itemSpec points to the FSSpec of the item to be selected
    // hookRecPtr->theSFR points to the standard file reply record
 
    // make sure we're dealing with the proper dialog
    if (GetWRefCon(theDialog) == sfMainDialogRefCon) {
    
        // just when opening the dialog...
        if (item == sfHookFirstCall) {
    
            // make the reply record hold the spec of the specified item
            hookRecPtr->theSFR->sfFile = *hookRecPtr->itemSpec;
            
            // ThereÕs a gotcha in Standard File when using sfHookChangeSelection. 
            // Even though New Inside Macintosh: Files has a sample that doesn't set
            // the sfScript field, it should be set, or the last object in the
            // selected directory  will always be selected.
            hookRecPtr->theSFR->sfScript = smSystemScript;
 
            // tell std file to change the selection to that item
            item = sfHookChangeSelection;
        }
    }           
        
    return item;
}
 
 
// this std file dialog hook for System 6 selects the file
// name in the global gSelectFileName
 
pascal short OldDlgHook(short item, DialogPtr theDialog)
{
#pragma unused (theDialog)
    
    // the idea here is to post keydown events, one per
    // null hook-event, until the entire file name
    // has been "typed" in (remember that the event queue
    // is shorter than the maximum file name so we only post
    // one key per null event)
 
    // reset the character counter initially
    
    if (item == sfHookFirstCall)
        gSelectFileCounter = 0;
        
    // post one keyDown per null event until the string is exhausted
    // This may not be a good idea for international software since 
    // different input methods may be used.
    // Instead, you may want to check the System version and temporarily 
    // set the KeyScript to zero before doing these PostEvents.  
    // Afterwards, set KeyScript back to its original mode.
    else if (item == sfHookNullEvent) {
        if (gSelectFileCounter < *gSelectFileName) {
            gSelectFileCounter++;
            PostEvent(keyDown, *(gSelectFileName+gSelectFileCounter));
        }
    }
 
    return item;
}
 
 
OSErr GetSystemFileSpec(FSSpecPtr systemSpec)
{
    // the System folder location is returned by FindFolder (or under
    // System 6 by the compiler's FindFolder glue)
    //
    // the System file name is available in low-memory
    
    OSErr       retCode;
    StringPtr   systemName;
    
    systemName = LMGetSysResName();     // Get the name of the System resource file
 
    retCode = FindFolder(kOnSystemDisk, kSystemFolderType, kCreateFolder,
        &systemSpec->vRefNum, &systemSpec->parID);
    if (retCode == noErr)
        BlockMove((Ptr)systemName, systemSpec->name, systemName[0] + 1);
    
    return retCode;
}