home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 Christmas / macformat-045.iso / Shareware Plus / Developers / enteract-377 / enteract-377.sit / EnterAct Stuff / hAWK project / AWK Source / CodeResource_Helper.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-24  |  25.5 KB  |  4 lines  |  [TEXT/KEEN]

  1. CodeResource_Helper.cTEXTKEEN`´¬
  2. ´¬
  3. ÅÅ»Ç/* CodeResource_Helper.c - some handy functions for this and that */
  4. /* Copyright not bothered with - this is pretty standard stuff. */
  5. #include "CodeResource.h"
  6. #include <stdlib.h>
  7.  
  8. /* Resources */
  9. short OpenOrCreateResourceFork(StringPtr fileName);
  10. void DeleteAllExistingRsrcs(long theType, short theNum);
  11. /* Dialogs */
  12. void GetDlogOrigin (short dlogID, Point *where);
  13. Boolean GetAndAlignDialog(short  resID);
  14. void FrameDialogItem(DialogPtr theDP,short theItem);
  15. void SetEText(DialogPtr dPtr, short theItem, StringPtr newStr);
  16. void GetEText(DialogPtr dPtr, short theItem, StringPtr currentStr);
  17. void SetCheck(DialogPtr dPtr, short chkItem, short zeroMeansNoCheck);
  18. void GetCheck(DialogPtr dPtr, short chkItem, Boolean *trueIfChecked);
  19. Handle GetButton(DialogPtr dPtr, short btnItem);
  20. void HiliteDlgControl(DialogPtr dPtr, short btnItem, short state);
  21. /* Pascal strings */
  22. void CopyPStr(Byte *srcStr, Byte *dstStr);
  23. void AppendPStr(Byte *s1, Byte *s2);
  24. Boolean PEqualStrs(Byte *aStr, Byte *bStr);
  25. /* Files, names and locations */
  26. Byte *FullPathNameFromDirectory(long DirID, short vRefNum, Byte *s);
  27. Byte *FullPathNameFromVRefNum(short vRefNum, Byte *s);
  28. short    OpenWorkingDirectoryFromFullName(char *name, short len);
  29. /* Memory allocation */
  30. void InitTempCodeMemory(void);
  31. void *TMalloc(size_t size);
  32. void *Trealloc(void *ptr, size_t size);
  33. void Tfree(void *ptr);
  34. void TFreeAll(void);
  35. /* more memory allocation - faster, more efficient version */
  36. void *Fmalloc(register size_t nbytes);
  37. static void morecore(register short bucket);
  38. static void *true_get_memory(size_t size);
  39. void Ffree(void *cp);
  40. void *Frealloc(void *cp, size_t nbytes);
  41. static short findbucket(union overhead *freep, short srchlen);
  42. void FFreeAll(void);
  43. /* Misc */
  44. void NullOut(char *str, long nBytes);
  45. Boolean TaskWasInterrupted(void);
  46. Boolean CheckInWithCallingApp(void);
  47.  
  48. /* Resources */
  49.  
  50. /* Returns nonzero refnum if successful */
  51. short OpenOrCreateResourceFork(StringPtr fileName)
  52.     {
  53.     short refNum;
  54.     
  55.     if ((refNum = OpenResFile(fileName)) != -1 && refNum
  56.         && ResError() == noErr) /* perfect paranoia */
  57.         return(refNum);
  58.     else
  59.         {
  60.         CreateResFile(fileName);
  61.         if (ResError() != noErr)
  62.             return(0);
  63.         if ((refNum = OpenResFile(fileName)) != -1 && refNum
  64.             && ResError() == noErr)
  65.             return(refNum);
  66.         }
  67.     return(0);
  68.     }
  69.  
  70. /* Delete all instances of a particular resource.
  71. Call before creating each resource. */
  72. void DeleteAllExistingRsrcs(long theType, short theNum)
  73.     {
  74.     Handle        rsrcHdle;
  75.     
  76.     while (rsrcHdle = Get1Resource(theType, theNum))
  77.         {
  78.         RmveResource(rsrcHdle);
  79.         DisposHandle(rsrcHdle);
  80.         }
  81.     }
  82.  
  83.  
  84. /* Dialogs */
  85.  
  86. void GetDlogOrigin (short dlogID, Point *where)
  87.     {
  88.     short     screenWidth = GetScreenWidth();
  89.     short     screenHeight = GetScreenHeight();
  90.     register DialogTHndl dlogHandle;
  91.     register Rect * drp;
  92.     register short     dlogWidth, dlogHeight;
  93.  
  94.     /* Get a handle to the dialog */
  95.     dlogHandle = (DialogTHndl) GetResource ('DLOG', dlogID);
  96.  
  97.     if (!dlogHandle)
  98.         {
  99.         SetPt (where, 85, 85);
  100.         return;
  101.         }
  102.  
  103.     /* get pointer to its bounding rectangle */
  104.     drp = &((**dlogHandle).boundsRect);
  105.  
  106.     dlogWidth = drp->right - drp->left;
  107.     dlogHeight = drp->bottom - drp->top;
  108.  
  109.     /* Calculate upper left corner that will leave box centered */
  110.     where->h = (screenWidth - dlogWidth) >> 1;
  111.     where->v = (screenHeight - dlogHeight) >> 1;
  112.     }
  113.  
  114.  
  115. Boolean GetAndAlignDialog(short  resID)
  116.     {
  117.     short            sW,sH,dW,dH,left;
  118.     Rect        *drp;
  119.     DialogTHndl    dlogHandle;
  120.     Boolean        bigScreen;
  121.     
  122.     if (!GetResource('DLOG', resID)
  123.         || !GetResource('DITL', resID)
  124.         || ResError())
  125.         {
  126.         MemoryAlert();
  127.         return(FALSE);
  128.         }
  129.     sW = GetScreenWidth();
  130.     sH = GetScreenHeight();
  131.     dlogHandle = (DialogTHndl) GetResource('DLOG', resID);
  132.     drp = &((**dlogHandle).boundsRect);
  133.     dW = drp->right - drp->left;
  134.     dH = drp->bottom - drp->top;
  135.     left = (sW - dW)>>1;
  136.     /* all dialogs centered left-right */
  137.     drp->left = left;
  138.     drp->right = left + dW;
  139.     /* vertical placement depends on screen size */
  140.     if (sW >= 640 && sH >= 480)
  141.         bigScreen = TRUE;
  142.     else
  143.         bigScreen = FALSE;
  144.     
  145.     if (bigScreen)
  146.         {
  147.         /* leave one-third of white at top */
  148.         drp->top = (sH - dH) / 3;
  149.         if (drp->top < 85)
  150.             {
  151.             if (drp->top < 40)
  152.                 drp->top = 40;
  153.             if (sH <= 85 + dH)
  154.                 drp->top = 85;
  155.             }
  156.         }
  157.     else if (sH <= 85 + dH)
  158.         drp->top = 85;
  159.     else
  160.         drp->top = 40;
  161.     drp->bottom = drp->top + dH;
  162.     return(TRUE);
  163.     }
  164.  
  165. /* Place thick border around default item in a dialog */
  166. void FrameDialogItem(DialogPtr dPtr,short theItem)
  167.     {
  168.     GrafPtr            savePort;
  169.     PenState        savePen;
  170.     Handle           h;
  171.     Rect            theBox;
  172.     short                theType, ovalSize;
  173.  
  174.     GetDItem(dPtr,theItem,&theType,&h,&theBox);
  175.     GetPort(&savePort);
  176.     SetPort(dPtr);
  177.     GetPenState(&savePen);
  178.     PenNormal();
  179.     PenSize(2,2);
  180.     InsetRect(&theBox,-3,-3);
  181.     ovalSize = (theBox.bottom + 8 - theBox.top) / 2;    
  182.     FrameRoundRect(&theBox,ovalSize,ovalSize);
  183.     SetPenState(&savePen);
  184.     SetPort(savePort);
  185.     }
  186.  
  187. /* Set text content in a dialog edit field */
  188. void SetEText(DialogPtr dPtr, short theItem, StringPtr newStr)
  189.     {
  190.     short     theType;
  191.     Handle     theItemH;
  192.     Rect     theBox;
  193.  
  194.     GetDItem(dPtr, theItem, &theType, &theItemH, &theBox);
  195.     SetIText(theItemH, newStr);
  196.     }
  197.  
  198. /* Get current text in edit field - note storage for the string must
  199. be allocated by the calling function. */
  200. void GetEText(DialogPtr dPtr, short theItem, StringPtr currentStr)
  201.     {
  202.     short     theType;
  203.     Handle     theItemH;
  204.     Rect     theBox;
  205.  
  206.     GetDItem(dPtr, theItem, &theType, &theItemH, &theBox);
  207.     GetIText(theItemH, currentStr);
  208.     }
  209.  
  210. /* Set/clear check for check box or radio button, pass 0/1 or TRUE/FALSE . */
  211. void SetCheck(DialogPtr dPtr, short chkItem, short zeroMeansNoCheck)
  212.     {
  213.     short     theType;
  214.     Handle     theItemH;
  215.     Rect     theBox;
  216.  
  217.     GetDItem(dPtr, chkItem, &theType, &theItemH, &theBox);
  218.     SetCtlValue((ControlHandle)theItemH, zeroMeansNoCheck);
  219.     }
  220.  
  221. /* For check boxes and radio buttons, requires address of a Boolean from 
  222. the call as in GetCheck(dPtr, 3, &myBoolean). */
  223. /* Usage tip, to toggle a box do
  224. GetCheck (dPtr, chkItem, &myBoolean);
  225. SetCheck (dPtr, chkItem, !myBoolean);
  226. */
  227. void GetCheck(DialogPtr dPtr, short chkItem, Boolean *trueIfChecked)
  228.     {
  229.     short     theType;
  230.     Handle     theItemH;
  231.     Rect     theBox;
  232.  
  233.     GetDItem(dPtr, chkItem, &theType, &theItemH, &theBox);
  234.     *trueIfChecked = (GetCtlValue((ControlHandle)theItemH) != 0);
  235.     }
  236.  
  237. /* Retrieve ControlHandle for button, in the form of a Handle */
  238. Handle GetButton(DialogPtr dPtr, short btnItem)
  239.     {
  240.     short     theType;
  241.     Handle     theItem;
  242.     Rect     theBox;
  243.  
  244.     GetDItem(dPtr, btnItem, &theType, &theItem, &theBox);
  245.     return(theItem);
  246.     }
  247.  
  248. /* Enable (state 0) or disable (state 255) a dialog control */
  249. void HiliteDlgControl(DialogPtr dPtr, short btnItem, short state)
  250.     {
  251.     ControlHandle theButton;
  252.     
  253.     theButton = (ControlHandle) GetButton(dPtr, btnItem);
  254.     if ((**theButton).contrlHilite != state)
  255.         HiliteControl (theButton, state);
  256.     }
  257.  
  258. /* Pascal strings */
  259.  
  260. /* Copy one pascal string to another */
  261. void CopyPStr(Byte *srcStr, Byte *dstStr)
  262.     {
  263.     long   srcLen = srcStr[0];
  264.  
  265.     BlockMove(srcStr, dstStr, srcLen + 1);
  266.     }
  267.  
  268. /* Append pascal s2 to pascal s1, avoiding overflow. */
  269. void AppendPStr(Byte *s1, Byte *s2)
  270.     {
  271.     short    s1Len = s1[0];
  272.     short    s2Len = s2[0];
  273.  
  274.     if (s1Len + s2Len > 255)
  275.         s2Len = 255 - s1Len;
  276.  
  277.     if (s2Len)
  278.         {
  279.         BlockMove (s2 + 1, s1 + s1Len + 1, s2Len);
  280.         s1Len += s2Len;
  281.         s1[0] = s1Len;
  282.         }
  283.     }
  284.  
  285. Boolean PEqualStrs(Byte *aStr, Byte *bStr)
  286.     {
  287.     short i, lena = aStr[0], lenb = bStr[0];
  288.     
  289.     if (!lena || !lenb || lena != lenb)return(FALSE);
  290.     for (i = 1; i <= lena; ++i)
  291.         {
  292.         if (aStr[i] != bStr[i])
  293.             return(FALSE);
  294.         }
  295.     return(TRUE);
  296.     }
  297.  
  298. /* Files, names and locations */
  299.  
  300. /* NOTE the following two functions are based on examples supplied
  301. by Apple on one of their DTS disks - error checking has been added,
  302. and these versions are independent of the signed vs unsigned char
  303. controversy surrounding str255. Byte is defined in MacTypes.h
  304. for THINK C v4. */
  305.  
  306. /* Warning, these calls can fail! And why not? Everything else can... */
  307. /* Bug, these two are not for use by unix imitations. */
  308.  
  309. /* Construct "\PDisk:folder1:folder2:...folderN:" where folderN
  310. contains the file of interest. */
  311. Byte *FullPathNameFromDirectory(long DirID, short vRefNum, Byte *s)
  312.     {
  313.     CInfoPBRec    pb;
  314.     Byte        directoryName[256];
  315.  
  316.     s[0] = 0;
  317.     pb.dirInfo.ioNamePtr = (StringPtr)directoryName;
  318.     pb.dirInfo.ioDrParID = DirID;
  319.  
  320.     do 
  321.         {
  322.         pb.dirInfo.ioVRefNum = vRefNum;
  323.         pb.dirInfo.ioFDirIndex = -1;
  324.         pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
  325.         if (PBGetCatInfo(&pb, FALSE))
  326.             {
  327.             break;
  328.             }
  329.         /* Append a colon  */
  330.         AppendPStr(directoryName, (Byte *)"\p:");
  331.         AppendPStr(directoryName, s);
  332.         CopyPStr(directoryName, s);
  333.         } while (pb.dirInfo.ioDrDirID != 2);
  334.     return(s);
  335.     }
  336.  
  337.  
  338. Byte *FullPathNameFromVRefNum(short vRefNum, Byte *s)
  339.     {
  340.  
  341.     WDPBRec    pb;
  342.  
  343.     pb.ioNamePtr = NULL;
  344.     pb.ioVRefNum = vRefNum;
  345.     pb.ioWDIndex = 0;
  346.     pb.ioWDProcID = 0;
  347.  
  348.     if (PBGetWDInfo(&pb,false))
  349.         {
  350.         s[0] = 0;
  351.         return(s);
  352.         }
  353.     return(FullPathNameFromDirectory(pb.ioWDDirID,pb.ioWDVRefNum,s));
  354.     }
  355.  
  356. /* Determine working directory for file based on full path name. */
  357. short    OpenWorkingDirectoryFromFullName(char *name, short len)
  358.     {
  359.     WDPBRec        theParms;
  360.     OSErr     IOResult;
  361.     char volname[256];
  362.     extern void FileError(OSErr theFileErrorNum);
  363.     
  364.     volname[0] = len;
  365.     BlockMove(name, volname+1, len);
  366.     
  367.     theParms.ioCompletion = NULL;
  368.     theParms.ioVRefNum = 0;
  369.     theParms.ioNamePtr = (StringPtr)volname;
  370.     theParms.ioWDDirID = 2;
  371.     theParms.ioWDProcID = 'ERIK';
  372.     if (IOResult = PBOpenWD(&theParms, FALSE)) /* IM IV pg 158 */
  373.         {
  374.         OKStopAlert("Disk may not be on-line, \
  375. or file may have been moved, deleted, or renamed.");
  376.         theParms.ioVRefNum = 0;
  377.         }
  378.     return(theParms.ioVRefNum);
  379.     }
  380.  
  381.  
  382. /* Memory allocation */
  383. /* Preamble: at present, code resources fall into two camps; those
  384. that allocate a few chunks of memory via NewHandle, and those that
  385. allocate many chunks of memory via malloc. For the latter type,
  386. the following functions keep track of what memory was allocated,
  387. allowing it to be all freed at the end of a run with one call
  388. to TFreeAll().
  389.  
  390. To use the functions TMalloc etc  below instead of the standard malloc etc,
  391. place these lines in some header which is included in all your
  392. code resource files (see eg AWK.H), or at the top of each file:
  393.  
  394. extern void *TMalloc(size_t size);
  395. extern void *Trealloc(void *ptr, size_t size);
  396. extern void Tfree(void *ptr);
  397.  
  398. #define malloc(x) TMalloc(x)
  399. #define realloc(x, y) Trealloc(x, y)
  400. #define free(x) Tfree(x)
  401.  
  402. - before firing up your code resource, call InitTempCodeMemory()
  403.     - see eg InvokeHAWK() in hAWK_Interface.c
  404. -- and after your code resource is done, call TFreeAll()
  405.     - see eg CleanUpAfterHAWK() in hAWK_Interface.c
  406. NOTE InitTempCodeMemory() is called whether using TMalloc() etc
  407. or Fmalloc() etc, BUT the FreeAll() functions are different
  408. -TFreeAll() for the former, FFreeAll() for the latter.
  409. */
  410.  
  411.  
  412. #ifdef malloc
  413. #undef malloc
  414. #undef realloc
  415. #undef free
  416. #endif malloc
  417.  
  418. typedef struct MemoryLinks
  419.     {
  420.     struct     MemoryLinks *next, *prev;
  421.     short    flags;
  422.     }MemoryLinks;
  423.  
  424. MemoryLinks    THead;
  425. MemoryLinks *THeadPtr /* = {&THead, NULL}*/;
  426.  
  427. void InitTempCodeMemory(void)
  428.     {
  429.     THeadPtr = &THead;
  430.     THeadPtr->next = &THead;
  431.     THeadPtr->prev = &THead;
  432.     }
  433.  
  434. /* Tracking versions of malloc, realloc, free - the T stands for temp */
  435. void *TMalloc(size_t size)
  436.     {
  437.     MemoryLinks *new, *old;
  438.     
  439.     size += sizeof(MemoryLinks);
  440.     if (!(new = (MemoryLinks *)malloc(size)))
  441.         return(NULL);
  442.     old = THeadPtr->next; /* true next or THead itself */
  443.     old->prev = new;
  444.     new->next = old;
  445.     new->prev = THeadPtr;
  446.     THeadPtr->next = new;
  447.     return((void *)(new + 1)); /* user doesn't "see" the links */
  448.     }
  449.  
  450. void *Trealloc(void *ptr, size_t size)
  451.     {
  452.     MemoryLinks *retPtr;
  453.     
  454.     if (!ptr)
  455.         return(TMalloc(size));
  456.     if (!size)
  457.         {
  458.         Tfree(ptr);
  459.         return(NULL);
  460.         }
  461.     retPtr = ((MemoryLinks *)(ptr)) - 1;
  462.     /* allocate MemoryLinks, too */
  463.     size += sizeof(MemoryLinks);
  464.     retPtr = (MemoryLinks *)realloc(retPtr, size);
  465.     if (!retPtr) /* failure, but block is still there */
  466.         return(NULL);
  467.     (retPtr->prev)->next = (retPtr->next)->prev = retPtr;
  468.     return((void *)(retPtr + 1));
  469.     }
  470.  
  471. void Tfree(void *ptr)
  472.     {
  473.     MemoryLinks *out;
  474.     
  475.     if (!ptr) return;
  476.     out = ((MemoryLinks *)(ptr)) - 1;
  477.     (out->next)->prev = out->prev;
  478.     (out->prev)->next = out->next;
  479.     free(out);
  480.     }
  481.  
  482. /* list wraps around */
  483. void TFreeAll(void)
  484.     {
  485.     MemoryLinks *dump = THeadPtr->next, *nextOne;
  486. #ifdef TMEMDEBUG
  487.     long    diff;
  488.     char    numStr[16];
  489. #endif
  490.     
  491.     while (dump != THeadPtr)
  492.         {
  493.         nextOne = dump->next;
  494.         free(dump);
  495.         dump = nextOne;
  496.         }
  497. #ifdef TMEMDEBUG
  498.     NumToString(malled, (StringPtr)numStr);
  499.     PtoCstr(numStr);
  500.     OKStopAlert("Total malloc'd:");
  501.     OKStopAlert(numStr);
  502.     NumToString(realled, (StringPtr)numStr);
  503.     PtoCstr(numStr);
  504.     OKStopAlert("Total realloc'd:");
  505.     OKStopAlert(numStr);
  506.  
  507.     if (numfreedAtEnd + tfreeNum != tmallocNum)
  508.         {
  509.         diff = numfreedAtEnd + tfreeNum - tmallocNum;
  510.         if (diff < 0L)
  511.             {
  512.             diff = -diff;
  513.             NumToString(diff, (StringPtr)numStr);
  514.             PtoCstr(numStr);
  515.             OKStopAlert(numStr);
  516.             }
  517.         else /* very odd - more freed than allocated */
  518.             {
  519.             NumToString(diff, (StringPtr)numStr);
  520.             PtoCstr(numStr);
  521.             SysBeep(2);
  522.             SysBeep(2);
  523.             OKStopAlert(numStr);
  524.             }
  525.         
  526.         }
  527.     else
  528.         {
  529.         NumToString(tmallocNum, (StringPtr)numStr);
  530.         PtoCstr(numStr);
  531.         OKStopAlert("Num malloc calls total:");
  532.         OKStopAlert(numStr);
  533.         }
  534. #endif
  535.     }
  536.  
  537. /* more memory allocation - a more efficient (frugal) version */
  538.  
  539. /* A frugal malloc, especially suited for allocating many many
  540. small blocks of memory. Currently used by hAWK, which is 
  541. constantly allocating and freeing small blocks. Note TMalloc()
  542. above basically uses THINK C's malloc, which suffers from
  543. severe fragmentation problems. There is also more overhead with
  544. TMalloc (8 bytes vs 4 here).
  545. Memory is pre–allocated on demand for specific sizes only which
  546. are all powers of two (plus overhead). When you request a block
  547. of memory, your requested size is rounded up to the next power
  548. of two, and the request is satisfied from an array of similar-
  549. sized blocks. */
  550.  
  551. /* Modified for the Mac and THINK C by Ken Earle.
  552.    Based on Larry Wall’s modification (1989) of:
  553.  * malloc.c (Caltech) 2/21/82
  554.  * Chris Kingsley, kingsley@cit-20.
  555.  *
  556.  * This is a very fast storage allocator.  It allocates blocks of a small
  557.  * number of different sizes, and keeps free lists of each size.  Blocks that
  558.  * don't exactly fit are passed up to the next larger size.  In this
  559.  * implementation, the available sizes are 2^n-4 bytes long.
  560.  * This is designed for use in a program that uses vast quantities of memory,
  561.  * but bombs when it runs out.
  562.  
  563. To use the functions Fmalloc etc  below instead of the standard malloc etc,
  564. place these lines in some header which is included in all your
  565. code resource files (see eg AWK.H and CodeResHelper.h), or at 
  566. the top of each file:
  567.  
  568. extern void *Fmalloc(size_t size);
  569. extern void *Frealloc(void *ptr, size_t size);
  570. extern void Ffree(void *ptr);
  571.  
  572. #define malloc(x) Fmalloc(x)
  573. #define realloc(x, y) Frealloc(x, y)
  574. #define free(x) Ffree(x)
  575.  
  576. - before firing up your code resource, call InitTempCodeMemory()
  577.     - see eg InvokeHAWK() in hAWK_Interface.c
  578. -- and after your code resource is done, call FFreeAll()
  579.     - see eg CleanUpAfterHAWK() in hAWK_Interface.c
  580. NOTE InitTempCodeMemory() is called whether using TMalloc() etc
  581. or Fmalloc() etc, BUT the FreeAll() functions are different
  582. -TFreeAll() for the former, FFreeAll() for the latter.
  583.  */
  584.  
  585. #define u_char unsigned char
  586. #define u_int unsigned short
  587. #define u_short unsigned short
  588.  
  589. /*
  590.  * The overhead on a block is at least 4 bytes.  When free, this space
  591.  * contains a pointer to the next free block, and the bottom two bits must
  592.  * be zero.  When in use, the first byte is set to MAGIC, and the second
  593.  * byte is the size index.  The remaining bytes are for alignment.
  594.  */
  595. union    overhead {
  596.     union    overhead *ov_next;    /* when free */
  597.     struct {
  598.         u_char    ovu_magic;    /* magic number */
  599.         u_char    ovu_index;    /* bucket # */
  600.     } ovu;
  601. };
  602. #define    ov_magic    ovu.ovu_magic
  603. #define    ov_index    ovu.ovu_index
  604.  
  605. #define    MAGIC        0xff        /* magic # on accounting info */
  606.  
  607. /*
  608.  * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
  609.  * smallest allocatable block is 8 bytes.  The overhead information
  610.  * precedes the data area returned to the user.
  611.  */
  612. #define    NBUCKETS 30
  613. static    union overhead *nextf[NBUCKETS];
  614.  
  615. #ifdef MSTATS
  616. /*
  617.  * nmalloc[i] is the difference between the number of mallocs and frees
  618.  * for a given block size.
  619.  */
  620. static    u_int nmalloc[NBUCKETS];
  621. #endif
  622.  
  623. /* F stands for Frugal */
  624. void *Fmalloc(register size_t nbytes)
  625.     {
  626.     union overhead *p;
  627.     short e, bucket;
  628.     
  629.     /*
  630.      * Convert amount of memory requested into
  631.      * closest block size stored in hash buckets
  632.      * which satisfies request.  Account for
  633.      * space used per block for accounting.
  634.      */
  635.     --nbytes;
  636.     if (nbytes < 1)
  637.         nbytes = 1;
  638.     e = 1;
  639.     while (nbytes >>= 1)
  640.         ++e;
  641.     if (e <= 3)
  642.         bucket = 0;
  643.     else
  644.         bucket = e - 3;
  645.     // If nothing in hash bucket right now,
  646.     // request more memory from the system.
  647.     if (nextf[bucket] == NULL)
  648.         morecore(bucket);
  649.     if ((p = (union overhead *)nextf[bucket]) == NULL)
  650.         return (NULL);
  651.     // remove from linked list
  652.     nextf[bucket] = p->ov_next;
  653.     p->ov_magic = MAGIC;
  654.     p->ov_index = bucket;
  655. #ifdef MSTATS
  656.     nmalloc[bucket]++;
  657. #endif
  658.     return ((void *)(p + 1));
  659.     }
  660.  
  661. /*
  662.  * Allocate more memory to the indicated bucket.
  663.  */
  664. static void morecore(register short bucket)
  665.     {
  666.     register union overhead *op;
  667.     register short rnu;       /* 2^rnu bytes will be requested */
  668.     register short nblks;     /* become nblks blocks of the desired size */
  669.     register short siz;
  670.  
  671.     if (nextf[bucket])
  672.         return;
  673.     if (bucket > 11)
  674.         {
  675.         nblks = 1;
  676.         rnu = bucket + 3;
  677.         }
  678.     else
  679.         {
  680.         nblks = 1 << (11 - bucket);
  681.         rnu = 14;
  682.         }
  683.     op = (union overhead *)true_get_memory((size_t)(1 << rnu)
  684.             + (size_t)(nblks) * sizeof(union overhead));
  685.     if (op == NULL)
  686.         return;
  687.     // Add new memory allocated to that on
  688.     // free list for this hash bucket.
  689.     nextf[bucket] = op;
  690.     siz = (1 << (bucket + 3)) + sizeof(union overhead);
  691.     while (--nblks > 0) {
  692.         op->ov_next = (union overhead *)((char *)op + siz);
  693.         op = (union overhead *)((char *)op + siz);
  694.     }
  695.     op->ov_next = NULL;
  696. }
  697.  
  698. /* Allocate a large lump of memory, and remember it in a linked
  699. list so that it can be disposed later.
  700. Rev Apr 95, go for tempmem (requires sys 7) before giving up. */
  701. static void *true_get_memory(size_t size)
  702.     {
  703.     MemoryLinks *new, *old;
  704.     
  705.     size += sizeof(MemoryLinks);
  706.     if (!(new = (MemoryLinks *)NewPtr((long)size)))
  707.         {
  708.         // try for tempmem before giving up
  709.         Handle    tempHandle;
  710.         OSErr    err;
  711.         
  712.         tempHandle = TempNewHandle(size, &err);
  713.         if (err == noErr)
  714.             {
  715.             HLock(tempHandle);
  716.             new = (MemoryLinks *)(*tempHandle);
  717.             new->flags = 1; // using temp mem
  718.             }
  719.         else
  720.             return(NULL);
  721.         }
  722.     else
  723.         new->flags = 0; // not using temp mem
  724.     old = THeadPtr->next; /* true next or THead itself */
  725.     old->prev = new;
  726.     new->next = old;
  727.     new->prev = THeadPtr;
  728.     THeadPtr->next = new;
  729.     return((void *)(new + 1)); /* user doesn't "see" the links */
  730.     }
  731.  
  732. void Ffree(void *cp)
  733.     {
  734.     short bucket;
  735.     union overhead *op;
  736.     
  737.     if (cp == NULL)
  738.         return;
  739.     op = (union overhead *)((char *)cp - sizeof (union overhead));
  740.     if (op->ov_magic != MAGIC) {
  741.         return;                /* sanity */
  742.     }
  743.     bucket = op->ov_index;
  744.     op->ov_next = nextf[bucket];
  745.     nextf[bucket] = op;
  746. #ifdef MSTATS
  747.     nmalloc[bucket]--;
  748. #endif
  749.     }
  750.  
  751. /*
  752.  * When a program attempts "storage compaction" as mentioned in the
  753.  * old malloc man page, it realloc's an already freed block.  Usually
  754.  * this is the last block it freed; occasionally it might be farther
  755.  * back.  We have to search all the free lists for the block in order
  756.  * to determine its bucket: 1st we make one pass thru the lists
  757.  * checking only the first block in each; if that fails we search
  758.  * ``reall_srchlen'' blocks in each list for a match (the variable
  759.  * is extern so the caller can modify it).  If that fails we just copy
  760.  * however many bytes was given to realloc() and hope it's not huge.
  761.  */
  762. short reall_srchlen = 4;    /* 4 should be plenty, -1 =>'s whole list */
  763.  
  764. void *Frealloc(void *cp, size_t nbytes)
  765.     {
  766.     register size_t onb;
  767.     union overhead *op;
  768.     char *res;
  769.     register short i;
  770.     short was_alloced = 0;
  771.  
  772.     if (cp == NULL)
  773.         return (Fmalloc(nbytes));
  774.     if (!nbytes)
  775.         {
  776.         Ffree(cp);
  777.         return(NULL);
  778.         }
  779.     op = (union overhead *)((char *)cp - sizeof (union overhead));
  780.     if (op->ov_magic == MAGIC) {
  781.         was_alloced++;
  782.         i = op->ov_index;
  783.     } else {
  784.         /*
  785.          * Already free, doing "compaction".
  786.          *
  787.          * Search for the old block of memory on the
  788.          * free list.  First, check the most common
  789.          * case (last element free'd), then (this failing)
  790.          * the last ``reall_srchlen'' items free'd.
  791.          * If all lookups fail, then assume the size of
  792.          * the memory block being realloc'd is the
  793.          * smallest possible.
  794.          */
  795.         if ((i = findbucket(op, 1)) < 0 &&
  796.             (i = findbucket(op, reall_srchlen)) < 0)
  797.             i = 0;
  798.     }
  799.     onb = (1 << (i + 3));
  800.     /* avoid the copy if same size block */
  801.     if (was_alloced &&
  802.         nbytes <= onb && nbytes > (onb >> 1) ) {
  803.         return(cp);
  804.     }
  805.     if ((res = Fmalloc(nbytes)) == NULL)
  806.         return (NULL);
  807.     if (cp != res)            /* common optimization */
  808.         BlockMove ((Ptr)cp, (Ptr)res, (Size)((nbytes < onb) ? nbytes : onb));
  809.     if (was_alloced)
  810.         Ffree(cp);
  811.     return (res);
  812. }
  813.  
  814. /*
  815.  * Search ``srchlen'' elements of each free list for a block whose
  816.  * header starts at ``freep''.  If srchlen is -1 search the whole list.
  817.  * Return bucket number, or -1 if not found.
  818.  */
  819. static short findbucket(union overhead *freep, short srchlen)
  820.     {
  821.     register union overhead *p;
  822.     register short i, j;
  823.  
  824.     for (i = 0; i < NBUCKETS; i++) {
  825.         j = 0;
  826.         for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
  827.             if (p == freep)
  828.                 return (i);
  829.             j++;
  830.         }
  831.     }
  832.     return (-1);
  833.     }
  834.  
  835. #ifdef MSTATS
  836. /*
  837.  * mstats - print out statistics about malloc
  838.  *
  839.  * Prints two lines of numbers, one showing the length of the free list
  840.  * for each size category, the second showing the number of mallocs -
  841.  * frees for each size category.
  842.  */
  843. void mstats(char *s);
  844. void mstats(char *s)
  845.     {
  846.     register short i, j;
  847.     register union overhead *p;
  848.     short totfree = 0,
  849.     totused = 0;
  850.  
  851.     fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
  852.     for (i = 0; i < NBUCKETS; i++) {
  853.         for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
  854.             ;
  855.         fprintf(stderr, " %d", j);
  856.         totfree += j * (1 << (i + 3));
  857.     }
  858.     fprintf(stderr, "\nused:\t");
  859.     for (i = 0; i < NBUCKETS; i++) {
  860.         fprintf(stderr, " %d", nmalloc[i]);
  861.         totused += nmalloc[i] * (1 << (i + 3));
  862.     }
  863.     fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
  864.         totused, totfree);
  865.     }
  866. #endif
  867.  
  868. /* list wraps around */
  869. void FFreeAll(void)
  870.     {
  871.     MemoryLinks *dump = THeadPtr->next, *nextOne;
  872.     Handle        tempHandle;
  873.     
  874.     while (dump != THeadPtr)
  875.         {
  876.         nextOne = dump->next;
  877.         //dump->flags = 1 means using temp mem
  878.         if (dump->flags & 1)
  879.             {
  880.             tempHandle = RecoverHandle((Ptr)dump);
  881.             if (MemError() == noErr)
  882.                 DisposeHandle(tempHandle);
  883.             }
  884.         else // just a regular pointer
  885.             DisposePtr((Ptr)dump);
  886.         dump = nextOne;
  887.         }
  888.     }
  889.  
  890.  
  891. /* Misc */
  892.  
  893. void NullOut(char *str, long nBytes)
  894.     {
  895.     register long i;
  896.     
  897.     i = nBytes;
  898.     while (--i >= 0)
  899.         *str++ = '\0';
  900.     }
  901.  
  902. /* Check for the generic "Command<period>" that signals a
  903. wish to stop. */
  904. Boolean TaskWasInterrupted()
  905.     {
  906.     EventRecord    event;
  907.     long        thisTime;
  908.     Boolean        gotEvent;
  909.     static long    lastTime;
  910.     
  911.     Delay(0L, &thisTime);
  912.     if (thisTime - lastTime < 60L) return(FALSE);
  913.     lastTime = thisTime;
  914.     SystemTask();
  915.     gotEvent = GetNextEvent(62, &event);
  916.     if (gotEvent) /* see if interrupt */
  917.         {
  918.         switch (event.what)
  919.             {
  920.         case keyDown:
  921.         case autoKey:
  922.             /* look for abort key (Command-<period>) */
  923.         if ((event.modifiers & cmdKey)
  924.              && ((event.message & charCodeMask) == '.'))
  925.             {
  926.             return(TRUE);
  927.             }
  928.         break;
  929.         default:
  930.         break;
  931.             } /* switch */
  932.         }
  933.     return(FALSE);
  934.     }
  935.  
  936. /* Check for events 15 times a second, allow hAWK to run for
  937. at most 12 ticks if no event. Return control to calling
  938. app's event loop, so that hAWK can run at the same time
  939. as calling app without too much slowdown. Return TRUE
  940. if interrupted, FALSE if should continue. */
  941. Boolean CheckInWithCallingApp()
  942.     {
  943.     EventRecord    event;
  944.     long        thisTime;
  945.     Boolean        gotEvent;
  946.     static long    lastTime, tickAlong;
  947.     
  948.     Delay(0L, &thisTime);
  949.     if (thisTime < tickAlong) return(FALSE);
  950.     tickAlong = thisTime + 4L;
  951.     
  952.     if ((gotEvent = EventAvail(everyEvent, &event))
  953.         || thisTime - lastTime > 12L)
  954.         {
  955.         if (gotEvent)
  956.             {
  957.             switch (event.what)
  958.                 {
  959.             case keyDown:
  960.             case autoKey:
  961.                 /* look for abort key (Command-<period>) */
  962.             if ((event.modifiers & cmdKey)
  963.                  && ((event.message & charCodeMask) == '.'))
  964.                 {
  965.                 GetNextEvent(62, &event);
  966.                 return(TRUE);
  967.                 }
  968.             break;
  969.             default:
  970.             break;
  971.                 } /* switch */
  972.             }
  973.         else
  974.             lastTime = thisTime;
  975.         DoEventLoopOnce();
  976.         }
  977.     return(FALSE);
  978.     }
  979. ``¢Helper.c - some handy functions CodeResource_Helper.cTEXTKETEXTKEEN“$§ƒ≠ª`an replace the
  980. three calls above to stringLength() with strlen().
  981. */
  982. long stringLength(char *s)
  983.     {
  984.     long        len = 0L;
  985.     
  986.     while (*s++fi!_i AppendPStr]>]SCheckInWithCallingApp±π    CopyPStr    S    iDeleteAllExistingRsrcsWÇWä    FFreeAllIïIöFfree?Â?ÏFmalloc&FrameDialogItemMñMû    FreallocgÄFullPathNameFromDirectory!û!µFullPathNameFromVRefNumSS findbucket 
  987. GetAndAlignDialogñü    GetButtonYa    GetCheck
  988. %
  989. 2
  990. GetDlogOriginRZ    GetETextâôHiliteDlgControl*fi*InitTempCodeMemoryC!C)    morecoreU0U6mstatsY&Y-NullOuttåOpenOrCreateResourceFork##&!OpenWorkingDirectoryFromFullNameV` PEqualStrszÇ    SetCheck    SetETextY‰YˆTaskWasInterrupted/ã/ì    TFreeAll.ø.ƒTfree+ï+úTMalloc,Û,˚    TreallocF˜Gtrue_get_memory
  991.     Monaco´¡Δ¡2TH    MonacoX]Ù÷X]Ù÷≠¬·IïIöIê``¢;cå¢MPSR2ETABJEFNTVJAGZbWSIZnMWBBzÔˇˇÌˇˇ ÏˇˇΡˇÍÌˇˇ¯ÓˇˇˇˇX