icon cache.c

/*
    File:       icon cache.c
 
    Contains:   This sample demonstrates the use of an icon cache
                to limit the search for icon resource to one resource
                file. It does this by installing an icon getter function
                into the cache which calls Get1(Ind)Resource instead of the
                usual GetResource.
        
                The application is meant to display the first
                suite produced by an indexed resource call. There's nothing
                stopping you from calling Get1Resource or anything else
                which might produce a handle to a member of an icon suite.
        
                There's also some jiggery-pokery having to do with my
                distaste for purgeable handles; see below for details.
 
    Written by: Pete Gontier    
 
    Copyright:  Copyright © 1984-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):
                8/6/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
 
#define OLDROUTINELOCATIONS     0
#define OLDROUTINENAMES         0
#define SystemSevenOrLater      1
 
#ifndef __FONTS__
#   include <Fonts.h>
#endif
 
#ifndef __DIALOGS__
#   include <Dialogs.h>
#endif
 
#ifndef __RESOURCES__
#   include <Resources.h>
#endif
 
#ifndef __STANDARDFILE__
#   include <StandardFile.h>
#endif
 
#ifndef __ICONS__
#   include <Icons.h>
#endif
 
static pascal Handle MyIconGetter (ResType rt, void *)
{
    //
    //  DisposeIconSuite assumes resources are purgeable and doesn't
    //  release them. Since we would rather the memory be freed,
    //  we have our icon getter function ('MyIconGetter') detach
    //  each resource it gets. This turns off the resource bit for
    //  the handle and clues DisposeIconSuite it should call DisposeHandle.
    //
 
    Handle iconH = Get1IndResource (rt,1);
    if (!iconH || ResError ( ))
        return nil;
 
    DetachResource (iconH);
    if (ResError ( ))
    {
        ReleaseResource (iconH);
        return nil;
    }
 
    return iconH;
}
 
static pascal void Plot1IndIconSuite (Rect *rect)
{
    Handle iconCacheH;
 
    static IconGetterUPP iconGetterUPP;
 
    if (!iconGetterUPP)
        iconGetterUPP = NewIconGetterProc (MyIconGetter);
    if (!iconGetterUPP)
        return;
    if (!MakeIconCache (&iconCacheH,iconGetterUPP,nil))
    {
        PlotIconSuite (rect,kAlignNone,kTransformNone,iconCacheH);
 
        //
        //  DisposeIconSuite assumes resources are purgeable and doesn't
        //  release them. Since we would rather the memory be freed,
        //  we have our icon getter function ('MyIconGetter') detach
        //  each resource it gets. This turns off the resource bit for
        //  the handle and clues DisposeIconSuite it should call DisposeHandle.
        //
 
        DisposeIconSuite (iconCacheH,true);
    }
}
 
//////////////////////////////////////////////////////////////////////
//
//  Below please find the usual sort of application boilerplate.
//
//////////////////////////////////////////////////////////////////////
 
static Boolean gQuitting;
 
static pascal OSErr InitMac (void)
{
    MaxApplZone ( );
    InitGraf (&(qd.thePort));
    InitFonts ( );
    InitWindows ( );
    InitMenus ( );
    TEInit ( );
    InitDialogs (nil);
 
    return noErr;
}
 
static pascal void IconUserItem (WindowRef dlgRef, short itemNo)
{
    short crf = CurResFile ( );
    short iType; Handle iHandle; Rect iRect;
    GetDialogItem (dlgRef,itemNo,&iType,&iHandle,&iRect);
    UseResFile (GetWRefCon (dlgRef));
    if (!ResError ( ))
    {
        Plot1IndIconSuite (&iRect);
        UseResFile (crf);
    }
}
 
static pascal void GrabIcon (void)
{
    StandardFileReply sfr;
    StandardGetFile (nil,-1,nil,&sfr);
    if (sfr.sfGood)
    {
        short crf = CurResFile ( );
        short resRefNum = FSpOpenResFile (&(sfr.sfFile),fsRdPerm);
        if (resRefNum != -1)
        {
            DialogRef dlgRef = nil;
 
            UseResFile (crf);
 
            dlgRef = GetNewDialog (128,nil,(WindowRef)-1);
            if (dlgRef)
            {
                short itemHit;
                short iType; Handle iHandle; Rect iRect;
                static UserItemUPP userItemUPP;
 
                if (!userItemUPP)
                    userItemUPP = NewUserItemProc (IconUserItem);
                if (userItemUPP)
                {
                    GetDialogItem (dlgRef,2,&iType,&iHandle,&iRect);
                    SetDialogItem (dlgRef,2,iType,(Handle)userItemUPP,&iRect);
                    SetWRefCon (dlgRef,resRefNum);
 
                    ShowWindow (dlgRef);
                    ModalDialog ( NewModalFilterProc(nil),&itemHit);
                }
                DisposeDialog (dlgRef);
            }
            
            CloseResFile (resRefNum);
        }
    }
}
 
static pascal void Command (long ms)
{
    short   menuID = ms >> 16,
            menuItem = ms;
 
    if (menuID == 129)
    {
        if (menuItem == 2)
            gQuitting = true;
        else if (menuItem == 1)
            GrabIcon ( );
    }
}
 
static pascal void HandleEvent (const EventRecord *eventP)
{
    if (eventP->what == mouseDown)
    {
        WindowRef whichWindow;
        short partCode = FindWindow (eventP->where, &whichWindow);
        if (partCode == inMenuBar)
        {
            long ms = MenuSelect (eventP->where);
            if (ms) Command (ms);
            HiliteMenu (0);
        }
    }
}
 
static pascal Boolean SetUpMenuBar (void)
{
    Boolean result = false;
    Handle mBar = GetNewMBar (128);
    if (!ResError ( ) && mBar)
    {
        SetMenuBar (mBar);
        AppendResMenu (GetMenuHandle (130), 'DRVR');
        DrawMenuBar ( );
        result = true;
        ReleaseResource (mBar);
    }
    return result;
}
 
void main (void)
{
    if (!InitMac ( ) && SetUpMenuBar ( ))
    {   
        do
        {
            EventRecord event;
            InitCursor ( );
            WaitNextEvent (everyEvent, &event, -1, nil);
            HandleEvent (&event);
        }
        while (!gQuitting);
    }
}