/*
 *   This program displays a constantly-updating window indicated your
 *   memory fragmentation, free memory, and sizes of the largest
 *   available chunks.  Useful for finding out why those large programs
 *   won't load.  Also useful during development to see what impact
 *   your application is having on memory fragmentation.
 *
 *   To run, simply type
 *
 *      run wfrags
 *
 *   That's all!  Enjoy this program.  Bugs to Tomas Rokicki, Box 2081,
 *   Stanford, CA  94309.
 */
#include "intuition/intuition.h"
#include "functions.h"
#include <exec/exec.h>
#include <exec/execbase.h>
long delayval = 40 ;
struct Window *window ;
struct MsgPort *myport ;
struct IntuitionBase *IntuitionBase ;
struct NewWindow newwindow = {
   0,                                        /* left edge */
   0,                                        /* top edge */
   544,                                      /* width */
   46,                                       /* height */
   0,                                        /* detail pen */
   1,                                        /* block pen */
   CLOSEWINDOW,                              /* these messages we receive. */
   WINDOWDEPTH | WINDOWCLOSE | WINDOWDRAG | SMART_REFRESH,
                                             /* a few gadgets */
   NULL,                                     /* no gadgets initially */
   NULL,                                     /* default checkmark */
   (UBYTE *)"Wfrags (by Radical Eye Software)",  /* title */
   NULL,                                     /* initialize this! */
   NULL,                                     /* use screen bitmap */
   -1, -1, -1, -1,                           /* min sizes */
   WBENCHSCREEN } ;                          /* this is a customscreen */
long chip[25], fast[25] ;
char buf[80] ;
struct TextAttr myfont = {
   (STRPTR) "topaz.font",
   TOPAZ_EIGHTY,
   0,
   0
};
struct IntuiText intuitext = {
   1, 0,
   JAM2,
   0, 0,
   &myfont,
   (UBYTE *)buf,
   NULL
};
draw(where)
long where ;
{
   PrintIText(window->RPort, &intuitext, 4L, where) ;
}
static char tbuf[8] ;
icat(i, s)
long i ;
register char *s ;
{
   register char *p, *q ;

   p = tbuf ;
   do {
      *p++ = '0' + i % 10 ;
      i = i / 10 ;
   } while (i) ;
   q = buf + strlen(buf) ;
   while (p > tbuf)
      *q++ = *--p ;
   strcpy(q, s) ;
}
fillout(s, i)
char *s ;
register long *i ;
{
   register char *p ;
   int j ;

   strcpy(buf, s) ;
   p = buf + strlen(buf) ;
   i += 3 ;
   for (j=0; j<21; j++, i++, p += 3) {
      if (*i == 0)
         p[2] = ' ' ;
      else
         p[2] = '0' + *i % 10 ;
      if (*i < 10)
         p[1] = ' ' ;
      else
         p[1] = '0' + (*i / 10) % 10 ;
      if (*i < 100)
         *p = ' ' ;
      else
         *p = '0' + *i / 100 ;
   }
   *p = 0 ;
}
updatescreen() {
   register long size ;
   register long i ;
   register struct MemHeader *hdr ;
   register struct MemChunk *chunk ;
   extern struct ExecBase *SysBase ;
   register long *which ;

   for (i=0; i<25; i++) {
      chip[i] = 0 ;
      fast[i] = 0 ;
   }
   Forbid() ;
   hdr = (struct MemHeader *) SysBase->MemList.lh_Head ;
   while (hdr->mh_Node.ln_Succ) {
      if (hdr->mh_Attributes & MEMF_CHIP)
         which = chip ;
      else
         which = fast ;
      for (chunk = hdr->mh_First; chunk; chunk = chunk->mc_Next) {
         size = chunk->mc_Bytes ;
         *which += size ;
         if (size > which[1])
            which[1] = size ;
         i = 0 ;
         if (size >= 0x10000) {
            size >>= 16 ;
            i += 16 ;
         }
         if (size >= 0x100) {
            size >>= 8 ;
            i += 8 ;
         }
         if (size >= 0x10) {
            size >>= 4 ;
            i += 4 ;
         }
         if (size >= 4) {
            size >>= 2 ;
            i += 2 ;
         }
         if (size >= 2) {
            size >>= 1 ;
            i += 1 ;
         }
         which[i]++ ;
      }
      hdr = (struct MemHeader *)hdr->mh_Node.ln_Succ ;
   }
   Permit() ;
   strcpy(buf,
   "      3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23") ;
   draw(11L) ;
   fillout("chip", chip) ;
   draw(19L) ;
   fillout("fast", fast) ;
   draw(27L) ;
   strcpy(buf, "(Chip tot=") ;
   icat(chip[0], " big=") ;
   icat(chip[1], ") (Fast tot=") ;
   icat(fast[0], " big=") ;
   icat(fast[1], ")     ") ;
   draw(35L) ;
}
main() {
   struct IntuiMessage *message ;

   if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary(
         "intuition.library",33L))!=NULL &&
         (window=OpenWindow(&newwindow))!=NULL) {
      while ((message=(struct IntuiMessage *)GetMsg(window->UserPort))
              ==NULL) {
         updatescreen() ;
         Delay(delayval) ;
      }
   }
   if (window)
      CloseWindow(window) ;
   if (IntuitionBase)
      CloseLibrary(IntuitionBase) ;
}
_cli_parse() {}
_wb_parse() {}
