CustIcon.c

/*
    File:       CustIcon.c
 
    Contains:   This snippet shows how to use custom document icons in an application.  
                The correct procedure for doing this is to add the Icon family 
                to the document and set bit 10 of the finder info.
    
                An elegant way of adding the icon family is to use one of the routines 
                described in the Icon Utilities chapter of Inside Macintosh More Toolbox 
                Essentials:   ForEachIconDo().  You can define  an action proc that is called 
                each time for each icon an an icon suite.
 
    Written by: NICKT   
 
    Copyright:  Copyright © 1994-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/19/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                8/96:                       CustIcon.h added as prefix file for 68K and PPC MC 
                                            projects; old routine names changed; void *myDataPtr
                                            removed from definition of routine MyIconAction; FSSpec
                                            theFSSpec and short theRef removed from HandleMenuCommand;
                                            Rect screenRect and GrafPtr oldPort removed from
                                            MainEventLoop; OSErr retCode, long gestResponse, EventRecord
                                            Event and short count removed from InitToolbox; long
                                            lByteCnt removed from HandleKeyPress
                
 
*/
#define WWIDTH      470
#define WHEIGHT     330
 
#define WLEFT       (((qd.screenBits.bounds.right - qd.screenBits.bounds.left) - WWIDTH) / 2)
#define WTOP        (((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - WHEIGHT) / 2)
 
#define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
#define LoWrd(aLong)    ((aLong) & 0xFFFF)
 
#include <Processes.h>
#include <DiskInit.h>
#include <Resources.h>
#include <Menus.h>
#include <Devices.h>
#include <StandardFile.h>
#include <Dialogs.h>
#include <Fonts.h>
#include <Icons.h>
#include <Finder.h>
#include <Script.h>
 
//------------------------------------------------------------------------------
// enumerated types for the menus
 
enum {
    mApple = 128,
    mFile
} ;
 
enum {
    iAbout = 1
} ;
enum {
    iNew = 1,
    iIcon,
    iUnused1,
    iQuit = 4
} ;
 
//------------------------------------------------------------------------------
 
static Boolean pQuitFlag = false ;
 
//------------------------------------------------------------------------------
// function prototypes
 
void InitToolbox( void ) ;
void MainEventLoop( void ) ;
void HandleKeyPress(EventRecord *event) ; 
void HandleMenuCommand(long menuResult) ;
void AdjustMenus( void ) ;
pascal OSErr    MyIconAction( ResType   theType,
                              Handle    *theIcon);
OSErr TouchDir(short vRefNum, long dirID) ;
 
//-----------------------------------------------------------------------------
 
 
void HandleMenuCommand(long menuResult)
{
    short       menuID;
    short       menuItem;
    Str255      daName;
    DialogPtr   theDialog ; 
    short       itemHit ;
    SFTypeList  myTypes = { '????' } ;
    Handle      myIconSuite ;
    OSErr       theErr ;
    
    short       savedResFile ;
    short       theResFile ;
    
    FInfo       myFndrInfo ;
        
    StandardFileReply   theSFReply ;
 
    menuID = HiWrd(menuResult);
    menuItem = LoWrd(menuResult);
    switch ( menuID ) {
        case mApple:
            switch ( menuItem ) {
                case iAbout:
                    theDialog = GetNewDialog ( 128, nil, (WindowPtr)-1 );
                    SetDialogDefaultItem(theDialog, 1) ;
 
                    do {
                        ModalDialog ( nil, &itemHit );
                    } while( itemHit != ok ) ;
                    DisposeDialog ( theDialog );
                    break;
                    
                default:
                    GetMenuItemText(GetMenuHandle(mApple), menuItem, daName);
                    (void) OpenDeskAcc(daName);
                    break;
            }
            break;
        case mFile:
            switch ( menuItem ) {
                case iNew:
                    // create a file
                    // put up a standard file put dialog to get the name
                    StandardPutFile("\pCreate File", "\pUntitled", &theSFReply) ;
                    if( theSFReply.sfGood ) {
                        FSpCreateResFile( &theSFReply.sfFile, '????', 'TEXT', smSystemScript) ;
                        theErr = ResError();
                    }
                    break ;
                    
                case iIcon:
                    // add icon family to file
                    
                    // put up std get file dlog
                    StandardGetFile( nil, -1, myTypes, &theSFReply ) ;
                    if( theSFReply.sfGood ) {
                        
                        // save the current resource file
                        savedResFile = CurResFile();
                        
                        // Load the icon suite we want to set up
                        theErr = GetIconSuite( &myIconSuite, 129, svAllAvailableData )  ;
                        
                        // get the finder info for the file
                        theErr = FSpGetFInfo( &theSFReply.sfFile, &myFndrInfo ) ;
                        
                        // set bit 10 (has custom icon) and unset the inited flag
                        // kHasBeenInited is 0x0100 so the mask will be 0xFEFF:
                        
                        myFndrInfo.fdFlags = 0xFEFF & (myFndrInfo.fdFlags | kHasCustomIcon ) ;
                        
                        // write it back
                        theErr = FSpSetFInfo( &theSFReply.sfFile, &myFndrInfo ) ;
                        
                        // just check it already has a resource fork
                        FSpCreateResFile( &theSFReply.sfFile, '????', 'TEXT', smSystemScript) ;
                        theErr = ResError();
                        
                        // open the resfile the user picked
                        theResFile = FSpOpenResFile ( &theSFReply.sfFile, fsWrPerm);
                        theErr = ResError() ;
                    
                        UseResFile ( theResFile );
                        theErr = ResError() ;
                        
                        theErr = ForEachIconDo( myIconSuite, svAllAvailableData, NewIconActionProc(MyIconAction), nil ) ;
                        CloseResFile( theResFile );
                        
                        theErr = ResError() ;
                        
                        UseResFile ( savedResFile );
                        
                    }
                    
 
                    break ;
                case iQuit:
                
                    pQuitFlag = true;
                    break;
            }
            break;
            
    }
    HiliteMenu(0);      // Unhighlight whatever MenuSelect or MenuKey hilited
}
 
