Source/windows.c

/*************************************************************************************
#
#       Windows.c
#
#       This segment handles the window creation, close, updates,
#
#       Author(s):  Michael Marinkovich & Guillermo Ortiz
#                   marink@apple.com
#
#       Modification History: 
#
#           4/3/96      MWM     Initial coding                   
#
#       Copyright © 1992-96 Apple Computer, Inc., All Rights Reserved
#
#
#       You may incorporate this sample code into your applications without
#       restriction, though the sample code has been provided "AS IS" and the
#       responsibility for its operation is 100% yours.  However, what you are
#       not permitted to do is to redistribute the source as "DSC Sample 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 Code, but that you've made changes.
#
*************************************************************************************/
 
#include <TextUtils.h>
#include <Windows.h>
 
#include "App.h"
#include "Proto.h"
 
 
//----------------------------------------------------------------------
//
//  Globals - 
//
//----------------------------------------------------------------------
 
extern Boolean      gHasAbout;      // have an about box?
extern short        gWindCount;
 
 
//----------------------------------------------------------------------
//
//  CreateWindow - create a window from the info passed in. Will try to 
//                 load from resource if resID is supplied.
//
//----------------------------------------------------------------------
 
WindowPtr CreateWindow(short resID, void *wStorage, Rect *bounds,  Str255 title,
                       Boolean visible, short procID , short kind,
                       WindowRef behind, Boolean goAwayFlag, long refCon)
{
    OSErr           err = nil;
    WindowRef       newWindow = nil;
    
    
    if (resID != nil)       // if res id isn't nil then load from disk
        newWindow = GetNewWindow(resID, wStorage, behind);
    else                    // otherwise make a new windowRecord
        newWindow = NewWindow(wStorage, bounds, title, visible, 
                               procID, behind, goAwayFlag, refCon);
                               
    if (newWindow != nil) 
    {
        NewWindowTitle(newWindow, title);
        err = InitWindowProcs(newWindow, kind);
        
        if (err == noErr) 
        {
            SetPort(newWindow);
            ShowWindow(newWindow);
        }
                
        // initialization of Document Record failed
        // so kill the return window    
        else 
        {
            newWindow = nil;
            HandleError(err, false);
        }       
    }
    
    return newWindow;
 
}
    
 
//----------------------------------------------------------------------
//
//  RemoveWindow - applications Doc window disposal routine.
//               
//
//----------------------------------------------------------------------
 
OSErr RemoveWindow( WindowRef window )
{
    OSErr           err = nil;
    short           kind;
    DocHnd          doc;
    
    
    kind = GetWindKind( window );
    if ( kind < kDocKind || kind > kAboutKind )
        return -1; // not our window
    
    doc = (DocHnd)GetWRefCon( window );
    if ( doc != nil ) {
        switch( kind ) {
            case kDocKind:
                DisposeGWorld((**doc).world);
                DisposeHandle( (Handle)doc );
                DisposeWindow( window );
                err = noErr;
                break;
            
            case kAboutKind:
                DisposeHandle( (Handle)doc );
                DisposeWindow( window );
                err = noErr;
                gHasAbout = false;  // allow new about box
                break;
            
            default:
                break;
                    
 
        }   
    }
    
    return err;
}       
 
 
//----------------------------------------------------------------------
//
//  NewWindowTitle - if supplied title is nil then title is set to 
//                   global "gWindCount".
//
//----------------------------------------------------------------------
 
void NewWindowTitle(WindowRef window, Str255 str)
{
    Str255      catStr = "\pUntitled ";
    Str255      newStr;
    
    
    if (str == nil || StrLength(str) == 0) 
    {
        pstrcpy(newStr, catStr);
        NumToString(gWindCount, catStr);
        pstrcat(newStr, catStr);
        gWindCount++;
        
        SetWTitle(window,newStr);
    }
    else
        SetWTitle(window, str);
 
}
 
 
//----------------------------------------------------------------------
//
//  InitWindowProcs - init a window with proper callback event. fills 
//                    out custom procs for different windowkinds.
//
//----------------------------------------------------------------------
 
