
// ---------------------------------------------------------------------
//
// ViewMain.c - Picture Viewer - QuickTime for Windows
//
//              Version 1.0
//
//              (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
//
// ---------------------------------------------------------------------


// Includes
// --------
#include <Windows.h> // Required by Windows

#include <qtw.h>   // Interface to QuickTime
#include <qtole.h> // Interface to qtole dll

#include "common.h" // Interface to common.c routines

#include "viewer.h"  // Interface to other *.c files
#include "viewer.hr" // Defines used in *.rc files
#include "picture.h" // Needed for registering
                     // child window controls


// Message-Persistent Data
// -----------------------
static struct // Hungarian notation: g
  {HINSTANCE     hInstance;          // Instance handle
   HINSTANCE     hResources;         // Resource-only DLL handle
   HWND          hwndFrame;          // Frame window handle
   HWND          hwndClient;         // MDI client window
   HMENU         hMenu;              // Frame window menu
   HACCEL        hAccel;             // Frame window accelerators
   HWND          hActiveModelessDlg; // Handle of active modeless dlg if any
   BOOL          fPalettized;        // Palettized device
   QTOLE_OLEDATA qtoleOleData;       // OLE data struct
  } g;


// Internal Function Declarations
// ------------------------------
static LPSTR NEAR ViewerParseCmdLine    (LPSTR);
static  BOOL NEAR ViewerInitAppl        (VOID);
static  HWND NEAR ViewerInitInst        (HINSTANCE, LPSTR, int);
static  LONG NEAR ViewerTerminateInst   (VOID);
static  BOOL NEAR DoQuickTimeInit       (HINSTANCE, LPSTR, LPINT);
static  VOID NEAR KillQuickTime         (VOID);

