ThreeDMetafile.c

/*
    File:       ThreeDMetafile.c
 
    Contains:   3D viewer support for SimpleText
 
    Version:    SimpleText 1.4 or later
 
** Copyright 1994-1996 Apple Computer. 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 "MacIncludes.h"
#include <String.h>
#include "ThreeDMetafile.h"
 
 
static GlobalEntry  gProcPointers[] =
    {
    {uppViewerLibNewProcInfo, nil},
    {uppViewerLibDisposeProcInfo, nil},
 
    {uppViewerLibUseFileProcInfo, nil},
    {uppViewerLibUseDataProcInfo, nil},
    
    {uppViewerLibWriteFileProcInfo, nil},
    {uppViewerLibWriteDataProcInfo, nil},
    
    {uppViewerLibDrawProcInfo, nil},
 
    {uppViewerLibGetPictProcInfo, nil},
    {uppViewerLibGetButtonRectProcInfo, nil},
 
    {uppViewerLibGetDimensionProcInfo, nil},
 
    {uppViewerLibSetFlagsProcInfo, nil},
    {uppViewerLibGetFlagsProcInfo, nil},
 
    {uppViewerLibSetBoundsProcInfo, nil},
    {uppViewerLibGetBoundsProcInfo, nil},
 
    {uppViewerLibSetPortProcInfo, nil},
    {uppViewerLibGetPortProcInfo, nil},
 
    {uppViewerLibEventProcInfo, nil},
    {uppViewerLibAdjustCursorProcInfo, nil},
 
    {uppViewerLibGetStateProcInfo, nil},
 
    {uppViewerLibClearProcInfo, nil},
    {uppViewerLibCutProcInfo, nil},
    {uppViewerLibCopyProcInfo, nil},
    {uppViewerLibPasteProcInfo, nil}
    };  
    
 
// --------------------------------------------------------------------------------------------------------------
// PRIVATE ROUTINES
// --------------------------------------------------------------------------------------------------------------
/* rather than include the whole StdCLib, I'll just define it here */
static int strcmp(const char * str1, const char * str2)
{
    const   unsigned char* p1 = (unsigned char *) str1;
    const   unsigned char* p2 = (unsigned char *) str2;
    unsigned char       c1, c2;
    
    while ((c1 = *p1++) == (c2 = *p2++))
        if (!c1)
            return(0);
 
    return(c1 - c2);
}
 
static UniversalProcPtr MakeARoutineDescriptor(void *theProc, ProcInfoType theProcInfo)
/*
    The Symantec compiler doesn't like jumping into staticly done routine descriptors,
    so we have to actually allocate them as pointers.  Sigh.
*/
{
    RoutineDescriptor rd = BUILD_ROUTINE_DESCRIPTOR(0, nil);
    
    Ptr newPtr;
    
    rd.routineRecords[0].procInfo = theProcInfo;
    rd.routineRecords[0].procDescriptor = theProc;
    rd.routineRecords[0].ISA = kPowerPCISA + kPowerPCRTA;
    newPtr = NewPtrClear(sizeof(rd));
    if (newPtr)
        BlockMove(&rd, newPtr, sizeof(rd));
    return((UniversalProcPtr) newPtr);
    
} // MakeARoutineDescriptor
 
