/*--------------------------------------------------------------------------- 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 /*----------------------------------------------------------------------- | 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; { PL * ppl; ppl = (PL *) pvPl; if (ppl== NULL || ppl->cbItem == 0 || ppl->iMac < 0 || ppl->iMax < 0 || ppl->iMax < ppl->iMac) { return(fFalse); } return(fTrue); } #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; { PL * ppl; ppl = (PL *) pvPl; if (ppl == NULL) return(0); Assert(FValidPl(ppl)); return(WAlign(cbPL + (ppl->iMax * ppl->cbItem))); } /*---------------------------------------------------------------------------- | FreePpl | | Frees a PL. | | Arguments: | ppl PL to free | | Returns: | Nothing. ----------------------------------------------------------------------------*/ void FreePpl(pvPl) VOID *pvPl; { Assert(FValidPl(pvPl)); LocalFree(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 *) LocalAlloc( LPTR, cb ); if(ppl==NULL) return(NULL); ppl->cbItem = cbItem; ppl->dAlloc = dAlloc; ppl->iMax = iMax; ppl->fUseCount = fFalse; Assert(FValidPl(ppl)); 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; Assert(FValidPl(ppl)); cbItem = ppl->cbItem; iMac = ppl->iMac; if (iMac == ppl->iMax) { pplNew = PplAlloc(cbItem, ppl->dAlloc, iMac + ppl->dAlloc); if(pplNew==NULL) return(-1); pplNew->fUseCount = ppl->fUseCount; CopyMemory( 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; } CopyMemory( &ppl->rg[iMac * cbItem], pv, cbItem ); ppl->iMac = iMac + 1; Assert(FValidPl(*ppvPl)); 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; PL * ppl; ppl = (PL *) pvPl; Assert(FValidPl(ppl) && i < ppl->iMac); iMac = ppl->iMac; cbItem = ppl->cbItem; p = &ppl->rg[i * cbItem]; if (i != iMac - 1) { CopyMemory( p, p+cbItem, (iMac - i - 1) * cbItem ); } ppl->iMac = iMac - 1; Assert(FValidPl(ppl)); return fTrue; } /*---------------------------------------------------------------------------- | 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; PL * ppl; ppl = (PL *) pvPl; if (ppl == NULL) return(-1); Assert(FValidPl(ppl)); 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); } /*---------------------------------------------------------------------------- | 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; PL * hppl; hppl = (PL *) hpvPl; if ((hppl)==NULL) { *pi = 0; return(fFalse); } Assert(FValidPl(hppl)); 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); } /*---------------------------------------------------------------------------- | 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; PL ** phppl; 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); } /*---------------------------------------------------------------------------- | 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; PL ** phppl; 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); CopyMemory( hpT + cbItem, hpT, ((*phppl)->iMac - i - 1) * cbItem ); CopyMemory( hpT, hpv, cbItem ); Assert(FValidPl(*phppl)); return(i); } 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); }