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