MenusStuff.c

/*
    File:       MenusStuff.c
 
    Contains:   Handles the application's menus
 
    Written by: Chris White 
 
    Copyright:  Copyright © 1995-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/5/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
 
#include <Menus.h>
#include <Windows.h>
#include <Dialogs.h>
#include <TextUtils.h>
#include <Devices.h>
#include <CodeFragments.h>
 
 
#ifndef __MENUSTUFF__
    #include "MenuStuff.h"
#endif
 
#include "DialogStuff.h"
 
#ifndef __STREAMS__
    #include "Streams.h"
#endif
 
#ifndef __UTILITIES__
    #include "Utilities.h"
#endif
 
#ifndef __PROTOTYPES__
    #include "Prototypes.h"
#endif
 
 
 
 
 
static Boolean EnableFileCommands ( WindowRef frontWindow );
static Boolean EnableEditCommands ( WindowRef frontWindow );
static Boolean EnableFragmentCommands ( WindowRef frontWindow );
static void SetItemEnable ( MenuHandle theMenu, int16 theItem, Boolean bEnabled );
static void DoAppleCmds ( int16 theItem );
static void DoFileCmds ( int16 theItem );
static void DoFragmentCmds ( int16 theItem );
static void DoGetInfo ( WindowRef theWindow );
static void DoDisplayExports ( WindowRef theWindow );
static void DoMoveFragments ( WindowRef theWindow );
static void DoCopyFragments ( WindowRef theWindow );
static void DoRemoveFragments ( WindowRef theWindow );
static OSErr PackageWindowData ( WindowRef theWindow, Ptr* theData );
 
 
 
 
void MenuDispatch ( int32 menuResult )
{
    int16   theMenu = (menuResult >> 16);                   // menu selected
    int16   theItem = (menuResult & 0x0000FFFF);            // item selected
    
    switch (theMenu)
    {
        case kAppleMenu: 
            DoAppleCmds ( theItem );
        break;
        
        case kFileMenu: 
            DoFileCmds ( theItem );
        break;
        
        case kEditMenu: 
            SystemEdit ( theItem - 1 );
        break;
        
        case kFragmentMenu:
            DoFragmentCmds ( theItem );
        break;
    }
    
    HiliteMenu ( 0 );           // un-hilite selected menu
    
    return;
    
} // MenuDispatch
 
 
 
void AdjustMenus ( void )
{
    Boolean     bRedraw = false;
    WindowRef   frontWindow;
    
    frontWindow = FrontWindow ( );
    if ( EnableFileCommands ( frontWindow ) )
        bRedraw = true;
    if ( EnableEditCommands ( frontWindow ) )
        bRedraw = true;
    if ( EnableFragmentCommands ( frontWindow ) )
        bRedraw = true;
    
    if ( bRedraw )
        DrawMenuBar ( );
    
    return;
    
} // AdjustMenus
 
 
 
static Boolean EnableFileCommands ( WindowRef frontWindow )
{
    static Boolean  bIsEnabled = true;
    Boolean         bHasDialog = false;
    Boolean         bUpdate = false;
    MenuHandle  theMenu = GetMenuHandle ( kFileMenu );
    
    
    bHasDialog = frontWindow && GetWindowKind ( frontWindow ) == dialogKind;
    
    if ( bIsEnabled == bHasDialog )     // Or bIsEnabled != !bHasDialog
    {
        SetItemEnable ( theMenu, 0, !bHasDialog );
        bIsEnabled = !bHasDialog;
        bUpdate = true;
    }
    
    SetItemEnable ( theMenu, cNew, !bHasDialog );
    SetItemEnable ( theMenu, cOpen, !bHasDialog );
    SetItemEnable ( theMenu, cClose, frontWindow && GetWindowGoAwayFlag ( frontWindow ) );
    SetItemEnable ( theMenu, cSave, frontWindow && IsDocumentDirty ( frontWindow ) );
    SetItemEnable ( theMenu, cSaveAs, frontWindow  && GetWindowType ( frontWindow ) == kDocumentWindowType );
    SetItemEnable ( theMenu, cQuit, !bHasDialog );
    
    return bUpdate;
    
} // EnableFileCommands
 
 
 
static Boolean EnableEditCommands ( WindowRef frontWindow )
{
    #pragma unused(frontWindow)
    static Boolean  bIsEnabled = true;
    Boolean         bEnable = false;
    MenuHandle      theMenu = GetMenuHandle ( kEditMenu );
    
    
    bEnable = false;
    if ( bIsEnabled != bEnable )
    {
        SetItemEnable ( theMenu, 0, bEnable );
        bIsEnabled = bEnable;
        
        return true;
    }
    
    return false;
    
} // EnableEditCommands
 
 
 
static Boolean EnableFragmentCommands ( WindowRef frontWindow )
{
    static Boolean  bIsEnabled = true;
    Boolean         bHasSelection = false;
    Boolean         bHasMultiSelection = false;
    MenuHandle      theMenu = GetMenuHandle ( kFragmentMenu );
    
    
    if ( frontWindow && GetWindowType ( frontWindow ) == kDocumentWindowType )
    {
        int16           theIndex = 0;
        tWindowInfoPtr  theInfo;
        
        theInfo = (tWindowInfoPtr) GetWRefCon ( frontWindow );
        if ( theInfo->listRef )
        {
            bHasSelection = GetSelection ( theInfo->listRef, &theIndex );
            theIndex++;
            bHasMultiSelection = GetSelection ( theInfo->listRef, &theIndex );
        }
    }
    
    if ( bIsEnabled != bHasSelection )
    {
        if ( bHasSelection )
        {
            Boolean bHasMultiWindows;
            
            
            // Always better to assign true or false so that if it's checked
            // against the constants, it'll still work. If we simply cast the
            // result of GetNextWindow to a boolean, a true value may not be
            // exactly 1. If we then use Òif ( bHasMultiWindows == true )Ó
            // the evaluation will not be what we wanted. Further, because
            // only 1 byte is assigned to the boolean, we could miss all the
            // important bytes (those non-zero ones) so that bHasMultiWindows
            // turned out to be false.
            
            bHasMultiWindows = (GetNextWindow ( frontWindow )) ? true : false;
            
            SetItemEnable ( theMenu, 0, true );
            SetItemEnable ( theMenu, cGetInfo, !bHasMultiSelection );
            SetItemEnable ( theMenu, cExports, !bHasMultiSelection );
            SetItemEnable ( theMenu, cMoveTo, bHasMultiWindows );
            SetItemEnable ( theMenu, cCopyTo, bHasMultiWindows );
            SetItemEnable ( theMenu, cRemove, true );
        }
        else
            SetItemEnable ( theMenu, 0, false );
            
        bIsEnabled = bHasSelection;
        
        return true;
    }
    
    return false;
    
} // EnableFragmentCommands
 
 
 
static void SetItemEnable ( MenuHandle theMenu, int16 theItem, Boolean bEnabled )
{
    if ( theMenu )
    {
        if ( bEnabled )
            EnableItem ( theMenu, theItem );
        else
            DisableItem ( theMenu, theItem );
    }
        
    return;
    
} // SetItemEnable
 
 
 
static void DoAppleCmds ( int16 theItem )
{
    Str255  name;           // string for DA name
    
    
    switch ( theItem )
    {
        case cAbout:
            Alert ( kAboutDialog, nil );
        break;
        
        default:
            GetMenuItemText ( GetMenuHandle ( kAppleMenu ), theItem, (StringPtr) &name );
            OpenDeskAcc( (StringPtr) &name );
        break;
    }
}
 
 
 
static void DoFileCmds ( int16 theItem )
{   
    switch ( theItem )
    {
        case cNew:
            DoNewDocument ( );
        break;
        
        case cOpen:
            DoOpenDocument ( );
        break;
        
        case cClose:
            DoCloseDocument ( FrontWindow ( ) );
        break;
        
        case cSave:
            DoSave ( FrontWindow ( ) );
        break;
        
        case cSaveAs:
            DoSaveAs ( FrontWindow ( ) );
        break;
        
        case cQuit:
                                                // Tell the application immediatly. It
            gQuit = true;                       // might need to know.
                                                
            if ( DoCloseAllDocuments ( ) )      // Did the user cancel?
                gQuit = false;
        break;
    }
    
    return;
    
} // DoFileCmds
 
 
 
static void DoFragmentCmds ( int16 theItem )
{
    WindowRef frontWindow = FrontWindow ( );
    
    switch ( theItem )
    {
        case cGetInfo:
            DoGetInfo ( frontWindow );
        break;
        
        case cExports:
            DoDisplayExports ( frontWindow );
        break;
        
        case cMoveTo:
            DoMoveFragments ( frontWindow );
        break;
        
        case cCopyTo:
            DoCopyFragments ( frontWindow );
        break;
        
        case cRemove:
            DoRemoveFragments ( frontWindow );
        break;
    }
    
    return;
    
} // DoFragmentCmds
 
 
 
static void DoGetInfo ( WindowRef theWindow )
{
    int16       theIndex = 0;
    ListRef     theList;
    
    theList = GetWListRef ( theWindow );
    if ( GetSelection ( theList, &theIndex ) )
    {
        OSErr                   theErr;
        DialogRef               theDialog;
        tItemPtr                theItem;
        Str255                  theTitle;
        
        
        theItem = GetNthWindowItem ( theWindow, theIndex );
        
        GetIndString ( theTitle, 1000, 5 );
        ConcatPStr ( theTitle, theItem->name, sizeof ( Str255 ) );
        
        theErr = CreateInfoDialog ( &theDialog, theTitle, theWindow, theIndex );
        if ( theErr )
            AlertUser ( kGenericErrorStr, theErr, nil );
    }
    
    
    return;
}
 
 
 
static void DoDisplayExports ( WindowRef theWindow )
{
    int16       theIndex = 0;
    ListRef     theList;
    
    theList = GetWListRef ( theWindow );
    if ( GetSelection ( theList, &theIndex ) )
    {
        OSErr                   theErr;
        DialogRef               theDialog;
        tItemPtr                theItem;
        Str255                  theTitle;
        tWindowInfoPtr          theInfo;
        tAddFragmentExportsRec  theRec;
        
        
        theInfo = (tWindowInfoPtr) GetWRefCon ( theWindow );
        theItem = GetNthWindowItem ( theWindow, theIndex );
        
        GetIndString ( theTitle, 1000, 1 );
        ConcatPStr ( theTitle, theItem->name, sizeof ( Str255 ) );
        
        theRec.bIn = false;
        theRec.u.out.theSpecPtr = &theInfo->fileSpec;
        theRec.u.out.theItem = theItem;
        theErr = CreateListDialog ( &theDialog, kListDialogOkay, theTitle,
                                    &AddFragmentExports, (void*) &theRec );
        if ( theErr )
        {
            // If an error occured, the record may contain some useful information
            
            StringPtr   theString = nil;
            
            if ( theRec.bIn )
                theString = theRec.u.in.theErrorStr;
            if ( theErr == cfragNoLibraryErr )
                AlertUser ( kUnresolvedDependenciesStr, 0, theString );
            else
                AlertUser ( kGenericErrorStr, theErr, nil );
        }
    }
    
    
    return;
}
 
 
 
static void DoMoveFragments ( WindowRef theWindow )
{
    OSErr           theErr;
    DialogRef       theDialog;
    tDialogInfo*    theInfo;
    Ptr             theData;
    Str255          theTitle, windowTitle;
    
    
    GetWTitle ( theWindow, windowTitle );
    GetIndString ( theTitle, 1000, 2 );
    ConcatPStr ( theTitle, windowTitle, sizeof ( Str255 ) );
    
    theErr = CreateListDialog ( &theDialog, kListDialogOkayCancel, theTitle,
                                &AddDocuments, nil );
    if ( theErr )
    {
        AlertUser ( kGenericErrorStr, theErr, nil );
        return;
    }
    
    SetWindowSubType ( theDialog, kMoveFragmentWindowSubType );
    
    
    // Packages up the window reference and an array of index
    // values (precceded by an element count).
    theErr = PackageWindowData ( theWindow, &theData );
    if ( theErr )
    {
        AlertUser ( kGenericErrorStr, theErr, nil );
        return;
    }
    
    theInfo = (tDialogInfo*) GetWRefCon ( theDialog );
    theInfo->refCon = (int32) theData;
    
    return;
    
}
 
 
 
static void DoCopyFragments ( WindowRef theWindow )
{   
    OSErr           theErr;
    DialogRef       theDialog;
    tDialogInfo*    theInfo;
    Ptr             theData;
    Str255          theTitle, windowTitle;
    
    
    
    GetWTitle ( theWindow, windowTitle );
    GetIndString ( theTitle, 1000, 3 );
    ConcatPStr ( theTitle, windowTitle, sizeof ( Str255 ) );
    
    theErr = CreateListDialog ( &theDialog, kListDialogOkayCancel, theTitle,
                                &AddDocuments, nil );
    if ( theErr )
    {
        AlertUser ( kGenericErrorStr, theErr, nil );
        return;
    }
    
    SetWindowSubType ( theDialog, kCopyFragmentWindowSubType );
    
    
    // Packages up the window reference and an array of index
    // values (precceded by an element count).
    theErr = PackageWindowData ( theWindow, &theData );
    if ( theErr )
    {
        AlertUser ( kGenericErrorStr, theErr, nil );
        return;
    }
    
    theInfo = (tDialogInfo*) GetWRefCon ( theDialog );
    theInfo->refCon = (int32) theData;
    
    return;
    
}
 
 
 
static void DoRemoveFragments ( WindowRef theWindow )
{
    int16       theIndex = 0;
    ListRef     theList;
    
    theList = GetWListRef ( theWindow );
    while ( GetSelection ( theList, &theIndex ) )
    {
        DeleteWindowFragment ( theWindow, theIndex );
        theIndex++;
    }
    
    return;
}
 
 
 
//
// Our refCon field is used to encapsulate the information about
// the fragments being copied. Namely, the window reference and
// an array of index values (precceded by an element count). This
// packages up the information using a data stream.
//
static OSErr PackageWindowData ( WindowRef theWindow, Ptr* theData )
{
    OSErr           theErr;
    int16           theIndex = 0;
    int             theCount = 0;
    ListRef         theList;
    tStreamRef      theStream;
    tStreamCursor   countCursor;
    
    
    
    theErr = NewStream ( &theStream, 100 );
    if ( theErr )
        return theErr;
    
    theErr = SetStreamData ( theStream, (Ptr) &theWindow, sizeof ( WindowRef ) );
    if ( theErr )
    {
        DisposeStream ( theStream );
        return theErr;
    }
    countCursor = GetStreamCursor ( theStream );
    theErr = SetStreamData ( theStream, nil, sizeof ( int ) );
    if ( theErr )
    {
        DisposeStream ( theStream );
        return theErr;
    }
    
    theList = GetWListRef ( theWindow );
    while ( GetSelection ( theList, &theIndex ) )
    {
        SetStreamData ( theStream, (Ptr) &theIndex, sizeof ( int16 ) );
        theCount++;
        theIndex++;
    }
    
    theErr = SetStreamCursor ( theStream, countCursor );
    if ( theErr )
    {
        DisposeStream ( theStream );
        return theErr;
    }
    theErr = SetStreamData ( theStream, (Ptr) &theCount, sizeof ( int ) );
    if ( theErr )
    {
        DisposeStream ( theStream );
        return theErr;
    }
    theErr = CompactStream ( theStream );
    if ( theErr )
        return theErr;
    
    *theData = (Ptr) theStream;
    
    return noErr;
    
} // PackageWindowData