/*
 *MB.c 
 *
 * Version 1.0 
 *
 * Display della memoria nella menu bar
 *
 *    Il display rappresenta (da sinistra a destra)
 *        Chip memory utilizzata
 *        Chip memory utilizzabile
 *        Fast memory utilizzata
 *        Fast memory utilizzabile
 *
 *
 *     Sebbene il display nasconda i gadget di chiusura e di profondita'
 * essi sono comunque utilizzabili, essendo posizionati dietro il display.
 *
 *     LeRoy M. Hutzenbiler
 *     16 June 1986
 *
 */
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/exec.h>
#include <exec/execbase.h>
#include <exec/ports.h>
#include <exec/devices.h>
#include <exec/memory.h>
#include <devices/timer.h>
#include <graphics/regions.h>
#include <graphics/rastport.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <intuition/intuition.h>

/* #include <stdio.h> */

#define WIN_WIDTH 188
#define THICKNESS 10
#define Y_DRAW  7
#define LEFT_GADGET 28
#define RIGHT_GADGET 56
#define x_chip_used 2
#define x_chip_free 50
#define x_fast_used 98
#define x_fast_free 146

extern struct ExecBase *SysBase;
char ProgramName[] = "MB";
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct MsgPort *timerport, *CreatePort();
struct timerequest timereq;

char size_buff[6]; /* dimensione delle stringhe per le dimensione
                      del display */
long mem_size;   

struct NewWindow NewWindow = {
   (450 - WIN_WIDTH), 0, WIN_WIDTH, THICKNESS,
   -1, -1,
   CLOSEWINDOW | REFRESHWINDOW,
   WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SIMPLE_REFRESH,
   (struct Gadget *) NULL,
   (struct Image *) NULL,
   "MB",
   (struct Screen *) NULL,
   (struct Bitmap *) NULL,
   0, 0, 0, 0,
   WBENCHSCREEN
};

ULONG    AvailMem ();
ULONG    ChipMax, FastMax, ChipFree, FastFree;
ULONG    ChipLargest, FastLargest;

/*
 *  MAXSIZE -- DETERMINA LA DIMENSIONE MASSIMA TOTALE PER TUTTE LE REGION
 *  DI UN TIPO DETERMINATO. QUESTO CODICE DEVE ESSERE ESEGUITO DOPO FORBID()
 *  PERCHE' ESSO ACCEDE A STRUTTURE CONDIVISE DAL SISTEMA.
 */
ULONG
maxsize (t)
    ULONG t;
{
    /* QUESTO CODICE DEVE SEMPRE ESSERE CHIAMATO DOPO FORBID() */
    ULONG size = 0;
    struct MemHeader *mem;
    struct ExecBase *EB = SysBase;

    for (mem = (struct MemHeader *) EB->MemList.lh_Head;
                        mem->mh_Node.ln_Succ; mem = mem->mh_Node.ln_Succ)
       if (mem -> mh_Attributes & t)
          size += ((ULONG) mem->mh_Upper - (ULONG) mem->mh_Lower);
    return size;
}

getsizes()
{
   if (ChipMax == 0) {  /* ONLY DO THIS ONCE */
      Forbid ();
      ChipMax = maxsize (MEMF_CHIP);
      FastMax = maxsize (MEMF_FAST);
      Permit();
   }
   ChipFree = AvailMem (MEMF_CHIP);
   ChipLargest = AvailMem (MEMF_CHIP | MEMF_LARGEST);
   FastFree = AvailMem (MEMF_FAST);
   FastLargest = AvailMem (MEMF_FAST | MEMF_LARGEST);
}

starttimer()
{
   timereq.tr_time.tv_secs = 1;
   timereq.tr_time.tv_micro = 0;
   timereq.tr_node.io_Command = TR_ADDREQUEST;
   timereq.tr_node.io_Flags = 0;
   timereq.tr_node.io_Error = 0;
   timereq.tr_node.io_Message.mn_ReplyPort = timerport;
   SendIO((char *) & timereq.tr_node);
}

/*
 *  QUESTA FUNZIONE VIENE CHIAMATA DURANTE LO STARTUP E QUANDO VENGONO
 *  EFFETTUATE NUOVE SELEZIONI ( PREFERENCES ). OTTIENE LA DIMESIONE DELLA
 *  FONT DALLA STRUTTURA PREFERENCES.
 */

/*
 *  FUNZIONE MAIN. CHIAMA INTUITION PER CREARE UNA NUOVA WINDOW
 *  SUL NOSTRO SCREEN. 
 */
