/*
 *	lav.c - Amiga load average
 *
 *	Written by:
 *	William J. Rucklidge
 *	wjr@unicus.UUCP		(soon to be wjr@unicus.com)
 *
 *	You may take this program and skywrite it and sell tickets for all
 *	I care. (i.e this program is placed in the public domain).
 *	However, if you have any improvements, suggestions or comments, mail
 *	a note to me.
 *
 *      Modified to be font sensitive and "2.0ish" by Eric G. Suchanek, Ph.D.,
 *      BIX: esuchanek
 *      INET: procter!suchanek_eg@ms.uky.edu
 *      12/29/92
 */

#include	<intuition/intuition.h>
#include	<exec/exec.h>
#include	<exec/execbase.h>

#define	TIME15	900	/* Number of samples in 15 minutes */
#define	TIME5	300	/* Number of samples in 5 minutes */
#define	TIME1	60	/* Number of samples in 1 minute */
#define	TPS	50	/* Ticks per sample, for Delay() */
#define	CLOSEWIDTH	30	/* Width of the close gadget in pixels */
#define WDRAGBARLEN     40      /* Width of close and drag gadget */
#define INTUI_REV       37L

UBYTE MyIdent[] = "$VER: LAV 1.1 " __DATE__ " ";
UBYTE MyScreenTitle[] = "LAV 1.1 William J. Rucklidge and Eric G. Suchanek, Ph.D. "__DATE__ " ";

struct NewWindow windef = 
{
	430, 0, 240, 12,
	-1, -1,
	CLOSEWINDOW,
	WINDOWCLOSE | WINDOWDRAG,
	NULL, NULL,
	(UBYTE *) "    ",
	NULL, NULL, 0, 0, 0, 0,
	WBENCHSCREEN
};


extern void *OpenLibrary(), *OpenWindow(), *FindTask();

struct IntuitionBase *IntuitionBase;

void convertTime(long sum, int count, register char *position)
{
    register long temp;
    
    temp = (sum * 100L + 50L) / count;
    *(position + 4) = '0' + (int)(temp % 10);
    temp /= 10;
    *(position + 3) = '0' + (int)(temp % 10);
    temp /= 10;
    *(position + 1) = '0' + (int)(temp % 10);
    temp /= 10;
    if (temp != 0) 
      {
	*position = '0' + (int)(temp % 10);
      }
    else 
      {
	*position = ' ';
      }
  }

#define	FORMAT	"Load: ##.## ##.## ##.##"

main()
{
  register int length;	/* Length of the current run queue */
  register struct Node *mynode; /* Node to walk through the queue */
  register int i;	/* General counter */
  int last[TIME15];	/* Length of the run queue in the last TIME seconds */
  long sum15 = 0;	/* Sum of the last 15 minutes */
  long sum5 = 0;	/* Sum of the last 5 minutes */
  long sum1 = 0;	/* Sum of the last minute */
  int pos = 0;	/* Current position in last for new value */
  int pos15 = 0;	/* Current position in last for sum15 */
  int pos5 = TIME15-TIME5;	/* Current position in last for sum5 */
  int pos1 = TIME15-TIME1;	/* Current position in last for sum1 */
  char uptimestr[26];
  struct ExecBase *ExecBase;
  struct Window *win;
  struct Screen *myscr = NULL;
    
  struct RastPort tmprp;   /* RastPort for font-sensitive trick */
  struct TextFont *f;
  ULONG ww = 0;
  
  SetTaskPri(FindTask(0L), 5L);
  
  (void) strcpy(uptimestr, FORMAT);
  
  if (!(ExecBase = (struct ExecBase *)OpenLibrary("exec.library", INTUI_REV))) {
    VPrintf("Couldn't open exec... the sky is falling!\n");
    exit(999);
  }
  
  if (!(IntuitionBase =
	(struct IntuitionBase *)OpenLibrary("intuition.library", INTUI_REV))) 
    {
      VPrintf("Couldn't open intuition - must be dumb\n");
      CloseLibrary(ExecBase);
      exit(998);
    }
  
  if (!(myscr = LockPubScreen(NULL)))
    {
      VPrintf("Couldn't lock Workbench screen");
      CloseLibrary(IntuitionBase);
      CloseLibrary(ExecBase);
      exit(996);
    }
  
  
  if (!(f=OpenFont(myscr->Font))) goto done;
  InitRastPort(&tmprp);
  SetFont(&tmprp,f);
  ww=TextLength(&tmprp,FORMAT,strlen(FORMAT));
  CloseFont(f);
  
  if (!(win = OpenWindowTags(&windef,
			     WA_Height, myscr->BarHeight + 1, 
			     WA_Width, ww+WDRAGBARLEN,
			     WA_PubScreen, myscr, TAG_END))) 
    {
      printf("Couldn't open window\n");
      CloseLibrary(IntuitionBase);
      CloseLibrary(ExecBase);
      exit(997);
    }
  
  UnlockPubScreen(NULL);
  
  
  for (i = 0; i < TIME15 ; i++) 
    {
      last[i] = 0;
    }
  
  for (;;) 
    {
      Delay((long)TPS);
      if (GetMsg(win -> UserPort)) 
	{
	  break;
	}
    
      length = 0;
      Disable();
      for (mynode = (ExecBase -> TaskReady).lh_Head;
	   mynode = mynode -> ln_Succ; ) {
	length++;
      }
      Enable();
    
      sum15 += (length - last[pos15]);
      sum5 += (length - last[pos5]);
      sum1 += (length - last[pos1]);
      last[pos] = length;
      if (++pos15 == TIME15) 
	{
	  pos15 = 0;
	}
      if (++pos5 == TIME15) 
	{
	  pos5 = 0;
	}
      if (++pos1 == TIME15) 
	{
	  pos1 = 0;
	}
      if (++pos == TIME15) 
	{
	  pos = 0;
	}
    
      convertTime(sum1, TIME1, uptimestr + 6);
      convertTime(sum5, TIME5, uptimestr + 12);
      convertTime(sum15, TIME15, uptimestr + 18);
    
      SetWindowTitles(win, uptimestr, MyScreenTitle);
    }
  
 done:
  if (win) 
    CloseWindow(win);
  if (IntuitionBase) 
    CloseLibrary(IntuitionBase);
  if (ExecBase) 
    CloseLibrary(ExecBase);
}




