OLEUTL.C

/* 
* OLEUTL.C
*
* Miscellaneous utility functions for OLE 2.0 Applications:
*
* Function Purpose
* -------------------------------------------------------------------
* SetDCToDrawInHimetricRect Sets up an HIMETRIC mapping mode in a DC.
* ResetOrigDC Performs the opposite of
* SetDCToDrawInHimetricRect
* XformWidthInPixelsToHimetric Converts an int width into HiMetric units
* XformWidthInHimetricToPixels Converts an int width from HiMetric units
* XformHeightInPixelsToHimetric Converts an int height into HiMetric units
* XformHeightInHimetricToPixels Converts an int height from HiMetric units
* XformRectInPixelsToHimetric Converts a rect into HiMetric units
* XformRectInHimetricToPixels Converts a rect from HiMetric units
* XformSizeInPixelsToHimetric Converts a SIZEL into HiMetric units
* XformSizeInHimetricToPixels Converts a SIZEL from HiMetric units
* AreRectsEqual Compares to Rect's
*
* ParseCmdLine Determines if -Embedding exists
* OpenOrCreateRootStorage Creates a root docfile for OLE storage
* CommitStorage Commits all changes in a docfile
* CreateChildStorage Creates child storage in another storage
* OpenChildStorage Opens child storage in another storage
*
*
* Copyright (c)1992-1996 Microsoft Corporation, All Right Reserved
*/


#define STRICT 1
#include "olestd.h"
#include <stdlib.h>
#include <ctype.h>

//Internal function to this module
static LPSTR GetWord(LPSTR lpszSrc, LPSTR lpszDst);


/*
* SetDCToAnisotropic
*
* Purpose:
* Setup the correspondence between the rect in device unit (Viewport) and
* the rect in logical unit (Window) so that the proper scaling of
* coordinate systems will be calculated. set up both the Viewport and
* the window as follows:
*
* 1) ------------------ ( 2
* | |
* | |
* | |
* | |
* | |
* 3) ------------------ ( 4
*
* Origin = P3
* X extent = P2x - P3x
* Y extent = P2y - P3y
*
* Parameters:
* hDC HDC to affect
* lprcPhysical LPRECT containing the physical (device) extents of DC
* lprcLogical LPRECT containing the logical extents
* lprcWindowOld LPRECT in which to preserve the window for ResetOrigDC
* lprcViewportOld LPRECT in which to preserver the viewport for ResetOrigDC
*
* Return Value:
* int The original mapping mode of the DC.
*/

STDAPI_(int) SetDCToAnisotropic(
HDC hDC,
LPRECT lprcPhysical, LPRECT lprcLogical,
LPRECT lprcWindowOld, LPRECT lprcViewportOld)
{
int nMapModeOld=SetMapMode(hDC, MM_ANISOTROPIC);

SetWindowOrgEx(hDC, lprcLogical->left, lprcLogical->bottom, (LPPOINT)&lprcWindowOld->left);
SetWindowExtEx(hDC, (lprcLogical->right-lprcLogical->left), (lprcLogical->top-lprcLogical->bottom), (LPSIZE)&lprcWindowOld->right);
SetViewportOrgEx(hDC, lprcPhysical->left, lprcPhysical->bottom, (LPPOINT)&lprcViewportOld->left);
SetViewportExtEx(hDC, (lprcPhysical->right-lprcPhysical->left), (lprcPhysical->top-lprcPhysical->bottom), (LPSIZE)&lprcViewportOld->right);

return nMapModeOld;
}