// --------------------------------------------------------------------------------------------------------------
static void FillInEntryPoints(void)
{
    long                result;
    
    if ( 
        (Gestalt('qd3d', &result) == noErr) && 
        (Gestalt('sysa', &result) == noErr) && (result == 2) 
        )
        {
        CFragSymbolClass    symClass;
        CFragConnectionID   connID;
        Ptr                 mainAddr;
        Str255              errName;
        long                procID = 0;
        
        if (GetSharedLibrary("\pQD3DViewerLib", 'pwpc', 1, &connID, &mainAddr, errName) == noErr)
            {
            FindSymbol(connID, "\pQ3ViewerNew", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerDispose", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            
            FindSymbol(connID, "\pQ3ViewerUseFile", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerUseData", (Ptr*)&gProcPointers[procID++].entry, &symClass);
 
            FindSymbol(connID, "\pQ3ViewerWriteFile", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerWriteData", (Ptr*)&gProcPointers[procID++].entry, &symClass);
 
            FindSymbol(connID, "\pQ3ViewerDraw", (Ptr*)&gProcPointers[procID++].entry, &symClass);
 
            FindSymbol(connID, "\pQ3ViewerGetPict", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerGetButtonRect", (Ptr*)&gProcPointers[procID++].entry, &symClass);
 
            FindSymbol(connID, "\pQ3ViewerGetDimension", (Ptr*)&gProcPointers[procID++].entry, &symClass);
 
            FindSymbol(connID, "\pQ3ViewerSetFlags", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerGetFlags", (Ptr*)&gProcPointers[procID++].entry, &symClass);
 
            FindSymbol(connID, "\pQ3ViewerSetBounds", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerGetBounds", (Ptr*)&gProcPointers[procID++].entry, &symClass);
 
            FindSymbol(connID, "\pQ3ViewerSetPort", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerGetPort", (Ptr*)&gProcPointers[procID++].entry, &symClass);
 
            FindSymbol(connID, "\pQ3ViewerEvent", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerAdjustCursor", (Ptr*)&gProcPointers[procID++].entry, &symClass);
 
            FindSymbol(connID, "\pQ3ViewerGetState", (Ptr*)&gProcPointers[procID++].entry, &symClass);
 
            FindSymbol(connID, "\pQ3ViewerClear", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerCut", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerCopy", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            FindSymbol(connID, "\pQ3ViewerPaste", (Ptr*)&gProcPointers[procID++].entry, &symClass);
            }
        
        // build the routine descriptors
        {
        short   i;
        
        for (i = 0; i < procID; ++i)
            gProcPointers[i].entry = MakeARoutineDescriptor(gProcPointers[i].entry, gProcPointers[i].info);
        }
        
        // as long as it isn't NIL, we're OK
        if (gProcPointers[0].entry)
            gMachineInfo.haveThreeD = true;
        }
 
} // FillInEntryPoints
 
// --------------------------------------------------------------------------------------------------------------
// OOP INTERFACE ROUTINES
// --------------------------------------------------------------------------------------------------------------
 
static OSErr ThreeDCloseWindow(
            WindowRef pWindow, 
            WindowDataPtr pData)
{
#pragma unused (pWindow)
 
 
    ViewerLib_Dispose( ((ThreeDDataPtr)pData)->viewerObject);
 
    return(noErr);
    
} // ThreeDCloseWindow
 
// --------------------------------------------------------------------------------------------------------------
static OSErr ThreeDGetBalloon(
            WindowRef pWindow, 
            WindowDataPtr pData, 
            Point *localMouse,
            short * returnedBalloonIndex, 
            Rect *returnedRectangle)
{
#pragma unused (pWindow, pData, localMouse, returnedBalloonIndex, returnedRectangle)
 
    *returnedBalloonIndex = iDidTheBalloon;
    
    return(noErr);
    
} // ThreeDGetBalloon
 
// --------------------------------------------------------------------------------------------------------------
static Boolean  ThreeDFilterEvent(
            WindowRef pWindow, 
            WindowDataPtr pData, 
            EventRecord *pEvent)
{
#pragma unused (pWindow)
    
    if (pEvent->what == activateEvt)
        {
        if (pEvent->modifiers & activeFlag)
            ViewerLib_SetFlags(((ThreeDDataPtr)pData)->viewerObject, ViewerLib_GetFlags(((ThreeDDataPtr)pData)->viewerObject) | kQ3ViewerActive);
        else
            ViewerLib_SetFlags(((ThreeDDataPtr)pData)->viewerObject, ViewerLib_GetFlags(((ThreeDDataPtr)pData)->viewerObject) & ~kQ3ViewerActive);
        }
        
    return((Boolean)ViewerLib_Event (((ThreeDDataPtr)pData)->viewerObject, pEvent));
    
} // ThreeDFilterEvent
 
 
// --------------------------------------------------------------------------------------------------------------
static OSErr ThreeDAdjustCursor(WindowRef pWindow, WindowDataPtr pData, Point *localMouse, Rect *globalRect)
{
#pragma unused (pWindow, globalRect)
 
    OSErr anErr = noErr;
 
    ViewerLib_AdjustCursor(((ThreeDDataPtr)pData)->viewerObject, localMouse);
    
    return(eActionAlreadyHandled);
    
} // ThreeDAdjustCursor
 
// --------------------------------------------------------------------------------------------------------------
static OSErr ThreeDGetCoachRectangle(WindowRef pWindow, WindowDataPtr pData, Rect *pRect, Ptr name)
{
#pragma unused (pWindow)
 
    OSErr anErr = fnfErr;
    
    if (strcmp(name, "Camera") == 0)
        anErr = ViewerLib_GetButtonRect(((ThreeDDataPtr)pData)->viewerObject, kQ3ViewerButtonCamera, pRect);
    if (strcmp(name, "Truck") == 0)
        anErr = ViewerLib_GetButtonRect(((ThreeDDataPtr)pData)->viewerObject, kQ3ViewerButtonTruck, pRect);
    if (strcmp(name, "Orbit") == 0)
        anErr = ViewerLib_GetButtonRect(((ThreeDDataPtr)pData)->viewerObject, kQ3ViewerButtonOrbit, pRect);
    if (strcmp(name, "Zoom") == 0)
        anErr = ViewerLib_GetButtonRect(((ThreeDDataPtr)pData)->viewerObject, kQ3ViewerButtonZoom, pRect);
    if (strcmp(name, "Dolly") == 0)
        anErr = ViewerLib_GetButtonRect(((ThreeDDataPtr)pData)->viewerObject, kQ3ViewerButtonDolly, pRect);
            
    return(anErr);
    
} // ThreeDGetCoachRectangle
 
// --------------------------------------------------------------------------------------------------------------
void ThreeDGetFileTypes(
        OSType * pFileTypes,
        OSType * pDocumentTypes,
        short * numTypes)
{
    if (!gMachineInfo.haveThreeD)
        FillInEntryPoints();
        
    if (gMachineInfo.haveThreeD)
        {
        pFileTypes[*numTypes]       = '3DMF';
        pDocumentTypes[*numTypes]   = kThreeDWindow;
        (*numTypes)++;
        }
    
} // ThreeDGetFileTypes
 
// --------------------------------------------------------------------------------------------------------------
static OSErr    ThreeDUpdateWindow(WindowRef pWindow, WindowDataPtr pData)
{
#pragma unused (pWindow)
 
    
    ViewerLib_Draw(((ThreeDDataPtr)pData)->viewerObject);
    
    return(noErr);
    
} // ThreeDUpdateWindow
 
// --------------------------------------------------------------------------------------------------------------
static OSErr    ThreeDAdjustMenus(WindowRef pWindow, WindowDataPtr pData)
{
#pragma unused (pWindow)
 
    OSErr anErr = noErr;
    
    if (ViewerLib_GetState(((ThreeDDataPtr)pData)->viewerObject) ) 
        EnableCommand(cCopy);
 
    return(anErr);
    
} // ThreeDAdjustMenus
 
// --------------------------------------------------------------------------------------------------------------
static OSErr    ThreeDCommand(WindowRef pWindow, WindowDataPtr pData, short commandID, long menuResult)
{
#pragma unused (menuResult)
 
    OSErr                       anErr = noErr;
    ViewerObject                theViewer = ((ThreeDDataPtr)pData)->viewerObject;
    
    SetPort((GrafPtr) GetWindowPort(pWindow));
        
    switch (commandID) 
        {
        case cCopy:
            anErr = ViewerLib_Copy(theViewer);
            if (anErr == noErr)
                anErr = eActionAlreadyHandled;
            break;
        } // switch (commandID)
        
    return(anErr);
    
} // ThreeDCommand
 
// --------------------------------------------------------------------------------------------------------------
static OSErr    ThreeDMakeWindow(
            WindowRef pWindow,
            WindowDataPtr pData)
{
    OSErr                       anErr = noErr;
    ViewerObject                viewerObj;
 
    pData->pCloseWindow         = (CloseWindowProc)         ThreeDCloseWindow;
    pData->pFilterEvent         = (FilterEventProc)         ThreeDFilterEvent;
    pData->pGetBalloon          = (GetBalloonProc)          ThreeDGetBalloon;
    pData->pUpdateWindow        = (UpdateWindowProc)        ThreeDUpdateWindow;
    pData->pAdjustMenus         = (AdjustMenusProc)         ThreeDAdjustMenus;
    pData->pCommand             = (CommandProc)             ThreeDCommand;
    pData->pAdjustCursor        = (AdjustCursorProc)        ThreeDAdjustCursor;
    pData->pGetCoachRectangle   = (GetCoachRectangleProc)   ThreeDGetCoachRectangle;
 
    pData->dragWindowAligned    = 0;
 
    viewerObj = ViewerLib_New((CGrafPtr )pWindow,  &pData->contentRect,  kQ3ViewerDefault | kQ3ViewerDraggingOff); 
 
    if (viewerObj == 0)
        {
        anErr = memFullErr;
        }
    else
        {
        anErr = ViewerLib_UseFile(viewerObj, pData->dataRefNum);
        if (anErr == noErr)
            ((ThreeDDataPtr)pData)->viewerObject = viewerObj;
        else
            ViewerLib_Dispose(viewerObj);
        
        }
    
    return(anErr);
    
} // ThreeDMakeWindow
 
// --------------------------------------------------------------------------------------------------------------
OSErr   ThreeDPreflightWindow(PreflightPtr pPreflightData)
{   
    pPreflightData->continueWithOpen    = true;
    pPreflightData->makeProcPtr         = ThreeDMakeWindow;
    pPreflightData->resourceID          = kThreeDWindowID;
    pPreflightData->storageSize         = sizeof(ThreeDDataRecord);
 
    return(noErr);
    
} // ThreeDPreflightWindow