
// ---------------------------------------------------------------------
//
// Common.c - Common Routines - QuickTime for Windows
//
//            Version 1.0
//
//            (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
//
// ---------------------------------------------------------------------


// Includes
// --------
#include <Windows.H>  // Required by Windows
#include <WindowsX.H> // Required by Windows

#include <dos.h>    // Standard "C" header
#include <errno.h>  // Standard "C" header
#include <stdarg.h> // Standard "C" header
#include <stdlib.h> // Standard "C" header
#include <stdio.h>  // Standard "C" header

#include "Common.H" // Interface to Common.C


// Globals
// -------
static struct
   {char szOutOfMemory[COMMON_STRING_MAX]; // Out of memory message
    WORD idNoMemMsg;                       // Non memory message id
   } g;


// Region Code Table
// --------------------------------------------------------------------
// Ordinal position represents corresponding Mac region code
// --------------------------------------------------------------------
static char* pszRegion[] = {
   "enu", // 0
   "fra", // 1
   "eng", // 2
   "deu", // 3
   "ita", // 4
   "nld", // 5
   "fra", // 6
   "sve", // 7
   "esn", // 8
   "dan", // 9
   "ptg", // 10
   "frc", // 11
   "nor", // 12
   "---", // 13
   "---", // 14
   "eng", // 15
   "---", // 16
   "fin", // 17
   "fra", // 18
   "deu", // 19
   "---", // 20
   "isl", // 21
   ""     // Last entry must be NULL
  };


// Function: CommonAlloc - Allocate memory
// --------------------------------------------------------------------
// Parameters: LONG lBytes;            /* Number of bytes to allocate */
//
// Returns:    VOID FAR *pvMemory;     /* Memory block */
// --------------------------------------------------------------------
VOID FAR * FAR CommonAlloc (LONG lBytes)

// Perform simple allocation for now

{
    HGLOBAL  hmem; // Memory handle

    if( hmem = GlobalAlloc( GHND, (DWORD) lBytes ))
        return GlobalLock( hmem );
    else
        return NULL;
}


// Function: CommonFormatMessage - Format Message
// --------------------------------------------------------------------
// Parameters: HINSTANCE hResources;   /* Resource-only DLL handle */
//             WORD idMsg;             /* ID of message in resource file */
//             LPSTR lpszMsg;          /* Area in which to build message */
//
// Returns:    LPSTR lpszMsg;
// --------------------------------------------------------------------
LPSTR FAR CommonFormatMessage
    (HINSTANCE hResources, WORD idMsg, LPSTR lpszMsg, ...)

// Define function data

{
    char szFormat[COMMON_STRING_MAX]; // Message format
    va_list pArgs;                    // String substitution arguments

    // Load the message string

    LoadString (hResources, idMsg, szFormat, sizeof (szFormat));

    // Build the message text

    va_start (pArgs, lpszMsg);
    wvsprintf (lpszMsg, szFormat, (LPSTR) pArgs);
    va_end (pArgs);

    // Return to caller

    return lpszMsg;

}


// Function: CommonFree - Free memory allocated by CommonAlloc
// --------------------------------------------------------------------
// Parameters: VOID FAR *pvMemory;     /* Memory to free */
//
// Returns:    None
// --------------------------------------------------------------------
VOID FAR CommonFree (VOID FAR *pvMemory)

// Perform simple free for now

{
    HGLOBAL   hmem; //Memory handle

    if( hmem = (HGLOBAL) LOWORD( GlobalHandle( SELECTOROF( pvMemory )))) {
        GlobalUnlock( hmem );
        GlobalFree( hmem );
    }

    return;
}


// Function: CommonGetDirectoryOfModule - Get Path of Module
// --------------------------------------------------------------------
// Parameters: HINSTANCE hInstance;      /* Application's instance handle */
//             LPSTR lpPath;             /* pointer to path buffer */

// Returns:    LPSTR lpPath;
// --------------------------------------------------------------------
LPSTR FAR CommonGetDirectoryOfModule (HINSTANCE hInstance, LPSTR lpPath)

