📄 util.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*
* UTIL.C
*
* Purpose:
* Implementation of various useful utility functions
*
* Author:
* alexgo (4/25/95)
*/
#include "_common.h"
#include "_rtfconv.h"
ASSERTDATA
//Global instance of SystemParams for keeping track of
//certain system wide parameters used in richedit.
CSystemParams sysparam;
// Author revision color table
const COLORREF rgcrRevisions[] =
{
RGB(0, 0, 255),
RGB(0, 128, 0),
RGB(255, 0, 0),
RGB(0, 128, 128),
RGB(128, 0, 128),
RGB(0, 0, 128),
RGB(128, 0, 0),
RGB(255, 0, 255)
};
#if REVMASK != 7
#pragma message ("WARNING, Revision mask not equal to table!");
#endif
/*
* DuplicateHGlobal
*
* Purpose:
* duplicates the passed in hglobal
*/
HGLOBAL DuplicateHGlobal( HGLOBAL hglobal )
{
TRACEBEGIN(TRCSUBSYSUTIL, TRCSCOPEINTERN, "DuplicateHGlobal");
UINT flags;
DWORD size;
HGLOBAL hNew;
BYTE * pSrc;
BYTE * pDest;
if( hglobal == NULL )
{
return NULL;
}
flags = GlobalFlags(hglobal);
size = GlobalSize(hglobal);
hNew = GlobalAlloc(flags, size);
if( hNew )
{
pDest = (BYTE *)GlobalLock(hNew);
pSrc = (BYTE *)GlobalLock(hglobal);
if( pDest == NULL || pSrc == NULL )
{
GlobalUnlock(hNew);
GlobalUnlock(hglobal);
GlobalFree(hNew);
return NULL;
}
memcpy(pDest, pSrc, size);
GlobalUnlock(hNew);
GlobalUnlock(hglobal);
}
return hNew;
}
/*
* CountMatchingBits (*pA, *pB, n)
*
* @mfunc
* Count matching bit fields
*
* @comm
* This is used to help decide how good the match is between
* code page bit fields. Mainly for KB/font switching support.
*
* Author:
* Jon Matousek
*/
INT CountMatchingBits(
const DWORD *pA, //@parm Array A to be matched
const DWORD *pB, //@parm Array B to be matched
INT n) //@parm # DWORDs to be matched
{
TRACEBEGIN(TRCSUBSYSUTIL, TRCSCOPEINTERN, "CountMatchingBits");
//0 1 2 3 4 5 6 7 8 9 A B C D E F
static INT bitCount[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
INT c = 0; // Bit count to return
DWORD matchBits; // Next DWORD match
while(n--)
{
//matchBits = ~(*pA++ ^ *pB++); // 1 and 0's
matchBits = *pA++ & *pB++; // 1 only
for( ; matchBits; matchBits >>= 4) // Early out
c += bitCount[matchBits & 15];
#if 0
c += bitCount [(matchBits >> 0) & 15]; // No early out
c += bitCount [(matchBits >> 4) & 15];
c += bitCount [(matchBits >> 8) & 15];
c += bitCount [(matchBits >> 12) & 15];
c += bitCount [(matchBits >> 16) & 15];
c += bitCount [(matchBits >> 20) & 15];
c += bitCount [(matchBits >> 24) & 15];
c += bitCount [(matchBits >> 28) & 15];
#endif
#if 0
for( ; matchBits; c++) // For random data, has
matchBits &= matchBits - 1; // about 16 passes
#endif
}
return c;
}
//FUTURE: (v-richa) If it becomes practical to detect when the various
//system values handled by this class change, we should add a mechanism
//to update them dynamically.
/*
* CSystemParams::CSystemParams(void)
*
* @mfunc
* This class is used to handle certain system wide parameters that
* that are used in richedit. the constructor just initializes
* things to a known state so we can tell whether they have been
* previously set.
*
*/
CSystemParams::CSystemParams(void)
{
TRACEBEGIN(TRCSUBSYSUTIL, TRCSCOPEINTERN, "SystemParams::SystemParams");
_nScrollInset = 0;
_nScrollDelay = 0;
_nScrollInterval = 0;
_nScrollVAmount = 0;
_nScrollHAmount = 0;
_nDragDelay = 0;
_hcurSizeNS = NULL;
_hcurSizeWE = NULL;
_hcurSizeNWSE = NULL;
_hcurSizeNESW = NULL;
_fDirty = TRUE;
}
/*
* CSystemParams::~CSystemParams(void)
*
* @mfunc
* Destructor.
*
*/
CSystemParams::~CSystemParams(void)
{
TRACEBEGIN(TRCSUBSYSUTIL, TRCSCOPEINTERN, "SystemParams::~SystemParams");
}
/*
* CSystemParams::GetScrollInset(void)
*
* @mfunc
* If value has been set, return it.
* Otherwise get the default and then return the value.
*
*/
WORD CSystemParams::GetScrollInset(void)
{
if (_nScrollInset)
return _nScrollInset;
_nScrollInset =
(WORD)GetProfileIntA( "windows", "ScrollInset", DD_DEFSCROLLINSET );
return _nScrollInset;
}
/*
* CSystemParams::GetScrollDelay(void)
*
* @mfunc
* If value has been set, return it.
* Otherwise get the default and then return the value.
*
*/
WORD CSystemParams::GetScrollDelay(void)
{
if (_nScrollDelay)
return _nScrollDelay;
_nScrollDelay =
(WORD)GetProfileIntA( "windows", "ScrollDelay", DD_DEFSCROLLDELAY );
return _nScrollDelay;
}
/*
* CSystemParams::GetScrollInterval(void)
*
* @mfunc
* If value has been set, return it.
* Otherwise get the default and then return the value.
*
*/
WORD CSystemParams::GetScrollInterval(void)
{
if (_nScrollInterval)
return _nScrollInterval;
_nScrollInterval =
(WORD)GetProfileIntA( "windows", "ScrollInterval", DD_DEFSCROLLINTERVAL );
return _nScrollInterval;
}
/*
* CSystemParams::GetScrollVAmount(void)
*
* @mfunc
* If value has been set, return it.
* Otherwise get the default and then return the value.
*
*/
WORD CSystemParams::GetScrollVAmount(void)
{
if (_nScrollVAmount)
return _nScrollVAmount;
_nScrollVAmount = (GetYPerInchScreenDC()*DEFSCROLLVAMOUNT)/100;
return _nScrollVAmount;
}
/*
* CSystemParams::GetScrollHAmount(void)
*
* @mfunc
* If value has been set, return it.
* Otherwise get the default and then return the value.
*
*/
WORD CSystemParams::GetScrollHAmount(void)
{
if (_nScrollHAmount)
return _nScrollHAmount;
_nScrollHAmount = (GetXPerInchScreenDC()*DEFSCROLLHAMOUNT)/100;
return _nScrollHAmount;
}
/*
* CSystemParams::GetDragDelay(void)
*
* @mfunc
* If value has been set, return it.
* Otherwise get the default and then return the value.
*
*/
WORD CSystemParams::GetDragDelay(void)
{
if (_nDragDelay)
return _nDragDelay;
_nDragDelay =
(WORD)GetProfileIntA( "windows", "DragDelay", DD_DEFDRAGDELAY );
return _nDragDelay;
}
/*
* CSystemParams::GetDragMinDist(void)
*
* @mfunc
* If value has been set, return it.
* Otherwise get the default and then return the value.
*
*/
WORD CSystemParams::GetDragMinDist(void)
{
if (_nDragMinDist)
return _nDragMinDist;
_nDragMinDist =
(WORD)GetProfileIntA( "windows", "DragMinDist", DD_DEFDRAGMINDIST );
return _nDragMinDist;
}
/*
* CSystemParams::GetSizeCursor(void)
*
* @mfunc
* Get the sizing cursor (double arrow) specified by
* the resource id. If the cursors are not loaded
* load them and cache them.
* parameters:
* idcur - cursor resource id.
*
* @rdesc
* Handle to cursor or null if failure. Returns NULL if
* idcur is null.
*/
HCURSOR CSystemParams::GetSizeCursor(LPTSTR idcur)
{
if( !idcur )
{
return NULL;
}
//If any of the cursors aren't loaded, try loading them.
if( !(_hcurSizeNS && _hcurSizeWE && _hcurSizeNWSE && _hcurSizeNESW) )
{
if (!_hcurSizeNS)
{
_hcurSizeNS = LoadCursor(NULL, IDC_SIZENS);
}
if (!_hcurSizeWE)
{
_hcurSizeWE = LoadCursor(NULL, IDC_SIZEWE);
}
if (!_hcurSizeNWSE)
{
_hcurSizeNWSE = LoadCursor(NULL, IDC_SIZENWSE);
}
if (!_hcurSizeNESW)
{
_hcurSizeNESW = LoadCursor(NULL, IDC_SIZENESW);
}
}
//Return the cursor corresponding to the id passed in.
if( (idcur == IDC_SIZENS) && _hcurSizeNS)
{
return _hcurSizeNS;
}
if( (idcur == IDC_SIZEWE) && _hcurSizeWE )
{
return _hcurSizeWE;
}
if( (idcur == IDC_SIZENWSE) && _hcurSizeNWSE )
{
return _hcurSizeNWSE;
}
if( (idcur == IDC_SIZENESW) && _hcurSizeNESW )
{
return _hcurSizeNESW;
}
AssertSz(FALSE, "Failure loading sizing cursor.");
return NULL;
}
/* excerpt from new winuser.h for calls to SystemParametersInfo */
#ifndef SPI_GETWHEELSCROLLLINES
#define SPI_GETWHEELSCROLLLINES 104
#endif
/*
* CSystemParams::GetRollerLineScrollCount()
*
* @mfunc returns the number of lines to scroll with a roller mouse wheel.
* -1 means scroll by pages
*
* @devnote We have to do different things for different platforms; NT4.0 has
* built in support for this functionality.
*/
LONG CSystemParams::GetRollerLineScrollCount()
{
#ifndef PEGASUS
if( _cLineScroll == 0 )
{
// this stuff isn't supported on the MAC
#ifndef _MAC
HKEY hdlKey;
DWORD keyDataType;
CHAR charData[128];
DWORD dwDataBufSize;
// Read registry directly for Windows 9x & WinNT3.51, if WinNT 4.0
// and above then use SystemParametersInfo
if( (dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) ||
(dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(dwMajorVersion < 4))
{
// Read registry directly
if ( RegOpenKeyExA(HKEY_CURRENT_USER,
"Control Panel\\Desktop",
0,
KEY_QUERY_VALUE,
&hdlKey) == ERROR_SUCCESS )
{
dwDataBufSize = sizeof(charData);
if ( RegQueryValueExA(hdlKey,
"WheelScrollLines",
NULL, // reserved
&keyDataType,
(LPBYTE) &charData,
&dwDataBufSize) == ERROR_SUCCESS )
{
_cLineScroll = strtoul( charData, //String representation
NULL,
10);
}
}
RegCloseKey(hdlKey);
}
else if ( (dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(dwMajorVersion >= 4) )
{
SystemParametersInfoA(SPI_GETWHEELSCROLLLINES, 0, &_cLineScroll, 0);
}
#endif // _MAC
// if we still didn't get anything good, fall back to the default
if( _cLineScroll == 0 )
{
_cLineScroll = 3;
}
}
#endif
return _cLineScroll;
}
//
// Object Stabilization classes
//
//+-------------------------------------------------------------------------
//
// Member: CSafeRefCount::CSafeRefCount
//
// Synopsis: constructor for the safe ref count class
//
// Effects:
//
// Arguments: none
//
// Requires:
//
// Returns: none
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 28-Jul-94 alexgo author
//
// Notes:
//
//--------------------------------------------------------------------------
CSafeRefCount::CSafeRefCount()
{
m_cRefs = 0;
m_cNest = 0;
m_fInDelete = FALSE;
m_fForceZombie = FALSE;
}
//+-------------------------------------------------------------------------
//
// Member: CSafeRefCount::CSafeRefCount (virtual)
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 28-Jul-94 alexgo author
//
// Notes:
//
//--------------------------------------------------------------------------
CSafeRefCount::~CSafeRefCount()
{
Assert(m_cRefs == 0 && m_cNest == 0 && m_fInDelete == TRUE);
}
//+-------------------------------------------------------------------------
//
// Member: CSafeRefCount::SafeAddRef
//
// Synopsis: increments the reference count on the object
//
// Effects:
//
// Arguments: none
//
// Requires:
//
// Returns: ULONG -- the reference count after the increment
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm: increments the reference count.
//
// History: dd-mmm-yy Author Comment
// 28-Jul-94 alexgo author
//
// Notes:
//
//--------------------------------------------------------------------------
ULONG CSafeRefCount::SafeAddRef()
{
m_cRefs++;
//AssertSz(m_fInDelete == FALSE, "AddRef called on deleted object!");
// this *could* be really bad. If we are deleting the object,
// it means that during the destructor, somebody made an outgoing
// call eventually ended up with another addref to ourselves
// (even though all pointers to us had been 'Released').
//
// this is usually caused by code like the following:
// m_pFoo->Release();
// m_pFoo = NULL;
//
// If the the Release may cause Foo to be deleted, which may cause
// the object to get re-entered during Foo's destructor. However,
// 'this' object has not yet set m_pFoo to NULL, so it may
// try to continue to use m_pFoo.
//
// However, the May '94 aggregation rules REQUIRE this behaviour
// In your destructor, you have to addref the outer unknown before
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -