mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
780 lines
30 KiB
780 lines
30 KiB
//*-----------------------------------------------------------------------
|
|
//| MODULE: WCTMEM.C
|
|
//| PROJECT: Windows Comparison Tool
|
|
//|
|
|
//| PURPOSE: This module contains some memory management routines, as
|
|
//| well as control info pump routines for the WCT engine.
|
|
//|
|
|
//| REVISION HISTORY:
|
|
//| 04-16-92 w-steves TestDlgs (2.0) code complete
|
|
//| 11-07-90 randyki Incorporated coding standards,
|
|
//| lots of clean-up, etc.
|
|
//| 10-09-90 randyki Ported to engine from UI sources
|
|
//| 08-29-90 garysp Created file
|
|
//*-----------------------------------------------------------------------
|
|
#include "enghdr.h"
|
|
|
|
#ifndef WIN32
|
|
#pragma hdrstop ("engpch.pch")
|
|
#endif
|
|
|
|
CHAR szSeparator[] = "MF_SEPARATOR";
|
|
CHAR szBreak[] = "MF_MENUBREAK";
|
|
CHAR szBarBreak[] = "MF_MENUBARBREAK";
|
|
|
|
BOOL APIENTRY EnumAddChildren (HWND hWnd, DWORD lParam);
|
|
VOID GlobolToLocal (RECT ParentRect, LPCTLDEF LpCtl);
|
|
|
|
//------------------------------------------------------------------------
|
|
// Define the OutDebug macro on definition of the DEBUG macro
|
|
//------------------------------------------------------------------------
|
|
#ifdef DEBUG
|
|
#define OutDebug(N) OutputDebugString(N)
|
|
#else
|
|
#define OutDebug(N)
|
|
#endif
|
|
|
|
//*-----------------------------------------------------------------------
|
|
//| fAddControlToList
|
|
//|
|
|
//| PURPOSE: Adds a control to a given control array.
|
|
//|
|
|
//| ENTRY: hWnd - Handle to control to add
|
|
//| hCtlList - Handle to destination control array
|
|
//| nCount - Number of controls in array (updated)
|
|
//|
|
|
//| EXIT: 0 if successful
|
|
//*-----------------------------------------------------------------------
|
|
INT FARPUBLIC fAddControlToList (HWND hWnd, HANDLE hCtlList, INT FAR *nCount,
|
|
LPRECT lpParentRect)
|
|
{
|
|
CTLDEF Ctl;
|
|
INT fRetVal;
|
|
|
|
if ((fRetVal = fCtlFromHwnd(hWnd, (LPCTLDEF)&Ctl)) == WCT_NOERR)
|
|
{
|
|
if (lpParentRect)
|
|
GlobolToLocal(*lpParentRect,(LPCTLDEF)&Ctl); // WCT Ver2
|
|
return (fAddCtl (hCtlList, (LPCTLDEF)&Ctl, nCount));
|
|
}
|
|
return (fRetVal);
|
|
}
|
|
|
|
//*-----------------------------------------------------------------------
|
|
//| GlobolToLocal
|
|
//|
|
|
//| PURPOSE: Convert the Control's Rect from absolute screen co-or to
|
|
//| co-or relative to its parent dialog window.
|
|
//|
|
|
//| ENTRY: ParentRect - Parent Window Rect
|
|
//| LpCtl - Pointer to Control Array
|
|
//|
|
|
//*-----------------------------------------------------------------------
|
|
VOID GlobolToLocal (RECT ParentRect, LPCTLDEF LpCtl)
|
|
{
|
|
|
|
// Recalculate Control's Rect using
|
|
// Parent Window's TOP LEFT cornor co-or
|
|
//--------------------------------------
|
|
LpCtl->dcr.yMin -= (WORD) ParentRect.top;
|
|
LpCtl->dcr.yLast -= (WORD) ParentRect.top;
|
|
LpCtl->dcr.xLeft -= (WORD) ParentRect.left;
|
|
LpCtl->dcr.xRight -= (WORD) ParentRect.left;
|
|
}
|
|
|
|
//*-----------------------------------------------------------------------
|
|
//| fAddMenuItem
|
|
//|
|
|
//| PURPOSE: Create a CTL using information obtained from a menu given
|
|
//| (hMenu) and an item number (i), and add that CTL to the
|
|
//| array of controls hGMemCtls.
|
|
//|
|
|
//| ENTRY: hMenu - Handle to menu
|
|
//| i - Number of menu item to add to control array
|
|
//| hCtls - Handle of control array
|
|
//| nCount - Number of controls in array (updated)
|
|
//|
|
|
//| EXIT: Number of items in submenu, or -1 if an error occurs
|
|
//*-----------------------------------------------------------------------
|
|
INT fAddMenuItem (HMENU hMenu, INT i, HANDLE hCtls, INT FAR *nCount)
|
|
{
|
|
CTLDEF Ctl;
|
|
WORD RetVal, nMstate;
|
|
|
|
// Add the information from the menu item to Ctl
|
|
//----------------------------------------------------------------
|
|
GetMenuString (hMenu, i, (LPSTR)Ctl.rgText, cchTextMac, MF_BYPOSITION);
|
|
lstrcpy (Ctl.rgClass, "MenuItem");
|
|
|
|
// Add Menu State to lower word of lStyleBits
|
|
//-------------------------------------------
|
|
nMstate = GetMenuState (hMenu, i, MF_BYPOSITION);
|
|
|
|
// Check to see if this menu has a submenu. If so, return the
|
|
// number of items in the submenu and mask the flags to a BYTE;
|
|
// else just return 0 and use the flag WORD.
|
|
//
|
|
// Also, store the number of submenu in lStyleBits field.
|
|
//----------------------------------------------------------------
|
|
if (GetSubMenu (hMenu, i))
|
|
{
|
|
Ctl.lStyleBits = (LONG)(nMstate >> 8);
|
|
Ctl.nState = nMstate & 255;
|
|
RetVal = nMstate >> 8;
|
|
nMstate &= 255;
|
|
}
|
|
else
|
|
{
|
|
Ctl.nState = nMstate;
|
|
Ctl.lStyleBits = 0;
|
|
RetVal = 0;
|
|
}
|
|
|
|
// Zero out the rect/style/enabled/visible to keep random-ness away
|
|
//----------------------------------------------------------------
|
|
Ctl.dcr.xLeft = 0;
|
|
Ctl.dcr.yMin = 0;
|
|
Ctl.dcr.xRight = 0;
|
|
Ctl.dcr.yLast = 0;
|
|
|
|
// If this is a separator, splat the text "MF_SEPARATOR" into the
|
|
// rgText field of Ctl (same for MF_MENUBREAK and MF_MENUBARBREAK)
|
|
//----------------------------------------------------------------
|
|
if (nMstate & MF_SEPARATOR)
|
|
lstrcpy (Ctl.rgText, szSeparator);
|
|
else if (nMstate & MF_MENUBREAK)
|
|
lstrcpy (Ctl.rgText, szBreak);
|
|
else if (nMstate & MF_MENUBARBREAK)
|
|
lstrcpy (Ctl.rgText, szBarBreak);
|
|
|
|
// Add Ctl to the control array hCtls
|
|
//----------------------------------------------------------------
|
|
if (fAddCtl (hCtls, (LPCTLDEF)&Ctl, nCount) != WCT_NOERR)
|
|
{
|
|
OutDebug ("Out of Control Memory");
|
|
return (-1);
|
|
}
|
|
|
|
// Return the number of items in sub-menu (may be 0)
|
|
//----------------------------------------------------------------
|
|
return (RetVal);
|
|
}
|
|
|
|
|
|
//*------------------------------------------------------------------------
|
|
//| AddMenuStructure
|
|
//|
|
|
//| PURPOSE: This routine adds all menu items (recursively) in the
|
|
//| menu identified by hMenu to the control array defined by
|
|
//| hGMemCtls (size in nItemCount).
|
|
//|
|
|
//| ENTRY: hMenu - Handle to menu (sub-menu) to add to array
|
|
//| hGMemCtls - Handle of control array
|
|
//| nItemCount - Number of controls in array (updated)
|
|
//|
|
|
//|EXIT: TRUE if successful, or FALSE if error occurred (any level)
|
|
//------------------------------------------------------------------------
|
|
INT AddMenuStructure (HMENU hMenu, HANDLE hGMemCtls, INT FAR *nItemCount)
|
|
{
|
|
INT nMenuItems, i, SubCount;
|
|
HMENU hSubMenu;
|
|
|
|
nMenuItems = GetMenuItemCount (hMenu);
|
|
if (nMenuItems == -1)
|
|
{
|
|
OutDebug ("GetMenuItemCount failed!\n\r");
|
|
return (FALSE);
|
|
}
|
|
for (i=0; i<nMenuItems; i++)
|
|
{
|
|
SubCount = fAddMenuItem (hMenu, i, hGMemCtls, nItemCount);
|
|
if (SubCount == -1)
|
|
return (FALSE);
|
|
if (SubCount > 0)
|
|
{
|
|
hSubMenu = GetSubMenu (hMenu, i);
|
|
|
|
// Assert that hSubMenu is not NULL
|
|
//--------------------------------------------------
|
|
WinAssert (hSubMenu != NULL)
|
|
|
|
// Add this sub-menu structure to the control array
|
|
//--------------------------------------------------
|
|
if (!AddMenuStructure (hSubMenu, hGMemCtls,
|
|
nItemCount) )
|
|
return (FALSE);
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
//*-----------------------------------------------------------------------
|
|
//| fPumpHandleForInfo
|
|
//|
|
|
//| PURPOSE: This routine grabs control information out of the window
|
|
//| indicated by hWnd. The information obtained depends on
|
|
//| the value of the Operation variable:
|
|
//|
|
|
//| Value What it does
|
|
//| ----------------------------------------------------------
|
|
//| PUMP_CTL Adds a control item with the information
|
|
//| extracted directly from the hWnd given.
|
|
//|
|
|
//| PUMP_ALL Using EnumChildWindows, adds a control
|
|
//| item with the information extracted from
|
|
//| every child window of hWnd. Does NOT
|
|
//| add the information from hWnd itself.
|
|
//| Adds nothing if hWnd has no children.
|
|
//| The contents of hGMemCtls prior to the
|
|
//| call are *lost*.
|
|
//|
|
|
//| PUMP_MENU Adds control items which contain info
|
|
//| extracted from the menu associated with
|
|
//| hWnd. Adds nothing if hWnd has no menu.
|
|
//| The contents of hGMemCtls prior to the
|
|
//| call are retained.
|
|
//|
|
|
//| SPECIAL CASES: If the hWnd given points to an SDM dialog,
|
|
//| all the controls are placed in hGMemCtls -- the previous
|
|
//| contents are lost. If hWnd indicates a group box, all
|
|
//| elements of that group box and hWnd itself are added to
|
|
//| hGMemCtls -- the previous contents are retained.
|
|
//|
|
|
//| ENTRY: hWnd - Handle of target window
|
|
//| hGMemCtls - Handle of control array
|
|
//| nItemCount - Number of controls in array (updated)
|
|
//| Operation - Operation code (see above)
|
|
//|
|
|
//| EXIT: WCT_NOERR indicates success, otherwise error code returned
|
|
//*-----------------------------------------------------------------------
|
|
INT FARPUBLIC fPumpHandleForInfo (HWND hWnd, HANDLE hGMemCtls,
|
|
INT FAR *nItemCount, INT Operation)
|
|
{
|
|
DWORD sm;
|
|
RECT TempRect, Rect1, Rect2, ParentRect;
|
|
LPCTLDEF lpMem;
|
|
CTLDEF Ctl;
|
|
HWND hWndNext;
|
|
INT i, fIn, fRes;
|
|
LONG lWndStyle;
|
|
ENUMPARM Enum;
|
|
HMENU hMenu;
|
|
CHAR szClass[11];
|
|
|
|
// First thing to do is check for an SDM dialog type
|
|
//--------------------------------------------------
|
|
sm = SendMessage (hWnd, WM_GETCOUNT, wVerEB, 0L);
|
|
if (sm > 0)
|
|
{
|
|
// This IS an SDM dialog, so get all the controls out
|
|
// of it and place them in our array (we must allocate
|
|
// for it first -- sm indicates size in bytes)
|
|
//----------------------------------------------------
|
|
if (hGMemCtls)
|
|
i=fReallocBlock (hGMemCtls, (INT)(sm/sizeof(CTLDEF))+1);
|
|
else
|
|
i=fInitBlock ((HANDLE FAR *)&hGMemCtls,
|
|
(INT)(sm/sizeof(CTLDEF))+1);
|
|
if (i != WCT_NOERR)
|
|
return (i);
|
|
|
|
// Place the size in bytes as the first longword in the block
|
|
//----------------------------------------------------
|
|
lpMem = (LPCTLDEF)GlobalLock (hGMemCtls);
|
|
((DWORD FAR *)lpMem)[0] = sm;
|
|
|
|
// Get the control information UNDONE: error checking here!
|
|
//----------------------------------------------------
|
|
SendMessage (hWnd, WM_GETCONTROLS, wVerEB, (DWORD)lpMem);
|
|
*nItemCount = (INT)(sm / sizeof(CTLDEF));
|
|
|
|
// Done - unlock and leave
|
|
//----------------------------------------------------
|
|
GlobalUnlock (hGMemCtls);
|
|
return (WCT_NOERR);
|
|
}
|
|
if (sm == errNoCurrentDlg)
|
|
{
|
|
OutDebug ("No Current SDM Dialog");
|
|
return (WCT_APPSPECIFIC);
|
|
}
|
|
if (sm == errInvalidVerId)
|
|
{
|
|
OutDebug ("Invalid SDM Version ID");
|
|
return (WCT_APPSPECIFIC);
|
|
}
|
|
if (sm != 0)
|
|
{
|
|
OutDebug ("Unexpected SDM SendMessage return value");
|
|
return (WCT_APPSPECIFIC);
|
|
}
|
|
|
|
// The hWnd given is NOT an SDM dialog (sm came back 0). Here we
|
|
// check the value of Operation. If PUMP_MENU, we take care of
|
|
// that case first.
|
|
//------------------------------------------------------------------
|
|
if (Operation == PUMP_MENU)
|
|
{
|
|
// Get a handle to the window's system menu (if one exists)
|
|
//----------------------------------------------------------
|
|
hMenu = GetSystemMenu (hWnd, 0);
|
|
if (hMenu)
|
|
if (!AddMenuStructure (hMenu, hGMemCtls, nItemCount))
|
|
OutDebug ("AddMenuStructure failed!\n\r");
|
|
|
|
// Get a handle to the window's menu (if there is one)
|
|
//----------------------------------------------------------
|
|
hMenu = GetMenu (hWnd);
|
|
if (hMenu)
|
|
if (!AddMenuStructure (hMenu, hGMemCtls, nItemCount))
|
|
OutDebug ("AddMenuStructure failed!\n\r");
|
|
return (WCT_NOERR);
|
|
}
|
|
|
|
// Version 2.00 (Changed)
|
|
// In version 1.00, user cannot grep the parent control because
|
|
// Testdlgs will froce PUMP_ALL if it sees a individual grep of
|
|
// a true dialog box.
|
|
// In version 2.00, Testdlgs will not force the PUMP type, so
|
|
// the user can get the parent dialog box.
|
|
// (the next few lines are from Version 1.00, for reference)
|
|
//
|
|
// // The operation is NOT PUMP_MENU - here, we check for PUMP_ALL.
|
|
// // If so, force the DIALOG BOX class which in turn forces the
|
|
// // enumeration of the child windows of hWnd.
|
|
//---------------------------------------------------------------
|
|
|
|
GetClassName (hWnd, (LPSTR)szClass, 10);
|
|
|
|
// This is the check for groupboxes. If this guy is a groupbox,
|
|
// we grab next windows (with GetNextWindow()) starting with the
|
|
// groupbox, and add the ones whose rectangles intersect with the
|
|
// groupbox's rectangle.
|
|
//---------------------------------------------------------------
|
|
lWndStyle = GetWindowLong (hWnd, GWL_STYLE);
|
|
if ( !(lstrcmpi(szClass, "BUTTON")) && (lWndStyle & BS_GROUPBOX))
|
|
{
|
|
if (fAddControlToList (hWnd, hGMemCtls, nItemCount, NULL))
|
|
OutDebug ("Error adding control");
|
|
GetWindowRect (hWnd, &Rect1);
|
|
hWndNext = hWnd;
|
|
do
|
|
{
|
|
hWndNext = GetNextWindow (hWndNext, GW_HWNDNEXT);
|
|
GetWindowRect (hWndNext, &Rect2);
|
|
fIn = IntersectRect ((LPRECT)&TempRect,
|
|
(LPRECT)&Rect1,
|
|
(LPRECT)&Rect2);
|
|
if (fIn)
|
|
if (fAddControlToList (hWndNext, hGMemCtls,
|
|
nItemCount, NULL))
|
|
OutDebug ("Error adding control");
|
|
}
|
|
while (fIn);
|
|
return (WCT_NOERR);
|
|
}
|
|
|
|
// Version 2.00 will ignore the check for "#32770" and will only
|
|
// check for the Operation type. This allows the user to grep
|
|
// an individual parent dialog window (control) which is not
|
|
// possible in Version 1.00
|
|
//
|
|
// // Version 1.00 comments
|
|
// // This is the check for "real" dialog boxes. This is kind of
|
|
// // interesting, but we found that the class name for all "normal"
|
|
// // dialog boxes is "#32770". So, that is what we check for. If
|
|
// // that is found to be the class name, we add ALL the children of
|
|
// // that window (using EnumChildWindows() with a callback routine
|
|
// // (EnumAddChildren()) that adds the child given) to the list.
|
|
//----------------------------------------------------------------
|
|
if (Operation == PUMP_ALL)
|
|
{
|
|
Enum.ItemCount = 0;
|
|
Enum.MemHandle = hGMemCtls;
|
|
GetWindowRect(hWnd,(LPRECT)&ParentRect);
|
|
Enum.lpParentRect = (LPRECT)&ParentRect;
|
|
EnumChildWindows (hWnd, (WNDENUMPROC) EnumAddChildren,
|
|
(LPARAM) (ENUMPARM FAR *)&Enum);
|
|
*nItemCount = Enum.ItemCount;
|
|
return (WCT_NOERR);
|
|
}
|
|
|
|
// Well, it looks like this is just a little ol' control, so we'll
|
|
// simply add it to the CTLDEF array by itself.
|
|
//----------------------------------------------------------------
|
|
else
|
|
{
|
|
if (fRes = (fCtlFromHwnd(hWnd, (LPCTLDEF)&Ctl)) == WCT_NOERR)
|
|
{
|
|
if (fRes = fAddCtl (hGMemCtls,
|
|
(LPCTLDEF)&Ctl, nItemCount) )
|
|
{
|
|
OutDebug ("Out of Control Memory");
|
|
return (fRes);
|
|
}
|
|
return (WCT_NOERR);
|
|
}
|
|
OutDebug ("fCtlFromHwnd did not return WCT_NOERR");
|
|
return (fRes);
|
|
}
|
|
}
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| EnumAddChildren
|
|
//|
|
|
//| PURPOSE: Callback routine for EnumChildWindows - simply adds the
|
|
//| window to the CTLDEF array (pointed to by the MemHandle field
|
|
//| of the ENUMPARM structure passed in the lParam parameter)
|
|
//| and increments the count (in the ItemCount field of the
|
|
//| ENUMPARM structure)
|
|
//|
|
|
//| ENTRY: (Per Windows convention)
|
|
//| hWnd - Handle of child window
|
|
//| lParam - Pointer to structure containing handle and count
|
|
//|
|
|
//| EXIT: Always returns TRUE (Per Windows convention)
|
|
//*-------------------------------------------------------------------------
|
|
BOOL APIENTRY EnumAddChildren (HWND hWnd, DWORD lParam)
|
|
{
|
|
if (fAddControlToList (hWnd,
|
|
((ENUMPARM FAR *)lParam)->MemHandle,
|
|
(INT FAR *)&((ENUMPARM FAR *)lParam)->ItemCount,
|
|
(LPRECT)(((ENUMPARM FAR *)lParam)->lpParentRect)
|
|
)
|
|
)
|
|
OutDebug ("Error adding control in EnumAddChildren");
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| fInitBlock
|
|
//|
|
|
//| PURPOSE: Initialize a control array (allocate global memory)
|
|
//|
|
|
//| ENTRY: hmem - Pointer to global memory handle (updated)
|
|
//| nSize - Size requirement of new array (in controls)
|
|
//|
|
|
//| EXIT: 0 if successful
|
|
//*-------------------------------------------------------------------------
|
|
INT FARPUBLIC fInitBlock(HANDLE FAR *hmem, INT nSize)
|
|
{
|
|
HANDLE hTmpMem;
|
|
INT i;
|
|
|
|
// Fail if requested block size is > 200 controls
|
|
// I'm Imposing this limit because I get GP faults when
|
|
// the buffer grows above 64K, so pick a round number and limit
|
|
// to that number.
|
|
//--------------------------------------------------------------
|
|
if (nSize > 200)
|
|
return ( WCT_OUTOFMEMORY );
|
|
|
|
// Assume no problems
|
|
//--------------------------------------------------------------
|
|
i = WCT_NOERR;
|
|
|
|
hTmpMem = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE,
|
|
nSize * sizeof(CTLDEF));
|
|
|
|
if (hTmpMem != NULL)
|
|
*hmem = hTmpMem;
|
|
else
|
|
i = WCT_OUTOFMEMORY;
|
|
|
|
return (i);
|
|
}
|
|
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| fReallocBlock
|
|
//|
|
|
//| PURPOSE: Change the size of an existing control array
|
|
//|
|
|
//| ENTRY: hmem - Handle to control array
|
|
//| nSize - New size requirement of array (in controls)
|
|
//|
|
|
//| EXIT: 0 if successful
|
|
//*-------------------------------------------------------------------------
|
|
INT FARPUBLIC fReallocBlock(HANDLE hmem, INT nSize)
|
|
{
|
|
HANDLE hTmpMem;
|
|
INT i=WCT_NOERR;
|
|
|
|
// Fail if requested block size is > 200 controls
|
|
// I'm Imposing this limit because I get GP faults when
|
|
// the buffer grows above 64K, so pick a round number and limit
|
|
// to that number.
|
|
//--------------------------------------------------------------
|
|
if (nSize > 200)
|
|
return ( WCT_OUTOFMEMORY );
|
|
|
|
// Re-Alloc will zero initilize any new memory area. It will fail
|
|
// if the new size is greater than 64K (-16 bytes in std mode)
|
|
//--------------------------------------------------------------
|
|
hTmpMem = GlobalReAlloc(hmem, nSize * sizeof(CTLDEF),
|
|
GMEM_ZEROINIT | GMEM_MOVEABLE);
|
|
|
|
if (hTmpMem != hmem)
|
|
i = WCT_OUTOFMEMORY;
|
|
|
|
return (i);
|
|
}
|
|
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| fAddCtl
|
|
//|
|
|
//| PURPOSE: Add a control to the end of a given control array
|
|
//|
|
|
//| ENTRY: hmem - Handle to control array
|
|
//| ctl - Control to add to array
|
|
//| nCount - Pointer to number of controls in array (updated)
|
|
//|
|
|
//| EXIT: 0 if successful
|
|
//*-------------------------------------------------------------------------
|
|
INT FARPUBLIC fAddCtl(HANDLE hmem, LPCTLDEF ctl, INT FAR *nCount)
|
|
{
|
|
WORD wFlags;
|
|
INT nSizeBlock, i=WCT_NOERR, j;
|
|
LPCTLDEF lpTmp;
|
|
|
|
// Assume block is not discardable
|
|
//--------------------------------------------------------------
|
|
wFlags = GlobalFlags (hmem);
|
|
WinAssert( !(wFlags && GMEM_DISCARDABLE) );
|
|
|
|
// how big is the current memory block?
|
|
//--------------------------------------------------------------
|
|
nSizeBlock = (INT)GlobalSize (hmem);
|
|
nSizeBlock /= sizeof(CTLDEF);
|
|
|
|
if (nSizeBlock == *nCount)
|
|
{
|
|
// Try increasing by twenty
|
|
// loop decrements immediatly so .. add an extra one.
|
|
// Will loop through trying to allocate memory
|
|
// will stop if I'm at the starting size of the
|
|
// memory block OR if i'm successful in reallocating
|
|
//------------------------------------------------------
|
|
j = nSizeBlock + 21;
|
|
do
|
|
{
|
|
j--;
|
|
i = fReallocBlock(hmem, j);
|
|
}
|
|
while ( (i != WCT_NOERR) && (j > (nSizeBlock+1) ) );
|
|
|
|
if (i != WCT_NOERR)
|
|
return (i);
|
|
}
|
|
|
|
// Assume the rest should pass
|
|
//--------------------------------------------------------------
|
|
i = WCT_NOERR;
|
|
|
|
// Either block is big enough or reallocation passed so
|
|
// lets add the control to the end of the array
|
|
//--------------------------------------------------------------
|
|
lpTmp = (LPCTLDEF)GlobalLock( hmem );
|
|
|
|
if (lpTmp != NULL)
|
|
{
|
|
// Add control to nCount location (zero based array)
|
|
//------------------------------------------------------
|
|
lpTmp[*nCount] = *ctl;
|
|
|
|
// increment number of controls stored
|
|
//------------------------------------------------------
|
|
(*nCount)++;
|
|
|
|
// unlock the buffer.
|
|
//------------------------------------------------------
|
|
GlobalUnlock (hmem);
|
|
}
|
|
else
|
|
i = WCT_OUTOFMEMORY;
|
|
|
|
return (i);
|
|
}
|
|
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| fDelCtl
|
|
//|
|
|
//| PURPOSE: Delete a control from a given array of controls
|
|
//|
|
|
//| ENTRY: hmem - Handle to control array
|
|
//| nCtl - Index of the control to delete
|
|
//| nCount - Pointer to the number of controls in array
|
|
//|
|
|
//| EXIT: 0 if successful
|
|
//*-------------------------------------------------------------------------
|
|
INT FARPUBLIC fDelCtl(HANDLE hmem, INT nCtl, INT FAR *nCount)
|
|
{
|
|
INT i, j;
|
|
LPCTLDEF lpTmp;
|
|
|
|
if ( (nCtl < 1) || (nCtl > *nCount) )
|
|
return (WCT_BADCTLINDEX);
|
|
|
|
// Assume the rest should pass
|
|
//--------------------------------------------------------------
|
|
i = WCT_NOERR;
|
|
|
|
// lets Delete the control from the array
|
|
//--------------------------------------------------------------
|
|
lpTmp = (LPCTLDEF)GlobalLock( hmem );
|
|
|
|
if (lpTmp != NULL)
|
|
{
|
|
// iff nCtl < nCount go through the loop
|
|
// sliding controls down in array.
|
|
// because in the case where nCtl = *nCount
|
|
// control will be deleted by just decrementing
|
|
// *nCount
|
|
//------------------------------------------------------
|
|
if ( nCtl < *nCount)
|
|
for (j = nCtl-1; j < *nCount-1; j++)
|
|
lpTmp[j] = lpTmp[j+1];
|
|
|
|
// decrement number of controls stored
|
|
//------------------------------------------------------
|
|
(*nCount)--;
|
|
|
|
// unlock the buffer
|
|
//------------------------------------------------------
|
|
GlobalUnlock( hmem );
|
|
}
|
|
else
|
|
i = WCT_OUTOFMEMORY;
|
|
|
|
return (i);
|
|
}
|
|
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| fRepCtl
|
|
//|
|
|
//| PURPOSE: Place a control at a given index in a control array
|
|
//|
|
|
//| ENTRY: hmem - Handle to control array
|
|
//| Ctl - Control to be placed in array
|
|
//| nCtl - Index into array to place control
|
|
//| nCount - Number of controls in the array (updated)
|
|
//|
|
|
//| EXIT: 0 if successful
|
|
//*-------------------------------------------------------------------------
|
|
INT FARPUBLIC fRepCtl(HANDLE hmem, LPCTLDEF Ctl, INT nCtl,
|
|
INT FAR *nCount)
|
|
{
|
|
INT i;
|
|
LPCTLDEF lpTmp;
|
|
|
|
if ( (nCtl < 1) || (nCtl > *nCount) )
|
|
return (WCT_BADCTLINDEX);
|
|
|
|
// Assume the rest should pass
|
|
//--------------------------------------------------------------
|
|
i = WCT_NOERR;
|
|
|
|
// Lock down the array and copy the given control to slot nCtl
|
|
//--------------------------------------------------------------
|
|
lpTmp = (LPCTLDEF)GlobalLock( hmem );
|
|
|
|
if (lpTmp != NULL)
|
|
{
|
|
// array is zero based, number passed in is 1 based
|
|
//------------------------------------------------------
|
|
lpTmp[nCtl-1] = Ctl[0];
|
|
GlobalUnlock (hmem);
|
|
}
|
|
else
|
|
i = WCT_OUTOFMEMORY;
|
|
|
|
return (i);
|
|
}
|
|
|
|
|
|
//*-------------------------------------------------------------------------
|
|
//| fInsCtl
|
|
//|
|
|
//| PURPOSE: Insert a control into a control array
|
|
//|
|
|
//| ENTRY: hmem - Handle to control array
|
|
//| Ctl - Control to insert into the array
|
|
//| nCtl - Insertion point index into array
|
|
//| nCount - Number of controls in array (updated)
|
|
//|
|
|
//| EXIT: 0 if successful
|
|
//*-------------------------------------------------------------------------
|
|
INT FARPUBLIC fInsCtl(HANDLE hmem, LPCTLDEF Ctl, INT nCtl,
|
|
INT FAR *nCount)
|
|
{
|
|
LPCTLDEF lpTmp;
|
|
WORD wFlags;
|
|
INT nSizeBlock;
|
|
INT i, j;
|
|
|
|
if ( (nCtl < 1) || (nCtl > *nCount) )
|
|
return (WCT_BADCTLINDEX);
|
|
|
|
// Assume block is not discardable
|
|
//--------------------------------------------------------------
|
|
wFlags = GlobalFlags (hmem);
|
|
WinAssert( !(wFlags && GMEM_DISCARDABLE) );
|
|
|
|
// how big is the current memory block?
|
|
//--------------------------------------------------------------
|
|
nSizeBlock = (INT)GlobalSize( hmem );
|
|
nSizeBlock /= sizeof(CTLDEF);
|
|
|
|
if (nSizeBlock == *nCount)
|
|
{
|
|
// Try increasing by twenty
|
|
// loop decrements immediatly so .. add an extra one.
|
|
// Will loop through trying to allocate memory
|
|
// will stop if I'm at the starting size of the
|
|
// memory block OR if i'm successful in reallocating
|
|
//------------------------------------------------------
|
|
j = nSizeBlock + 21;
|
|
do
|
|
{
|
|
j--;
|
|
i = fReallocBlock(hmem, j);
|
|
}
|
|
while ( (i != WCT_NOERR) && (j > (nSizeBlock + 1) ) );
|
|
|
|
// Return error message - if couldn't reallocate...
|
|
//------------------------------------------------------
|
|
if (i != WCT_NOERR)
|
|
return (i);
|
|
}
|
|
|
|
// Assume the rest should pass
|
|
//--------------------------------------------------------------
|
|
i = WCT_NOERR;
|
|
|
|
// Copy the controls after the insertion point down one slot,
|
|
// and then place the new control in the newly "opened" slot.
|
|
//--------------------------------------------------------------
|
|
lpTmp = (LPCTLDEF)GlobalLock( hmem );
|
|
|
|
if (lpTmp != NULL)
|
|
{
|
|
for (j = *nCount; j >= nCtl; j--)
|
|
lpTmp[j] = lpTmp[j-1];
|
|
|
|
// Assign new value
|
|
//------------------------------------------------------
|
|
lpTmp[nCtl-1] = Ctl[0];
|
|
|
|
GlobalUnlock( hmem );
|
|
}
|
|
else
|
|
i = WCT_OUTOFMEMORY;
|
|
|
|
return (i);
|
|
}
|