windows-nt/Source/XPSP1/NT/shell/ext/docprop/plex.c
2020-09-26 16:20:57 +08:00

1404 lines
29 KiB
C

/*---------------------------------------------------------------------------
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