mirror of https://github.com/tongzx/nt5src
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.
1403 lines
29 KiB
1403 lines
29 KiB
/*---------------------------------------------------------------------------
|
|
FILE : PLEX.C
|
|
AUTHOR: STOLEN FROM EXCEL modified by NavPal
|
|
This file contains routines used to manipulate the PL (pronounced:
|
|
"plex") structures.
|
|
----------------------------------------------------------------------------*/
|
|
#include "priv.h"
|
|
#pragma hdrstop
|
|
|
|
#ifndef WINNT
|
|
#include "plex.h"
|
|
#include "debug.h"
|
|
#endif
|
|
/*-----------------------------------------------------------------------
|
|
| FInRange
|
|
| Simple little routine that tells you if a number lies within a
|
|
| range.
|
|
|
|
|
|
|
|
| Arguments:
|
|
| w: Number to check
|
|
| wFirst: First number in the range
|
|
| wLast: Last number in the range
|
|
|
|
|
| Returns:
|
|
| fTrue if the number is in range
|
|
|
|
|
| Keywords: in range check
|
|
-----------------------------------------------------------------------*/
|
|
BOOL FInRange(w, wFirst, wLast)
|
|
int w;
|
|
int wFirst, wLast;
|
|
{
|
|
Assert(wLast >= wFirst);
|
|
return(w >= wFirst && w <= wLast);
|
|
}
|
|
#ifdef DEBUG
|
|
/*----------------------------------------------------------------------------
|
|
| FValidPl
|
|
|
|
|
| Checks for a valid PL structure.
|
|
|
|
|
| Arguments:
|
|
| ppl PL to check
|
|
|
|
|
| Returns:
|
|
| fTrue if the PL looks reasonable.
|
|
----------------------------------------------------------------------------*/
|
|
BOOL FValidPl(pvPl)
|
|
VOID *pvPl;
|
|
{
|
|
#define ppl ((PL *)pvPl)
|
|
if (ppl== NULL ||
|
|
ppl->cbItem == 0 ||
|
|
ppl->iMac < 0 ||
|
|
ppl->iMax < 0 ||
|
|
ppl->iMax < ppl->iMac)
|
|
return(fFalse);
|
|
return(fTrue);
|
|
#undef ppl
|
|
}
|
|
#endif //DEBUG
|
|
/*----------------------------------------------------------------------------
|
|
| CbPlAlloc
|
|
|
|
|
| Returns amount of memory allocated to the given PL
|
|
|
|
|
| Arguments:
|
|
| ppl PL to return info for.
|
|
|
|
|
| Returns:
|
|
| memory allocated to the PL
|
|
----------------------------------------------------------------------------*/
|
|
int CbPlAlloc(pvPl)
|
|
VOID *pvPl;
|
|
{
|
|
#define ppl ((PL *)pvPl)
|
|
if (ppl == NULL)
|
|
return(0);
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(ppl));
|
|
#endif // DEBUG
|
|
return(WAlign(cbPL + (ppl->iMax * ppl->cbItem)));
|
|
#undef ppl
|
|
}
|
|
/*----------------------------------------------------------------------------
|
|
| FreePpl
|
|
|
|
|
| Frees a PL.
|
|
|
|
|
| Arguments:
|
|
| ppl PL to free
|
|
|
|
|
| Returns:
|
|
| Nothing.
|
|
----------------------------------------------------------------------------*/
|
|
void FreePpl(pvPl)
|
|
VOID *pvPl;
|
|
{
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(pvPl));
|
|
#endif // DEBUG
|
|
VFreeMemP(pvPl, (unsigned) CbPlAlloc(pvPl));
|
|
}
|
|
/*----------------------------------------------------------------------------
|
|
| PplAlloc
|
|
|
|
|
| Allocates and initializes a PL.
|
|
|
|
|
| Arguments:
|
|
| cbItem sizeof structure in the PL
|
|
| dAlloc number of items to allocate at a time
|
|
| iMax number of items in initial allocation
|
|
|
|
|
| Returns:
|
|
| Pointer to PL.
|
|
|
|
|
| Notes:
|
|
| returns NULL if OOM
|
|
----------------------------------------------------------------------------*/
|
|
VOID *PplAlloc(cbItem, dAlloc, iMax)
|
|
unsigned cbItem;
|
|
int dAlloc;
|
|
unsigned iMax;
|
|
{
|
|
PL *ppl;
|
|
long cb;
|
|
|
|
if (iMax > 32767) /* not too likely, but what the heck. */
|
|
return(NULL);
|
|
|
|
Assert((cbItem>=1 && cbItem<=65535u) && FInRange(dAlloc, 1, 31));
|
|
|
|
cb = WAlign((long) cbPL + (long) cbItem * (long) iMax);
|
|
|
|
ppl = (PL *)PvMemAlloc((unsigned) cb);
|
|
if(ppl==NULL)
|
|
return(NULL);
|
|
FillBuf(ppl,0, (unsigned) cb);
|
|
ppl->cbItem = cbItem;
|
|
ppl->dAlloc = dAlloc;
|
|
ppl->iMax = iMax;
|
|
ppl->fUseCount = fFalse;
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(ppl));
|
|
#endif // DEBUG
|
|
return(ppl);
|
|
}
|
|
/*----------------------------------------------------------------------------
|
|
| IAddPl
|
|
|
|
|
| Adds an item to a PL.
|
|
|
|
|
| Arguments:
|
|
| pppl Pointer to PL. May change if reallocated.
|
|
| pv New item to add.
|
|
|
|
|
| Returns:
|
|
| Index of new item.
|
|
|
|
|
| Notes:
|
|
| returns -1 if OOM
|
|
----------------------------------------------------------------------------*/
|
|
int IAddPl(ppvPl, pv)
|
|
VOID **ppvPl;
|
|
VOID *pv;
|
|
{
|
|
int cbItem;
|
|
int iMac;
|
|
PL *ppl, *pplNew;
|
|
|
|
ppl = *ppvPl;
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(ppl));
|
|
#endif // DEBUG
|
|
cbItem = ppl->cbItem;
|
|
iMac = ppl->iMac;
|
|
#ifdef UNUSED
|
|
if (ppl->fUseCount)
|
|
{
|
|
int i;
|
|
BYTE *pb;
|
|
|
|
(*(int *)pv) = 1;
|
|
|
|
// Search for an unused entry
|
|
for (i = 0, pb = ppl->rg; i < iMac; i++, pb += cbItem)
|
|
{
|
|
if ((*(int *) pb) == 0)
|
|
{
|
|
bltbh(hpv, hpb, cbItem);
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
if (iMac == ppl->iMax)
|
|
{
|
|
pplNew = PplAlloc(cbItem, ppl->dAlloc, iMac + ppl->dAlloc);
|
|
if(pplNew==NULL)//OOM
|
|
return(-1);
|
|
pplNew->fUseCount = ppl->fUseCount;
|
|
PbMemCopy(pplNew->rg,ppl->rg, iMac * cbItem);
|
|
/* pplNew->iMac = iMac; /* This is not needed because hppl->iMac
|
|
will be over-written later */
|
|
FreePpl(ppl);
|
|
*ppvPl = ppl = pplNew;
|
|
}
|
|
PbMemCopy(&ppl->rg[iMac * cbItem],pv,cbItem);
|
|
ppl->iMac = iMac + 1;
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(*ppvPl));
|
|
#endif // DEBUG
|
|
return(iMac);
|
|
}
|
|
/*----------------------------------------------------------------------------
|
|
| RemovePl
|
|
|
|
|
| Removes an item from a PL.
|
|
|
|
|
| Arguments:
|
|
| ppl PL to remove item from
|
|
| i index of item to remove
|
|
|
|
|
| Returns:
|
|
| fTrue if an item was removed (only fFalse for use count plexes).
|
|
----------------------------------------------------------------------------*/
|
|
BOOL RemovePl(pvPl, i)
|
|
VOID *pvPl;
|
|
int i;
|
|
{
|
|
int iMac;
|
|
int cbItem;
|
|
BYTE *p;
|
|
#define ppl ((PL *)pvPl)
|
|
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(ppl) && i < ppl->iMac);
|
|
#endif // DEBUG
|
|
iMac = ppl->iMac;
|
|
cbItem = ppl->cbItem;
|
|
p = &ppl->rg[i * cbItem];
|
|
#ifdef UNUSED
|
|
if (ppl->fUseCount)
|
|
{
|
|
Assert((*(int HUGE *) hp) > 0);
|
|
if (--(*(int HUGE *) hp) > 0)
|
|
return fFalse;
|
|
}
|
|
#endif
|
|
if (i != iMac - 1)
|
|
{
|
|
PbMemCopy(p,p+cbItem,(iMac - i - 1) * cbItem);
|
|
}
|
|
ppl->iMac = iMac - 1;
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(ppl));
|
|
#endif // DEBUG
|
|
return fTrue;
|
|
#undef ppl
|
|
}
|
|
/*----------------------------------------------------------------------------
|
|
| ILookupPl
|
|
|
|
|
| Searches a PL for an item.
|
|
|
|
|
| Arguments:
|
|
| ppl PL to lookup into
|
|
| p item to lookup
|
|
| pfnSgn Comparison function
|
|
|
|
|
| Returns:
|
|
| index of item, if found.
|
|
| -1 if not found.
|
|
----------------------------------------------------------------------------*/
|
|
int ILookupPl(pvPl, pvItem, pfnSgn)
|
|
VOID *pvPl;
|
|
VOID *pvItem;
|
|
int (*pfnSgn)();
|
|
{
|
|
int i;
|
|
BYTE *p;
|
|
#define ppl ((PL *)pvPl)
|
|
|
|
if (ppl == NULL)
|
|
return(-1);
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(ppl));
|
|
#endif // DEBUG
|
|
#ifdef UNUSED
|
|
if (ppl->fUseCount)
|
|
{
|
|
for (i = 0, p = ppl->rg; i < ppl->iMac; i++, p += ppl->cbItem)
|
|
{
|
|
if (*(int *)p != 0 && (*(int (*)(void *,void *))pfnSgn)(p, pvItem) == sgnEQ)
|
|
return(i);
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
for (i = 0, p = ppl->rg; i < ppl->iMac; i++, p += ppl->cbItem)
|
|
{
|
|
if ((*(int (*)(void *, void *))pfnSgn)(p, pvItem) == sgnEQ)
|
|
return(i);
|
|
}
|
|
}
|
|
return(-1);
|
|
#undef ppl
|
|
}
|
|
/*----------------------------------------------------------------------------
|
|
| PLookupPl
|
|
|
|
|
| Searches a PL for an item
|
|
|
|
|
| Arguments:
|
|
| ppl PL to search
|
|
| pItem item to search for
|
|
| pfnSgn comparison function
|
|
|
|
|
| Returns:
|
|
| Pointer to item, if found
|
|
| Null, if not found
|
|
----------------------------------------------------------------------------*/
|
|
VOID *PLookupPl(pvPl, pvItem, pfnSgn)
|
|
VOID *pvPl;
|
|
VOID *pvItem;
|
|
int (*pfnSgn)();
|
|
{
|
|
int i;
|
|
|
|
if ((i = ILookupPl(pvPl, pvItem, pfnSgn)) == -1)
|
|
return(NULL);
|
|
return(&((PL *)pvPl)->rg[i * ((PL *)pvPl)->cbItem]);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| FLookupSortedPl
|
|
|
|
|
| Searches a sorted PL for an item.
|
|
|
|
|
| Arguments:
|
|
| hppl PL to lookup into
|
|
| hpItem Item to lookup
|
|
| pi Index of found item (or insertion location if not)
|
|
| pfnSgn Comparison function
|
|
|
|
|
| Returns:
|
|
| index of item, if found.
|
|
| index of location to insert if not found.
|
|
----------------------------------------------------------------------------*/
|
|
int FLookupSortedPl(hpvPl, hpvItem, pi, pfnSgn)
|
|
VOID *hpvPl;
|
|
VOID *hpvItem;
|
|
int *pi;
|
|
int (*pfnSgn)();
|
|
{
|
|
int sgn;
|
|
unsigned iMin, iMid, iMac;
|
|
int cbItem;
|
|
BYTE *hprg;
|
|
BYTE *hpMid;
|
|
#define hppl ((PL *)hpvPl)
|
|
|
|
if ((hppl)==NULL)
|
|
{
|
|
*pi = 0;
|
|
return(fFalse);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
Assert(!hppl->fUseCount);
|
|
|
|
sgn = 1;
|
|
cbItem = hppl->cbItem;
|
|
iMin = iMid = 0;
|
|
iMac = hppl->iMac;
|
|
hprg = hppl->rg;
|
|
while (iMin != iMac)
|
|
{
|
|
iMid = iMin + (iMac-iMin)/2;
|
|
Assert(iMid != iMac);
|
|
|
|
hpMid = hprg + iMid*cbItem;
|
|
if ((sgn = (*(int (*)(void *, void *))pfnSgn)(hpMid, hpvItem)) == 0)
|
|
break;
|
|
|
|
/* Too low, look in upper interval */
|
|
if (sgn < 0)
|
|
iMin = ++iMid;
|
|
/* Too high, look in lower interval */
|
|
else
|
|
iMac = iMid;
|
|
}
|
|
|
|
/* Not found, return index of location to insert it */
|
|
*pi = iMid;
|
|
return(sgn == 0);
|
|
#undef hppl
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| IAddNewPl
|
|
|
|
|
| Adds an item to a PL, creating the PL if it's initially NULL.
|
|
|
|
|
| Arguments:
|
|
| phppl pointer to PL
|
|
| hp pointer to item to add
|
|
| cbItem size of item
|
|
|
|
|
| Returns:
|
|
| the index of item added, if successful
|
|
| -1, if out-of-memory
|
|
----------------------------------------------------------------------------*/
|
|
int IAddNewPl(phpvPl, hpv, cbItem)
|
|
VOID **phpvPl;
|
|
VOID *hpv;
|
|
int cbItem;
|
|
{
|
|
int i;
|
|
|
|
#define phppl ((PL **)phpvPl)
|
|
|
|
Assert(((*phppl)==NULL) || !(*phppl)->fUseCount);
|
|
i = -1;
|
|
if ((*phppl)==NULL)
|
|
{
|
|
*phppl = PplAlloc(cbItem, 5, 5);
|
|
}
|
|
if((*phppl)!=NULL)
|
|
{
|
|
Assert((*phppl)->cbItem == cbItem);
|
|
i = IAddPl((VOID **)phppl, hpv);
|
|
}
|
|
return(i);
|
|
#undef phppl
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| IAddNewPlPos
|
|
|
|
|
| Inserts an item into a plex at a specific position.
|
|
|
|
|
| Arguments:
|
|
| the index of the item added, if successful
|
|
| -1 if out-of-memory
|
|
----------------------------------------------------------------------------*/
|
|
int IAddNewPlPos(phpvPl, hpv, cbItem, i)
|
|
VOID **phpvPl;
|
|
VOID *hpv;
|
|
int cbItem;
|
|
int i;
|
|
{
|
|
BYTE *hpT;
|
|
#define phppl ((PL **)phpvPl)
|
|
|
|
Assert(((*phppl)==NULL) || !(*phppl)->fUseCount);
|
|
if (IAddNewPl((VOID **)phppl, hpv, cbItem) == -1)
|
|
return(-1);
|
|
Assert(i < (*phppl)->iMac);
|
|
hpT = &(*phppl)->rg[i * cbItem];
|
|
// bltbh(hpT, hpT + cbItem, ((*phppl)->iMac - i - 1) * cbItem);
|
|
// bltbh(hpv, hpT, cbItem);
|
|
PbMemCopy(hpT + cbItem, hpT, ((*phppl)->iMac - i - 1) * cbItem);
|
|
PbMemCopy(hpT, hpv, cbItem);
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(*phppl));
|
|
#endif // DEBUG
|
|
return(i);
|
|
#undef phppl
|
|
}
|
|
|
|
int IAddPlSort(phpvPl, hpv, pfnSgn)
|
|
VOID **phpvPl;
|
|
VOID *hpv;
|
|
int (*pfnSgn)();
|
|
{
|
|
int i;
|
|
#ifdef DEBUG
|
|
int iOld;
|
|
#endif
|
|
Assert((*phpvPl)!=NULL);
|
|
|
|
if (FLookupSortedPl(*phpvPl, hpv, &i, pfnSgn))
|
|
return(-1);
|
|
|
|
#ifdef DEBUG
|
|
iOld = i;
|
|
#endif
|
|
i = IAddNewPlPos(phpvPl, hpv, (*(PL **)phpvPl)->cbItem, i);
|
|
#ifdef DEBUG
|
|
Assert(i == -1 || i == iOld);
|
|
#endif
|
|
return(i);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//NO CHANGES BELOW THIS LINE PLEASE
|
|
//---------------------------------------------------------------------------
|
|
#ifdef FROMEXCEL
|
|
/*---------------------------------------------------------------------------
|
|
THIS CODE IS FROM EXCEL SOURCES. ITS KEPT HERE FOR REFERENCE
|
|
---------------------------------------------------------------------------*/
|
|
#pragma hdrstop("Excel.pre")
|
|
VSZASSERT
|
|
#include "new.h"
|
|
|
|
|
|
/* This file contains routines used to manipulate the PL (pronounced:
|
|
"plex") structures. They should probably be moved somewhere a little
|
|
more appropriate, like maybe alloc.c */
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| HpLookupPl
|
|
|
|
|
| Searches a PL for an item
|
|
|
|
|
| Arguments:
|
|
| hppl PL to search
|
|
| hpItem item to search for
|
|
| pfnSgn comparison function
|
|
|
|
|
| Returns:
|
|
| Pointer to item, if found
|
|
| hpNull, if not found
|
|
----------------------------------------------------------------------------*/
|
|
VOID HUGE *HpLookupPl(hpvPl, hpvItem, pfnSgn)
|
|
VOID HUGE *hpvPl;
|
|
VOID HUGE *hpvItem;
|
|
int (*pfnSgn)();
|
|
{
|
|
int i;
|
|
|
|
if ((i = ILookupPl(hpvPl, hpvItem, pfnSgn)) == -1)
|
|
return(hpNull);
|
|
return(&((PL HUGE *)hpvPl)->rg[i * ((PL HUGE *)hpvPl)->cbItem]);
|
|
}
|
|
|
|
#ifndef GRAF
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, HpplAlloc)
|
|
#else
|
|
#pragma alloc_text(window2, HpplAlloc)
|
|
#endif
|
|
#else
|
|
#pragma alloc_text(plgboot, HpplAlloc)
|
|
#endif
|
|
/*----------------------------------------------------------------------------
|
|
| HpplAlloc
|
|
|
|
|
| Allocates and initializes a PL.
|
|
|
|
|
| Arguments:
|
|
| cbItem sizeof structure in the PL
|
|
| dAlloc number of items to allocate at a time
|
|
| iMax number of items in initial allocation
|
|
| dg memory group to allocate from
|
|
|
|
|
| Returns:
|
|
| Pointer to PL.
|
|
|
|
|
| Notes:
|
|
| May DoJmp(penvMem).
|
|
----------------------------------------------------------------------------*/
|
|
/*<<mcmain*/
|
|
#pragma NATIVE_START
|
|
VOID HUGE *HpplAlloc(cbItem, dAlloc, iMax, dg)
|
|
unsigned cbItem;
|
|
int dAlloc;
|
|
unsigned iMax;
|
|
unsigned dg;
|
|
{
|
|
PL HUGE *hppl;
|
|
long cb;
|
|
int dgShift;
|
|
|
|
if (iMax > 32767) /* not too likely, but what the heck. */
|
|
DoJmp(penvMem, alctNoMem);
|
|
|
|
Assert((cbItem>=1 && cbItem<=65535u) && FInRange(dAlloc, 1, 31) &&
|
|
FInRange(BLow(dg), 1, 255));
|
|
|
|
cb = WAlign((long) cbPL + (long) cbItem * (long) iMax);
|
|
#ifndef LARGEALLOC
|
|
if(cb >= cbHeapMax)
|
|
{
|
|
ErrorNoMem();
|
|
DoJmp(penvMem, alctNoMem);
|
|
}
|
|
#endif
|
|
|
|
hppl = (PL HUGE *)HpAlloc((unsigned) cb, dg);
|
|
bltcbh(0, hppl, (unsigned) cb);
|
|
Assert(dg!=0);
|
|
for (dgShift = 0; !(dg & 1); dg >>= 1, dgShift++)
|
|
;
|
|
Assert(dgShift<8);
|
|
hppl->cbItem = cbItem;
|
|
hppl->dAlloc = dAlloc;
|
|
hppl->iMax = iMax;
|
|
hppl->fUseCount = fFalse;
|
|
hppl->dgShift = dgShift;
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
return(hppl);
|
|
}
|
|
#pragma NATIVE_END
|
|
/*<<plex*/
|
|
|
|
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, HpplUseCountAlloc)
|
|
#else
|
|
#pragma alloc_text(window2, HpplUseCountAlloc)
|
|
#endif
|
|
VOID HUGE *HpplUseCountAlloc(cbItem, dAlloc, iMax, dg)
|
|
unsigned cbItem;
|
|
int dAlloc;
|
|
unsigned iMax;
|
|
unsigned dg;
|
|
{
|
|
PL HUGE *hppl;
|
|
|
|
hppl = HpplAlloc(cbItem, dAlloc, iMax, dg);
|
|
hppl->fUseCount = fTrue;
|
|
return hppl;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| FreeHppl
|
|
|
|
|
| Frees a PL.
|
|
|
|
|
| Arguments:
|
|
| hppl PL to free
|
|
|
|
|
| Returns:
|
|
| Nothing.
|
|
----------------------------------------------------------------------------*/
|
|
/*<<mcmain*/
|
|
#ifndef GRAF
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, FreeHppl)
|
|
#else
|
|
#pragma alloc_text(window2, FreeHppl)
|
|
#endif
|
|
#endif
|
|
#pragma NATIVE_START
|
|
FreeHppl(hpvPl)
|
|
VOID HUGE *hpvPl;
|
|
{
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hpvPl));
|
|
#endif // DEBUG
|
|
FreeHp(hpvPl, CbPlAlloc(hpvPl));
|
|
}
|
|
#pragma NATIVE_END
|
|
/*<<plex*/
|
|
|
|
#ifndef GRAF
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, ILookupPl)
|
|
#else
|
|
#pragma alloc_text(window2, ILookupPl)
|
|
#endif
|
|
#else
|
|
#pragma alloc_text(swpmisc, ILookupPl)
|
|
#endif
|
|
/*----------------------------------------------------------------------------
|
|
| ILookupPl
|
|
|
|
|
| Searches a PL for an item.
|
|
|
|
|
| Arguments:
|
|
| hppl PL to lookup into
|
|
| hp item to lookup
|
|
| pfnSgn Comparison function
|
|
|
|
|
| Returns:
|
|
| index of item, if found.
|
|
| -1 if not found.
|
|
----------------------------------------------------------------------------*/
|
|
#pragma NATIVE_START
|
|
int ILookupPl(hpvPl, hpvItem, pfnSgn)
|
|
VOID HUGE *hpvPl;
|
|
VOID HUGE *hpvItem;
|
|
int (*pfnSgn)();
|
|
{
|
|
int i;
|
|
BYTE HUGE *hp;
|
|
#define hppl ((PL HUGE *)hpvPl)
|
|
|
|
if (SbFromHp(hppl) == sbNull)
|
|
return(-1);
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
if (hppl->fUseCount)
|
|
{
|
|
for (i = 0, hp = hppl->rg; i < hppl->iMac; i++, hp += hppl->cbItem)
|
|
{
|
|
if (*(int HUGE *)hp != 0 && (*(int (*)(HP, HP))pfnSgn)(hp, hpvItem) == sgnEQ)
|
|
return(i);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0, hp = hppl->rg; i < hppl->iMac; i++, hp += hppl->cbItem)
|
|
{
|
|
if ((*(int (*)(HP, HP))pfnSgn)(hp, hpvItem) == sgnEQ)
|
|
return(i);
|
|
}
|
|
}
|
|
return(-1);
|
|
#undef hppl
|
|
}
|
|
#pragma NATIVE_END
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| FLookupSortedPl
|
|
|
|
|
| Searches a sorted PL for an item.
|
|
|
|
|
| Arguments:
|
|
| hppl PL to lookup into
|
|
| hpItem Item to lookup
|
|
| pi Index of found item (or insertion location if not)
|
|
| pfnSgn Comparison function
|
|
|
|
|
| Returns:
|
|
| index of item, if found.
|
|
| index of location to insert if not found.
|
|
----------------------------------------------------------------------------*/
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, FLookupSortedPl)
|
|
#else
|
|
#pragma alloc_text(window2, FLookupSortedPl)
|
|
#endif
|
|
#pragma NATIVE_START
|
|
int FLookupSortedPl(hpvPl, hpvItem, pi, pfnSgn)
|
|
VOID HUGE *hpvPl;
|
|
VOID HUGE *hpvItem;
|
|
int *pi;
|
|
int (*pfnSgn)();
|
|
{
|
|
int sgn;
|
|
unsigned iMin, iMid, iMac;
|
|
int cbItem;
|
|
BYTE HUGE *hprg;
|
|
BYTE HUGE *hpMid;
|
|
#define hppl ((PL HUGE *)hpvPl)
|
|
|
|
if (SbFromHp(hppl) == sbNull)
|
|
{
|
|
*pi = 0;
|
|
return(fFalse);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
Assert(!hppl->fUseCount);
|
|
|
|
sgn = 1;
|
|
cbItem = hppl->cbItem;
|
|
iMin = iMid = 0;
|
|
iMac = hppl->iMac;
|
|
hprg = hppl->rg;
|
|
while (iMin != iMac)
|
|
{
|
|
iMid = iMin + (iMac-iMin)/2;
|
|
Assert(iMid != iMac);
|
|
|
|
hpMid = hprg + iMid*cbItem;
|
|
if ((sgn = (*(int (*)(HP, HP))pfnSgn)(hpMid, hpvItem)) == 0)
|
|
break;
|
|
|
|
/* Too low, look in upper interval */
|
|
if (sgn < 0)
|
|
iMin = ++iMid;
|
|
/* Too high, look in lower interval */
|
|
else
|
|
iMac = iMid;
|
|
}
|
|
|
|
/* Not found, return index of location to insert it */
|
|
*pi = iMid;
|
|
return(sgn == 0);
|
|
#undef hppl
|
|
}
|
|
#pragma NATIVE_END
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| DeletePl
|
|
|
|
|
| Removes an item from a PL. The resulting PL is compacted.
|
|
|
|
|
| Arguments:
|
|
| phppl pointer to PL to remove item from
|
|
| i index of item to remove
|
|
|
|
|
| Returns:
|
|
| Nothing.
|
|
----------------------------------------------------------------------------*/
|
|
DeletePl(phpvPl, i)
|
|
VOID HUGE **phpvPl;
|
|
int i;
|
|
{
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(*phpvPl));
|
|
#endif // DEBUG
|
|
RemovePl(*phpvPl, i);
|
|
FCompactPl(phpvPl, (*(PL HUGE **)phpvPl)->iMac == 0);
|
|
#ifdef DEBUG
|
|
Assert(SbOfHp(*phpvPl) == sbNull || FValidPl(*phpvPl));
|
|
#endif // DEBUG
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| RemovePl
|
|
|
|
|
| Removes an item from a PL.
|
|
|
|
|
| Arguments:
|
|
| hppl PL to remove item from
|
|
| i index of item to remove
|
|
|
|
|
| Returns:
|
|
| fTrue if an item was removed (only fFalse for use count plexes).
|
|
----------------------------------------------------------------------------*/
|
|
BOOL RemovePl(hpvPl, i)
|
|
VOID HUGE *hpvPl;
|
|
int i;
|
|
{
|
|
int iMac;
|
|
int cbItem;
|
|
BYTE HUGE *hp;
|
|
#define hppl ((PL HUGE *)hpvPl)
|
|
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl) && i < hppl->iMac);
|
|
#endif // DEBUG
|
|
iMac = hppl->iMac;
|
|
cbItem = hppl->cbItem;
|
|
hp = &hppl->rg[i * cbItem];
|
|
|
|
if (hppl->fUseCount)
|
|
{
|
|
Assert((*(int HUGE *) hp) > 0);
|
|
if (--(*(int HUGE *) hp) > 0)
|
|
return fFalse;
|
|
}
|
|
|
|
if (i != iMac - 1)
|
|
{
|
|
bltbh(hp + cbItem, hp, (iMac - i - 1) * cbItem);
|
|
}
|
|
hppl->iMac = iMac - 1;
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
return fTrue;
|
|
#undef hppl
|
|
}
|
|
|
|
#ifndef GRAF
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, IAddPl)
|
|
#else
|
|
#pragma alloc_text(window2, IAddPl)
|
|
#endif
|
|
#else
|
|
#pragma alloc_text(swpmisc, IAddPl)
|
|
#endif
|
|
/*----------------------------------------------------------------------------
|
|
| IAddPl
|
|
|
|
|
| Adds an item to a PL.
|
|
|
|
|
| Arguments:
|
|
| phppl Pointer to PL. May change if reallocated.
|
|
| hp New item to add.
|
|
|
|
|
| Returns:
|
|
| Index of new item.
|
|
|
|
|
| Notes:
|
|
| May DoJmp(penvMem) when reallocating.
|
|
----------------------------------------------------------------------------*/
|
|
/*<<mcmain*/
|
|
#pragma NATIVE_START
|
|
int IAddPl(phpvPl, hpv)
|
|
VOID HUGE **phpvPl;
|
|
VOID HUGE *hpv;
|
|
{
|
|
int cbItem;
|
|
int iMac;
|
|
PL HUGE *hppl, HUGE *hpplNew;
|
|
|
|
hppl = *phpvPl;
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
cbItem = hppl->cbItem;
|
|
iMac = hppl->iMac;
|
|
|
|
if (hppl->fUseCount)
|
|
{
|
|
int i;
|
|
BYTE HUGE *hpb;
|
|
|
|
(*(int HUGE *)hpv) = 1;
|
|
|
|
// Search for an unused entry
|
|
for (i = 0, hpb = hppl->rg; i < iMac; i++, hpb += cbItem)
|
|
{
|
|
if ((*(int HUGE *) hpb) == 0)
|
|
{
|
|
bltbh(hpv, hpb, cbItem);
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (iMac == hppl->iMax || fShakeMem)
|
|
#else
|
|
if (iMac == hppl->iMax)
|
|
#endif
|
|
{
|
|
hpplNew = HpplAlloc(cbItem, hppl->dAlloc, iMac + hppl->dAlloc, 0x01<<hppl->dgShift);
|
|
hpplNew->fUseCount = hppl->fUseCount;
|
|
bltbh(hppl->rg, hpplNew->rg, iMac * cbItem);
|
|
/* hpplNew->iMac = iMac; /* This is not needed because hppl->iMac
|
|
will be over-written later */
|
|
FreeHppl(hppl);
|
|
*phpvPl = hppl = hpplNew;
|
|
}
|
|
bltbh(hpv, &hppl->rg[iMac * cbItem], cbItem);
|
|
hppl->iMac = iMac + 1;
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(*phpvPl));
|
|
#endif // DEBUG
|
|
return(iMac);
|
|
}
|
|
#pragma NATIVE_END
|
|
/*<<plex*/
|
|
|
|
|
|
/* Not used for Mac */
|
|
#ifndef MAC
|
|
/*----------------------------------------------------------------------------
|
|
| ILookAddPl
|
|
|
|
|
| Searces a PL for an item and adds the item if it's not already there.
|
|
|
|
|
| Arguments:
|
|
| phppl Pointer to PL. May change if reallocated.
|
|
| hp Item to find/add.
|
|
| pfnSgn Comparison function
|
|
|
|
|
| Returns:
|
|
| Index of item found/added.
|
|
|
|
|
| Notes:
|
|
| The PL must already be created.
|
|
| May DoJmp(penvMem) when reallocating.
|
|
----------------------------------------------------------------------------*/
|
|
#ifdef DDE
|
|
int ILookAddPl(phpvPl, hpv, pfnSgn)
|
|
VOID HUGE **phpvPl;
|
|
VOID HUGE *hpv;
|
|
int (*pfnSgn)();
|
|
{
|
|
int i;
|
|
#define phppl ((PL HUGE **)phpvPl)
|
|
|
|
Assert(!(*phppl)->fUseCount);
|
|
if ((i = ILookupPl(*phpvPl, hpv, pfnSgn)) == -1)
|
|
i = IAddPl(phpvPl, hpv);
|
|
return(i);
|
|
#undef phppl
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef GRAF
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, IAddNewPl)
|
|
#else
|
|
#pragma alloc_text(window2, IAddNewPl)
|
|
#endif
|
|
#endif
|
|
/*----------------------------------------------------------------------------
|
|
| IAddNewPl
|
|
|
|
|
| Adds an item to a PL, creating the PL if it's initially NULL.
|
|
|
|
|
| Arguments:
|
|
| phppl pointer to PL
|
|
| hp pointer to item to add
|
|
| cbItem size of item
|
|
| dg data group to alloc plex in
|
|
|
|
|
| Returns:
|
|
| the index of item added, if successful
|
|
| -1, if out-of-memory
|
|
----------------------------------------------------------------------------*/
|
|
/*<<mcmain*/
|
|
#pragma NATIVE_START
|
|
int IAddNewPl(phpvPl, hpv, cbItem, dg)
|
|
VOID HUGE **phpvPl;
|
|
VOID HUGE *hpv;
|
|
int cbItem;
|
|
int dg;
|
|
{
|
|
int i;
|
|
ENV *penvSav, env;
|
|
#ifdef DEBUG
|
|
BOOL fShakeMemSav = 2;
|
|
extern BOOL fShakeMem;
|
|
#endif
|
|
|
|
#define phppl ((PL HUGE **)phpvPl)
|
|
|
|
Assert(FNullHp(*phppl) || !(*phppl)->fUseCount);
|
|
i = -1;
|
|
penvSav = penvMem;
|
|
if (SetJmp(penvMem = &env) == 0)
|
|
{
|
|
if (SbOfHp(*phppl) == sbNull)
|
|
{
|
|
*phppl = HpplAlloc(cbItem, 5, 5, dg);
|
|
#ifdef DEBUG
|
|
/* Turn off shake mem in this case, since we don't accomplish
|
|
any additional memory checking when we've just allocated
|
|
the plex from scratch anyway. */
|
|
|
|
Assert(fShakeMem != 2);
|
|
fShakeMemSav = fShakeMem;
|
|
fShakeMem = FALSE;
|
|
#endif /* DEBUG */
|
|
}
|
|
Assert((*phppl)->cbItem == cbItem);
|
|
i = IAddPl((VOID HUGE **)phppl, hpv);
|
|
}
|
|
penvMem = penvSav;
|
|
#ifdef DEBUG
|
|
if (fShakeMemSav != 2)
|
|
fShakeMem = fShakeMemSav;
|
|
#endif /* DEBUG */
|
|
return(i);
|
|
#undef phppl
|
|
}
|
|
#pragma NATIVE_END
|
|
/*<<plex*/
|
|
|
|
#ifndef GRAF
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, IAddNewPlPos)
|
|
#else
|
|
#pragma alloc_text(window2, IAddNewPlPos)
|
|
#endif
|
|
#endif
|
|
/*----------------------------------------------------------------------------
|
|
| IAddNewPlPos
|
|
|
|
|
| Inserts an item into a plex at a specific position.
|
|
|
|
|
| Arguments:
|
|
| the index of the item added, if successful
|
|
| -1 if out-of-memory
|
|
----------------------------------------------------------------------------*/
|
|
/*<<mcmain*/
|
|
#pragma NATIVE_START
|
|
int IAddNewPlPos(phpvPl, hpv, cbItem, i, dg)
|
|
VOID HUGE **phpvPl;
|
|
VOID HUGE *hpv;
|
|
int cbItem;
|
|
int i;
|
|
int dg;
|
|
{
|
|
BYTE HUGE *hpT;
|
|
#define phppl ((PL HUGE **)phpvPl)
|
|
|
|
Assert(FNullHp(*phppl) || !(*phppl)->fUseCount);
|
|
if (IAddNewPl((VOID HUGE **)phppl, hpv, cbItem, dg) == -1)
|
|
return(-1);
|
|
Assert(i < (*phppl)->iMac);
|
|
hpT = &(*phppl)->rg[i * cbItem];
|
|
bltbh(hpT, hpT + cbItem, ((*phppl)->iMac - i - 1) * cbItem);
|
|
bltbh(hpv, hpT, cbItem);
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(*phppl));
|
|
#endif // DEBUG
|
|
return(i);
|
|
#undef phppl
|
|
}
|
|
#pragma NATIVE_END
|
|
/*<<plex*/
|
|
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, IAddPlSort)
|
|
#else
|
|
#pragma alloc_text(window2, IAddPlSort)
|
|
#endif
|
|
int IAddPlSort(phpvPl, hpv, pfnSgn)
|
|
VOID HUGE **phpvPl;
|
|
VOID HUGE *hpv;
|
|
int (*pfnSgn)();
|
|
{
|
|
int i;
|
|
#ifdef DEBUG
|
|
int iOld;
|
|
#endif
|
|
Assert(!FNullHp(*phpvPl));
|
|
|
|
if (FLookupSortedPl(*phpvPl, hpv, &i, pfnSgn))
|
|
return(-1);
|
|
|
|
#ifdef DEBUG
|
|
iOld = i;
|
|
#endif
|
|
i = IAddNewPlPos(phpvPl, hpv, (*(PL HUGE **)phpvPl)->cbItem, i, 1<<(*(PL HUGE **)phpvPl)->dgShift);
|
|
Assert(i == -1 || i == iOld);
|
|
return(i);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| FCompactPl
|
|
|
|
|
| Squeezes unused memory out of a PL
|
|
|
|
|
| Arguments:
|
|
| phppl Plex to compact
|
|
| fFull fTrue if maximal compaction should be made
|
|
|
|
|
| Returns:
|
|
| fTrue if some memory was freed.
|
|
----------------------------------------------------------------------------*/
|
|
BOOL FCompactPl(phpvPl, fFull)
|
|
VOID HUGE **phpvPl;
|
|
BOOL fFull;
|
|
{
|
|
int iMac, cbItem, cbFree, dAlloc;
|
|
BYTE HUGE *hp;
|
|
PL HUGE *hppl = *phpvPl;
|
|
BOOL fFreed = fFalse;
|
|
|
|
if (SbOfHp(hppl) != sbNull)
|
|
{
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
if ((iMac = hppl->iMac) == 0 && fFull)
|
|
{
|
|
FreeHppl(hppl);
|
|
fFreed = fTrue;
|
|
*phpvPl = hpNull;
|
|
}
|
|
else
|
|
{
|
|
if (!fFull)
|
|
{
|
|
dAlloc = hppl->dAlloc;
|
|
iMac = (iMac + dAlloc) / dAlloc * dAlloc;
|
|
}
|
|
hp = &hppl->rg[iMac * (cbItem = hppl->cbItem)];
|
|
if (IbOfHp(hp) & 1)
|
|
{
|
|
/* can't free on an odd boundary */
|
|
Assert((cbItem & 1) && (iMac & 1));
|
|
iMac++;
|
|
hp += cbItem;
|
|
}
|
|
Assert((IbOfHp(hp) & 1) == 0);
|
|
/* must free at least 4 bytes, and it had better
|
|
be an even number */
|
|
if ((cbFree = WAlign((hppl->iMax - iMac) * cbItem)) >= 4)
|
|
{
|
|
CbChopHp(hp, cbFree);
|
|
fFreed = fTrue;
|
|
hppl->iMax = iMac;
|
|
}
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
Assert(SbOfHp(*phpvPl) == sbNull || FValidPl(*phpvPl));
|
|
#endif // DEBUG
|
|
return(fFreed);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
| CbPlAlloc
|
|
|
|
|
| Returns amount of memory allocated to the given PL
|
|
|
|
|
| Arguments:
|
|
| hppl PL to return info for.
|
|
|
|
|
| Returns:
|
|
| memory allocated to the PL
|
|
----------------------------------------------------------------------------*/
|
|
/*<<mcmain*/
|
|
#ifndef GRAF
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, CbPlAlloc)
|
|
#else
|
|
#pragma alloc_text(window2, CbPlAlloc)
|
|
#endif
|
|
#endif
|
|
#pragma NATIVE_START
|
|
int CbPlAlloc(hpvPl)
|
|
VOID HUGE *hpvPl;
|
|
{
|
|
#define hppl ((PL HUGE *)hpvPl)
|
|
if (SbFromHp(hppl) == sbNull)
|
|
return(0);
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
return(WAlign(cbPL + (hppl->iMax * hppl->cbItem)));
|
|
#undef hppl
|
|
}
|
|
#pragma NATIVE_END
|
|
/*<<plex*/
|
|
|
|
#ifndef GRAF
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, ResizePl)
|
|
#else
|
|
#pragma alloc_text(window2, ResizePl)
|
|
#endif
|
|
#endif
|
|
/*----------------------------------------------------------------------------
|
|
| ResizePl
|
|
|
|
|
| Grows the given plex large enough to contain the given number
|
|
| of items.
|
|
|
|
|
| Arguments:
|
|
| phppl plex to reallocate - will change if
|
|
| the plex is grown.
|
|
| iMac number of items the plex must hold.
|
|
|
|
|
| Note:
|
|
| DoJmp(penvMem) if out-of-memory.
|
|
----------------------------------------------------------------------------*/
|
|
/*<<mcmain*/
|
|
#pragma NATIVE_START
|
|
ResizePl(phpvPl, iMac, iIns)
|
|
VOID HUGE **phpvPl;
|
|
int iMac, iIns;
|
|
{
|
|
int iMax;
|
|
int cbItem;
|
|
PL HUGE *hppl;
|
|
#define phppl ((PL HUGE **)phpvPl)
|
|
|
|
hppl = *phppl;
|
|
Assert(!hppl->fUseCount); // NYI
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
cbItem = hppl->cbItem;
|
|
if (hppl->iMax < iMac)
|
|
{
|
|
iMax = (iMac / (int) hppl->dAlloc + 1) * hppl->dAlloc;
|
|
*phppl = HpplAlloc(cbItem, hppl->dAlloc, iMax,
|
|
0x01<<hppl->dgShift);
|
|
#ifdef USECOUNTRESIZE
|
|
(*phppl)->fUseCount = hppl->fUseCount;
|
|
#endif
|
|
if (iIns >= 0)
|
|
{
|
|
bltbh(hppl->rg, (*phppl)->rg, iIns * cbItem);
|
|
bltbh(hppl->rg + iIns * cbItem,
|
|
(*phppl)->rg + (iIns+(iMac-hppl->iMac)) * cbItem,
|
|
(hppl->iMac-iIns) * cbItem);
|
|
}
|
|
else
|
|
bltbh(hppl->rg, (*phppl)->rg, hppl->iMax * cbItem);
|
|
FreeHppl(hppl);
|
|
}
|
|
else if (iIns >= 0)
|
|
{
|
|
bltbh(hppl->rg + iIns * hppl->cbItem,
|
|
hppl->rg + (iIns+(iMac-hppl->iMac)) * cbItem,
|
|
(hppl->iMac-iIns) * cbItem);
|
|
}
|
|
(*phppl)->iMac = iMac;
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(*phppl));
|
|
#endif // DEBUG
|
|
#undef phppl
|
|
}
|
|
#pragma NATIVE_END
|
|
/*<<plex*/
|
|
|
|
|
|
#ifdef MAC
|
|
#pragma alloc_text(window, IIncUseCountPl)
|
|
#else
|
|
#pragma alloc_text(window2, IIncUseCountPl)
|
|
#endif
|
|
int IIncUseCountPl(hpvPl, i)
|
|
VOID HUGE *hpvPl;
|
|
int i;
|
|
{
|
|
#define hppl ((PL HUGE *)hpvPl)
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
Assert(i < hppl->iMac);
|
|
return ++(*(int HUGE *)&hppl->rg[i*hppl->cbItem]);
|
|
#undef hppl
|
|
}
|
|
|
|
#pragma NATIVE_START
|
|
int IDecUseCountPl(hpvPl, i)
|
|
VOID HUGE *hpvPl;
|
|
int i;
|
|
{
|
|
#define hppl ((PL HUGE *)hpvPl)
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
Assert(i < hppl->iMac);
|
|
Assert((*(int HUGE *)&hppl->rg[i*hppl->cbItem]) != 0);
|
|
return --(*(int HUGE *)&hppl->rg[i*hppl->cbItem]);
|
|
#undef hppl
|
|
}
|
|
#pragma NATIVE_END
|
|
|
|
int IAddUseCountPl(phpvPl, hpv)
|
|
VOID HUGE **phpvPl;
|
|
VOID HUGE *hpv;
|
|
{
|
|
BYTE HUGE *hpb;
|
|
int cbItem;
|
|
int i;
|
|
int iMac;
|
|
PL HUGE *hppl;
|
|
|
|
hppl = *phpvPl;
|
|
#ifdef DEBUG
|
|
Assert(FValidPl(hppl));
|
|
#endif // DEBUG
|
|
Assert(hppl->fUseCount);
|
|
cbItem = hppl->cbItem;
|
|
iMac = hppl->iMac;
|
|
// Search for an unused entry
|
|
for (i = 0, hpb = hppl->rg; i < iMac; i++, hpb += cbItem)
|
|
{
|
|
if ((*(int HUGE *) hpb) == 0)
|
|
{
|
|
bltbh(hpv, hpb, cbItem);
|
|
(*(int HUGE *) hpb) = 1;
|
|
return i;
|
|
}
|
|
}
|
|
return IAddPl(phpvPl, hpv);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
/*----------------------------------------------------------------------------
|
|
| FValidPl
|
|
|
|
|
| Checks for a valid PL structure.
|
|
|
|
|
| Arguments:
|
|
| hppl PL to check
|
|
|
|
|
| Returns:
|
|
| fTrue if the PL looks reasonable.
|
|
----------------------------------------------------------------------------*/
|
|
BOOL FValidPl(hpvPl)
|
|
VOID HUGE *hpvPl;
|
|
{
|
|
#define hppl ((PL HUGE *)hpvPl)
|
|
if (SbOfHp(hppl) == sbNull ||
|
|
hppl->cbItem == 0 ||
|
|
hppl->iMac < 0 ||
|
|
hppl->iMax < 0 ||
|
|
hppl->iMax < hppl->iMac)
|
|
return(fFalse);
|
|
return(fTrue);
|
|
#undef hppl
|
|
}
|
|
#endif
|
|
|
|
/*----------------------------------------------------------------------------
|
|
END OF THE CODE FROM EXCEL
|
|
----------------------------------------------------------------------------*/
|
|
#endif
|