Windows2003-3790/multimedia/opengl/toolkits/libmtk/mtkwproc.cxx
2020-09-30 16:53:55 +02:00

904 lines
27 KiB
C++

/******************************Module*Header*******************************\
* Module Name: sswproc.cxx
*
* Window procedure functions.
*
* Copyright (c) 1996 Microsoft Corporation
\**************************************************************************/
#include "mtk.hxx"
#include "mtkinit.hxx"
#include "palette.hxx"
#include "clear.hxx"
#include "mtkwproc.hxx"
//mf: some of this stuff should be per window-group eventually
SSW_TABLE sswTable;
//mf: this needs to be per window group
static BOOL bInBackground;
// forward declarations of internal functions
LONG SS_ScreenSaverProc( HWND, UINT, WPARAM, LPARAM );
LONG MainPaletteManageProc(HWND, UINT, WPARAM, LPARAM );
static LONG InputManageProc(HWND, UINT, WPARAM, LPARAM );
static void ForceRedraw( HWND Window );
static void ssw_RealizePalette( PMTKWIN pssw, BOOL bBackground );
static void ssw_DeletePalette( PMTKWIN pssw );
/**************************************************************************\
* ScreenSaverProc
*
* Processes messages for the top level screen saver window.
*
* Unhandled msgs are sent to DefScreenSaverProc
\**************************************************************************/
LONG
mtkWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
MTKWIN *pmtkwin;
switch (message)
{
case WM_CREATE:
case WM_ERASEBKGND:
return SS_ScreenSaverProc( hwnd, message, wParam, lParam);
case WM_ACTIVATE:
if ( LOWORD(wParam) == WA_INACTIVE ) {
SS_DBGMSG( "Main_Proc: WM_ACTIVATE inactive\n" );
bInBackground = TRUE;
} else {
SS_DBGMSG( "Main_Proc: WM_ACTIVATE active\n" );
bInBackground = FALSE;
}
// fall thru
case WM_QUERYNEWPALETTE:
case WM_PALETTECHANGED:
case WM_SYSCOLORCHANGE:
case MTK_WM_PALETTE:
return( MainPaletteManageProc( hwnd, message, wParam, lParam ) );
case WM_DESTROY:
pmtkwin = sswTable.PsswFromHwnd( hwnd );
if( ! pmtkwin ) {
SS_WARNING( "WM_DESTROY : pmtkwin is NULL\n" );
return 0;
}
//mf: Before deleting this top level window, we need to use its
// still-valid dc to things like restore SystemPaletteUse mode. Ideally this
// should be done after ~SSW has dumped GL, but ~SSW also releases the DC.
// If this is a problem, we can create a new function SSW::DeleteGL that just
// gets rid of the GL part
if( sswTable.GetNumWindows() == 1 ) {
// This is the last window, special considerations
// Handle any palette stuff
if( gpssPal )
ssw_DeletePalette( pmtkwin );
delete pmtkwin;
// All win's have now been deleted - remove global ptr to top of
// window chain.
gpMtkwinMain = NULL;
}
// mf: ! this kills the app !, that's not what we want...
// Doesn't seem to make much of a difference if call it or not
// PostQuitMessage(0);
return 0;
case WM_PAINT:
SS_DBGMSG( "mtkWndProc: WM_PAINT\n" );
pmtkwin = sswTable.PsswFromHwnd( hwnd );
pmtkwin->Repaint( TRUE );
#ifdef SS_DO_PAINT
// We do the painting rather than letting the system do it
hdc = BeginPaint(hwnd, &ps);
// This is case where bg brush is NULL and we have to do repaint
// We only do it after bInited, as this will avoid the first
// -> bInited removed 5/1/97
// WM_PAINT for the entire window.
DrawGdiRect( hdc, ghbrBg, &ps.rcPaint );
EndPaint(hwnd, &ps);
return 0; // painting has been handled by us
#endif // SS_DO_PAINT
break;
case MTK_WM_REDRAW:
SS_DBGMSG( "mtkWndProc: MTK_WM_REDRAW\n" );
pmtkwin = sswTable.PsswFromHwnd( hwnd );
pmtkwin->Display();
return 0;
case WM_MOVE:
SS_DBGMSG( "mtkWndProc: WM_MOVE\n" );
pmtkwin = sswTable.PsswFromHwnd( hwnd );
pmtkwin->pos.x = LOWORD(lParam);
pmtkwin->pos.y = HIWORD(lParam);
break;
//mf
#if 1
// This allows us to pick up under-bits on window moves
case WM_WINDOWPOSCHANGING:
{
LPWINDOWPOS lpwp = (LPWINDOWPOS) lParam;
SS_DBGMSG1( "mtkWndProc: WM_WINDOWPOSCHANGING, flags = %x\n",
lpwp->flags );
pmtkwin = sswTable.PsswFromHwnd( hwnd );
if( pmtkwin->pBackgroundBitmap ) {
#if 0
// If window moving, don't want to copy old bits...
//mf: this actually fukin works (sometimes) !
if( !(lpwp->flags & SWP_NOMOVE) ) {
SS_DBGMSG( "mtkWndProc: WM_WINDOWPOSCHANGING, moving\n" );
// window moving
if( !(lpwp->flags & SWP_NOCOPYBITS) ) {
lpwp->flags |= SWP_NOCOPYBITS;
}
}
}
#else
// Things seem to work better if we always force this flag, otherwise now
// and then get partial update rects, even if window active and moving (in
// which case update rect should always be entire client area.
lpwp->flags |= SWP_NOCOPYBITS;
}
#endif
}
break;
case WM_WINDOWPOSCHANGED:
{
LPWINDOWPOS lpwp = (LPWINDOWPOS) lParam;
SS_DBGMSG1( "mtkWndProc: WM_WINDOWPOSCHANGED, flags = %x\n",
lpwp->flags );
pmtkwin = sswTable.PsswFromHwnd( hwnd );
if( pmtkwin->pBackgroundBitmap ) {
if( !(lpwp->flags & SWP_NOMOVE) ) {
// window moved
// SS_DBGMSG( "mtkWndProc: WM_WINDOWPOSCHANGED, moved\n" );
}
}
}
break;
#endif
case WM_TIMER:
SS_DBGMSG( "mtkWndProc: WM_TIMER\n" );
if( pmtkwin = sswTable.PsswFromHwnd( hwnd ) )
pmtkwin->mtkAnimate();
return 0;
}
//mf: for now...
return SS_ScreenSaverProc(hwnd, message, wParam, lParam);
}
/**************************************************************************\
* SS_ScreenSaverProc
*
* Wndproc for child windows, and some messages from top-level window
*
* Unhandled msgs are sent to DefWindowProc
\**************************************************************************/
LONG
SS_ScreenSaverProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
int i;
int retVal;
MTKWIN *pmtkwin;
switch (message)
{
case WM_CREATE:
SS_DBGMSG1( "SS_Proc: WM_CREATE for 0x%x\n", hwnd );
pmtkwin = (PMTKWIN) ( ((LPCREATESTRUCT)lParam)->lpCreateParams );
sswTable.Register( hwnd, pmtkwin );
pmtkwin->hwnd = hwnd;
break;
case MTK_WM_PALETTE:
return( MainPaletteManageProc( hwnd, message, wParam, lParam ) );
case WM_DESTROY:
pmtkwin = sswTable.PsswFromHwnd( hwnd );
SS_DBGMSG1( "SS_Proc: WM_DESTROY for 0x%x\n", hwnd );
// Delete the pssw - this does all necessary cleanup
if( pmtkwin )
delete pmtkwin;
else
SS_WARNING( "WM_DESTROY : pmtkwin is NULL\n" );
break;
case WM_PAINT:
// We get this msg every time window moves, since SWP_NOCOPYBITS is
// specified with the window move.
hdc = BeginPaint(hwnd, &ps);
//mf: will need to call DisplayFunc here...
// -> currently being handled in tkWndProc
EndPaint(hwnd, &ps);
break;
case WM_SIZE:
SS_DBGMSG( "mtkWndProc: WM_SIZE\n" );
pmtkwin = sswTable.PsswFromHwnd( hwnd );
// Suspend drawing if minimized
if( wParam == SIZE_MINIMIZED ) {
// Stop any animation
pmtkwin->animator.Stop(); // noop if no timer
// We can return here, since for now we don't do anything
// in a minimized window
return 0;
}
else { // either SIZE_RESTORED or SIZE_MAXIMIZED
// If there is an animation func, restart animation
//mf: potential problem here if timer was not started...
pmtkwin->animator.Start();
}
pmtkwin->Resize( LOWORD(lParam), HIWORD(lParam) );
break;
// these msg's are never received by the child window ?
case WM_ACTIVATE:
case WM_QUERYNEWPALETTE:
case WM_PALETTECHANGED:
return( MainPaletteManageProc( hwnd, message, wParam, lParam ) );
case WM_MOUSEMOVE:
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
case WM_KEYDOWN:
case WM_CHAR:
//mf: this can be fn ptr eventually, so ss's can use it too
return( InputManageProc( hwnd, message, wParam, lParam ) );
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
/**************************************************************************\
* InputManageProc
*
\**************************************************************************/
static LONG
InputManageProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
MTKWIN *pmtkwin = sswTable.PsswFromHwnd( hWnd );
int key;
switch( message ) {
case WM_MOUSEMOVE:
if (pmtkwin->MouseMoveFunc)
{
GLenum mask;
mask = 0;
if (wParam & MK_LBUTTON) {
mask |= TK_LEFTBUTTON;
}
if (wParam & MK_MBUTTON) {
mask |= TK_MIDDLEBUTTON;
}
if (wParam & MK_RBUTTON) {
mask |= TK_RIGHTBUTTON;
}
if ((*pmtkwin->MouseMoveFunc)( LOWORD(lParam), HIWORD(lParam), mask ))
{
ForceRedraw( hWnd );
}
}
return (0);
case WM_LBUTTONDOWN:
SetCapture(hWnd);
if (pmtkwin->MouseDownFunc)
{
if ( (*pmtkwin->MouseDownFunc)(LOWORD(lParam), HIWORD(lParam),
TK_LEFTBUTTON) )
{
ForceRedraw( hWnd );
}
}
return (0);
case WM_LBUTTONUP:
ReleaseCapture();
if (pmtkwin->MouseUpFunc)
{
if ((*pmtkwin->MouseUpFunc)(LOWORD(lParam), HIWORD(lParam), TK_LEFTBUTTON))
{
ForceRedraw( hWnd );
}
}
return (0);
case WM_MBUTTONDOWN:
SetCapture(hWnd);
if (pmtkwin->MouseDownFunc)
{
if ((*pmtkwin->MouseDownFunc)(LOWORD(lParam), HIWORD(lParam),
TK_MIDDLEBUTTON))
{
ForceRedraw( hWnd );
}
}
return (0);
case WM_MBUTTONUP:
ReleaseCapture();
if (pmtkwin->MouseUpFunc)
{
if ((*pmtkwin->MouseUpFunc)(LOWORD(lParam), HIWORD(lParam),
TK_MIDDLEBUTTON))
{
ForceRedraw( hWnd );
}
}
return (0);
case WM_RBUTTONDOWN:
SetCapture(hWnd);
if (pmtkwin->MouseDownFunc)
{
if ((*pmtkwin->MouseDownFunc)(LOWORD(lParam), HIWORD(lParam),
TK_RIGHTBUTTON))
{
ForceRedraw( hWnd );
}
}
return (0);
case WM_RBUTTONUP:
ReleaseCapture();
if (pmtkwin->MouseUpFunc)
{
if ((*pmtkwin->MouseUpFunc)(LOWORD(lParam), HIWORD(lParam),
TK_RIGHTBUTTON))
{
ForceRedraw( hWnd );
}
}
return (0);
case WM_KEYDOWN:
switch (wParam) {
case VK_SPACE: key = TK_SPACE; break;
case VK_RETURN: key = TK_RETURN; break;
case VK_ESCAPE: key = TK_ESCAPE; break;
case VK_LEFT: key = TK_LEFT; break;
case VK_UP: key = TK_UP; break;
case VK_RIGHT: key = TK_RIGHT; break;
case VK_DOWN: key = TK_DOWN; break;
default: key = GL_FALSE; break;
}
if (key && pmtkwin->KeyDownFunc)
{
GLenum mask;
mask = 0;
if (GetKeyState(VK_CONTROL)) {
mask |= TK_CONTROL;
}
if (GetKeyState(VK_SHIFT)) {
mask |= TK_SHIFT;
}
if ( (*pmtkwin->KeyDownFunc)(key, mask) )
{
ForceRedraw( hWnd );
}
}
return (0);
case WM_CHAR:
if (('0' <= wParam && wParam <= '9') ||
('a' <= wParam && wParam <= 'z') ||
('A' <= wParam && wParam <= 'Z')) {
key = wParam;
} else {
key = GL_FALSE;
}
if (key && pmtkwin->KeyDownFunc) {
GLenum mask;
mask = 0;
if (GetKeyState(VK_CONTROL)) {
mask |= TK_CONTROL;
}
if (GetKeyState(VK_SHIFT)) {
mask |= TK_SHIFT;
}
if ( (*pmtkwin->KeyDownFunc)(key, mask) )
{
ForceRedraw( hWnd );
}
}
return (0);
}
return 0;
}
static void
ForceRedraw( HWND hwnd )
{
MSG Message;
#if 0
if (!PeekMessage(&Message, hwnd, WM_PAINT, WM_PAINT, PM_NOREMOVE) )
{
InvalidateRect( hwnd, NULL, FALSE );
}
#else
//mf: There is a problem with doing the redraw via WM_PAINT. WM_PAINT is sent
// by the system when part of the window needs to be redrawn. For transparent
// windows, we hook a grab background off of this, so if we use WM_PAINT for
// our redraws, we'll just grab the previous gl image. Solutions are :
// 1) Call redraw proc immediately here (possible timing problem)
// 2) * Send redraw msg to queue
// Possible side-effect : by not sending a WM_PAINT, the system is less
// informed about what we're doing, but heck, we don't use PAINT for animations
// anyways.
if (!PeekMessage(&Message, hwnd, MTK_WM_REDRAW, MTK_WM_REDRAW, PM_NOREMOVE) )
{
PostMessage( hwnd, MTK_WM_REDRAW, 0, 0l );
}
#endif
}
/**************************************************************************\
* UpdateDIBColorTable
*
* Wrapper for SSDIB_UpdateColorTable.
*
* This controls the hPal parameter for SSDIB_UpdateColorTable.
*
\**************************************************************************/
void
ssw_UpdateDIBColorTable( HDC hdcbm, HDC hdcwin )
{
SS_PAL *pssPal = gpssPal;
if( !pssPal )
return;
#if 0
HPALETTE hpal = pssPal->bTakeOver ? pssPal->hPal : NULL;
#else
HPALETTE hpal = pssPal->hPal;
#endif
SSDIB_UpdateColorTable( hdcbm, hdcwin, hpal );
}
/**************************************************************************\
* RealizePalette
*
\**************************************************************************/
static void
ssw_RealizePalette( PMTKWIN pmtkwin, BOOL bBackground )
{
// assumed pssPal valid if get here
SS_PAL *pssPal = gpssPal;
if( !pmtkwin->hrc ) {
// Can assume this window doesn't need to worry about palettes, but
// if any of its children are subWindows, it will have to take care
// of it *for* them.
return; // no hrc and no subWindow children
}
pssPal->Realize( pmtkwin->hwnd, pmtkwin->hdc, bBackground );
}
/**************************************************************************\
* ssw_DeletePalette
*
\**************************************************************************/
static void
ssw_DeletePalette( PMTKWIN pmtkwin )
{
SS_PAL *pssPal = gpssPal;
//mf: !!! ? this din't seem to be used
#if 0
if( pssPal->bTakeOver ) {
// We took over the system palette - make a note of this
// for any special ss termination conditions.
gpss->flags |= SS_PALETTE_TAKEOVER;
}
#endif
pssPal->SetDC( pmtkwin->hdc );
delete pssPal;
gpssPal = NULL;
}
/**************************************************************************\
* PaletteManage Procs
\**************************************************************************/
/* palette related msgs's:
- WM_ACTIVATE:
The WM_ACTIVATE message is sent when a window is being activated or
deactivated. This message is sent first to the window procedure of
the top-level window being deactivated; it is then sent to the
window procedure of the top-level window being activated.
- WM_QUERYNEWPALETTE:
The WM_QUERYNEWPALETTE message informs a window that it is about
to receive the keyboard focus, giving the window the opportunity
to realize its logical palette when it receives the focus.
If the window realizes its logical palette, it must return TRUE;
otherwise, it must return FALSE.
- WM_PALETTECHANGED:
The WM_PALETTECHANGED message is sent to all top-level and overlapped
windows after the window with the keyboard focus has realized its
logical palette, thereby changing the system palette. This message
enables a window that uses a color palette but does not have the
keyboard focus to realize its logical palette and update its client
area.
This message must be sent to all top-level and overlapped windows,
including the one that changed the system palette. If any child
windows use a color palette, this message must be passed on to them
as well.
To avoid creating an infinite loop, a window that receives this
message must not realize its palette, unless it determines that
wParam does not contain its own window handle.
- WM_SYSCOLORCHANGE:
The WM_SYSCOLORCHANGE message is sent to all top-level windows when
a change is made to a system color setting.
- MTK_WM_PALETTE:
Internal msg. Uses:
- In fullscreen mode, we send this from Main wndproc to main
window's children on WM_ACTIVATE.
- When this is received in SS_ScreenSaverProc, if fullscreen,
it does:
UnrealizeObject( pssPal->hPal );
RealizePalette( hdc );
otherwise, it is passed to PaletteManageProc, where
Realize is called (for 'floater' windows to realize
their palettes).
- It is also sent by DelayPaletteRealization() when it can't get
the system palette.
*/
/**************************************************************************\
* MainPaletteManageProc
*
* Top-level palette management proc.
* Returns immediately if no palette set - otherwise calls through
* paletteManageProc function pointer
*
\**************************************************************************/
LONG
MainPaletteManageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if( !gpssPal )
// No palette management required
return 0;
// else call approppriate palette manage proc
return (*gpssPal->paletteManageProc)(hwnd, message, wParam, lParam);
}
/**************************************************************************\
* FullScreenPaletteManageProc
*
* Processes messages relating to palette management in full screen mode.
*
\**************************************************************************/
LONG
FullScreenPaletteManageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
SS_PAL *pssPal;
MTKWIN *pmtkwin;
switch (message)
{
case WM_ACTIVATE:
#if SS_DEBUG
if ( LOWORD(wParam) == WA_INACTIVE )
SS_DBGMSG1( "FullScreen_PMProc: WM_ACTIVATE : inactive for 0x%x\n",
hwnd );
else
SS_DBGMSG1( "FullScreen_PMProc: WM_ACTIVATE : active for 0x%x\n",
hwnd );
#endif
// !! This msg is only sent to main top level window
pmtkwin = sswTable.PsswFromHwnd( hwnd );
pssPal = gpssPal;
if ( pssPal->bUseStatic ) {
HDC hdc = pmtkwin->hdc; // hdc *always* valid for top-level pssw
// Note: wParam = 0 when window going *inactive*
SetSystemPaletteUse( hdc, wParam ? SYSPAL_NOSTATIC
: pssPal->uiOldStaticUse);
}
// Send MTK_WM_PALETTE msg to main window
SendMessage( hwnd, MTK_WM_PALETTE, wParam, 0);
break;
case MTK_WM_PALETTE:
SS_DBGMSG1( "FullScreen_PMProc: MTK_WM_PALETTE for 0x%x\n", hwnd );
pmtkwin = sswTable.PsswFromHwnd( hwnd );
HDC hdc;
if( hdc = pmtkwin->hdc )
{
pssPal = gpssPal;
//mf: this should call thru ssw_RealizePalette for bitmap case ? (for now
// don't need to, since we take over palette...)
// This resets the logical palette, causing remapping of
// logical palette to system palette
// mf: !!! ?? how come no dc with UnrealizeObject ? does that
// mean its done once per app, not per child window ?
// yeah, we should move this up...
UnrealizeObject( pssPal->hPal );
RealizePalette( hdc );
}
break;
}
return 0;
}
/**************************************************************************\
* PaletteManageProc
*
* Processes messages relating to palette management for the general case.
*
* Note: this msg handling strategy is based loosely on the tk, so any changes
* there should be reflected here
\**************************************************************************/
LONG
PaletteManageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// One global palette for all windows
MTKWIN *pmtkwin;
if( !gpssPal )
return 0;
switch (message)
{
case WM_ACTIVATE:
SendMessage( hwnd, MTK_WM_PALETTE, bInBackground, 0);
// Allow DefWindowProc() to finish the default processing (which
// includes changing the keyboard focus).
//mf: I added this - watch out for ss implications
return DefWindowProc( hwnd, message, wParam, lParam );
break;
case WM_QUERYNEWPALETTE:
#if 0
SS_DBGMSG1( "Palette_Proc: WM_QUERYNEWPALETTE for 0x%x\n", hwnd );
// We don't actually realize palette here (we do it at WM_ACTIVATE
// time), but we need the system to think that we have so that a
// WM_PALETTECHANGED message is generated.
//mf: why can't we just realize here ? and who wants even more messages to
// be generated !!! :)
// This is the only msg preview mode gets wrt palettes !
if( !ss_fPreviewMode() )
return (1);
// We are in preview mode - realize the palette
SendMessage( hwnd, MTK_WM_PALETTE, bInBackground, 0);
break;
#else
return (1);
#endif
case WM_PALETTECHANGED:
SS_DBGMSG1( "Palette_Proc: WM_PALETTECHANGED for 0x%x\n", hwnd );
// Respond to this message only if the window that changed the palette
// is not this app's window.
// We are not the foreground window, so realize palette in the
// background. We cannot call Realize to do this because
// we should not do any of the gbUseStaticColors processing while
// in background.
// Actually, we *can* be the fg window, so don't realize if
// we're in foreground
if( (hwnd != (HWND) wParam) && bInBackground )
SendMessage( hwnd, MTK_WM_PALETTE, TRUE, 0);
break;
case WM_SYSCOLORCHANGE:
// If the system colors have changed and we have a palette
// for an RGB surface then we need to recompute the static
// color mapping because they might have been changed in
// the process of changing the system colors.
SS_DBGMSG1( "Palette_Proc: WM_SYSCOLORCHANGE for 0x%x\n", hwnd );
gpssPal->ReCreateRGBPalette();
SendMessage( hwnd, MTK_WM_PALETTE, bInBackground, 0);
break;
case MTK_WM_PALETTE:
SS_DBGMSG2( "Palette_Proc: MTK_WM_PALETTE for 0x%x, bg = %d\n",
hwnd, wParam );
// Realize palette for this window and its children
// wParam = TRUE if realize as bg
pmtkwin = sswTable.PsswFromHwnd( hwnd );
ssw_RealizePalette( pmtkwin, wParam );
break;
}
return 0;
}
/******************************Public*Routine******************************\
* SSW_TABLE constructor
*
\**************************************************************************/
SSW_TABLE::SSW_TABLE()
{
nEntries = 0;
}
/******************************Public*Routine******************************\
* Register
*
* Register a HWND/PSSW pair.
\**************************************************************************/
void
SSW_TABLE::Register( HWND hwnd, PMTKWIN pssw )
{
SSW_TABLE_ENTRY *pEntry;
// Check if already in table
if( PsswFromHwnd( hwnd ) )
return;
// put hwnd/pssw pair in the table
pEntry = &sswTable[nEntries];
pEntry->hwnd = hwnd;
pEntry->pssw = pssw;
nEntries++;
}
/******************************Public*Routine******************************\
* PsswFromHwnd
*
* Return PSSW for the HWND
\**************************************************************************/
PMTKWIN
SSW_TABLE::PsswFromHwnd( HWND hwnd )
{
int count = nEntries;
SSW_TABLE_ENTRY *pEntry = sswTable;
while( count-- ) {
if( pEntry->hwnd == hwnd )
return pEntry->pssw;
pEntry++;
}
return NULL;
}
/******************************Public*Routine******************************\
* Remove
*
* Remove HWND/PSSW entry from table
\**************************************************************************/
BOOL
SSW_TABLE::Remove( HWND hwnd )
{
SSW_TABLE_ENTRY *pEntry = sswTable;
// Locate the hwnd/pssw pair
for( int count = 0 ; count < nEntries ; count++, pEntry++ ) {
if( pEntry->hwnd == hwnd )
break;
}
if( count == nEntries )
// couldn't find it in the table
return FALSE;
// Remove entry / shuffle up other entries
for( int i = count; i < nEntries-1; i ++ ) {
sswTable[i] = sswTable[i+1];
}
nEntries--;
return TRUE;
}