Windows.c

/*
    File:       Windows.c
 
    Contains:   Handle application's windows
 
    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/10/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
 
 
#pragma segment Core
 
 
#include <Sound.h>
// System Includes
 
#ifndef __TYPES__
    #include <Types.h>
#endif
 
#ifndef __WINDOWS__
    #include <Windows.h>
#endif
 
#ifndef __QUICKDRAW__
    #include <Quickdraw.h>
#endif
 
#ifndef __RESOURCES__
    #include <Resources.h>
#endif
 
#ifndef __FONTS__
    #include <Fonts.h>
#endif
 
#ifndef __ERRORS__
    #include <Errors.h>
#endif
 
 
 
 
// Application Includes
 
#ifndef __BAREBONES__
    #include "BareBones.h"
#endif
 
#ifndef __PROTOTYPES__
    #include "Prototypes.h"
#endif
 
 
 
 
// Static prototypes
 
static OSErr    CreateContentList ( WindowRef theWindow, tContentsProcPtr contentsProc, void* refCon );
static OSErr    AddListContents ( ListRef theList, void* refCon );
 
 
OSErr           PatchListLDEF ( ListRef theList );
 
 
 
 
 
//
// This is called to create the application's window.
//
void CreateWindow ( void )
{
    OSErr       theErr;
    WindowRef   theWindow;
    
    theErr = CreateListWindow ( &theWindow, AddListContents, nil );
    if ( theErr )
        AlertUser ( kGenericErrorStr, theErr, "\p" );
    
    return;
}
 
 
 
//
// This will close the application's window, dispose of any storage we've hung
// off the window, and then dispose of the window itself.
//
WindowRef DestroyWindow ( WindowRef windowRef )
{
    if ( windowRef )
    {
        ListRef theList;
        
        theList = (ListRef) GetWRefCon ( windowRef );
        if ( theList )
            LDispose ( theList );
        
        DisposeWindow ( windowRef );
        
    }
    
    return nil;
}
 
 
 
//
// Creates a window with a list in the centre. contentsProc is a routine
// pointer to intitialize the list. It's passed the refCon to assist.
//
OSErr CreateListWindow ( WindowRef* windowRef, tContentsProcPtr contentsProc, void* refCon )
{
    OSErr       theErr;
    WindowRef   theWindow;
    
    
    theWindow = GetNewCWindow ( kDisplayWindow, nil, (WindowRef) -1 );
    if ( theWindow == nil )
        return (ResError ( )) ? ResError ( ) : resNotFound;
    
    SetPortWindowPort ( theWindow );
    TextFont ( kFontIDGeneva );
    TextFace ( normal );
    TextSize ( 9 );
    
    theErr = CreateContentList ( theWindow, contentsProc, refCon );
    if ( theErr )   goto CleanupAndBail;
    
    SelectWindow ( theWindow );
    ShowWindow ( theWindow );
    
    *windowRef = theWindow;
    
    return noErr;
    
 
CleanupAndBail:
    
    // Don't forget to free any storage we've used so far
    DestroyWindow ( theWindow );
    
    return theErr;
}
 
 
 
//
// This is passed into the CreateDocumentWindow routine
// to add the contents to the newly created list.
//
static OSErr AddListContents ( ListRef theList, void* refCon )
{
    #pragma unused(refCon)
    AddToList ( theList, "\pApple Extras\t-\tfolder\tThu, Dec 19, 1995, 12:07 pm" );
    AddToList ( theList, "\pApplications\t-\tfolder\tWed, Dec 18, 1995, 12:04 pm" );
    AddToList ( theList, "\pClean System Folder\t-\tfolder\tThu, Dec 7, 1995, 1:46 pm" );
    AddToList ( theList, "\pCommunications\t-\tfolder\tWed, Dec 6, 1995, 2:21 pm" );
    AddToList ( theList, "\pCopland Stuff\t-\tfolder\tTue, Aug 29, 1995, 1:14 pm" );
    AddToList ( theList, "\pDevelopment\t-\tfolder\tWed, Dec 13, 1995, 4:27 pm" );
    AddToList ( theList, "\pDocumentation\t-\tfolder\tThu, Dec 19, 1995, 12:07 pm" );
    AddToList ( theList, "\pDTS\t-\tfolder\tWed, Dec 18, 1995, 1:07 pm" );
    AddToList ( theList, "\pMisc\t-\tfolder\tMon, Dec 16, 1995, 8:56 pm" );
    AddToList ( theList, "\pProjects\t-\tfolder\tThu, Dec 19, 1995, 12:07 pm" );
    AddToList ( theList, "\pStress\t-\tfolder\tTue, Aug 29, 1995, 1:14 pm" );
    AddToList ( theList, "\pSystem Folder\t-\tfolder\tThu, Dec 19, 1995, 12:07 pm" );
    AddToList ( theList, "\pSystem Installers\t-\tfolder\tWed, Dec 6, 1995, 2:21 pm" );
    AddToList ( theList, "\pSystem Picker\t-\tapplication program\tMon, Dec 16, 1995, 8:56 pm" );
    AddToList ( theList, "\pTools\t-\tfolder\tThu, Dec 19, 1995, 12:07 pm" );
    AddToList ( theList, "\pAppleScriptª Utilities\t-\tfolder\tThu, Dec 7, 1995, 12:46 pm" );
    AddToList ( theList, "\pDebuggers\t-\tfolder\tThu, Dec 19, 1995, 12:07 pm" );
    AddToList ( theList, "\pDebugging Modern Memory Manager\t-\tfolder\tMon, Dec 16, 1995, 8:56 pm" );
    AddToList ( theList, "\pDebugging OD Part Editors\t33K\tSimpleText document\tThu, Dec 19, 1995, 12:07 pm" );
    AddToList ( theList, "\pDocumentation Viewers\t-\tfolder\tMon, Dec 16, 1995, 12:56 pm" );
    AddToList ( theList, "\pPartMaker 4.3\t-\tfolder\tMon, Dec 16, 1995, 8:56 pm" );
    AddToList ( theList, "\pReference\t-\tfolder\tThu, Dec 19, 1995, 12:07 pm" );
    AddToList ( theList, "\pResource Editors\t5,049K\tfolder\tWed, Dec 6, 1995, 2:21 pm" );
    AddToList ( theList, "\pSDK\t-\tfolder\tThu, Dec 19, 1995, 12:07 pm" );
    AddToList ( theList, "\pSoundMgr3.2Dev.sea\t198K\tapplication program\tThu, Dec 19, 1995, 12:07 pm" );
    
    
    return noErr;
    
} // AddContents
 
 
 
 
//
// This is called to create the List Manager list, and initialize it.
//
static OSErr CreateContentList ( WindowRef theWindow, tContentsProcPtr contentsProc, void* refCon )
{
    OSErr       theErr;
    ListHandle  theList;
    Point       cellSize = {0, 0};
    Cell        firstCell = {0, 0};
    Rect        dataRect = {0, 0, 0, 1};
    Rect        viewRect;
    
    
    // The width of a cell needs to be 32767 so any hiliting
    // doesn't stop short of the window width after it's been resized.
    
    viewRect = theWindow->portRect;
    InsetRect ( &viewRect, 20, 20 );
    viewRect.right -= 15;               // minus scrollbar width
    theList = LNew ( &viewRect, &dataRect, cellSize, kLDEFID, theWindow, 
                        false, false, false, true );
 
    #ifndef USE_LDEF
        theErr = PatchListLDEF ( theList );
        if ( theErr )
            return theErr;
    #endif
    
    if ( theList )
    {
        static short    theOffsets[] = { 4, 0, 100, 134, 200 };
        
        (*theList)->refCon = (long) &theOffsets;
        (*theList)->selFlags = lOnlyOne;
        SetWRefCon ( theWindow, (long) theList );
        
        // Since the calling routine is always in the same architecture type as
        // the callback routine, we don't need to worry about any Mixed Mode
        // complications. We just treat it as a straight forward routine pointer.
        if ( contentsProc )
        {
            theErr = (*contentsProc) ( theList, refCon );
            if ( theErr )
                return theErr;
        }
        
        LSetSelect ( true, firstCell, theList );
        
        // Now the list has been fully prepared, turn the drawing mode on
        LSetDrawingMode ( true, theList );
    }
    
    return noErr;
    
} // CreateContentList
 
 
 
void DoActivate ( EventRecord* theEvent )
{
    Boolean     bActiveFlag = theEvent->modifiers & resumeFlag;
    GrafPtr     savePort;
    WindowRef   theWindow = (WindowRef) theEvent->message;
    
    
    GetPort ( &savePort );
    SetPortWindowPort ( theWindow );
    LActivate ( bActiveFlag, (ListRef) GetWRefCon ( theWindow ) );
    SetPort ( savePort );
    
    return;
}
 
 
 
void DoUpdate ( EventRecord* theEvent )
{
    GrafPtr         savePort;
    CGrafPtr        thePort;
    WindowRef       theWindow = (WindowRef) theEvent->message;
    ListRef         theList = nil;
    Rect            theRect;
    
    
    
    thePort = GetWindowPort ( theWindow );
    
    GetPort ( &savePort );
    SetPortWindowPort ( theWindow );
    BeginUpdate ( theWindow );                  // visRgn temporarily = updateRgn
    EraseRect ( &thePort->portRect );
    
    theList = (ListRef) GetWRefCon ( theWindow );
    if ( theList )
    {
        PenNormal ( );
        GetListRect ( theList, &theRect );
        InsetRect ( &theRect, -1, -1 );
        FrameRect ( &theRect );
        
        LUpdate ( thePort->visRgn, theList );
    }
    
    EndUpdate ( theWindow );                    // restore normal visRgn of grafport
    SetPort ( savePort );
    
    return;
}
 
 
 
void DoContentClick ( WindowRef theWindow, EventRecord* theEvent )
{
    WindowRef   frontWindow;
    
    // If a movable modal is active, ignore click in an inactive 
    // window, otherwise select it or handle the content click.
    
    frontWindow = FrontWindow ( );
    if ( theWindow != frontWindow )
    {
        if ( IsMovableModal ( frontWindow ) )
            SysBeep ( 30 );
        else
            SelectWindow ( theWindow );
    }
    else
    {
        GrafPtr     savePort;
        
        GetPort ( &savePort );
        SetPortWindowPort ( theWindow );
        HandleListClick ( theWindow, theEvent );
        SetPort ( savePort );
    }
    
    return;
    
} // DoContentClick
 
 
 
void DoDragWindow ( WindowRef theWindow, EventRecord* theEvent )
{
    WindowRef   frontWindow;
    
    
    // If a movable modal is active, ignore click in an inactive 
    // title bar, otherwise let the Window Manager handle it.
    
    frontWindow = FrontWindow ( );
    if ( theWindow != frontWindow && IsMovableModal ( frontWindow ) )
        SysBeep ( 30 );
    else                                
    {
        RgnHandle   theRgn;
        Rect        dragRect;
        
        theRgn = GetGrayRgn ( );
        dragRect = (*theRgn)->rgnBBox;
        DragWindow ( theWindow, theEvent->where, &dragRect );
    }
    
    return;
}