// Function: WinMain - Required Windows "Main" Routine
// --------------------------------------------------------------------
// Parameters: As required by Microsoft Windows
//
// Returns:    As required by Microsoft Windows
// --------------------------------------------------------------------
int PASCAL WinMain( HINSTANCE hInstance,
                 HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

// Define function data

{
    MSG  msg; // Message

    g.hInstance = hInstance; // Initialize global data

    // Load resource-only DLL
    if( !(g.hResources = CommonGetLocalizedResources
        ( VIEWER_ROOT_NAME, hInstance, VIEWER_STRING_NOMEMORY )))
        return 0;

    // Perform one-time initialization

    if( !hPrevInstance && !ViewerInitAppl() )
        return 0;

    // Perform initializations that apply to a specific instance and
    // create window
    if( !ViewerInitInst( hPrevInstance, lpCmdLine, nCmdShow ))
        return 0;


    // main message loop
    while( GetMessage( &msg, NULL, NULL, NULL )) {
        if( !g.hActiveModelessDlg ||
            !IsDialogMessage( g.hActiveModelessDlg, &msg )) {
            if( !g.hwndClient ||
                !TranslateMDISysAccel( g.hwndClient, &msg )) {
                if( !g.hwndFrame ||
                    !TranslateAccelerator( g.hwndFrame, g.hAccel, &msg )) {
                    TranslateMessage(&msg);
                    DispatchMessage (&msg);
                }
            }
        }
    }

    // Cleanup Picture Viewer

    ViewerTerminateInst();

    return msg.wParam;
}


// Function: ViewerInitAppl - Perform One-time Initialization
// --------------------------------------------------------------------
// Parameters: None
//
// Returns:    TRUE if OK, else FALSE
// --------------------------------------------------------------------
static BOOL NEAR ViewerInitAppl( VOID )

{
    WNDCLASS wc; // Window class information

    // Register the frame (main) window class

    wc.style         = 0;
    wc.lpfnWndProc   = ViewerFrameWndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = g.hInstance;
    wc.hIcon         = LoadIcon( g.hResources,
        MAKEINTRESOURCE( VIEWER_VIEWER_ICON ));
    wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground = (HBRUSH) ( COLOR_APPWORKSPACE + 1 );
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = VIEWER_FRAME_CLASS;

    if( !RegisterClass( &wc ))
        return FALSE;

    // Register the picture window class

    wc.style         = 0;
    wc.lpfnWndProc   = ViewerPictureWndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = sizeof( VOID NEAR * );
    wc.hInstance     = g.hInstance;
    wc.hIcon         = NULL;
    wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground = PICBACKGRNDBRUSH;
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = VIEWER_PICTURE_CLASS;

    if( !RegisterClass( &wc ))
        return FALSE;

    // Register the child classes used by the picture windows
    // This function is in PictKids.c

    if( !RegisterChildControls( g.hInstance ))
        return FALSE;

    return TRUE;
}


// Function: ViewerInitInst - Perform Instance Initialization
// --------------------------------------------------------------------
// Parameters: HINSTANCE hPrevInstance;  Previous instance
//             LPSTR     lpCmdLine;      -->Command line arguments
//             int       nCmdShow;       Parameter for first ShowWindow()
//
// Returns:    HWND      hwndFrame;      Frame window handle
//                                       or NULL if initialization failed
// --------------------------------------------------------------------
static HWND NEAR ViewerInitInst
              ( HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{
    HDC hdcIC;

    // Do QuickTime Initializations.
    if( !DoQuickTimeInit( hPrevInstance, lpCmdLine, &nCmdShow ))
        return NULL;

    // Is this a palettized device?
    if( hdcIC = CreateIC( "DISPLAY", NULL, NULL, NULL )) {
        g.fPalettized = 
            ( GetDeviceCaps( hdcIC, RASTERCAPS ) & RC_PALETTE );
        DeleteDC( hdcIC );
    }

    // get menu and accelerators from localized resource
    g.hAccel = LoadAccelerators( g.hResources,
        MAKEINTRESOURCE( VIEWER_ACCELERATORS ));
    g.hMenu  = LoadMenu( g.hResources,
        MAKEINTRESOURCE( VIEWER_FRAME_MENU ));
    if( !g.hAccel || !g.hMenu ) {
        CommonTellUser( g.hResources, VIEWER_STRING_NOACCELORMENU,
            VIEWER_STRING_CAPTION, MB_OK );
        return NULL;
    }

    // Create a main window for this application instance.
    if( !(g.hwndFrame = CreateWindow( VIEWER_FRAME_CLASS, "",
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, g.hMenu, g.hInstance, NULL ))) {
        CommonTellUser( g.hResources, VIEWER_STRING_NOWINDOW,
            VIEWER_STRING_CAPTION, MB_OK );
        return NULL;
    }

    // Tell qtole.dll the server hwnd
    QTOLE_SetApplicationHwnd( &g.qtoleOleData, g.hwndFrame ); 

    // save MDI client window created during WM_CREATE message processing
    g.hwndClient = ViewerQueryClientWindow(); // this is in FrameWnd.c

    // Display the frame window
    // If ole started the app, the window will be initially hidden
    ShowWindow( g.hwndFrame, nCmdShow );
    if( nCmdShow != SW_HIDE )
        UpdateWindow( g.hwndFrame );

    // Check command line for picture file.
    // Note: this must come after ShowWindow, UpdateWindow
    if( lpCmdLine = ViewerParseCmdLine( lpCmdLine ))
        SendMessage( g.hwndFrame, 
        WM_VIEWER_CMDLINE, 0, (LPARAM) lpCmdLine );

    return g.hwndFrame;
}

// Function: ViewerParseCmdLine - Parse the command line. Return -> to
//                                first argument and ignore any extras.
//                                The default extension is added if there
//                                is no extension
// --------------------------------------------------------------------
// Parameters: LPSTR      lpCmdLine     command line pointer
//
// Returns:    LPSTR      lpCmdLine     command line pointer to first
//                                      argument, else NULL
// --------------------------------------------------------------------
static LPSTR NEAR ViewerParseCmdLine( LPSTR lpCmdLine )

{
    LPSTR  lpTemp;                        //  Temp pointer
    char   szExtension[FILE_EXT_LEN + 1]; // Default file extension
    BOOL   bExtension;                    // Extension flag

    // Command line is already in Ansi char set even if entered from
    // DOS command line

    // remove any leading blanks
    while( *lpCmdLine == ' ' )
        lpCmdLine = AnsiNext( lpCmdLine );

    if( *lpCmdLine == '\0' )
        return NULL;

    // look for blank or end of string
    bExtension = FALSE;
    lpTemp = lpCmdLine;
    while( *lpTemp && (*lpTemp != ' ' )) {
        if( *lpTemp == '.' )
            bExtension = TRUE;
        lpTemp = AnsiNext( lpTemp );
    }

    *lpTemp = '\0';

    if( !bExtension ) {
        LoadString( g.hResources,
            VIEWER_STRING_FILEEXT, szExtension, sizeof( szExtension ));
        lstrcat( lpCmdLine, szExtension );
    }

    return lpCmdLine;
}


// Function: ViewerTerminateInst - Terminate Instance
// --------------------------------------------------------------------
// Parameters: VOID
//
// Returns:    Always 0L
// --------------------------------------------------------------------
static LONG NEAR ViewerTerminateInst( VOID )

{
    // Clean up OLE
    if( g.qtoleOleData.lpqtoleServer )
        QTOLE_OLECleanUp( &g.qtoleOleData );

    // Cut the connections to QuickTime.
    KillQuickTime();

    // Free the resource-only DLL
    if( g.hResources && ( g.hInstance != g.hResources ))
        FreeLibrary( g.hResources );

    return 0L;
}


// The next two functions are used to initialize and kill QuickTime

// Function: DoQuickTimeInit - Establishes connections to QuickTime
// --------------------------------------------------------------------
// Parameters: HINSTANCE  hPrevInstance  Previous instance
//             LPSTR      lpCmdLine      -> command line
//             LPINT      lpnCmdShow     Parameter for first ShowWindow()
//
// Returns:    BOOL       TRUE if OK, else FALSE
// --------------------------------------------------------------------
static BOOL NEAR DoQuickTimeInit
            ( HINSTANCE hPrevInstance, LPSTR lpCmdLine, LPINT lpnCmdShow )

{
    OSErr       oserr;     // Temp return value
    WORD        wIDString; // ID of error message string
    QTOLE_INIT  qtoleInit;
    QTOLE_ERR   qtole_err;
    char        szCaption[30];

    LoadString( g.hResources, VIEWER_STRING_CAPTION,
        szCaption, sizeof( szCaption ));

    // Do OLE initialization before QTInitialize so we
    // don't have to kill qt for install only
    if( !( qtoleInit.fpServerCallBack = 
        (QTOLEPROC) MakeProcInstance
        ( (FARPROC) QTOLEServerCallBack, g.hInstance ))) {
        CommonTellUser( g.hResources, VIEWER_STRING_NOMEMORY,
            VIEWER_STRING_CAPTION, MB_OK );
        return FALSE;
    }
    else {
        qtoleInit.lStructSize           = sizeof( qtoleInit );
        qtoleInit.lVersion              = VERSION_1;
        qtoleInit.hInstance             = g.hInstance;
        qtoleInit.hResources            = g.hResources;
        qtoleInit.lpCmdLine             = lpCmdLine;
        qtoleInit.lpClassName           = VIEWER_FRAME_CLASS;
        qtoleInit.lpServerCaption       = szCaption;
        qtoleInit.lpnCmdShow            = lpnCmdShow;
        qtoleInit.wIDFirstString        = OLE_STRING_FIRST;
        qtoleInit.wIDFirstDlg           = OLE_DLG_FIRST;
        qtoleInit.bMultipleObjectServer = TRUE;

        g.qtoleOleData.lStructSize      = sizeof( g.qtoleOleData );
        g.qtoleOleData.lVersion         = VERSION_1;
        g.qtoleOleData.wObjectType      = PICTURE_OBJECT;

        if( QTOLE_OK != 
            ( qtole_err = QTOLE_Initialize( &g.qtoleOleData, &qtoleInit ))) {
            if( QTOLE_INSTALL_ONLY != qtole_err )
                CommonTellUser( g.hResources, 
                VIEWER_STRING_OLEINITFAILED,
                VIEWER_STRING_CAPTION, MB_OK );
            return FALSE;
        }
    }

    if( ( oserr = QTInitialize( NULL )) != QTI_OK ) {
        switch( oserr ) {
            case QTI_FAIL_NOEXIST:
                wIDString = VIEWER_STRING_QTWNOEXIST;
                break;

            case QTI_FAIL_CORRUPTDLL:
                wIDString = VIEWER_STRING_QTWBADDLL;
                break;

            case QTI_FAIL_286:
                wIDString = VIEWER_STRING_QTW286;
                break;

            case QTI_FAIL_WIN30:
                wIDString = VIEWER_STRING_QTWWIN30;
                break;

            default:
                wIDString = VIEWER_STRING_QTWFAILED;
                break;
        }

        CommonTellUser( g.hResources, wIDString,
            VIEWER_STRING_CAPTION, MB_OK );
        return FALSE;
    }

    // This function call is necessary to make possible the use of
    // the function GetMovieStickyError() that returns the error code
    // for certain QTW functions.
    if( EnterMovies() ) {
        CommonTellUser( g.hResources, VIEWER_STRING_ENTMOVFAILED,
            VIEWER_STRING_CAPTION, MB_OK );
        return FALSE;
    }

    return TRUE;
}


// Function: KillQuickTime - Cuts the connections to QuickTime
// --------------------------------------------------------------------
// Parameters: VOID
//
// Returns:    VOID
// --------------------------------------------------------------------
static VOID NEAR KillQuickTime( VOID )

{
    ExitMovies();
    QTTerminate();

    return;
}


//  This function is called by other modules whenever a modeless dialog
//  is activated or deactivated

// Function: ViewerSetActiveModeless - Set handle of active modeless dlg
// --------------------------------------------------------------------
// Parameters: WPARAM   wParam          WA_ flag defined in Windows.h
//             HWND     hModelessDlg    Handle of dlg being activated or
//                                      deactivated
//
// Returns:    VOID
// --------------------------------------------------------------------
VOID FAR ViewerSetActiveModeless( WPARAM wParam, HWND hModelessDlg )

{
    if( wParam != WA_INACTIVE )
        g.hActiveModelessDlg = hModelessDlg;
    else if( g.hActiveModelessDlg == hModelessDlg )
        g.hActiveModelessDlg = NULL;

    return;
}

// Function: ViewerNoMoreWindow - Sets global handles to NULL. Called during
//                                frame window WM_DESTROY message processing
//                                This is needed for accelerator tests in 
//                                main message loop after window is destroyed
// --------------------------------------------------------------------
// Parameters: VOID
//
// Returns:    VOID
// --------------------------------------------------------------------
VOID FAR ViewerNoMoreWindow( VOID )

{
    g.hwndFrame  = NULL;
    g.hwndClient = NULL;

    return;
}


///  The remaining functions are the query functions called by other modules

// Function: ViewerQueryInstance - Query Instance Handle
// --------------------------------------------------------------------
// Parameters: None.
//
// Returns:    HINSTANCE hInstance;    Application instance handle
// --------------------------------------------------------------------
HINSTANCE FAR ViewerQueryInstance( VOID )

{
    return g.hInstance;
}

// Function: ViewerQueryResources - Query Resource-Only DLL Handle
// --------------------------------------------------------------------
// Parameters: None.
//
// Returns:    HINSTANCE hResources    Resource-only DLL handle
// --------------------------------------------------------------------
HINSTANCE FAR ViewerQueryResources( VOID )

{
    return g.hResources;
}

// Function: ViewerQueryFrameWindow - Query Frame Window Handle
// --------------------------------------------------------------------
// Parameters: None.
//
// Returns:    HWND hwndFrame;          Frame window handle
// --------------------------------------------------------------------
HWND FAR ViewerQueryFrameWindow( VOID )

{
    return g.hwndFrame;
}

// Function: ViewerIsPalettized - Are we running on a palettized device?
// --------------------------------------------------------------------
// Parameters: None.
//
// Returns:    BOOL fPalettized;        TRUE if palettized device
// --------------------------------------------------------------------
BOOL FAR ViewerIsPalettized( VOID )

{
    return g.fPalettized;
}

// Function: ViewerQueryOleData - Query -> to Ole Data struct
// --------------------------------------------------------------------
// Parameters: None.
//
// Returns:    LPQTOLE_OLEDATA        -> ole data struct
// --------------------------------------------------------------------
LPQTOLE_OLEDATA FAR ViewerQueryOleData( VOID )

{
    return &g.qtoleOleData;
}


