Test Code/TinselWindow.c

/******************************************************************************
 **                                                                          **
 **     Module:     TinselWindow.c                                           **
 **                                                                          **
 **     Purpose:    Window/GDevice stuff for Tinsel Town test app            **
 **                                                                          **
 **     Author:     Mike W. Kelley                                           **
 **                                                                          **
 **                 2/3/95  Revised for 0.9 SDK release                      **
 **                                                                          **
 **     Copyright (C) 1994-95 Apple Computer, Inc.  All rights reserved.     **
 **                                                                          **
 *****************************************************************************/
 
 
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
 
/* Macintosh */
#include <Types.h>
#include <Resources.h>
#include <QuickDraw.h>
#include <Fonts.h>
#include <Events.h>
#include <Windows.h>
#include <Menus.h>
#include <TextEdit.h>
#include <Dialogs.h>
#include <Desk.h>
#include <ToolUtils.h>
#include <Memory.h>
#include <SegLoad.h>
#include <Files.h>
#include <OSUtils.h>
#include <OSEvents.h>
#include <DiskInit.h>
#include <Packages.h>
 
/* Project */
#include "RAVE.h"
#include "TinselTest.h"
 
/*******************************************************************************************
 *
 * Static variables used by this file's functions only.
 *
 ******************************************************************************************/
 
static  GDHandle        gGDevice;
static  WindowPtr       gTinselWindow [kTinselWindows];
static  RgnHandle       gClipRgn [kTinselWindows];
 
/*******************************************************************************************
 *
 * Utility functions
 *
 ******************************************************************************************/
 
void InitToolbox (void)
{
    InitGraf((Ptr) &qd.thePort);
    InitFonts();
    InitWindows();
    InitMenus();
    FlushEvents(everyEvent,0);
    TEInit();
    InitDialogs(0L);
    InitCursor();
}
 
/************************************************************************************************
 *
 * Error handling stuff.
 *
 ***********************************************************************************************/
 
void TinselError (
    const char      *message)
{
    char            ErrorStr[256];
 
    sprintf (&ErrorStr[1], "TinselError: %s\n", message);
    ErrorStr[0] = strlen (&ErrorStr[1]) - 1;
    DebugStr ( (ConstStr255Param) ErrorStr);
}
 
/************************************************************************************************
 *
 * Choose a drawing engine for 'windowNumber'. This returns the engine name.
 *
 ***********************************************************************************************/
 
static TQAEngine *ChooseEngine (
    TQADevice       *device,
    long            windowNumber,
    char            engineName[64])     /* Out */
{
    TQAEngine       *engine;
    long            i;
    Boolean         alreadyUsed;
    TQAError        gestaltStatus;
    long            engineNameLength;
    
    for (engine = QADeviceGetFirstEngine (device);
            engine;
            engine = QADeviceGetNextEngine (device, engine))
    {
        /*
         * Search to see if this engine is already being used.
         */
        
        for (i = 0, alreadyUsed = false; i < windowNumber; ++i)
        {
            if (gEngine [i] == engine)
            {
                alreadyUsed = true;
            }
        }
        
        if ( ! alreadyUsed)
        {
            /*
             * Use this engine.
             */
            
            break;
        }
    }
    
    if (engine)
    {
        /*
         * A unique drawing engine was found. Do a gestalt call to get the
         * engine name.
         */
        
        gestaltStatus = QAEngineGestalt (engine, kQAGestalt_ASCIINameLength, &engineNameLength);
        if ((gestaltStatus == kQANoErr) && (engineNameLength < 63))
        {
            gestaltStatus = QAEngineGestalt (engine, kQAGestalt_ASCIIName, &engineName[1]);
        }
        
        if (gestaltStatus != kQANoErr)
        {
            /*
             * Gestalt call failed!
             */
            
            sprintf (&engineName[1], "<Gestalt Error>");
        }
    }
    else
    {
        /*
         * No unused engine was found. Assign a NULL engine pointer, and
         * set a dummy engine name.
         */
        
        sprintf (&engineName[1], "<No Drawing Engine>");
    }
    engineName[0] = strlen (&engineName[1]);
    
    return (engine);
}
 