OSErr InitWindowProcs(WindowRef window, short windKind)
{
    OSErr           err = nil;
    DocHnd          doc;
    
    doc = (DocHnd)NewHandle(sizeof(DocRec));
    if (doc != nil) {
        SetWRefCon(window, (long)doc);
 
        switch(windKind) {
            case kDocKind:
                (**doc).idleProc        = DoIdle;
                (**doc).mMenuProc       = HandleMenuChoice;
                (**doc).inContentProc   = HandleContentClick;
                (**doc).inGoAwayProc    = nil;
                (**doc).inZoomProc      = HandleZoomClick;
                (**doc).inGrowProc      = HandleGrow;
                (**doc).keyProc         = nil;
                (**doc).activateProc    = DoActivate;
                (**doc).updateProc      = DrawWindow;   
                (**doc).hScroll         = nil;
                (**doc).vScroll         = nil;
                (**doc).world           = nil;
                (**doc).pict            = nil;
                (**doc).printer         = nil;
                (**doc).dirty           = false;
                
                InstallScrollBars(window, doc);
 
                break;
                
            case kDialogKind:
                (**doc).idleProc        = DoIdle;
                (**doc).mMenuProc       = HandleMenuChoice;
                (**doc).inContentProc   = nil;
                (**doc).inGoAwayProc    = nil;
                (**doc).inZoomProc      = nil;
                (**doc).inGrowProc      = nil;
                (**doc).keyProc         = nil;
                (**doc).activateProc    = nil;
                (**doc).updateProc      = DrawAboutWindow;  
                (**doc).hScroll         = nil;
                (**doc).vScroll         = nil;
                (**doc).world           = nil;
                (**doc).pict            = GetPicture(rAboutPictID);
                (**doc).printer         = nil;
                (**doc).dirty           = false;
                break;
 
            case kAboutKind:
                (**doc).idleProc        = DoIdle;
                (**doc).mMenuProc       = HandleMenuChoice;
                (**doc).inContentProc   = nil;
                (**doc).inGoAwayProc    = nil;
                (**doc).inZoomProc      = nil;
                (**doc).inGrowProc      = nil;
                (**doc).keyProc         = nil;
                (**doc).activateProc    = nil;
                (**doc).updateProc      = DrawAboutWindow;  
                (**doc).hScroll         = nil;
                (**doc).vScroll         = nil;
                (**doc).world           = nil;
                (**doc).pict            = GetPicture(rAboutPictID);
                (**doc).printer         = nil;
                (**doc).dirty           = false;
                
                break;
                
            default:
                err = 25;
                break;  
        }
        ((WindowPeek)window)->windowKind = windKind;
 
    }           
    return err;
 
}
 
 
//----------------------------------------------------------------------
//
//  PictToWorld - create a GWorld from a Pict. Size is determined by the
//                bounds of the pict. If the pict is nil then a default
//                bounds is used, in case of an empty window.
//----------------------------------------------------------------------
    
GWorldPtr PictToWorld(PicHandle pict, OSErr *rtnErr)
{
    OSErr           err;
    GWorldPtr       oldWorld;
    GWorldPtr       theWorld = nil;
    GDHandle        oldGD;
    PixMapHandle    thePix;
    Rect            bounds;
    
    GetGWorld(&oldWorld, &oldGD);
    
    if (pict != nil)
        bounds = (**pict).picFrame;
    else
        SetRect(&bounds, 0, 0, 200, 200);   
    
    err = NewGWorld(&theWorld, 8,&bounds, nil, nil, 0L);
    if (err == noErr && theWorld != nil) {
        thePix = GetGWorldPixMap(theWorld);
        if (LockPixels(thePix)) {
            SetGWorld(theWorld, nil);
            EraseRect(&bounds);
            if (pict != nil)
                DrawPicture(pict, &bounds);
            
            UnlockPixels(thePix);
        }
        SetGWorld(oldWorld, oldGD);
    }
    
    *rtnErr = err;
    
    return theWorld;
}
 
        
//----------------------------------------------------------------------
//
//  DrawWindow - custom proc that is called to update window contents.
//               
//
//----------------------------------------------------------------------
 
void DrawWindow(WindowRef window, void *refCon)
{
    #pragma unused (refCon)
 
    DocHnd          doc;
    GWorldPtr       theWorld;
    PixMapHandle    thePix;
    Rect            cRect;
    Rect            bounds;
    
    doc = (DocHnd)GetWRefCon(window);   
    if (doc != nil) {
        SetPort(window);
        GetContRect(window, &cRect);
        ClipRect(&cRect);
        
        theWorld = (**doc).world;
 
        if (theWorld != nil ) {
            bounds = theWorld->portRect;
            OffsetRect(&bounds, -GetCtlValue((**doc).hScroll), 
                       -GetCtlValue((**doc).vScroll));
            thePix = GetGWorldPixMap(theWorld);
            if (LockPixels(thePix)) {
                CopyBits((BitMap *) *thePix, &window->portBits,
                         &theWorld->portRect, &bounds, srcCopy, nil);
                
                UnlockPixels(thePix);
            }            
                        
        }
        else
            EraseRect(&cRect);  
 
        ClipRect(&window->portRect);
        DrawGrowIcon(window);
        UpdateControls(window, window->visRgn);
    }
 
}
 
 
//----------------------------------------------------------------------
//
//  DrawAboutWindow - custom proc that is called to update about window.
//               
//
//----------------------------------------------------------------------
 