{
    char  szBuffer[CCHMAXPATH]; // Temporary buffer
    LPSTR lpszTemp;             // Temporary pointer

    // Clear the buffer

    szBuffer[0] = '\0';

    // Get the fully qualified .EXE name

    if (!GetModuleFileName (hInstance, szBuffer, sizeof (szBuffer)))
        return (LPSTR) NULL;

    // Look backwards until we find the last backslash

    lpszTemp = szBuffer + lstrlen(szBuffer);

    while ((lpszTemp > szBuffer) && (*lpszTemp != '\\'))
        lpszTemp = AnsiPrev (szBuffer, lpszTemp);
    if (*lpszTemp != '\\')
        return (LPSTR) NULL;

    // We delete the last backslash; we now have the path specification

    *lpszTemp = '\0';
    lstrcpy (lpPath, AnsiUpper (szBuffer));

    // Return to caller

    return lpPath;

}


// Function: CommonGetLocalizedHelpFile - Get Help File Name
// --------------------------------------------------------------------
// Parameters: LPSTR lpszAppl;           /* Application's root name */
//             LPSTR lpszName;           /* Area in which to build name */
//             HINSTANCE hInstance;      /* Application's instance handle */
//
// Returns:    LPSTR pszName;
// --------------------------------------------------------------------
LPSTR FAR CommonGetLocalizedHelpFile
    (LPSTR lpszAppl, LPSTR lpszName, HINSTANCE hInstance)

// Define function data

{
    char   szBuffer[CCHMAXPATH];  // Temporary buffer
    char   szApplDir[CCHMAXPATH]; // Application's directory
    char   szLanguage[4];         // Language code
    struct _find_t  fileinfo;     // Temp file info

    // Clear the area in which the name will be built

    lpszName[0] = '\0';

    // Get the application's directory

    if (!CommonGetDirectoryOfModule (hInstance, (LPSTR) szApplDir))
        return lpszName;

    // Look for the localized help file in the ..\HELP directory

    GetProfileString( "intl", "sLanguage", "enu", szLanguage, sizeof(szLanguage));
    wsprintf( szBuffer, "%s\\..\\help\\%s%s.hlp",
        (LPSTR) szApplDir, (LPSTR) lpszAppl, (LPSTR) szLanguage );
    if (_dos_findfirst (szBuffer, _A_NORMAL, &fileinfo) == 0) {
        lstrcpy (lpszName, AnsiUpper (szBuffer));
        return lpszName;
    }

    // If it can't be found, look for the localized help
    // file in the application's directory

    wsprintf( szBuffer, "%s\\%s%s.hlp",
        (LPSTR) szApplDir, (LPSTR) lpszAppl, (LPSTR) szLanguage );
    if (_dos_findfirst (szBuffer, _A_NORMAL, &fileinfo) == 0) {
        lstrcpy (lpszName, AnsiUpper (szBuffer));
        return lpszName;
    }

    // If it can't be found, look for the US English help
    // file in the ..\HELP directory

    wsprintf( szBuffer, "%s\\..\\help\\%senu.hlp",
        (LPSTR) szApplDir, (LPSTR) lpszAppl );
    if (_dos_findfirst (szBuffer, _A_NORMAL, &fileinfo) == 0) {
        lstrcpy (lpszName, AnsiUpper (szBuffer));
        return lpszName;
    }

    // If it can't be found, look for the US English help
    // file in the application's directory

    wsprintf( szBuffer, "%s\\%senu.hlp", (LPSTR) szApplDir, (LPSTR) lpszAppl );
    if (_dos_findfirst (szBuffer, _A_NORMAL, &fileinfo) == 0) {
        lstrcpy (lpszName, AnsiUpper (szBuffer));
        return lpszName;
    }

    // Otherwise, return NULL to the caller

    return lpszName;

}


// Function: CommonGetLocalizedResources - Load Resource-Only DLL
// --------------------------------------------------------------------
// Parameters: LPSTR lpszAppl;         Application's root name
//             HINSTANCE hInstance;    Application's instance handle
//             WORD  idNoMemMsg;       id of no memory message
//
// Returns:    HINSTANCE hResource;    handle to resource instance
// --------------------------------------------------------------------
HINSTANCE FAR CommonGetLocalizedResources
    (LPSTR lpszAppl, HINSTANCE hInstance, WORD idNoMemMsg )

// Define function data