/*******************************************************************************************
 *
 * Create test windows on the deepest GDevice.
 *
 ******************************************************************************************/
 
Boolean CreateTestWindows (
    long            maxWidth,
    long            maxHeight)
{
    GDHandle        colourGDevice, deepestGDevice;
    long            deviceDepth, maxDepth;
    Rect            deviceRect;
    Rect            windowRect;
    long            deviceWidth, deviceHeight;
    long            windowWidth, windowHeight;
    TQADevice       device;
    char            engineName[64];
 
    /*
     * Find the deepest color display.
     */
    
    maxDepth = 0;
    
    for (colourGDevice = GetDeviceList(), deepestGDevice = NULL;
            colourGDevice;
            colourGDevice = GetNextDevice (colourGDevice))
    {
        deviceDepth = (*(*colourGDevice)->gdPMap)->pixelSize;
        
        if (deviceDepth > maxDepth)
        {
            maxDepth = deviceDepth;
            deepestGDevice = colourGDevice;
        }
    }
    gGDevice = deepestGDevice;
    
    /*
     * Open two side-by-side windows which almost fill the device, or to
     * maxWidth, maxHeight.
     */
 
    deviceRect = (*deepestGDevice)->gdRect;
    
    deviceWidth = (deviceRect.right - deviceRect.left) - 2 * kDeviceWindowBorder;
    deviceHeight = (deviceRect.bottom - deviceRect.top) - 2 * kDeviceWindowBorder;
    
    windowWidth = (deviceWidth / 2) - 2 * kDeviceWindowBorder;
    windowHeight = deviceHeight - 2 * kDeviceWindowBorder;
    
    if (windowWidth > maxWidth)
    {
        windowWidth = maxWidth;
    }
    if (windowHeight > maxHeight)
    {
        windowHeight = maxHeight;
    }
    
    gWindowWidth = windowWidth;
    gWindowHeight = windowHeight;
    
    device.deviceType = kQADeviceGDevice;
    device.device.gDevice = deepestGDevice;
 
    /*
     * Choose a drawing engine for the left window, and create the window.
     */
    
    gEngine[0] = ChooseEngine (&device, 0, engineName);
    
    windowRect.top = (deviceRect.top + deviceRect.bottom) / 2 - windowHeight / 2;
    windowRect.bottom = windowRect.top + windowHeight;
 
    windowRect.left = (deviceRect.left * 3 + deviceRect.right) / 4 - windowWidth / 2;
    windowRect.right = windowRect.left + windowWidth;
 
    gTinselWindow[0] = NewCWindow (nil, &windowRect, (void *) engineName, true, zoomDocProc, nil, true, 0);
    
    /*
     * Choose a drawing engine for the right window, and create the window.
     */
    
    gEngine[1] = ChooseEngine (&device, 1, engineName);
    
    windowRect.left = (deviceRect.left + deviceRect.right * 3) / 4 - windowWidth / 2;
    windowRect.right = windowRect.left + windowWidth;
 
    gTinselWindow[1] = NewCWindow (nil, &windowRect, (void *) engineName, true, zoomDocProc, nil, true, 0);
 
    /*
     * If both window creations were successful, return true.
     */
    
    return (gTinselWindow[0] && gTinselWindow[1]);
}
 
/*******************************************************************************************
 *
 * Create test windows on the deepest GDevice.
 *
 ******************************************************************************************/
 
void ClearWindows (void)
{
    long            i;
    WindowPtr       window;
    
    for (i = 0; i < kTinselWindows; ++i)
    {
        GrafPtr     previousPort;
        
        window = gTinselWindow [i];
        
        GetPort (&previousPort);
        SetPort (window);
        EraseRect (&window->portRect);
        SetPort (previousPort);
    }
}
 
/*******************************************************************************************
 *
 * Create test clip region (a round rect) for each test window.
 *
 ******************************************************************************************/
 