/*
* SetDCToDrawInHimetricRect
*
* Purpose:
* Setup the correspondence between the rect in pixels (Viewport) and
* the rect in HIMETRIC (Window) so that the proper scaling of
* coordinate systems will be calculated. set up both the Viewport and
* the window as follows:
*
* 1) ------------------ ( 2
* | |
* | |
* | |
* | |
* | |
* 3) ------------------ ( 4
*
* Origin = P3
* X extent = P2x - P3x
* Y extent = P2y - P3y
*
* Parameters:
* hDC HDC to affect
* lprcPix LPRECT containing the pixel extents of DC
* lprcHiMetric LPRECT to receive the himetric extents
* lprcWindowOld LPRECT in which to preserve the window for ResetOrigDC
* lprcViewportOld LPRECT in which to preserver the viewport for ResetOrigDC
*
* Return Value:
* int The original mapping mode of the DC.
*/
STDAPI_(int) SetDCToDrawInHimetricRect(
HDC hDC,
LPRECT lprcPix, LPRECT lprcHiMetric,
LPRECT lprcWindowOld, LPRECT lprcViewportOld)
{
int nMapModeOld=SetMapMode(hDC, MM_ANISOTROPIC);
BOOL fSystemDC =FALSE;

if (NULL==hDC)
{
hDC=GetDC(NULL);
fSystemDC=TRUE;
}

XformRectInPixelsToHimetric(hDC, lprcPix, lprcHiMetric);

SetWindowOrgEx(hDC, lprcHiMetric->left, lprcHiMetric->bottom, (LPPOINT)&lprcWindowOld->left);
SetWindowExtEx(hDC, (lprcHiMetric->right-lprcHiMetric->left), (lprcHiMetric->top-lprcHiMetric->bottom), (LPSIZE)&lprcWindowOld->right);
SetViewportOrgEx(hDC, lprcPix->left, lprcPix->bottom, (LPPOINT)&lprcViewportOld->left);
SetViewportExtEx(hDC, (lprcPix->right-lprcPix->left), (lprcPix->top-lprcPix->bottom), (LPSIZE)&lprcViewportOld->right);

if (fSystemDC)
ReleaseDC(NULL, hDC);

return nMapModeOld;
}



/*
* ResetOrigDC
*
* Purpose:
* Restores a DC set to draw in himetric from SetDCToDrawInHimetricRect.
*
* Parameters:
* hDC HDC to restore
* nMapModeOld int original mapping mode of hDC
* lprcWindowOld LPRECT filled in SetDCToDrawInHimetricRect
* lprcViewportOld LPRECT filled in SetDCToDrawInHimetricRect
*
* Return Value:
* int Same as nMapModeOld.
*/

STDAPI_(int) ResetOrigDC(
HDC hDC, int nMapModeOld,
LPRECT lprcWindowOld, LPRECT lprcViewportOld)
{
POINT pOld;

SetMapMode(hDC, nMapModeOld);

SetWindowOrgEx(hDC, lprcWindowOld->left, lprcWindowOld->top, (LPPOINT)&pOld);
SetWindowExtEx(hDC, lprcWindowOld->right, lprcWindowOld->bottom, (LPSIZE)&pOld);
SetViewportOrgEx(hDC, lprcViewportOld->left, lprcViewportOld->top, (LPPOINT)&pOld);
SetViewportExtEx(hDC, lprcViewportOld->right, lprcViewportOld->bottom, (LPSIZE)&pOld);

return nMapModeOld;
}



/*
* XformWidthInPixelsToHimetric
* XformWidthInHimetricToPixels
* XformHeightInPixelsToHimetric
* XformHeightInHimetricToPixels
*
* Functions to convert an int between a device coordinate system and
* logical HiMetric units.
*
* Parameters:
* hDC HDC providing reference to the pixel mapping. If
* NULL, a screen DC is used.
*
* Size Functions:
* lpSizeSrc LPSIZEL providing the structure to convert. This
* contains pixels in XformSizeInPixelsToHimetric and
* logical HiMetric units in the complement function.
* lpSizeDst LPSIZEL providing the structure to receive converted
* units. This contains pixels in
* XformSizeInPixelsToHimetric and logical HiMetric
* units in the complement function.
*
* Width Functions:
* iWidth int containing the value to convert.
*
* Return Value:
* Size Functions: None
* Width Functions: Converted value of the input parameters.
*
* NOTE:
* When displaying on the screen, Window apps display everything enlarged
* from its actual size so that it is easier to read. For example, if an
* app wants to display a 1in. horizontal line, that when printed is
* actually a 1in. line on the printed page, then it will display the line
* on the screen physically larger than 1in. This is described as a line
* that is "logically" 1in. along the display width. Windows maintains as
* part of the device-specific information about a given display device:
* LOGPIXELSX -- no. of pixels per logical in along the display width
* LOGPIXELSY -- no. of pixels per logical in along the display height
*
* The following formula converts a distance in pixels into its equivalent
* logical HIMETRIC units:
*
* DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix)
* -------------------------------
* PIXELS_PER_LOGICAL_IN
*
*/
STDAPI_(int) XformWidthInPixelsToHimetric(HDC hDC, int iWidthInPix)
{
int iXppli; //Pixels per logical inch along width
int iWidthInHiMetric;
BOOL fSystemDC=FALSE;

if (NULL==hDC)
{
hDC=GetDC(NULL);
fSystemDC=TRUE;
}

iXppli = GetDeviceCaps (hDC, LOGPIXELSX);

//We got pixel units, convert them to logical HIMETRIC along the display
iWidthInHiMetric = MAP_PIX_TO_LOGHIM(iWidthInPix, iXppli);

if (fSystemDC)
ReleaseDC(NULL, hDC);

return iWidthInHiMetric;
}


