// ---------------------------------------------------------------------
//
// MathComp.cpp - Math Components - QuickTime for Windows
//
//                Version 1.0
//
//                (c) 1988-1993 Apple Computer, Inc. All Rights Reserved.
//
// ---------------------------------------------------------------------


// Includes
// --------
#include <windows.h>
#include <windowsx.h>
#include <qtw.h>
#include <compmgr.h>
#include "mathcomp.h"


// No name decoration from C++
// ---------------------------
#ifdef __cplusplus
extern "C" {
#endif


// Function Selectors
// ------------------

// Add Component
#define fsAdd          0

// Sum Component
#define fsSum          0
#define fsSetSum       1
#define fsGetGlobalSum 2
#define fsSetGlobalSum 3


// Definitions
// -----------
#define ADD_VERSION    0x01000000
#define SUM_VERSION    0x01000000


// Typedefs
// --------
typedef struct tagSHARED {
   short sTotal;
} SHARED, FAR *LPSHARED;

typedef struct tagPRIVATE {
   short sTotal;
   LPSHARED lpShared;
} PRIVATE, FAR *LPPRIVATE;



////////////////////////////////////////////////////////////////////////////
// Component Manager Interface Section
//

// Glue code pointers from QTW.LIB
// -------------------------------
extern ENTRYFUNC lpfnQTToolbox;
extern ENTRYFUNC lpfnQTComponentManager;


// Internal Function Declarations
// ------------------------------
VOID FAR PASCAL FixupTB (ENTRYFUNC lpfnTB);
VOID FAR PASCAL FixupCM (ENTRYFUNC lpfnCM);

// Prototypes of ASM entry point functions
// ---------------------------------------
DWORD FAR CDECL AddEntryPoint (VOID);
DWORD FAR CDECL SumEntryPoint (VOID);


// Data structure defining components in this DLL
// ----------------------------------------------
ComponentDescription cdTable [2] =   // Number of components
{
{
   QTFOURCC ('a','d','d','2'),       // ostypeComponentType
   QTFOURCC ('s','h','r','t'),       // ostypeComponentSubType
   QTFOURCC ('a','p','p','l'),       // ostypeComponentManufacturer
   0,                                // dwComponentFlags
   0,                                // dwComponentFlagsMask
   (ComponentRoutine) AddEntryPoint, // crEntryPoint
   0,                                // hrsrcName
   0,                                // hrsrcInfo
   0                                 // hrsrcIcon
},
{
   QTFOURCC ('s','u','m',' '),       // ostypeComponentType
   QTFOURCC ('s','h','r','t'),       // ostypeComponentSubType
   QTFOURCC ('a','p','p','l'),       // ostypeComponentManufacturer
   0,                                // dwComponentFlags
   0,                                // dwComponentFlagsMask
   (ComponentRoutine) SumEntryPoint, // crEntryPoint
   0,                                // hrsrcName
   0,                                // hrsrcInfo
   0                                 // hrsrcIcon
}
};


// Function: THNGIDENTIFY - Required routine for components
// --------------------------------------------------------------------
// Parameters: LPCID FAR *lplpcid         pointer to LPCID
//
// Returns:    'thng' constant
// --------------------------------------------------------------------
OSType FAR PASCAL THNGIDENTIFY (LPCID FAR *lplpcid) {

    HGLOBAL hmem;
    LPCID   lpcid;

    // Allocate memory to store CID info (will be freed by Component Manager)
    if ((hmem = GlobalAlloc (GHND, sizeof CID)) == NULL)
        return 0;
    if ((lpcid = (LPCID) GlobalLock (hmem)) == NULL) {
        GlobalFree (hmem);
        return 0;
    }

    // Fill table
    lpcid->lVersion = CID_VERSION;      // Version of CompMgr interface
    lpcid->sComponentCount = 2;         // Number of components this DLL
    lpcid->lpcdTable = (LPCD) &cdTable; // Component Table
    lpcid->lpfnTBFixup = FixupTB;       // Quick fixup routine for Toolbox
    lpcid->lpfnCMFixup = FixupCM;       // Quick fixup routine for CompMgr
    *lplpcid = lpcid;                   // Store the pointer

    return THING;                       // 'thng' identifies component
}


// Function: FixupTB - Set glue ToolBox pointer to given value
// --------------------------------------------------------------------
// Parameters: ENTRYFUNC lpfnTB           pointer to ToolBox entry point
//
// Returns:    VOID
// --------------------------------------------------------------------
VOID FAR PASCAL FixupTB (ENTRYFUNC lpfnTB) {

    lpfnQTToolbox = lpfnTB;

    return;
}


// Function: FixupCM - Set glue Component Manager pointer to given value
// --------------------------------------------------------------------
// Parameters: ENTRYFUNC lpfnCM           pointer to CompMgr entry point
//
// Returns:    VOID
// --------------------------------------------------------------------
VOID FAR PASCAL FixupCM (ENTRYFUNC lpfnCM) {

    lpfnQTComponentManager = lpfnCM;

    return;
}


////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//  COMPONENT:   add2  shrt  -  Add two 16-bit (short) values
//

// Function: cfAddOpenSelect - Open an add component instance
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             ComponentInstance ci;      component instance handle
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfAddOpenSelect (STKOFF_CMP so, ComponentInstance ci) {

    return noErr;
}


// Function: cfAddCloseSelect - Close an open component instance
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             ComponentInstance ci;      component instance handle
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfAddCloseSelect (STKOFF_CMP so, ComponentInstance ci) {

    return noErr;
}


// Function: cfAddCanDoSelect - Report if function is implemented
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             LONG lFunctionSelector;    function selector
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfAddCanDoSelect (STKOFF_CMP so, LONG lFunctionSelector) {

    switch (lFunctionSelector) {
        case kComponentOpenSelect:
        case kComponentCloseSelect:
        case kComponentCanDoSelect:
        case kComponentVersionSelect:
        case kComponentRegisterSelect:
        case kComponentTargetSelect:
        case fsAdd:
            return TRUE;
        default:
            return FALSE;
    }
}


// Function: cfAddVersionSelect - Report component version
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             ComponentInstance ci;      component instance handle
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfAddVersionSelect (STKOFF_CMP so, ComponentInstance ci) {

    return ADD_VERSION;
}


// Function: cfAddRegisterSelect - Report if able to register
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             ComponentInstance ci;      component instance handle
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfAddRegisterSelect (STKOFF_CMP so, ComponentInstance ci) {

    return 0;
}


// Function: cfAddTargetSelect - Not implemented
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             ComponentInstance ci;      component instance handle
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfAddTargetSelect (STKOFF_CMP so, ComponentInstance ci) {

    return 0;
}


////////////////////////////////////////////////////////////////////////////
// Add2 Functions
//

// Function: cfAdd2 - Add two short values
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             LPVOID lpvStorage;         pointer to instance storage
//             short sOne;                first value to add
//             short wTwo;                second value to add
//
// Returns:    short                      sum of two given values
// --------------------------------------------------------------------
short QTAPI cfAdd2 (STKOFF_CMP so, LPVOID lpvStorage, short sOne, short sTwo) {

    return sOne + sTwo;
}



////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//  COMPONENT:   sum   shrt  -  Sum 16-bit (short) values
//

// Function: cfSumOpenSelect - Open a sum component instance
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             ComponentInstance ci;      component instance handle
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfSumOpenSelect (STKOFF_CMP so, ComponentInstance ci) {

    // Allocate private storage for this instance
    LPPRIVATE lpPrivate;
    if ((lpPrivate = (LPPRIVATE) GlobalAllocPtr (GHND, sizeof LPPRIVATE)) == NULL )
        return insufficientMemory;

    // Inform Component Manager of allocated storage for this instance
    SetComponentInstanceStorage (ci, (LPVOID) lpPrivate);

    // If this is the first instance allocate shared memory
    LPSHARED lpShared;
    if ((lpShared = (LPSHARED) GetComponentRefcon ((Component) ci)) == NULL) {
        if ((lpShared = (LPSHARED) GlobalAllocPtr (GHND, sizeof LPSHARED)) == NULL) {
            GlobalFreePtr (lpPrivate);
            return insufficientMemory;
        }
        SetComponentRefcon ((Component) ci, (LONG) lpShared);
    }

    // Provide quick access to the shared memory
    lpPrivate->lpShared = lpShared;

    return noErr;
}


// Function: cfSumCloseSelect - Close an open component instance
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             ComponentInstance ci;      component instance handle
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfSumCloseSelect (STKOFF_CMP so, ComponentInstance ci) {

    // Get the private memory pointer
    LPPRIVATE lpPrivate;
    lpPrivate = (LPPRIVATE) GetComponentInstanceStorage (ci);

    // Free shared memory if closing last instance
    if (CountComponentInstances ((Component) ci) == 1) {
        if (lpPrivate)
            GlobalFreePtr (lpPrivate->lpShared);

        // Prepare for next re-open
        SetComponentRefcon ((Component) ci, 0);
    }

    // Free private instance memory
    GlobalFreePtr (lpPrivate);

    return noErr;
}


// Function: cfSumCanDoSelect - Report if function is implemented
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             LONG lFunctionSelector;    function selector
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfSumCanDoSelect (STKOFF_CMP so, LONG lFunctionSelector) {

    switch (lFunctionSelector) {
        case kComponentOpenSelect:
        case kComponentCloseSelect:
        case kComponentCanDoSelect:
        case kComponentVersionSelect:
        case kComponentRegisterSelect:
        case kComponentTargetSelect:
        case fsSum:
        case fsSetSum:
        case fsGetGlobalSum:
        case fsSetGlobalSum:
            return TRUE;
        default:
            return FALSE;
    }
}


// Function: cfSumVersionSelect - Report component version
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             ComponentInstance ci;      component instance handle
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfSumVersionSelect (STKOFF_CMP so, ComponentInstance ci) {

    return SUM_VERSION;
}


// Function: cfSumRegisterSelect - Report if able to register
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             ComponentInstance ci;      component instance handle
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfSumRegisterSelect (STKOFF_CMP so, ComponentInstance ci) {

    return 0;
}


// Function: cfSumTargetSelect - Not implemented
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             ComponentInstance ci;      component instance handle
//
// Returns:    ComponentResult
// --------------------------------------------------------------------
ComponentResult QTAPI cfSumTargetSelect (STKOFF_CMP so, ComponentInstance ci) {

    return 0;
}


////////////////////////////////////////////////////////////////////////////
// Sum Functions
//

// Function: cfSum - Add given value to running total
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             LPVOID lpvStorage;         pointer to instance storage
//             short sOne;                first short to add
//             short wTwo;                second short to add
//
// Returns:    short                      instance total
// --------------------------------------------------------------------
short QTAPI cfSum (STKOFF_CMP so, LPVOID lpvStorage, short sValue) {

    LPPRIVATE lpPrivate = (LPPRIVATE) lpvStorage;

    // Add the given value into instance total
    lpPrivate->sTotal += sValue;

    // Add the given value into global total
    lpPrivate->lpShared->sTotal += sValue;

    // Return the instance total
    return lpPrivate->sTotal;
}


// Function: cfSetSum - Set instance total to given value
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             LPVOID lpvStorage;         pointer to instance storage
//             short sValue;              value to set
//
// Returns:    short                      instance total after set
// --------------------------------------------------------------------
short QTAPI cfSetSum (STKOFF_CMP so, LPVOID lpvStorage, short sValue) {

    LPPRIVATE lpPrivate = (LPPRIVATE) lpvStorage;

    // Set the given value into instance total
    lpPrivate->sTotal = sValue;

    // Return the instance total
    return lpPrivate->sTotal;
}


// Function: cfSetGlobalSum - Set global total to given value
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             LPVOID lpvStorage;         pointer to instance storage
//             short sValue;              value to set
//
// Returns:    short                      global total after set
// --------------------------------------------------------------------
short QTAPI cfSetGlobalSum (STKOFF_CMP so, LPVOID lpvStorage, short sValue) {

    LPPRIVATE lpPrivate = (LPPRIVATE) lpvStorage;

    // Set the given value into global total
    lpPrivate->lpShared->sTotal = sValue;

    // Return the global total
    return lpPrivate->lpShared->sTotal;
}


// Function: cfGetGlobalSum - Return the global total
// --------------------------------------------------------------------
// Parameters: STKOFF_CMP so;             component stack offset to parms
//             LPVOID lpvStorage;         pointer to instance storage
//
// Returns:    short                      global total
// --------------------------------------------------------------------
short QTAPI cfGetGlobalSum (STKOFF_CMP so, LPVOID lpvStorage) {

    LPPRIVATE lpPrivate = (LPPRIVATE) lpvStorage;

    // Return the global total
    return lpPrivate->lpShared->sTotal;
}


#ifdef __cplusplus
  } // extern "C"
#endif



////////////////////////////////////////////////////////////////////////////
// Standard Windows DLL interface functions
//

// Function: LibMain - DLL initialization routine called by Windows
// --------------------------------------------------------------------
// Parameters: HANDLE hInstance;          DLL instance handle
//             WORD   wDataSegment;       Value of DS register
//             WORD   wHeapSize;          Heap size
//             LPSTR  lpszCmdLine;        Command line info
//
// Returns:    TRUE if initialization successful; FALSE otherwise
// --------------------------------------------------------------------
int FAR PASCAL LibMain (HINSTANCE hInstance, WORD wDataSegment,
                        WORD wHeapSize, LPSTR lpszCmdLine) {

    // Unlock the current movable data segment
    if (wHeapSize > 0)
        UnlockData (0);

    // Return to Windows
    return TRUE;
}


// Function: WEP - Windows exit procedure
// --------------------------------------------------------------------
// Parameters: int nExitType              Exit type
//
// Returns:    Always 1
// --------------------------------------------------------------------
extern "C" BOOL FAR PASCAL WEP (int nValue);
#pragma alloc_text(WEP_TEXT,WEP)
extern "C" BOOL FAR PASCAL WEP (int nValue) {

    return TRUE;
}