void DrawAboutWindow( WindowRef window, void *refCon )
{   
    #pragma unused (refCon)
 
    DocHnd      doc;
    
    doc = (DocHnd)GetWRefCon(window);   
    if ( (**doc).pict != nil ) 
        DrawPicture( (**doc).pict, &window->portRect );
 
}
 
 
//----------------------------------------------------------------------
//
//  DoResizeWindow - custom proc that is called to update window.
//               
//
//----------------------------------------------------------------------
 
void DoResizeWindow (WindowRef window) 
{
    DocHnd          doc;
    ControlHandle   hCtl, vCtl;
    RgnHandle       tempRgn;
    RgnHandle       oldCtlRgn;
    short           max, oldCntlVal;
    short           pV, wV;
    short           pH, wH;
    Rect            hSRect;
    Rect            newDocRect;
    Rect            pictRect;
    Rect            paneRect;
 
    doc = (DocHnd)GetWRefCon(window);
    if (doc != nil) {
        pictRect = (**doc).world->portRect;
        newDocRect = (**window->visRgn).rgnBBox;
 
        hCtl = (**doc).hScroll;
        vCtl = (**doc).vScroll;
        
        hSRect = (**hCtl).contrlRect;
        hSRect.right += kScrollWidth;
        ClipRect(&window->portRect);
        RectRgn(oldCtlRgn = NewRgn(), &hSRect);
        RectRgn(tempRgn = NewRgn(), &(**vCtl).contrlRect);
        UnionRgn(oldCtlRgn, tempRgn, oldCtlRgn);
        EraseRgn(oldCtlRgn);
        
        (**hCtl).contrlVis = 0;
        (**vCtl).contrlVis = 0;
 
        paneRect = newDocRect;
        paneRect.bottom -= kScrollWidth;
        paneRect.right -= kScrollWidth;
        
        MoveControl(hCtl, paneRect.left - 1, paneRect.bottom);  
        MoveControl(vCtl, paneRect.right, paneRect.top - 1);
            
        SizeControl(hCtl, 2+paneRect.right - paneRect.left, kScrollWidth + 1);  
        SizeControl(vCtl, kScrollWidth + 1, 2+paneRect.bottom - paneRect.top);
        
        (**hCtl).contrlVis = 255;
        (**vCtl).contrlVis = 255;
        
        pV = pictRect.bottom - pictRect.top;
        wV = paneRect.bottom - paneRect.top;
        if (wV >= pV)
            max = 0;
        else
            max = ((MAX (0, pV - wV)) / kScrollDelta) + 1;
            
        oldCntlVal = GetControlValue(vCtl);
        SetControlMinimum(vCtl, 0);
        SetControlMaximum(vCtl, max);
        SetControlValue(vCtl, oldCntlVal );
        
        HiliteControl(vCtl, (max == 0) ? (255):(0));    
 
        pH = pictRect.right - pictRect.left;
        wH = paneRect.right - paneRect.left;
        if (wH >= pH)
            max = 0 ;
        else
            max = ((MAX (0, pH - wH )) / kScrollDelta) +1;
        oldCntlVal = GetControlValue(hCtl);
        SetControlMinimum(hCtl, 0);
        SetControlMaximum(hCtl, max) ;
        SetControlValue(hCtl, oldCntlVal);
        
        HiliteControl(hCtl, (max == 0) ? (255):(0));    
                
        DisposeRgn(oldCtlRgn);
        DisposeRgn(tempRgn);
        AdjustScrollValues(window);
        InvalRect(&window->portRect);
 
    }
 
}
 
 
//----------------------------------------------------------------------
//
//  GetWindKind - returns the windowkind.
//               
//
//----------------------------------------------------------------------
 
short GetWindKind(WindowRef window)
{
 
    return ((WindowPeek)window)->windowKind;
 
}
 
 
//----------------------------------------------------------------------
//
//  GetIsAppWindow - is the window a 'userKind'.
//               
//
//----------------------------------------------------------------------
 
Boolean GetIsAppWindow(WindowRef window)
{
    return (GetWindKind(window) == kDocKind);
 
}
 
 
//----------------------------------------------------------------------
//
//  GetIsAboutWindow - is the window an about box.
//               
//
//----------------------------------------------------------------------
 
Boolean GetIsAboutWindow(WindowRef window)
{
    return (GetWindKind(window) == kAboutKind);
    
}