STDAPI_(int) XformWidthInHimetricToPixels(HDC hDC, int iWidthInHiMetric)
{
int iXppli; //Pixels per logical inch along width
int iWidthInPix;
BOOL fSystemDC=FALSE;

if (NULL==hDC)
{
hDC=GetDC(NULL);
fSystemDC=TRUE;
}

iXppli = GetDeviceCaps (hDC, LOGPIXELSX);

//We got logical HIMETRIC along the display, convert them to pixel units
iWidthInPix = MAP_LOGHIM_TO_PIX(iWidthInHiMetric, iXppli);

if (fSystemDC)
ReleaseDC(NULL, hDC);

return iWidthInPix;
}


STDAPI_(int) XformHeightInPixelsToHimetric(HDC hDC, int iHeightInPix)
{
int iYppli; //Pixels per logical inch along height
int iHeightInHiMetric;
BOOL fSystemDC=FALSE;

if (NULL==hDC)
{
hDC=GetDC(NULL);
fSystemDC=TRUE;
}

iYppli = GetDeviceCaps (hDC, LOGPIXELSY);

//* We got pixel units, convert them to logical HIMETRIC along the display
iHeightInHiMetric = MAP_PIX_TO_LOGHIM(iHeightInPix, iYppli);

if (fSystemDC)
ReleaseDC(NULL, hDC);

return iHeightInHiMetric;
}


STDAPI_(int) XformHeightInHimetricToPixels(HDC hDC, int iHeightInHiMetric)
{
int iYppli; //Pixels per logical inch along height
int iHeightInPix;
BOOL fSystemDC=FALSE;

if (NULL==hDC)
{
hDC=GetDC(NULL);
fSystemDC=TRUE;
}

iYppli = GetDeviceCaps (hDC, LOGPIXELSY);

//* We got logical HIMETRIC along the display, convert them to pixel units
iHeightInPix = MAP_LOGHIM_TO_PIX(iHeightInHiMetric, iYppli);

if (fSystemDC)
ReleaseDC(NULL, hDC);

return iHeightInPix;
}



/*
* XformRectInPixelsToHimetric
* XformRectInHimetricToPixels
*
* Purpose:
* Convert a rectangle between pixels of a given hDC and HIMETRIC units
* as manipulated in OLE. If the hDC is NULL, then a screen DC is used
* and assumes the MM_TEXT mapping mode.
*
* Parameters:
* hDC HDC providing reference to the pixel mapping. If
* NULL, a screen DC is used.
* lprcSrc LPRECT providing the rectangle to convert. This
* contains pixels in XformRectInPixelsToHimetric and
* logical HiMetric units in the complement function.
* lprcDst LPRECT providing the rectangle to receive converted units.
* This contains pixels in XformRectInPixelsToHimetric and
* logical HiMetric units in the complement function.
*
* Return Value:
* None
*
* NOTE:
* When displaying on the screen, Window apps display everything enlarged
* from its actual size so that it is easier to read. For example, if an
* app wants to display a 1in. horizontal line, that when printed is
* actually a 1in. line on the printed page, then it will display the line
* on the screen physically larger than 1in. This is described as a line
* that is "logically" 1in. along the display width. Windows maintains as
* part of the device-specific information about a given display device:
* LOGPIXELSX -- no. of pixels per logical in along the display width
* LOGPIXELSY -- no. of pixels per logical in along the display height
*
* The following formula converts a distance in pixels into its equivalent
* logical HIMETRIC units:
*
* DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix)
* -------------------------------
* PIXELS_PER_LOGICAL_IN
*
* Rect in Pixels (MM_TEXT):
*
* 0---------- X
* |
* | 1) ------------------ ( 2 P1 = (rc.left, rc.top)
* | | | P2 = (rc.right, rc.top)
* | | | P3 = (rc.left, rc.bottom)
* | | | P4 = (rc.right, rc.bottom)
* | |
* Y | |
* 3) ------------------ ( 4
*
* NOTE: Origin = (P1x, P1y)
* X extent = P4x - P1x
* Y extent = P4y - P1y
*
*
* Rect in Himetric (MM_HIMETRIC):
*
*
* 1) ------------------ ( 2 P1 = (rc.left, rc.top)
* Y | | P2 = (rc.right, rc.top)
* | | P3 = (rc.left, rc.bottom)
* | | | P4 = (rc.right, rc.bottom)
* | | |
* | | |
* | 3) ------------------ ( 4
* |
* 0---------- X
*
* NOTE: Origin = (P3x, P3y)
* X extent = P2x - P3x
* Y extent = P2y - P3y
*
*
*/