main()
{
   struct Window *w;
   struct IntuiMessage *msg, *GetMsg();
   int waitmask;

   timerport = NULL;
   if ( (IntuitionBase = (struct IntuitionBase *) 
                   OpenLibrary("intuition.library", 0)) == NULL) {
      exit(1);
   };
   if ( (GfxBase = (struct GfxBase *)
              OpenLibrary("graphics.library", 0)) == NULL ){
      CloseLibrary(IntuitionBase);
      exit(2);
   };

   if ((w = (struct Window *) OpenWindow(&NewWindow)) == NULL) {
      CloseLibrary(GfxBase);
      CloseLibrary(IntuitionBase);
      exit(3);
   }
   if ((timerport = CreatePort("Timer Port", 0)) == NULL) {
      CloseWindow(w);
      CloseLibrary(GfxBase);
      CloseLibrary(IntuitionBase);
      exit(5);
   }
   if (OpenDevice(TIMERNAME, UNIT_VBLANK, (char *) &timereq, 0) != 0) {
      DeletePort(timerport);
      CloseWindow(w);
      CloseLibrary(GfxBase);
      CloseLibrary(IntuitionBase);
      exit(4);
   }

   redraw( w );
   starttimer();
   waitmask = (1 << w->UserPort->mp_SigBit) |
              (1 << timerport->mp_SigBit);
   for(;;) {
      Wait(waitmask);
      while (msg = GetMsg(w->UserPort)) {
         switch (msg->Class) {
         case CLOSEWINDOW:
            ReplyMsg(msg);
            AbortIO(&timereq);
            CloseDevice(&timereq);
            DeletePort(timerport);
            CloseWindow(w);
            CloseLibrary(GfxBase);
            CloseLibrary(IntuitionBase);
            exit(0);

         case REFRESHWINDOW:
            BeginRefresh( w );
       redraw( w );
       EndRefresh( w, TRUE );       
            break;
         }
         ReplyMsg(msg);
      } /* while */

      if (GetMsg(timerport)) {
         redraw(w );
         starttimer();
      }
   } /* for */
}


display_size()

{
   register char digit_temp;
   register short i;
   register unsigned char flag;

   flag = FALSE;
   for( i=0; i<6; i++) size_buff[i] = ' ';

   digit_temp = (char) (mem_size / 1000);
   if (digit_temp > 0) {
      size_buff[0] = digit_temp + '0';
      flag = TRUE;
   };

   mem_size %=  1000;       
   digit_temp = (char) (mem_size / 100);
   if ( (digit_temp > 0) || (flag == TRUE) ) {
      size_buff[1] = digit_temp + '0';
      flag = TRUE;
   };

   mem_size %= 100; 
   digit_temp = (char) (mem_size / 10);
   if ( (digit_temp > 0) || (flag) ) 
      size_buff[2] = digit_temp + '0';

   digit_temp = (char) mem_size % 10; 
   size_buff[3] = digit_temp + '0';

   size_buff[4]  = 'K';
}

/*
 *  Redisplay delle dimensioni della memoria nella window.
 */
redraw( w )
   struct Window *w;
{
   register struct RastPort *rp = w->RPort;
   register short x_min;

   getsizes();

/*
 * colori definiti nei termini del display
 * di Amiga
 */

#define screen_color 0
#define text_color   1
#define gadget_color 2
#define cursor_color 3

/* chip memory utilizzata */
   x_min = LEFT_GADGET;
   
   SetAPen(rp, cursor_color);
   SetBPen(rp, screen_color);
   mem_size = (ChipMax - ChipFree) >> 10;
   display_size();
   Move(rp, x_chip_used, Y_DRAW);
   Text(rp, size_buff, 6);

/* chip memory utilizzabile */
   SetBPen(rp, gadget_color);
   mem_size = ChipFree >> 10;
   display_size();
   Move(rp, x_chip_free, Y_DRAW);
   Text(rp, size_buff, 6);

/* fast memory utilizzata */
   SetAPen(rp, text_color);
   SetBPen(rp, screen_color);
   mem_size = (FastMax - FastFree) >> 10;
   display_size();
   Move(rp, x_fast_used, Y_DRAW);
   Text(rp, size_buff, 6);

/* fast memory utilizzabile */
   SetBPen(rp, gadget_color);
   mem_size = FastFree >> 10;
   display_size();
   Move(rp, x_fast_free, Y_DRAW);
   Text(rp, size_buff, 5);
}