{
    char szBuffer[CCHMAXPATH]; // Temporary buffer
    char szLanguage[4];        // Language code
    LPSTR  lpszSave;           // Temporary pointer
    HINSTANCE hResources;      // Resource handle

    // Suppress DLL load warnings

    SetErrorMode (SEM_NOOPENFILEERRORBOX);

    // Get the application path

    if (!CommonGetDirectoryOfModule (hInstance, (LPSTR) szBuffer))
        return NULL;

    // Build the name of the resource-only DLL

    lstrcat (szBuffer, "\\");
    lstrcat (szBuffer, lpszAppl);
    lpszSave = szBuffer + lstrlen(szBuffer);
    GetProfileString ("intl", "sLanguage", "enu", szLanguage, sizeof (szLanguage));
    lstrcat (szBuffer, szLanguage);
    lstrcat (szBuffer, ".dll");
    AnsiUpper (szBuffer);

    // Load the resource-only DLL. If it can't be found, use the US
    // English DLL. If it can't be found, we'll use the original .EXE
    // resources

    if ((hResources = LoadLibrary (szBuffer)) == 0)
        return NULL;
    else if (hResources < (HINSTANCE) 32) {
        lstrcpy (lpszSave, "enu");
        lstrcat (lpszSave, ".dll");
        AnsiUpper (szBuffer);
        if ((hResources = LoadLibrary (szBuffer)) == 0)
            return NULL;
        if (hResources < (HINSTANCE) 32)
            hResources = hInstance;
    }

    // Load the out of memory message

    if (idNoMemMsg > 0) {
        LoadString (hResources, idNoMemMsg, g.szOutOfMemory, sizeof (g.szOutOfMemory));
        g.idNoMemMsg = idNoMemMsg;
    }

    // Return to the caller

    return hResources;

}


// Function: CommonGetCurrentRegion - Get Region Code for Current Language
// --------------------------------------------------------------------
// Parameters: none
//
// Returns:    UINT uiRegion;          Mac region code corresponding
//                                     to current Windows language code
// --------------------------------------------------------------------
UINT FAR CommonGetCurrentRegion (VOID)

// Define function data

{
    char   szLanguage[4]; // Language code
    UINT   uiRegion;      // Region code

    // Match Windows language code to Mac region code

    GetProfileString( "intl", "sLanguage", "enu", szLanguage, sizeof(szLanguage));
    for (uiRegion = 0; *pszRegion[uiRegion]; uiRegion++)
        if (lstrcmpi (szLanguage, pszRegion[uiRegion]) == 0)
            break;

    // Return to the caller

    return (*pszRegion[uiRegion])? uiRegion : 0;

}


// Function: CommonTellUser - Issue message to User
// --------------------------------------------------------------------
// Parameters: HINSTANCE hResources;   /* Recource-only DLL handle */
//             WORD idMsg;             /* ID of message in resource DLL */
//             WORD idCaption;         /* ID of caption in resource DLL */
//             WORD idStyle            /* MessageBox style flags */
//
// Returns:    int idReply;            /* MessageBox reply flags */
// --------------------------------------------------------------------
int FAR CommonTellUser
  (HINSTANCE hResources, WORD idMsg, WORD idCaption, WORD idStyle, ...)

// Define function data

{
    char szFormat[COMMON_STRING_MAX];  // Message format
    char szBuffer[COMMON_STRING_MAX];  // Message buffer
    char szCaption[COMMON_STRING_MAX]; // Message caption
    WORD idReply;                      // Message response
    va_list pArgs;                     // String substitution arguments

    // check for out of memory id

    if (g.idNoMemMsg == idMsg) {
        idReply = MessageBox (NULL, g.szOutOfMemory, NULL, MB_OK | MB_SYSTEMMODAL | MB_ICONHAND );
        goto endTellUser;
    }

    // Load the caption string

    LoadString (hResources, idCaption, szCaption, sizeof (szCaption));

    // Load the message string

    LoadString (hResources, idMsg, szFormat, sizeof (szFormat));

    // Build the message text

    va_start (pArgs, idStyle);
    wvsprintf (szBuffer, szFormat, (LPSTR) pArgs);
    va_end (pArgs);

    // Display the message and capture response

    idReply = MessageBox (NULL, szBuffer, szCaption, idStyle);

 // Terminate if abort was requested

 endTellUser: 
    if (idReply == IDABORT)
        abort ();

    // Return reply

    return idReply;

}