STDAPI_(void) XformRectInPixelsToHimetric(
HDC hDC, LPRECT lprcPix, LPRECT lprcHiMetric)
{
int iXppli; //Pixels per logical inch along width
int iYppli; //Pixels per logical inch along height
int iXextInPix=(lprcPix->right-lprcPix->left);
int iYextInPix=(lprcPix->bottom-lprcPix->top);
BOOL fSystemDC=FALSE;

if (NULL==hDC ||
GetDeviceCaps(hDC, TECHNOLOGY) == DT_METAFILE ||
GetDeviceCaps(hDC, LOGPIXELSX) == 0)
{
hDC=GetDC(NULL);
fSystemDC=TRUE;
}

iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
iYppli = GetDeviceCaps (hDC, LOGPIXELSY);

//We got pixel units, convert them to logical HIMETRIC along the display
lprcHiMetric->right = MAP_PIX_TO_LOGHIM(iXextInPix, iXppli);
lprcHiMetric->top = MAP_PIX_TO_LOGHIM(iYextInPix, iYppli);

lprcHiMetric->left = 0;
lprcHiMetric->bottom = 0;

if (fSystemDC)
ReleaseDC(NULL, hDC);

return;
}



STDAPI_(void) XformRectInHimetricToPixels(
HDC hDC, LPRECT lprcHiMetric, LPRECT lprcPix)
{
int iXppli; //Pixels per logical inch along width
int iYppli; //Pixels per logical inch along height
int iXextInHiMetric=(lprcHiMetric->right-lprcHiMetric->left);
int iYextInHiMetric=(lprcHiMetric->bottom-lprcHiMetric->top);
BOOL fSystemDC=FALSE;

if (NULL==hDC ||
GetDeviceCaps(hDC, TECHNOLOGY) == DT_METAFILE ||
GetDeviceCaps(hDC, LOGPIXELSX) == 0)
{
hDC=GetDC(NULL);
fSystemDC=TRUE;
}

iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
iYppli = GetDeviceCaps (hDC, LOGPIXELSY);

//We got pixel units, convert them to logical HIMETRIC along the display
lprcPix->right = MAP_LOGHIM_TO_PIX(iXextInHiMetric, iXppli);
lprcPix->top = MAP_LOGHIM_TO_PIX(iYextInHiMetric, iYppli);

lprcPix->left = 0;
lprcPix->bottom= 0;

if (fSystemDC)
ReleaseDC(NULL, hDC);

return;
}




/*
* XformSizeInPixelsToHimetric
* XformSizeInHimetricToPixels
*
* Functions to convert a SIZEL structure (Size functions) or
* an int (Width functions) between a device coordinate system and
* logical HiMetric units.
*
* Parameters:
* hDC HDC providing reference to the pixel mapping. If
* NULL, a screen DC is used.
*
* Size Functions:
* lpSizeSrc LPSIZEL providing the structure to convert. This
* contains pixels in XformSizeInPixelsToHimetric and
* logical HiMetric units in the complement function.
* lpSizeDst LPSIZEL providing the structure to receive converted
* units. This contains pixels in
* XformSizeInPixelsToHimetric and logical HiMetric
* units in the complement function.
*
* Width Functions:
* iWidth int containing the value to convert.
*
* Return Value:
* Size Functions: None
* Width Functions: Converted value of the input parameters.
*
* NOTE:
* When displaying on the screen, Window apps display everything enlarged
* from its actual size so that it is easier to read. For example, if an
* app wants to display a 1in. horizontal line, that when printed is
* actually a 1in. line on the printed page, then it will display the line
* on the screen physically larger than 1in. This is described as a line
* that is "logically" 1in. along the display width. Windows maintains as
* part of the device-specific information about a given display device:
* LOGPIXELSX -- no. of pixels per logical in along the display width
* LOGPIXELSY -- no. of pixels per logical in along the display height
*
* The following formula converts a distance in pixels into its equivalent
* logical HIMETRIC units:
*
* DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix)
* -------------------------------
* PIXELS_PER_LOGICAL_IN
*
*/

