Source code of Windows XP (NT5)
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

  1. /*---------------------------------------------------------------------------
  2. FILE : PLEX.C
  3. AUTHOR: STOLEN FROM EXCEL modified by NavPal
  4. This file contains routines used to manipulate the PL (pronounced:
  5. "plex") structures.
  6. ----------------------------------------------------------------------------*/
  7. #include "priv.h"
  8. #pragma hdrstop
  9. #ifndef WINNT
  10. #include "plex.h"
  11. #include "debug.h"
  12. #endif
  13. /*-----------------------------------------------------------------------
  14. | FInRange
  15. | Simple little routine that tells you if a number lies within a
  16. | range.
  17. |
  18. |
  19. | Arguments:
  20. | w: Number to check
  21. | wFirst: First number in the range
  22. | wLast: Last number in the range
  23. |
  24. | Returns:
  25. | fTrue if the number is in range
  26. |
  27. | Keywords: in range check
  28. -----------------------------------------------------------------------*/
  29. BOOL FInRange(w, wFirst, wLast)
  30. int w;
  31. int wFirst, wLast;
  32. {
  33. Assert(wLast >= wFirst);
  34. return(w >= wFirst && w <= wLast);
  35. }
  36. #ifdef DEBUG
  37. /*----------------------------------------------------------------------------
  38. | FValidPl
  39. |
  40. | Checks for a valid PL structure.
  41. |
  42. | Arguments:
  43. | ppl PL to check
  44. |
  45. | Returns:
  46. | fTrue if the PL looks reasonable.
  47. ----------------------------------------------------------------------------*/
  48. BOOL FValidPl(pvPl)
  49. VOID *pvPl;
  50. {
  51. #define ppl ((PL *)pvPl)
  52. if (ppl== NULL ||
  53. ppl->cbItem == 0 ||
  54. ppl->iMac < 0 ||
  55. ppl->iMax < 0 ||
  56. ppl->iMax < ppl->iMac)
  57. return(fFalse);
  58. return(fTrue);
  59. #undef ppl
  60. }
  61. #endif //DEBUG
  62. /*----------------------------------------------------------------------------
  63. | CbPlAlloc
  64. |
  65. | Returns amount of memory allocated to the given PL
  66. |
  67. | Arguments:
  68. | ppl PL to return info for.
  69. |
  70. | Returns:
  71. | memory allocated to the PL
  72. ----------------------------------------------------------------------------*/
  73. int CbPlAlloc(pvPl)
  74. VOID *pvPl;
  75. {
  76. #define ppl ((PL *)pvPl)
  77. if (ppl == NULL)
  78. return(0);
  79. #ifdef DEBUG
  80. Assert(FValidPl(ppl));
  81. #endif // DEBUG
  82. return(WAlign(cbPL + (ppl->iMax * ppl->cbItem)));
  83. #undef ppl
  84. }
  85. /*----------------------------------------------------------------------------
  86. | FreePpl
  87. |
  88. | Frees a PL.
  89. |
  90. | Arguments:
  91. | ppl PL to free
  92. |
  93. | Returns:
  94. | Nothing.
  95. ----------------------------------------------------------------------------*/
  96. void FreePpl(pvPl)
  97. VOID *pvPl;
  98. {
  99. #ifdef DEBUG
  100. Assert(FValidPl(pvPl));
  101. #endif // DEBUG
  102. VFreeMemP(pvPl, (unsigned) CbPlAlloc(pvPl));
  103. }
  104. /*----------------------------------------------------------------------------
  105. | PplAlloc
  106. |
  107. | Allocates and initializes a PL.
  108. |
  109. | Arguments:
  110. | cbItem sizeof structure in the PL
  111. | dAlloc number of items to allocate at a time
  112. | iMax number of items in initial allocation
  113. |
  114. | Returns:
  115. | Pointer to PL.
  116. |
  117. | Notes:
  118. | returns NULL if OOM
  119. ----------------------------------------------------------------------------*/
  120. VOID *PplAlloc(cbItem, dAlloc, iMax)
  121. unsigned cbItem;
  122. int dAlloc;
  123. unsigned iMax;
  124. {
  125. PL *ppl;
  126. long cb;
  127. if (iMax > 32767) /* not too likely, but what the heck. */
  128. return(NULL);
  129. Assert((cbItem>=1 && cbItem<=65535u) && FInRange(dAlloc, 1, 31));
  130. cb = WAlign((long) cbPL + (long) cbItem * (long) iMax);
  131. ppl = (PL *)PvMemAlloc((unsigned) cb);
  132. if(ppl==NULL)
  133. return(NULL);
  134. FillBuf(ppl,0, (unsigned) cb);
  135. ppl->cbItem = cbItem;
  136. ppl->dAlloc = dAlloc;
  137. ppl->iMax = iMax;
  138. ppl->fUseCount = fFalse;
  139. #ifdef DEBUG
  140. Assert(FValidPl(ppl));
  141. #endif // DEBUG
  142. return(ppl);
  143. }
  144. /*----------------------------------------------------------------------------
  145. | IAddPl
  146. |
  147. | Adds an item to a PL.
  148. |
  149. | Arguments:
  150. | pppl Pointer to PL. May change if reallocated.
  151. | pv New item to add.
  152. |
  153. | Returns:
  154. | Index of new item.
  155. |
  156. | Notes:
  157. | returns -1 if OOM
  158. ----------------------------------------------------------------------------*/
  159. int IAddPl(ppvPl, pv)
  160. VOID **ppvPl;
  161. VOID *pv;
  162. {
  163. int cbItem;
  164. int iMac;
  165. PL *ppl, *pplNew;
  166. ppl = *ppvPl;
  167. #ifdef DEBUG
  168. Assert(FValidPl(ppl));
  169. #endif // DEBUG
  170. cbItem = ppl->cbItem;
  171. iMac = ppl->iMac;
  172. #ifdef UNUSED
  173. if (ppl->fUseCount)
  174. {
  175. int i;
  176. BYTE *pb;
  177. (*(int *)pv) = 1;
  178. // Search for an unused entry
  179. for (i = 0, pb = ppl->rg; i < iMac; i++, pb += cbItem)
  180. {
  181. if ((*(int *) pb) == 0)
  182. {
  183. bltbh(hpv, hpb, cbItem);
  184. return i;
  185. }
  186. }
  187. }
  188. #endif
  189. if (iMac == ppl->iMax)
  190. {
  191. pplNew = PplAlloc(cbItem, ppl->dAlloc, iMac + ppl->dAlloc);
  192. if(pplNew==NULL)//OOM
  193. return(-1);
  194. pplNew->fUseCount = ppl->fUseCount;
  195. PbMemCopy(pplNew->rg,ppl->rg, iMac * cbItem);
  196. /* pplNew->iMac = iMac; /* This is not needed because hppl->iMac
  197. will be over-written later */
  198. FreePpl(ppl);
  199. *ppvPl = ppl = pplNew;
  200. }
  201. PbMemCopy(&ppl->rg[iMac * cbItem],pv,cbItem);
  202. ppl->iMac = iMac + 1;
  203. #ifdef DEBUG
  204. Assert(FValidPl(*ppvPl));
  205. #endif // DEBUG
  206. return(iMac);
  207. }
  208. /*----------------------------------------------------------------------------
  209. | RemovePl
  210. |
  211. | Removes an item from a PL.
  212. |
  213. | Arguments:
  214. | ppl PL to remove item from
  215. | i index of item to remove
  216. |
  217. | Returns:
  218. | fTrue if an item was removed (only fFalse for use count plexes).
  219. ----------------------------------------------------------------------------*/
  220. BOOL RemovePl(pvPl, i)
  221. VOID *pvPl;
  222. int i;
  223. {
  224. int iMac;
  225. int cbItem;
  226. BYTE *p;
  227. #define ppl ((PL *)pvPl)
  228. #ifdef DEBUG
  229. Assert(FValidPl(ppl) && i < ppl->iMac);
  230. #endif // DEBUG
  231. iMac = ppl->iMac;
  232. cbItem = ppl->cbItem;
  233. p = &ppl->rg[i * cbItem];
  234. #ifdef UNUSED
  235. if (ppl->fUseCount)
  236. {
  237. Assert((*(int HUGE *) hp) > 0);
  238. if (--(*(int HUGE *) hp) > 0)
  239. return fFalse;
  240. }
  241. #endif
  242. if (i != iMac - 1)
  243. {
  244. PbMemCopy(p,p+cbItem,(iMac - i - 1) * cbItem);
  245. }
  246. ppl->iMac = iMac - 1;
  247. #ifdef DEBUG
  248. Assert(FValidPl(ppl));
  249. #endif // DEBUG
  250. return fTrue;
  251. #undef ppl
  252. }
  253. /*----------------------------------------------------------------------------
  254. | ILookupPl
  255. |
  256. | Searches a PL for an item.
  257. |
  258. | Arguments:
  259. | ppl PL to lookup into
  260. | p item to lookup
  261. | pfnSgn Comparison function
  262. |
  263. | Returns:
  264. | index of item, if found.
  265. | -1 if not found.
  266. ----------------------------------------------------------------------------*/
  267. int ILookupPl(pvPl, pvItem, pfnSgn)
  268. VOID *pvPl;
  269. VOID *pvItem;
  270. int (*pfnSgn)();
  271. {
  272. int i;
  273. BYTE *p;
  274. #define ppl ((PL *)pvPl)
  275. if (ppl == NULL)
  276. return(-1);
  277. #ifdef DEBUG
  278. Assert(FValidPl(ppl));
  279. #endif // DEBUG
  280. #ifdef UNUSED
  281. if (ppl->fUseCount)
  282. {
  283. for (i = 0, p = ppl->rg; i < ppl->iMac; i++, p += ppl->cbItem)
  284. {
  285. if (*(int *)p != 0 && (*(int (*)(void *,void *))pfnSgn)(p, pvItem) == sgnEQ)
  286. return(i);
  287. }
  288. }
  289. else
  290. #endif
  291. {
  292. for (i = 0, p = ppl->rg; i < ppl->iMac; i++, p += ppl->cbItem)
  293. {
  294. if ((*(int (*)(void *, void *))pfnSgn)(p, pvItem) == sgnEQ)
  295. return(i);
  296. }
  297. }
  298. return(-1);
  299. #undef ppl
  300. }
  301. /*----------------------------------------------------------------------------
  302. | PLookupPl
  303. |
  304. | Searches a PL for an item
  305. |
  306. | Arguments:
  307. | ppl PL to search
  308. | pItem item to search for
  309. | pfnSgn comparison function
  310. |
  311. | Returns:
  312. | Pointer to item, if found
  313. | Null, if not found
  314. ----------------------------------------------------------------------------*/
  315. VOID *PLookupPl(pvPl, pvItem, pfnSgn)
  316. VOID *pvPl;
  317. VOID *pvItem;
  318. int (*pfnSgn)();
  319. {
  320. int i;
  321. if ((i = ILookupPl(pvPl, pvItem, pfnSgn)) == -1)
  322. return(NULL);
  323. return(&((PL *)pvPl)->rg[i * ((PL *)pvPl)->cbItem]);
  324. }
  325. /*----------------------------------------------------------------------------
  326. | FLookupSortedPl
  327. |
  328. | Searches a sorted PL for an item.
  329. |
  330. | Arguments:
  331. | hppl PL to lookup into
  332. | hpItem Item to lookup
  333. | pi Index of found item (or insertion location if not)
  334. | pfnSgn Comparison function
  335. |
  336. | Returns:
  337. | index of item, if found.
  338. | index of location to insert if not found.
  339. ----------------------------------------------------------------------------*/
  340. int FLookupSortedPl(hpvPl, hpvItem, pi, pfnSgn)
  341. VOID *hpvPl;
  342. VOID *hpvItem;
  343. int *pi;
  344. int (*pfnSgn)();
  345. {
  346. int sgn;
  347. unsigned iMin, iMid, iMac;
  348. int cbItem;
  349. BYTE *hprg;
  350. BYTE *hpMid;
  351. #define hppl ((PL *)hpvPl)
  352. if ((hppl)==NULL)
  353. {
  354. *pi = 0;
  355. return(fFalse);
  356. }
  357. #ifdef DEBUG
  358. Assert(FValidPl(hppl));
  359. #endif // DEBUG
  360. Assert(!hppl->fUseCount);
  361. sgn = 1;
  362. cbItem = hppl->cbItem;
  363. iMin = iMid = 0;
  364. iMac = hppl->iMac;
  365. hprg = hppl->rg;
  366. while (iMin != iMac)
  367. {
  368. iMid = iMin + (iMac-iMin)/2;
  369. Assert(iMid != iMac);
  370. hpMid = hprg + iMid*cbItem;
  371. if ((sgn = (*(int (*)(void *, void *))pfnSgn)(hpMid, hpvItem)) == 0)
  372. break;
  373. /* Too low, look in upper interval */
  374. if (sgn < 0)
  375. iMin = ++iMid;
  376. /* Too high, look in lower interval */
  377. else
  378. iMac = iMid;
  379. }
  380. /* Not found, return index of location to insert it */
  381. *pi = iMid;
  382. return(sgn == 0);
  383. #undef hppl
  384. }
  385. /*----------------------------------------------------------------------------
  386. | IAddNewPl
  387. |
  388. | Adds an item to a PL, creating the PL if it's initially NULL.
  389. |
  390. | Arguments:
  391. | phppl pointer to PL
  392. | hp pointer to item to add
  393. | cbItem size of item
  394. |
  395. | Returns:
  396. | the index of item added, if successful
  397. | -1, if out-of-memory
  398. ----------------------------------------------------------------------------*/
  399. int IAddNewPl(phpvPl, hpv, cbItem)
  400. VOID **phpvPl;
  401. VOID *hpv;
  402. int cbItem;
  403. {
  404. int i;
  405. #define phppl ((PL **)phpvPl)
  406. Assert(((*phppl)==NULL) || !(*phppl)->fUseCount);
  407. i = -1;
  408. if ((*phppl)==NULL)
  409. {
  410. *phppl = PplAlloc(cbItem, 5, 5);
  411. }
  412. if((*phppl)!=NULL)
  413. {
  414. Assert((*phppl)->cbItem == cbItem);
  415. i = IAddPl((VOID **)phppl, hpv);
  416. }
  417. return(i);
  418. #undef phppl
  419. }
  420. /*----------------------------------------------------------------------------
  421. | IAddNewPlPos
  422. |
  423. | Inserts an item into a plex at a specific position.
  424. |
  425. | Arguments:
  426. | the index of the item added, if successful
  427. | -1 if out-of-memory
  428. ----------------------------------------------------------------------------*/
  429. int IAddNewPlPos(phpvPl, hpv, cbItem, i)
  430. VOID **phpvPl;
  431. VOID *hpv;
  432. int cbItem;
  433. int i;
  434. {
  435. BYTE *hpT;
  436. #define phppl ((PL **)phpvPl)
  437. Assert(((*phppl)==NULL) || !(*phppl)->fUseCount);
  438. if (IAddNewPl((VOID **)phppl, hpv, cbItem) == -1)
  439. return(-1);
  440. Assert(i < (*phppl)->iMac);
  441. hpT = &(*phppl)->rg[i * cbItem];
  442. // bltbh(hpT, hpT + cbItem, ((*phppl)->iMac - i - 1) * cbItem);
  443. // bltbh(hpv, hpT, cbItem);
  444. PbMemCopy(hpT + cbItem, hpT, ((*phppl)->iMac - i - 1) * cbItem);
  445. PbMemCopy(hpT, hpv, cbItem);
  446. #ifdef DEBUG
  447. Assert(FValidPl(*phppl));
  448. #endif // DEBUG
  449. return(i);
  450. #undef phppl
  451. }
  452. int IAddPlSort(phpvPl, hpv, pfnSgn)
  453. VOID **phpvPl;
  454. VOID *hpv;
  455. int (*pfnSgn)();
  456. {
  457. int i;
  458. #ifdef DEBUG
  459. int iOld;
  460. #endif
  461. Assert((*phpvPl)!=NULL);
  462. if (FLookupSortedPl(*phpvPl, hpv, &i, pfnSgn))
  463. return(-1);
  464. #ifdef DEBUG
  465. iOld = i;
  466. #endif
  467. i = IAddNewPlPos(phpvPl, hpv, (*(PL **)phpvPl)->cbItem, i);
  468. #ifdef DEBUG
  469. Assert(i == -1 || i == iOld);
  470. #endif
  471. return(i);
  472. }
  473. //---------------------------------------------------------------------------
  474. //NO CHANGES BELOW THIS LINE PLEASE
  475. //---------------------------------------------------------------------------
  476. #ifdef FROMEXCEL
  477. /*---------------------------------------------------------------------------
  478. THIS CODE IS FROM EXCEL SOURCES. ITS KEPT HERE FOR REFERENCE
  479. ---------------------------------------------------------------------------*/
  480. #pragma hdrstop("Excel.pre")
  481. VSZASSERT
  482. #include "new.h"
  483. /* This file contains routines used to manipulate the PL (pronounced:
  484. "plex") structures. They should probably be moved somewhere a little
  485. more appropriate, like maybe alloc.c */
  486. /*----------------------------------------------------------------------------
  487. | HpLookupPl
  488. |
  489. | Searches a PL for an item
  490. |
  491. | Arguments:
  492. | hppl PL to search
  493. | hpItem item to search for
  494. | pfnSgn comparison function
  495. |
  496. | Returns:
  497. | Pointer to item, if found
  498. | hpNull, if not found
  499. ----------------------------------------------------------------------------*/
  500. VOID HUGE *HpLookupPl(hpvPl, hpvItem, pfnSgn)
  501. VOID HUGE *hpvPl;
  502. VOID HUGE *hpvItem;
  503. int (*pfnSgn)();
  504. {
  505. int i;
  506. if ((i = ILookupPl(hpvPl, hpvItem, pfnSgn)) == -1)
  507. return(hpNull);
  508. return(&((PL HUGE *)hpvPl)->rg[i * ((PL HUGE *)hpvPl)->cbItem]);
  509. }
  510. #ifndef GRAF
  511. #ifdef MAC
  512. #pragma alloc_text(window, HpplAlloc)
  513. #else
  514. #pragma alloc_text(window2, HpplAlloc)
  515. #endif
  516. #else
  517. #pragma alloc_text(plgboot, HpplAlloc)
  518. #endif
  519. /*----------------------------------------------------------------------------
  520. | HpplAlloc
  521. |
  522. | Allocates and initializes a PL.
  523. |
  524. | Arguments:
  525. | cbItem sizeof structure in the PL
  526. | dAlloc number of items to allocate at a time
  527. | iMax number of items in initial allocation
  528. | dg memory group to allocate from
  529. |
  530. | Returns:
  531. | Pointer to PL.
  532. |
  533. | Notes:
  534. | May DoJmp(penvMem).
  535. ----------------------------------------------------------------------------*/
  536. /*<<mcmain*/
  537. #pragma NATIVE_START
  538. VOID HUGE *HpplAlloc(cbItem, dAlloc, iMax, dg)
  539. unsigned cbItem;
  540. int dAlloc;
  541. unsigned iMax;
  542. unsigned dg;
  543. {
  544. PL HUGE *hppl;
  545. long cb;
  546. int dgShift;
  547. if (iMax > 32767) /* not too likely, but what the heck. */
  548. DoJmp(penvMem, alctNoMem);
  549. Assert((cbItem>=1 && cbItem<=65535u) && FInRange(dAlloc, 1, 31) &&
  550. FInRange(BLow(dg), 1, 255));
  551. cb = WAlign((long) cbPL + (long) cbItem * (long) iMax);
  552. #ifndef LARGEALLOC
  553. if(cb >= cbHeapMax)
  554. {
  555. ErrorNoMem();
  556. DoJmp(penvMem, alctNoMem);
  557. }
  558. #endif
  559. hppl = (PL HUGE *)HpAlloc((unsigned) cb, dg);
  560. bltcbh(0, hppl, (unsigned) cb);
  561. Assert(dg!=0);
  562. for (dgShift = 0; !(dg & 1); dg >>= 1, dgShift++)
  563. ;
  564. Assert(dgShift<8);
  565. hppl->cbItem = cbItem;
  566. hppl->dAlloc = dAlloc;
  567. hppl->iMax = iMax;
  568. hppl->fUseCount = fFalse;
  569. hppl->dgShift = dgShift;
  570. #ifdef DEBUG
  571. Assert(FValidPl(hppl));
  572. #endif // DEBUG
  573. return(hppl);
  574. }
  575. #pragma NATIVE_END
  576. /*<<plex*/
  577. #ifdef MAC
  578. #pragma alloc_text(window, HpplUseCountAlloc)
  579. #else
  580. #pragma alloc_text(window2, HpplUseCountAlloc)
  581. #endif
  582. VOID HUGE *HpplUseCountAlloc(cbItem, dAlloc, iMax, dg)
  583. unsigned cbItem;
  584. int dAlloc;
  585. unsigned iMax;
  586. unsigned dg;
  587. {
  588. PL HUGE *hppl;
  589. hppl = HpplAlloc(cbItem, dAlloc, iMax, dg);
  590. hppl->fUseCount = fTrue;
  591. return hppl;
  592. }
  593. /*----------------------------------------------------------------------------
  594. | FreeHppl
  595. |
  596. | Frees a PL.
  597. |
  598. | Arguments:
  599. | hppl PL to free
  600. |
  601. | Returns:
  602. | Nothing.
  603. ----------------------------------------------------------------------------*/
  604. /*<<mcmain*/
  605. #ifndef GRAF
  606. #ifdef MAC
  607. #pragma alloc_text(window, FreeHppl)
  608. #else
  609. #pragma alloc_text(window2, FreeHppl)
  610. #endif
  611. #endif
  612. #pragma NATIVE_START
  613. FreeHppl(hpvPl)
  614. VOID HUGE *hpvPl;
  615. {
  616. #ifdef DEBUG
  617. Assert(FValidPl(hpvPl));
  618. #endif // DEBUG
  619. FreeHp(hpvPl, CbPlAlloc(hpvPl));
  620. }
  621. #pragma NATIVE_END
  622. /*<<plex*/
  623. #ifndef GRAF
  624. #ifdef MAC
  625. #pragma alloc_text(window, ILookupPl)
  626. #else
  627. #pragma alloc_text(window2, ILookupPl)
  628. #endif
  629. #else
  630. #pragma alloc_text(swpmisc, ILookupPl)
  631. #endif
  632. /*----------------------------------------------------------------------------
  633. | ILookupPl
  634. |
  635. | Searches a PL for an item.
  636. |
  637. | Arguments:
  638. | hppl PL to lookup into
  639. | hp item to lookup
  640. | pfnSgn Comparison function
  641. |
  642. | Returns:
  643. | index of item, if found.
  644. | -1 if not found.
  645. ----------------------------------------------------------------------------*/
  646. #pragma NATIVE_START
  647. int ILookupPl(hpvPl, hpvItem, pfnSgn)
  648. VOID HUGE *hpvPl;
  649. VOID HUGE *hpvItem;
  650. int (*pfnSgn)();
  651. {
  652. int i;
  653. BYTE HUGE *hp;
  654. #define hppl ((PL HUGE *)hpvPl)
  655. if (SbFromHp(hppl) == sbNull)
  656. return(-1);
  657. #ifdef DEBUG
  658. Assert(FValidPl(hppl));
  659. #endif // DEBUG
  660. if (hppl->fUseCount)
  661. {
  662. for (i = 0, hp = hppl->rg; i < hppl->iMac; i++, hp += hppl->cbItem)
  663. {
  664. if (*(int HUGE *)hp != 0 && (*(int (*)(HP, HP))pfnSgn)(hp, hpvItem) == sgnEQ)
  665. return(i);
  666. }
  667. }
  668. else
  669. {
  670. for (i = 0, hp = hppl->rg; i < hppl->iMac; i++, hp += hppl->cbItem)
  671. {
  672. if ((*(int (*)(HP, HP))pfnSgn)(hp, hpvItem) == sgnEQ)
  673. return(i);
  674. }
  675. }
  676. return(-1);
  677. #undef hppl
  678. }
  679. #pragma NATIVE_END
  680. /*----------------------------------------------------------------------------
  681. | FLookupSortedPl
  682. |
  683. | Searches a sorted PL for an item.
  684. |
  685. | Arguments:
  686. | hppl PL to lookup into
  687. | hpItem Item to lookup
  688. | pi Index of found item (or insertion location if not)
  689. | pfnSgn Comparison function
  690. |
  691. | Returns:
  692. | index of item, if found.
  693. | index of location to insert if not found.
  694. ----------------------------------------------------------------------------*/
  695. #ifdef MAC
  696. #pragma alloc_text(window, FLookupSortedPl)
  697. #else
  698. #pragma alloc_text(window2, FLookupSortedPl)
  699. #endif
  700. #pragma NATIVE_START
  701. int FLookupSortedPl(hpvPl, hpvItem, pi, pfnSgn)
  702. VOID HUGE *hpvPl;
  703. VOID HUGE *hpvItem;
  704. int *pi;
  705. int (*pfnSgn)();
  706. {
  707. int sgn;
  708. unsigned iMin, iMid, iMac;
  709. int cbItem;
  710. BYTE HUGE *hprg;
  711. BYTE HUGE *hpMid;
  712. #define hppl ((PL HUGE *)hpvPl)
  713. if (SbFromHp(hppl) == sbNull)
  714. {
  715. *pi = 0;
  716. return(fFalse);
  717. }
  718. #ifdef DEBUG
  719. Assert(FValidPl(hppl));
  720. #endif // DEBUG
  721. Assert(!hppl->fUseCount);
  722. sgn = 1;
  723. cbItem = hppl->cbItem;
  724. iMin = iMid = 0;
  725. iMac = hppl->iMac;
  726. hprg = hppl->rg;
  727. while (iMin != iMac)
  728. {
  729. iMid = iMin + (iMac-iMin)/2;
  730. Assert(iMid != iMac);
  731. hpMid = hprg + iMid*cbItem;
  732. if ((sgn = (*(int (*)(HP, HP))pfnSgn)(hpMid, hpvItem)) == 0)
  733. break;
  734. /* Too low, look in upper interval */
  735. if (sgn < 0)
  736. iMin = ++iMid;
  737. /* Too high, look in lower interval */
  738. else
  739. iMac = iMid;
  740. }
  741. /* Not found, return index of location to insert it */
  742. *pi = iMid;
  743. return(sgn == 0);
  744. #undef hppl
  745. }
  746. #pragma NATIVE_END
  747. /*----------------------------------------------------------------------------
  748. | DeletePl
  749. |
  750. | Removes an item from a PL. The resulting PL is compacted.
  751. |
  752. | Arguments:
  753. | phppl pointer to PL to remove item from
  754. | i index of item to remove
  755. |
  756. | Returns:
  757. | Nothing.
  758. ----------------------------------------------------------------------------*/
  759. DeletePl(phpvPl, i)
  760. VOID HUGE **phpvPl;
  761. int i;
  762. {
  763. #ifdef DEBUG
  764. Assert(FValidPl(*phpvPl));
  765. #endif // DEBUG
  766. RemovePl(*phpvPl, i);
  767. FCompactPl(phpvPl, (*(PL HUGE **)phpvPl)->iMac == 0);
  768. #ifdef DEBUG
  769. Assert(SbOfHp(*phpvPl) == sbNull || FValidPl(*phpvPl));
  770. #endif // DEBUG
  771. }
  772. /*----------------------------------------------------------------------------
  773. | RemovePl
  774. |
  775. | Removes an item from a PL.
  776. |
  777. | Arguments:
  778. | hppl PL to remove item from
  779. | i index of item to remove
  780. |
  781. | Returns:
  782. | fTrue if an item was removed (only fFalse for use count plexes).
  783. ----------------------------------------------------------------------------*/
  784. BOOL RemovePl(hpvPl, i)
  785. VOID HUGE *hpvPl;
  786. int i;
  787. {
  788. int iMac;
  789. int cbItem;
  790. BYTE HUGE *hp;
  791. #define hppl ((PL HUGE *)hpvPl)
  792. #ifdef DEBUG
  793. Assert(FValidPl(hppl) && i < hppl->iMac);
  794. #endif // DEBUG
  795. iMac = hppl->iMac;
  796. cbItem = hppl->cbItem;
  797. hp = &hppl->rg[i * cbItem];
  798. if (hppl->fUseCount)
  799. {
  800. Assert((*(int HUGE *) hp) > 0);
  801. if (--(*(int HUGE *) hp) > 0)
  802. return fFalse;
  803. }
  804. if (i != iMac - 1)
  805. {
  806. bltbh(hp + cbItem, hp, (iMac - i - 1) * cbItem);
  807. }
  808. hppl->iMac = iMac - 1;
  809. #ifdef DEBUG
  810. Assert(FValidPl(hppl));
  811. #endif // DEBUG
  812. return fTrue;
  813. #undef hppl
  814. }
  815. #ifndef GRAF
  816. #ifdef MAC
  817. #pragma alloc_text(window, IAddPl)
  818. #else
  819. #pragma alloc_text(window2, IAddPl)
  820. #endif
  821. #else
  822. #pragma alloc_text(swpmisc, IAddPl)
  823. #endif
  824. /*----------------------------------------------------------------------------
  825. | IAddPl
  826. |
  827. | Adds an item to a PL.
  828. |
  829. | Arguments:
  830. | phppl Pointer to PL. May change if reallocated.
  831. | hp New item to add.
  832. |
  833. | Returns:
  834. | Index of new item.
  835. |
  836. | Notes:
  837. | May DoJmp(penvMem) when reallocating.
  838. ----------------------------------------------------------------------------*/
  839. /*<<mcmain*/
  840. #pragma NATIVE_START
  841. int IAddPl(phpvPl, hpv)
  842. VOID HUGE **phpvPl;
  843. VOID HUGE *hpv;
  844. {
  845. int cbItem;
  846. int iMac;
  847. PL HUGE *hppl, HUGE *hpplNew;
  848. hppl = *phpvPl;
  849. #ifdef DEBUG
  850. Assert(FValidPl(hppl));
  851. #endif // DEBUG
  852. cbItem = hppl->cbItem;
  853. iMac = hppl->iMac;
  854. if (hppl->fUseCount)
  855. {
  856. int i;
  857. BYTE HUGE *hpb;
  858. (*(int HUGE *)hpv) = 1;
  859. // Search for an unused entry
  860. for (i = 0, hpb = hppl->rg; i < iMac; i++, hpb += cbItem)
  861. {
  862. if ((*(int HUGE *) hpb) == 0)
  863. {
  864. bltbh(hpv, hpb, cbItem);
  865. return i;
  866. }
  867. }
  868. }
  869. #ifdef DEBUG
  870. if (iMac == hppl->iMax || fShakeMem)
  871. #else
  872. if (iMac == hppl->iMax)
  873. #endif
  874. {
  875. hpplNew = HpplAlloc(cbItem, hppl->dAlloc, iMac + hppl->dAlloc, 0x01<<hppl->dgShift);
  876. hpplNew->fUseCount = hppl->fUseCount;
  877. bltbh(hppl->rg, hpplNew->rg, iMac * cbItem);
  878. /* hpplNew->iMac = iMac; /* This is not needed because hppl->iMac
  879. will be over-written later */
  880. FreeHppl(hppl);
  881. *phpvPl = hppl = hpplNew;
  882. }
  883. bltbh(hpv, &hppl->rg[iMac * cbItem], cbItem);
  884. hppl->iMac = iMac + 1;
  885. #ifdef DEBUG
  886. Assert(FValidPl(*phpvPl));
  887. #endif // DEBUG
  888. return(iMac);
  889. }
  890. #pragma NATIVE_END
  891. /*<<plex*/
  892. /* Not used for Mac */
  893. #ifndef MAC
  894. /*----------------------------------------------------------------------------
  895. | ILookAddPl
  896. |
  897. | Searces a PL for an item and adds the item if it's not already there.
  898. |
  899. | Arguments:
  900. | phppl Pointer to PL. May change if reallocated.
  901. | hp Item to find/add.
  902. | pfnSgn Comparison function
  903. |
  904. | Returns:
  905. | Index of item found/added.
  906. |
  907. | Notes:
  908. | The PL must already be created.
  909. | May DoJmp(penvMem) when reallocating.
  910. ----------------------------------------------------------------------------*/
  911. #ifdef DDE
  912. int ILookAddPl(phpvPl, hpv, pfnSgn)
  913. VOID HUGE **phpvPl;
  914. VOID HUGE *hpv;
  915. int (*pfnSgn)();
  916. {
  917. int i;
  918. #define phppl ((PL HUGE **)phpvPl)
  919. Assert(!(*phppl)->fUseCount);
  920. if ((i = ILookupPl(*phpvPl, hpv, pfnSgn)) == -1)
  921. i = IAddPl(phpvPl, hpv);
  922. return(i);
  923. #undef phppl
  924. }
  925. #endif
  926. #endif
  927. #ifndef GRAF
  928. #ifdef MAC
  929. #pragma alloc_text(window, IAddNewPl)
  930. #else
  931. #pragma alloc_text(window2, IAddNewPl)
  932. #endif
  933. #endif
  934. /*----------------------------------------------------------------------------
  935. | IAddNewPl
  936. |
  937. | Adds an item to a PL, creating the PL if it's initially NULL.
  938. |
  939. | Arguments:
  940. | phppl pointer to PL
  941. | hp pointer to item to add
  942. | cbItem size of item
  943. | dg data group to alloc plex in
  944. |
  945. | Returns:
  946. | the index of item added, if successful
  947. | -1, if out-of-memory
  948. ----------------------------------------------------------------------------*/
  949. /*<<mcmain*/
  950. #pragma NATIVE_START
  951. int IAddNewPl(phpvPl, hpv, cbItem, dg)
  952. VOID HUGE **phpvPl;
  953. VOID HUGE *hpv;
  954. int cbItem;
  955. int dg;
  956. {
  957. int i;
  958. ENV *penvSav, env;
  959. #ifdef DEBUG
  960. BOOL fShakeMemSav = 2;
  961. extern BOOL fShakeMem;
  962. #endif
  963. #define phppl ((PL HUGE **)phpvPl)
  964. Assert(FNullHp(*phppl) || !(*phppl)->fUseCount);
  965. i = -1;
  966. penvSav = penvMem;
  967. if (SetJmp(penvMem = &env) == 0)
  968. {
  969. if (SbOfHp(*phppl) == sbNull)
  970. {
  971. *phppl = HpplAlloc(cbItem, 5, 5, dg);
  972. #ifdef DEBUG
  973. /* Turn off shake mem in this case, since we don't accomplish
  974. any additional memory checking when we've just allocated
  975. the plex from scratch anyway. */
  976. Assert(fShakeMem != 2);
  977. fShakeMemSav = fShakeMem;
  978. fShakeMem = FALSE;
  979. #endif /* DEBUG */
  980. }
  981. Assert((*phppl)->cbItem == cbItem);
  982. i = IAddPl((VOID HUGE **)phppl, hpv);
  983. }
  984. penvMem = penvSav;
  985. #ifdef DEBUG
  986. if (fShakeMemSav != 2)
  987. fShakeMem = fShakeMemSav;
  988. #endif /* DEBUG */
  989. return(i);
  990. #undef phppl
  991. }
  992. #pragma NATIVE_END
  993. /*<<plex*/
  994. #ifndef GRAF
  995. #ifdef MAC
  996. #pragma alloc_text(window, IAddNewPlPos)
  997. #else
  998. #pragma alloc_text(window2, IAddNewPlPos)
  999. #endif
  1000. #endif
  1001. /*----------------------------------------------------------------------------
  1002. | IAddNewPlPos
  1003. |
  1004. | Inserts an item into a plex at a specific position.
  1005. |
  1006. | Arguments:
  1007. | the index of the item added, if successful
  1008. | -1 if out-of-memory
  1009. ----------------------------------------------------------------------------*/
  1010. /*<<mcmain*/
  1011. #pragma NATIVE_START
  1012. int IAddNewPlPos(phpvPl, hpv, cbItem, i, dg)
  1013. VOID HUGE **phpvPl;
  1014. VOID HUGE *hpv;
  1015. int cbItem;
  1016. int i;
  1017. int dg;
  1018. {
  1019. BYTE HUGE *hpT;
  1020. #define phppl ((PL HUGE **)phpvPl)
  1021. Assert(FNullHp(*phppl) || !(*phppl)->fUseCount);
  1022. if (IAddNewPl((VOID HUGE **)phppl, hpv, cbItem, dg) == -1)
  1023. return(-1);
  1024. Assert(i < (*phppl)->iMac);
  1025. hpT = &(*phppl)->rg[i * cbItem];
  1026. bltbh(hpT, hpT + cbItem, ((*phppl)->iMac - i - 1) * cbItem);
  1027. bltbh(hpv, hpT, cbItem);
  1028. #ifdef DEBUG
  1029. Assert(FValidPl(*phppl));
  1030. #endif // DEBUG
  1031. return(i);
  1032. #undef phppl
  1033. }
  1034. #pragma NATIVE_END
  1035. /*<<plex*/
  1036. #ifdef MAC
  1037. #pragma alloc_text(window, IAddPlSort)
  1038. #else
  1039. #pragma alloc_text(window2, IAddPlSort)
  1040. #endif
  1041. int IAddPlSort(phpvPl, hpv, pfnSgn)
  1042. VOID HUGE **phpvPl;
  1043. VOID HUGE *hpv;
  1044. int (*pfnSgn)();
  1045. {
  1046. int i;
  1047. #ifdef DEBUG
  1048. int iOld;
  1049. #endif
  1050. Assert(!FNullHp(*phpvPl));
  1051. if (FLookupSortedPl(*phpvPl, hpv, &i, pfnSgn))
  1052. return(-1);
  1053. #ifdef DEBUG
  1054. iOld = i;
  1055. #endif
  1056. i = IAddNewPlPos(phpvPl, hpv, (*(PL HUGE **)phpvPl)->cbItem, i, 1<<(*(PL HUGE **)phpvPl)->dgShift);
  1057. Assert(i == -1 || i == iOld);
  1058. return(i);
  1059. }
  1060. /*----------------------------------------------------------------------------
  1061. | FCompactPl
  1062. |
  1063. | Squeezes unused memory out of a PL
  1064. |
  1065. | Arguments:
  1066. | phppl Plex to compact
  1067. | fFull fTrue if maximal compaction should be made
  1068. |
  1069. | Returns:
  1070. | fTrue if some memory was freed.
  1071. ----------------------------------------------------------------------------*/
  1072. BOOL FCompactPl(phpvPl, fFull)
  1073. VOID HUGE **phpvPl;
  1074. BOOL fFull;
  1075. {
  1076. int iMac, cbItem, cbFree, dAlloc;
  1077. BYTE HUGE *hp;
  1078. PL HUGE *hppl = *phpvPl;
  1079. BOOL fFreed = fFalse;
  1080. if (SbOfHp(hppl) != sbNull)
  1081. {
  1082. #ifdef DEBUG
  1083. Assert(FValidPl(hppl));
  1084. #endif // DEBUG
  1085. if ((iMac = hppl->iMac) == 0 && fFull)
  1086. {
  1087. FreeHppl(hppl);
  1088. fFreed = fTrue;
  1089. *phpvPl = hpNull;
  1090. }
  1091. else
  1092. {
  1093. if (!fFull)
  1094. {
  1095. dAlloc = hppl->dAlloc;
  1096. iMac = (iMac + dAlloc) / dAlloc * dAlloc;
  1097. }
  1098. hp = &hppl->rg[iMac * (cbItem = hppl->cbItem)];
  1099. if (IbOfHp(hp) & 1)
  1100. {
  1101. /* can't free on an odd boundary */
  1102. Assert((cbItem & 1) && (iMac & 1));
  1103. iMac++;
  1104. hp += cbItem;
  1105. }
  1106. Assert((IbOfHp(hp) & 1) == 0);
  1107. /* must free at least 4 bytes, and it had better
  1108. be an even number */
  1109. if ((cbFree = WAlign((hppl->iMax - iMac) * cbItem)) >= 4)
  1110. {
  1111. CbChopHp(hp, cbFree);
  1112. fFreed = fTrue;
  1113. hppl->iMax = iMac;
  1114. }
  1115. }
  1116. }
  1117. #ifdef DEBUG
  1118. Assert(SbOfHp(*phpvPl) == sbNull || FValidPl(*phpvPl));
  1119. #endif // DEBUG
  1120. return(fFreed);
  1121. }
  1122. /*----------------------------------------------------------------------------
  1123. | CbPlAlloc
  1124. |
  1125. | Returns amount of memory allocated to the given PL
  1126. |
  1127. | Arguments:
  1128. | hppl PL to return info for.
  1129. |
  1130. | Returns:
  1131. | memory allocated to the PL
  1132. ----------------------------------------------------------------------------*/
  1133. /*<<mcmain*/
  1134. #ifndef GRAF
  1135. #ifdef MAC
  1136. #pragma alloc_text(window, CbPlAlloc)
  1137. #else
  1138. #pragma alloc_text(window2, CbPlAlloc)
  1139. #endif
  1140. #endif
  1141. #pragma NATIVE_START
  1142. int CbPlAlloc(hpvPl)
  1143. VOID HUGE *hpvPl;
  1144. {
  1145. #define hppl ((PL HUGE *)hpvPl)
  1146. if (SbFromHp(hppl) == sbNull)
  1147. return(0);
  1148. #ifdef DEBUG
  1149. Assert(FValidPl(hppl));
  1150. #endif // DEBUG
  1151. return(WAlign(cbPL + (hppl->iMax * hppl->cbItem)));
  1152. #undef hppl
  1153. }
  1154. #pragma NATIVE_END
  1155. /*<<plex*/
  1156. #ifndef GRAF
  1157. #ifdef MAC
  1158. #pragma alloc_text(window, ResizePl)
  1159. #else
  1160. #pragma alloc_text(window2, ResizePl)
  1161. #endif
  1162. #endif
  1163. /*----------------------------------------------------------------------------
  1164. | ResizePl
  1165. |
  1166. | Grows the given plex large enough to contain the given number
  1167. | of items.
  1168. |
  1169. | Arguments:
  1170. | phppl plex to reallocate - will change if
  1171. | the plex is grown.
  1172. | iMac number of items the plex must hold.
  1173. |
  1174. | Note:
  1175. | DoJmp(penvMem) if out-of-memory.
  1176. ----------------------------------------------------------------------------*/
  1177. /*<<mcmain*/
  1178. #pragma NATIVE_START
  1179. ResizePl(phpvPl, iMac, iIns)
  1180. VOID HUGE **phpvPl;
  1181. int iMac, iIns;
  1182. {
  1183. int iMax;
  1184. int cbItem;
  1185. PL HUGE *hppl;
  1186. #define phppl ((PL HUGE **)phpvPl)
  1187. hppl = *phppl;
  1188. Assert(!hppl->fUseCount); // NYI
  1189. #ifdef DEBUG
  1190. Assert(FValidPl(hppl));
  1191. #endif // DEBUG
  1192. cbItem = hppl->cbItem;
  1193. if (hppl->iMax < iMac)
  1194. {
  1195. iMax = (iMac / (int) hppl->dAlloc + 1) * hppl->dAlloc;
  1196. *phppl = HpplAlloc(cbItem, hppl->dAlloc, iMax,
  1197. 0x01<<hppl->dgShift);
  1198. #ifdef USECOUNTRESIZE
  1199. (*phppl)->fUseCount = hppl->fUseCount;
  1200. #endif
  1201. if (iIns >= 0)
  1202. {
  1203. bltbh(hppl->rg, (*phppl)->rg, iIns * cbItem);
  1204. bltbh(hppl->rg + iIns * cbItem,
  1205. (*phppl)->rg + (iIns+(iMac-hppl->iMac)) * cbItem,
  1206. (hppl->iMac-iIns) * cbItem);
  1207. }
  1208. else
  1209. bltbh(hppl->rg, (*phppl)->rg, hppl->iMax * cbItem);
  1210. FreeHppl(hppl);
  1211. }
  1212. else if (iIns >= 0)
  1213. {
  1214. bltbh(hppl->rg + iIns * hppl->cbItem,
  1215. hppl->rg + (iIns+(iMac-hppl->iMac)) * cbItem,
  1216. (hppl->iMac-iIns) * cbItem);
  1217. }
  1218. (*phppl)->iMac = iMac;
  1219. #ifdef DEBUG
  1220. Assert(FValidPl(*phppl));
  1221. #endif // DEBUG
  1222. #undef phppl
  1223. }
  1224. #pragma NATIVE_END
  1225. /*<<plex*/
  1226. #ifdef MAC
  1227. #pragma alloc_text(window, IIncUseCountPl)
  1228. #else
  1229. #pragma alloc_text(window2, IIncUseCountPl)
  1230. #endif
  1231. int IIncUseCountPl(hpvPl, i)
  1232. VOID HUGE *hpvPl;
  1233. int i;
  1234. {
  1235. #define hppl ((PL HUGE *)hpvPl)
  1236. #ifdef DEBUG
  1237. Assert(FValidPl(hppl));
  1238. #endif // DEBUG
  1239. Assert(i < hppl->iMac);
  1240. return ++(*(int HUGE *)&hppl->rg[i*hppl->cbItem]);
  1241. #undef hppl
  1242. }
  1243. #pragma NATIVE_START
  1244. int IDecUseCountPl(hpvPl, i)
  1245. VOID HUGE *hpvPl;
  1246. int i;
  1247. {
  1248. #define hppl ((PL HUGE *)hpvPl)
  1249. #ifdef DEBUG
  1250. Assert(FValidPl(hppl));
  1251. #endif // DEBUG
  1252. Assert(i < hppl->iMac);
  1253. Assert((*(int HUGE *)&hppl->rg[i*hppl->cbItem]) != 0);
  1254. return --(*(int HUGE *)&hppl->rg[i*hppl->cbItem]);
  1255. #undef hppl
  1256. }
  1257. #pragma NATIVE_END
  1258. int IAddUseCountPl(phpvPl, hpv)
  1259. VOID HUGE **phpvPl;
  1260. VOID HUGE *hpv;
  1261. {
  1262. BYTE HUGE *hpb;
  1263. int cbItem;
  1264. int i;
  1265. int iMac;
  1266. PL HUGE *hppl;
  1267. hppl = *phpvPl;
  1268. #ifdef DEBUG
  1269. Assert(FValidPl(hppl));
  1270. #endif // DEBUG
  1271. Assert(hppl->fUseCount);
  1272. cbItem = hppl->cbItem;
  1273. iMac = hppl->iMac;
  1274. // Search for an unused entry
  1275. for (i = 0, hpb = hppl->rg; i < iMac; i++, hpb += cbItem)
  1276. {
  1277. if ((*(int HUGE *) hpb) == 0)
  1278. {
  1279. bltbh(hpv, hpb, cbItem);
  1280. (*(int HUGE *) hpb) = 1;
  1281. return i;
  1282. }
  1283. }
  1284. return IAddPl(phpvPl, hpv);
  1285. }
  1286. #ifdef DEBUG
  1287. /*----------------------------------------------------------------------------
  1288. | FValidPl
  1289. |
  1290. | Checks for a valid PL structure.
  1291. |
  1292. | Arguments:
  1293. | hppl PL to check
  1294. |
  1295. | Returns:
  1296. | fTrue if the PL looks reasonable.
  1297. ----------------------------------------------------------------------------*/
  1298. BOOL FValidPl(hpvPl)
  1299. VOID HUGE *hpvPl;
  1300. {
  1301. #define hppl ((PL HUGE *)hpvPl)
  1302. if (SbOfHp(hppl) == sbNull ||
  1303. hppl->cbItem == 0 ||
  1304. hppl->iMac < 0 ||
  1305. hppl->iMax < 0 ||
  1306. hppl->iMax < hppl->iMac)
  1307. return(fFalse);
  1308. return(fTrue);
  1309. #undef hppl
  1310. }
  1311. #endif
  1312. /*----------------------------------------------------------------------------
  1313. END OF THE CODE FROM EXCEL
  1314. ----------------------------------------------------------------------------*/
  1315. #endif