Boolean CreateWindowClip (void)
{
    long            i;
    Point           topLeft, botRight;
    WindowPtr       window;
    Rect            windowRect, clipRect;
    
    for (i = 0; i < kTinselWindows; ++i)
    {
        GrafPtr     previousPort;
 
        window = gTinselWindow [i];
        
        /*
         * Get the boundaries of the target window, and compute its size.
         */
        
        topLeft.v = window->portRect.top;
        topLeft.h = window->portRect.left;
        botRight.v = window->portRect.bottom;
        botRight.h = window->portRect.right;
    
        /*
         * Convert window boundaries to global co-ordinates.
         */
        
        GetPort (&previousPort);
        SetPort (window);
        LocalToGlobal (&topLeft);
        LocalToGlobal (&botRight);
        SetPort (previousPort);
    
        /*
         * Create the window bound rectangle in device coordinates.
         */
        
        windowRect.top = topLeft.v - (*gGDevice)->gdRect.top;
        windowRect.left = topLeft.h - (*gGDevice)->gdRect.left;
        windowRect.bottom = botRight.v - (*gGDevice)->gdRect.top;
        windowRect.right = botRight.h - (*gGDevice)->gdRect.left;
        
        /*
         * Build the clip region for this window.
         */
        
        if ( ! (gClipRgn[i] = NewRgn()))
        {
            return (false);
        }
        
        OpenRgn();
        
        clipRect.top = windowRect.top + kWindowClipBoundary;
        clipRect.left = windowRect.left + kWindowClipBoundary;
        clipRect.bottom = windowRect.bottom - kWindowClipBoundary;
        clipRect.right = windowRect.right - kWindowClipBoundary;
        
        FrameRoundRect (&clipRect, kClipRoundRect, kClipRoundRect);
        CloseRgn (gClipRgn[i]);
    }
    
    return (true);
}
 
/*******************************************************************************************
 *
 * Create draw contexts for the test windows.
 *
 ******************************************************************************************/
 
Boolean TestDrawContextNew (
    unsigned long   flags,
    Boolean         do2DClipping)
{
    WindowPtr           window;
    Point               topLeft, botRight;
    TQARect             windowRect;
    long                i;
    TQADevice           device;
    TQAError            status;
    
    for (i = 0; i < kTinselWindows; ++i)
    {
        if (gEngine [i])
        {
            TQAClip     clip;
            
            window = gTinselWindow [i];
            
            /*
             * Get the boundaries of the target window, and compute its size.
             */
            
            topLeft.v = window->portRect.top;
            topLeft.h = window->portRect.left;
            botRight.v = window->portRect.bottom;
            botRight.h = window->portRect.right;
        
            /*
             * Convert window boundaries to global co-ordinates.
             */
            
            SetPort (window);
            LocalToGlobal (&topLeft);
            LocalToGlobal (&botRight);
        
            /*
             * Create the bound rectangle in device coordinates.
             */
            
            windowRect.top = topLeft.v - (*gGDevice)->gdRect.top;
            windowRect.left = topLeft.h - (*gGDevice)->gdRect.left;
            windowRect.bottom = botRight.v - (*gGDevice)->gdRect.top;
            windowRect.right = botRight.h - (*gGDevice)->gdRect.left;
        
            /*
             * Create the draw context.
             */
            
            device.deviceType = kQADeviceGDevice;
            device.device.gDevice = gGDevice;
    
            clip.clipType = kQAClipRgn;
            clip.clip.clipRgn = gClipRgn[i];
            
            status = QADrawContextNew (&device, &windowRect,
                    do2DClipping ? &clip : NULL, gEngine [i], flags, &gDrawContext [i]);
            
            if (status != kQANoErr)
            {
                TinselError ("Could not create draw context");
                return (false);
            }
        }
        else
        {
            /*
             * No drawing engine attached to this window.
             */
            
            gDrawContext [i] = NULL;
        }
    }
    return (true);
}
 
void TestDrawContextDelete (void)
{
    long        i;
    
    for (i = 0; i < kTinselWindows; ++i)
    {
        if (gDrawContext [i])
        {
            QADrawContextDelete (gDrawContext [i]);
            gDrawContext [i] = NULL;
        }
    }
}