STDAPI_(void) XformSizeInPixelsToHimetric(
HDC hDC, LPSIZEL lpSizeInPix, LPSIZEL lpSizeInHiMetric)
{
int iXppli; //Pixels per logical inch along width
int iYppli; //Pixels per logical inch along height
BOOL fSystemDC=FALSE;

if (NULL==hDC ||
GetDeviceCaps(hDC, TECHNOLOGY) == DT_METAFILE ||
GetDeviceCaps(hDC, LOGPIXELSX) == 0)
{
hDC=GetDC(NULL);
fSystemDC=TRUE;
}

iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
iYppli = GetDeviceCaps (hDC, LOGPIXELSY);

//We got pixel units, convert them to logical HIMETRIC along the display
lpSizeInHiMetric->cx = (long)MAP_PIX_TO_LOGHIM((int)lpSizeInPix->cx, iXppli);
lpSizeInHiMetric->cy = (long)MAP_PIX_TO_LOGHIM((int)lpSizeInPix->cy, iYppli);

if (fSystemDC)
ReleaseDC(NULL, hDC);

return;
}


STDAPI_(void) XformSizeInHimetricToPixels(
HDC hDC, LPSIZEL lpSizeInHiMetric, LPSIZEL lpSizeInPix)
{
int iXppli; //Pixels per logical inch along width
int iYppli; //Pixels per logical inch along height
BOOL fSystemDC=FALSE;

if (NULL==hDC ||
GetDeviceCaps(hDC, TECHNOLOGY) == DT_METAFILE ||
GetDeviceCaps(hDC, LOGPIXELSX) == 0)
{
hDC=GetDC(NULL);
fSystemDC=TRUE;
}

iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
iYppli = GetDeviceCaps (hDC, LOGPIXELSY);

//We got logical HIMETRIC along the display, convert them to pixel units
lpSizeInPix->cx = (long)MAP_LOGHIM_TO_PIX((int)lpSizeInHiMetric->cx, iXppli);
lpSizeInPix->cy = (long)MAP_LOGHIM_TO_PIX((int)lpSizeInHiMetric->cy, iYppli);

if (fSystemDC)
ReleaseDC(NULL, hDC);

return;
}


#if defined( OBSOLETE )
// This function has been converted to a macro

/* AreRectsEqual
** -------------
*/
STDAPI_(BOOL) AreRectsEqual(LPRECT lprc1, LPRECT lprc2)
{
if ((lprc1->top == lprc2->top) &&
(lprc1->left == lprc2->left) &&
(lprc1->right == lprc2->right) &&
(lprc1->bottom == lprc2->bottom))
return TRUE;

return FALSE;
}
#endif // OBSOLETE


/*
* ParseCmdLine
*
* Parses the Windows command line which was passed to WinMain.
* This function determines if the -Embedding switch has been given.
*
*/

STDAPI_(void) ParseCmdLine(
LPSTR lpszLine,
BOOL FAR* lpfEmbedFlag,
LPSTR szFileName)
{
int i=0;
char szBuf[256];

if(lpfEmbedFlag)
*lpfEmbedFlag = FALSE;
szFileName[0]='\0'; // NULL string

// skip blanks
while(isspace(*lpszLine)) lpszLine++;

if(!*lpszLine) // No filename or options, so start a fresh document.
return;

// Check for "-Embedding" or "/Embedding" and set fEmbedding.
if(lpfEmbedFlag && (*lpszLine == '-' || *lpszLine == '/')) {
lpszLine++;
lpszLine = GetWord(lpszLine, szBuf);
*lpfEmbedFlag = !lstrcmp(szBuf, EMBEDDINGFLAG);
}

// skip blanks
while(isspace(*lpszLine)) lpszLine++;

// set szFileName to argument
while(lpszLine[i]) {
szFileName[i]=lpszLine[i];
i++;
}
szFileName[i]='\0';
}


/* GetWord
* -------
*
* LPSTR lpszSrc - Pointer to a source string
* LPSTR lpszDst - Pointer to destination buffer
*
* Will copy one space-terminated or null-terminated word from the source
* string to the destination buffer.
* returns: pointer to next character following the word.
*/
static LPSTR GetWord(LPSTR lpszSrc, LPSTR lpszDst)
{
while (*lpszSrc && !isspace(*lpszSrc))
*lpszDst++ = *lpszSrc++;

*lpszDst = '\0';
return lpszSrc;
}