//---------------------------------------------------------------------------
// write out the icon to the currently set res file
 
pascal OSErr    MyIconAction( ResType   theType,
                              Handle    *theIcon)
                              //void        *myDataPtr )
{
 
    OSErr   theErr = noErr ;
    long    lByteCnt = GetHandleSize( *theIcon );
 
    // theIcon is already a resource.  If we try to do an AddResource, it will fail
    // with error -194, to prevent this, call detach resource.  You will need
    // to reload the suite if you want to use it after this.
    
    DetachResource( *theIcon ) ;
    if(( theErr = ResError()) != noErr )
        return theErr ; 
        
    // write out each resource we are passed by ForEachIconDo
    AddResource ( *theIcon, theType, kCustomIconResource, "\pCustom Finder Icon" );
 
    // check we are OK
    theErr = ResError() ;
 
    return theErr ;
    
}
 
//---------------------------------------------------------------------------
 
void MainEventLoop()
{
    EventRecord     event;
    WindowPtr       window;
    short           thePart;
    Point           aPoint = {100, 100};
 
    while( !pQuitFlag )
    {
        if (WaitNextEvent( everyEvent, &event, 0, nil ))
        {
            AdjustMenus() ;
 
            switch (event.what) {
                case mouseDown:
                
                    thePart = FindWindow( event.where, &window );
                    
                    switch( thePart ) {
                        case inMenuBar: 
                            HandleMenuCommand(MenuSelect(event.where));
                            break;
                        
                        case inDrag:
                            break ;
                    
                        case inContent:
                            break ;
                    
                        case inGoAway:
                            break ;
                            
                        default:
                            break ;
                    }
                    break ;
                            
                        
                case updateEvt:
                    break ;
                    
                case keyDown:
                case autoKey:
                    HandleKeyPress(&event);
                    break;
                    
                case diskEvt:
                    if ( HiWrd(event.message) != noErr ) 
                        (void) DIBadMount(aPoint, event.message);
                    break;
                    
                case osEvt:
                case activateEvt:
                    break;
 
 
            }
        }
    }
}
 
//------------------------------------------------------------------------------
 
void HandleKeyPress(EventRecord *event)
{
    char    key;
 
    key = event->message & charCodeMask;
    
    // just check to see if we want to quit...
    if ( event->modifiers & cmdKey ) {      /* Command key down? */
        HandleMenuCommand(MenuKey(key));
    } 
}
 
//------------------------------------------------------------------------------
 
void AdjustMenus( void ) 
{
    // ha - we don't got no menus
}
 
//------------------------------------------------------------------------------
 
void main()
{
    InitToolbox() ;
    
    MainEventLoop();
}
 
//------------------------------------------------------------------------------
 
void InitToolbox()
{
    Handle      menuBar = nil;
 
    InitGraf((Ptr) &qd.thePort);
    InitFonts();
    InitWindows();
    InitMenus();
    TEInit();
    InitDialogs(0L);
    InitCursor();
 
    // initialize application globals
    
    pQuitFlag = false;
    
    
    menuBar = GetNewMBar(128);              // Read menus into menu bar, MBAR res id is 128
    
    if ( menuBar == nil )
         ExitToShell();                     // if we dont have it then quit - your app 
                                            // needs a dialog here
 
    SetMenuBar(menuBar);                    // Install menus
    DisposeHandle(menuBar);
    
    AppendResMenu(GetMenuHandle(mApple), 'DRVR');   // Add DA names to Apple menu, ID 128
 
    DrawMenuBar();
}