543 lines
10 KiB
C++
543 lines
10 KiB
C++
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
|
|
//***************************************************************************
|
|
//
|
|
// (c) 1996 by Microsoft Corporation
|
|
//
|
|
// utils.cpp
|
|
//
|
|
// This file contains definitions for miscellaneous utility functions, classes,
|
|
// and so on.
|
|
//
|
|
// a-larryf 17-Sept-96 Created.
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "precomp.h"
|
|
#include "utils.h"
|
|
#include "resource.h"
|
|
//#include "gc.h"
|
|
|
|
|
|
#define MAXSTRING 1024
|
|
|
|
//***********************************************************************
|
|
// BStringToCString
|
|
//
|
|
// Convert a BSTR to a CString
|
|
//
|
|
// Parameters:
|
|
// CString& sResult
|
|
// The result is returned here.
|
|
//
|
|
// BSTR bstrSource
|
|
// The source BSTR
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//**********************************************************************
|
|
void BStringToCString(CString& sResult, BSTR bstrSource)
|
|
{
|
|
char sz[MAXSTRING];
|
|
wcstombs(sz, (OLECHAR*) bstrSource, sizeof(sz) - 1);
|
|
sResult = sz;
|
|
}
|
|
|
|
|
|
//***********************************************************************
|
|
// VariantToCString
|
|
//
|
|
// Convert a variant to a CString
|
|
//
|
|
// Parameters:
|
|
// CString& sResult
|
|
// The result is returned here.
|
|
//
|
|
// VARIANT& varSrc
|
|
// The source variant.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//**********************************************************************
|
|
void VariantToCString(CString& sResult, const VARIANT& varSrc)
|
|
{
|
|
if (varSrc.vt == VT_BSTR) {
|
|
sResult = varSrc.bstrVal;
|
|
}
|
|
else {
|
|
COleVariant var(varSrc);
|
|
ToBSTR(var);
|
|
sResult = var.bstrVal;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//********************************************************************
|
|
// ToBSTR
|
|
//
|
|
// Convert a COleVariant to a BSTR
|
|
//
|
|
// Parameters:
|
|
// COleVariant& var
|
|
// The variant to convert.
|
|
//
|
|
// Returns:
|
|
// BSTR
|
|
// The place where the converted value is returned.
|
|
//
|
|
// Note that the BSTR returned is owned by the COleVariant.
|
|
//*******************************************************************
|
|
BSTR ToBSTR(COleVariant& var)
|
|
{
|
|
switch(var.vt) {
|
|
case VT_BSTR:
|
|
break;
|
|
case VT_NULL:
|
|
var = L"";
|
|
break;
|
|
default:
|
|
try
|
|
{
|
|
var.ChangeType(VT_BSTR);
|
|
}
|
|
catch(CException* )
|
|
{
|
|
var = L"";
|
|
|
|
}
|
|
break;
|
|
}
|
|
return var.bstrVal;
|
|
}
|
|
|
|
|
|
//***********************************************************************
|
|
// GenerateWindowID
|
|
//
|
|
// A series of unique window IDs are generated by sucessive calls to this
|
|
// method.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// A unique window ID used when creating a new window.
|
|
//
|
|
//**********************************************************************
|
|
UINT GenerateWindowID()
|
|
{
|
|
static UINT nID = 2000;
|
|
return nID++;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//******************************************************************
|
|
// GetViewerFont
|
|
//
|
|
// Get the "global" font used by the HMOM object viewer. This method
|
|
// will probably be replaced when I can figure out a way to get the
|
|
// ambient font.
|
|
//
|
|
// Parameters:
|
|
// [in] CFont& font
|
|
// A reference to the font to return.
|
|
//
|
|
// [in] LONG lfHeight
|
|
// The desired font height.
|
|
//
|
|
// [in] LONG lfWeight
|
|
// The weight of the font (FW_BOLD, FW_NORMAL, etc.)
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//*******************************************************************
|
|
void GetViewerFont(CFont& font, LONG lfHeight, LONG lfWeight)
|
|
{
|
|
CFont fontTmp;
|
|
fontTmp.CreateStockObject(SYSTEM_FONT);
|
|
|
|
LOGFONT logFont;
|
|
fontTmp.GetObject(sizeof(LOGFONT), &logFont);
|
|
logFont.lfWidth = 0;
|
|
logFont.lfHeight = lfHeight;
|
|
logFont.lfWeight = lfWeight;
|
|
logFont.lfQuality = DEFAULT_QUALITY;
|
|
logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
|
|
lstrcpy(logFont.lfFaceName, _T("MS Shell Dlg"));
|
|
|
|
VERIFY(font.CreateFontIndirect(&logFont));
|
|
}
|
|
|
|
|
|
|
|
//***********************************************************
|
|
// LoadStringArray
|
|
//
|
|
// Load a string array with some number of strings from the
|
|
// string table.
|
|
//
|
|
// Parameters:
|
|
// CStringArray& sa
|
|
// The place where the strings are loaded into.
|
|
//
|
|
// UINT* puiResID
|
|
// Pointer to an array of resource ids for the strings.
|
|
//
|
|
// int nStrings
|
|
// The number of entries in the array.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//************************************************************
|
|
void LoadStringArray(CStringArray& sa, UINT* puiResID, int nStrings)
|
|
{
|
|
for (int iString=0; iString < nStrings; ++iString) {
|
|
CString sText;
|
|
sText.LoadString(puiResID[iString]);
|
|
sa.Add(sText);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************
|
|
// LoadStringMap
|
|
//
|
|
// This function should probably go away and CMapStringToLong should
|
|
// be used instead.
|
|
//
|
|
// This function loads a string array with the values in a TStrMap.
|
|
// This map is used to map string values to some integer value.
|
|
//
|
|
// Parameters:
|
|
// CStringArray& asGridStrings
|
|
// This is where the strings are returned.
|
|
//
|
|
// TStrMap* pStrMap
|
|
// A pointer to an array of entries containing {string, value} pairs
|
|
/// where the string is coded as a resource id.
|
|
//
|
|
// int nStrings
|
|
// The number of entries in the TStrMap array.
|
|
//
|
|
//*****************************************************************
|
|
void LoadStringMap(CStringArray& asGridStrings, TStrMap* pStrMap, int nStrings)
|
|
{
|
|
CString sValue;
|
|
for (int iStr =0; iStr<nStrings; ++iStr) {
|
|
sValue.LoadString(pStrMap[iStr].ids);
|
|
asGridStrings.SetAtGrow(pStrMap[iStr].iString, sValue);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//*****************************************************************
|
|
// CXStringArray::Load
|
|
//
|
|
// Given an array of resource ids, load the corresponding strings
|
|
// into this CStringArray.
|
|
//
|
|
// Parameters:
|
|
// UINT* puiResID
|
|
// Pointer to the array of string resource ids
|
|
//
|
|
// int nStrings
|
|
// The number of entries in the resource id array.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//****************************************************************
|
|
void CXStringArray::Load(UINT* puiResID, int nStrings)
|
|
{
|
|
// If this string array was already loaded, do nothing.
|
|
if (GetSize() > 0) {
|
|
return;
|
|
}
|
|
|
|
CString sValue;
|
|
while (--nStrings >= 0) {
|
|
sValue.LoadString(*puiResID++);
|
|
Add(sValue);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL IsEqualNoCase(BSTR bstr1, BSTR bstr2)
|
|
{
|
|
if (bstr1 == bstr2) {
|
|
return TRUE;
|
|
}
|
|
if (bstr1==NULL || bstr2==NULL) {
|
|
return FALSE;
|
|
}
|
|
while (TRUE) {
|
|
WCHAR wch1;
|
|
WCHAR wch2;
|
|
|
|
wch1 = towupper(*bstr1);
|
|
wch2 = towupper(*bstr2);
|
|
if (wch1 != wch2) {
|
|
break;
|
|
}
|
|
if (wch1 == 0) {
|
|
return TRUE;
|
|
}
|
|
|
|
++bstr1;
|
|
++bstr2;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL IsEqual(BSTR bstr1, BSTR bstr2)
|
|
{
|
|
if (bstr1 == bstr2) {
|
|
return TRUE;
|
|
}
|
|
if (bstr1==NULL || bstr2==NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
while (*bstr1 == *bstr2) {
|
|
if (*bstr1 == 0) {
|
|
return TRUE;
|
|
}
|
|
++bstr1;
|
|
++bstr2;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL IsEqual(COleVariant& varOperand1, BSTR bstrOperand2)
|
|
{
|
|
if (varOperand1.vt == VT_BSTR) {
|
|
return IsEqual(varOperand1.bstrVal, bstrOperand2);
|
|
}
|
|
else {
|
|
COleVariant varTemp;
|
|
varTemp = varOperand1;
|
|
ToBSTR(varTemp);
|
|
return IsEqual(varTemp.bstrVal, bstrOperand2);
|
|
}
|
|
}
|
|
|
|
|
|
//**********************************************
|
|
// IsEmptyString
|
|
//
|
|
// Check to see if a BSTR is all white space.
|
|
//
|
|
// Parameters:
|
|
// BSTR bstr
|
|
// The BSTR to examine.
|
|
//
|
|
// Returns:
|
|
// BOOL
|
|
// TRUE if the string is empty, FALSE otherwise.
|
|
//
|
|
//*********************************************
|
|
BOOL IsEmptyString(BSTR bstr)
|
|
{
|
|
ASSERT(bstr != NULL);
|
|
while (iswspace(*bstr)) {
|
|
++bstr;
|
|
}
|
|
return (*bstr == 0);
|
|
}
|
|
|
|
|
|
//**********************************************
|
|
// IsEmptyString
|
|
//
|
|
// Check to see if a CString is all white space.
|
|
//
|
|
// Parameters:
|
|
// CString& s
|
|
// The string to examine.
|
|
//
|
|
// Returns:
|
|
// BOOL
|
|
// TRUE if the string is empty, FALSE otherwise.
|
|
//
|
|
//*********************************************
|
|
BOOL IsEmptyString(CString& s)
|
|
{
|
|
LPCTSTR psz = s;
|
|
while(_istspace(*psz)) {
|
|
++psz;
|
|
}
|
|
return (*psz == 0);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************
|
|
// RemoveLeadingWhiteSpace
|
|
//
|
|
// Remove any leading white space from the string
|
|
// contained in the variant.
|
|
//
|
|
// Parameters:
|
|
// [in] COleVariant& var
|
|
// The variant containing the string to trim.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//****************************************************
|
|
void RemoveLeadingWhiteSpace(COleVariant& var)
|
|
{
|
|
ASSERT(var.vt == VT_BSTR);
|
|
if (var.vt != VT_BSTR) {
|
|
return;
|
|
}
|
|
|
|
BSTR bstr = var.bstrVal;
|
|
while (*bstr) {
|
|
if (!iswspace(*bstr)) {
|
|
break;
|
|
}
|
|
++bstr;
|
|
}
|
|
|
|
if (var.bstrVal != bstr) {
|
|
var = bstr;
|
|
}
|
|
}
|
|
|
|
//****************************************************
|
|
// RemoveTrailingWhiteSpace
|
|
//
|
|
// Remove any trailing white space from the string
|
|
// contained in the variant.
|
|
//
|
|
// Parameters:
|
|
// [in] COleVariant& var
|
|
// The variant containing the string to trim.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//****************************************************
|
|
void RemoveTrailingWhiteSpace(COleVariant& var)
|
|
{
|
|
ASSERT(var.vt == VT_BSTR);
|
|
if (var.vt != VT_BSTR) {
|
|
return;
|
|
}
|
|
|
|
BSTR bstrStart = var.bstrVal;
|
|
BSTR bstr = bstrStart;
|
|
// Move the pointer to the end of the string
|
|
while(*bstr) {
|
|
++bstr;
|
|
}
|
|
|
|
if (bstr > bstrStart) {
|
|
|
|
--bstr;
|
|
|
|
while (TRUE) {
|
|
if (!iswspace(*bstr)) {
|
|
break;
|
|
}
|
|
if (bstr == bstrStart) {
|
|
break;
|
|
}
|
|
*bstr = 0;
|
|
--bstr;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBSTR& CBSTR::operator=(LPCTSTR psz)
|
|
{
|
|
if (m_bstr) {
|
|
::SysFreeString(m_bstr);
|
|
}
|
|
CString s(psz);
|
|
m_bstr = s.AllocSysString();
|
|
return *this;
|
|
}
|
|
|
|
CBSTR& CBSTR::operator=(CString& s)
|
|
{
|
|
if (m_bstr) {
|
|
::SysFreeString(m_bstr);
|
|
}
|
|
m_bstr = s.AllocSysString();
|
|
return *this;
|
|
}
|
|
|
|
CBSTR& CBSTR::operator=(BSTR bstr)
|
|
{
|
|
if (m_bstr) {
|
|
::SysFreeString(m_bstr);
|
|
}
|
|
CString s;
|
|
s = bstr;
|
|
m_bstr = s.AllocSysString();
|
|
return *this;
|
|
}
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// IsPrefix
|
|
//
|
|
// Check to see if one string is the prefix of another.
|
|
//
|
|
// Parameters:
|
|
// [in] LPCTSTR pszPrefix
|
|
// The prefix to check for.
|
|
//
|
|
// [in] LPCTSTR pszValue
|
|
// The string to examine.
|
|
//
|
|
// Returns:
|
|
// TRUE if the pszPrefix is a prefix of sValue.
|
|
//
|
|
//**********************************************************************
|
|
BOOL IsPrefix(LPCTSTR pszPrefix, LPCTSTR pszValue)
|
|
{
|
|
while (*pszPrefix != 0) {
|
|
if (*pszPrefix != *pszValue) {
|
|
return FALSE;
|
|
}
|
|
++pszPrefix;
|
|
++pszValue;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|