/* SYSGRAPH  3.0
 *
 * Version 3.0 14-dec-90 J.R. Hasselbeck
 *			     o  Option to show CPU loading rather or
 *				a relative CPU freetime type of display.
 *			     o  Rebuilt for windows 3.0
 *			     o  Added user selectable update rate.
 *
 * Version 2.0 4/20/88    (c) Copyright 1988, Bill Crow, Hewlett-Packard Co
 *			 Renamed from SYSQUEUE to SYSGRAPH
 *                       Added dynnamic scaling
 *                       Added menu commands for rescaling and Auto Rescaling
 *                       Added About... Dialog box.
 *
 * Previous versions:
 *
 * SysQueue.C -- Windows application that displays system load
 * by Barry Press, adapted from FreeMem written
 * by Charles Petzold as printed in Microsoft Systems Journal
 *
 * Adapted for Graphic Display by Alec Saunders
 * Graph goes down when load increases and rises when
 * load decreases.
 */


#include <windows.h>	/* all Windows functions */
#include <stdlib.h>	/* ltoa */
#include <string.h>	/* strcat & strlen */
#include "sysgraph.h"   /* RC defines */

#define MAXCOUNT 25
 
static HANDLE globhInst;

static int  lLoopCount[MAXCOUNT];
static int  iMaxSize=0;

static BOOL bRescale=FALSE;
static BOOL bAutoRescale=FALSE;
static short nCurrentType = IDD_FREE;
static short nCurrentUpdate = IDD_1SEC;
static int lTmpCnt = 0;
static int smpcnt = 2; /* 2 samples per 1 sec def update */


long FAR PASCAL WndProc     (HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL AboutDlgProc(HWND, unsigned, WORD, LONG);

/* WinMain - Main loop for all Windows applications */
int PASCAL WinMain ( hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
HANDLE  hInstance, hPrevInstance;
LPSTR   lpszCmdLine;
int     nCmdShow;
{
	static   char szAppName [] = "SysGraph";
	WNDCLASS WndClass;
	HWND     hWnd;
	MSG      msg;
        HMENU    hMenu;
	int	 i;

	/* allow only one instance */
	if (hPrevInstance)
	   return FALSE;

        globhInst = hInstance;

	/* define Window class */
	WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon         = NULL;
	WndClass.cbClsExtra    = 0;
	WndClass.cbWndExtra    = 0;
	WndClass.lpszMenuName  = NULL;
	WndClass.lpszClassName = szAppName;
	WndClass.hbrBackground = GetStockObject( WHITE_BRUSH );
	WndClass.hInstance     = hInstance;
	WndClass.style         = CS_VREDRAW | CS_HREDRAW;
	WndClass.lpfnWndProc   = WndProc;

	/* register this new class with WINDOWS */
	if (!RegisterClass( &WndClass ))
	   return FALSE;   /* Initialization failed */

	/* create window */
	hWnd = CreateWindow( szAppName,
			szAppName,
			WS_TILEDWINDOW,
			0, 0, 0, 0,
			(HWND)   NULL,
			(HMENU)  NULL,
			hInstance,
			NULL);

	/* set up timer (1 update/sec) */
	if (!SetTimer (hWnd, 1, 1000, NULL) )
	   return FALSE;

	hMenu = GetSystemMenu(hWnd,FALSE);
	ChangeMenu(hMenu, 0, NULL, 999, MF_APPEND | MF_SEPARATOR);
	ChangeMenu(hMenu,0,(LPSTR)"R&escale", IDRESCALE,
            MF_APPEND | MF_STRING | (bAutoRescale? MF_GRAYED : MF_ENABLED));
	ChangeMenu(hMenu,0,(LPSTR)"A&uto Rescale", IDAUTORESCALE, 
            MF_APPEND | MF_STRING | (bAutoRescale? MF_CHECKED : MF_UNCHECKED));
	ChangeMenu(hMenu,0,(LPSTR)"A&bout...",IDABOUT, MF_APPEND | MF_STRING);
	   
        /* show window (start in ICONIC state) */
	ShowWindow( hWnd, SHOW_ICONWINDOW );
	UpdateWindow( hWnd );

	/* initialize loop count which is bumped in loop */
	for(i=0;i<MAXCOUNT;lLoopCount[i++] = 0)
		;

	/* main program loop */
	while (TRUE) {
 		lTmpCnt++;
		if (PeekMessage( &msg, NULL, 0, 0, TRUE )) {
			if (msg.message == WM_QUIT)
				break;
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
	}

	/* exit back to Windows */
	return (int) msg.wParam;

} /* end WinMain */

/* WndProc - Window procedure for main window */
long FAR PASCAL WndProc (hWnd, message, wParam, lParam)
HWND	 hWnd;
unsigned message;
WORD	 wParam;
LONG	 lParam;
{

char	buffer[MAXCOUNT];
PAINTSTRUCT ps;
RECT	rect;
HMENU   hMenu;
int	i;
static int lupdate;

	/* switch on message type sent to window by Windows dispatcher */
	switch(message) {

	   case WM_TIMER:
 	      if (lupdate != nCurrentUpdate)
	        {
	        KillTimer (hWnd, 1);
		lupdate = nCurrentUpdate;
		SetTimer (hWnd, 1, (lupdate - 9) * 1000, NULL);
		}

 	      lLoopCount[MAXCOUNT - 1] = lTmpCnt / smpcnt;
              if (iMaxSize<lLoopCount[MAXCOUNT-1])
                  iMaxSize=lLoopCount[MAXCOUNT-1];
	      for (i=0; i<(MAXCOUNT - 1); i++)
	     	 lLoopCount[i] = lLoopCount[i+1];
 	      lTmpCnt = 0;
              InvalidateRect( hWnd, NULL, TRUE );
	      break;

	   case WM_PAINT:
	      BeginPaint( hWnd, &ps );
	      GetClientRect( hWnd, &rect );
	      SetMapMode( ps.hdc, MM_ANISOTROPIC);
              if (bRescale | bAutoRescale) {
		 iMaxSize=0; 
		 for (i=0;i<MAXCOUNT;i++) {
		    if (iMaxSize<lLoopCount[i])
			iMaxSize=lLoopCount[i];
		 }
                 bRescale=FALSE;
              }
	      SetWindowOrg( ps.hdc, 0, 0);
	      SetWindowExt( ps.hdc, MAXCOUNT, iMaxSize);
	      SetViewportOrg(ps.hdc, 0, 0);
	      SetViewportExt(ps.hdc, rect.right - rect.left,
	      			  rect.bottom - rect.top);

 	      if (nCurrentType == IDD_LOAD)
	        {
	        MoveTo( ps.hdc, 0, lLoopCount[0]);
	        for (i = 1; i < (MAXCOUNT - 1); i++)
	      	  LineTo( ps.hdc, i, lLoopCount[i]);
                }
	      else
	        {
	        MoveTo( ps.hdc, 0, iMaxSize - lLoopCount[0]);
	        for (i = 1; i < (MAXCOUNT - 1); i++)
	      	  LineTo( ps.hdc, i, iMaxSize - lLoopCount[i]);
                }

	      EndPaint( hWnd, &ps );
	      break;

	      case WM_SYSCOMMAND:
		switch (wParam)
		{
		  case IDABOUT:
		    DialogBox(globhInst,
		      (LPSTR)"AboutBox",
		      hWnd,
		      MakeProcInstance( (FARPROC)AboutDlgProc, globhInst));
		    break;

		  case IDRESCALE:
		    bRescale=TRUE;
                    break;

		  case IDAUTORESCALE:
		    bAutoRescale = ! bAutoRescale;
		    hMenu = GetSystemMenu(hWnd,FALSE);
		    CheckMenuItem(hMenu,
		       IDAUTORESCALE,
                       MF_BYCOMMAND | 
                         (bAutoRescale? MF_CHECKED : MF_UNCHECKED));
		    EnableMenuItem(hMenu,
		       IDRESCALE,
		       MF_BYCOMMAND | 
                         (bAutoRescale? MF_GRAYED : MF_ENABLED));
		    break;

		  default:
		    return DefWindowProc(hWnd,message,wParam,lParam);  
		    break;

		}
		break;

	   case WM_DESTROY:
	      KillTimer (hWnd, 1);
	      PostQuitMessage( 0 );
	      break;

	   default:
	      return DefWindowProc( hWnd, message, wParam, lParam);
	}

	return (long) 0;

} /* end WndProc */



BOOL FAR PASCAL AboutDlgProc(hDlg, imessage, wParam, lParam )
HWND hDlg;
unsigned imessage;
WORD wParam;
LONG lParam;
{

static HWND hCtrlBlock;
static short nupdate;	/* Update rate */
static short ntype;

switch (imessage)
  {
  case WM_INITDIALOG:	nupdate = nCurrentUpdate;
    			ntype = nCurrentType;
			CheckRadioButton (hDlg, IDD_1SEC, IDD_5SEC, nupdate);
			CheckRadioButton (hDlg, IDD_FREE, IDD_LOAD, ntype);
			hCtrlBlock = GetDlgItem(hDlg, IDD_PAINT);
			SetFocus (GetDlgItem(hDlg, nupdate));
			return FALSE;

  case WM_COMMAND:
    switch (wParam)
      {
      case IDOK:	nCurrentType = ntype;
      			nCurrentUpdate = nupdate;
			EndDialog (hDlg, TRUE);
 		        smpcnt = 10;
 			if (nupdate == IDD_1SEC)
			  smpcnt = 2;
			if (nupdate == IDD_2SEC)
			  smpcnt = 4;

			break;

      case IDCANCEL:	EndDialog (hDlg, TRUE);
      			break;

      case IDD_1SEC:
      case IDD_2SEC:
      case IDD_5SEC:
      			nupdate = wParam;
			CheckRadioButton (hDlg, IDD_1SEC, IDD_5SEC, wParam);
			break;

      case IDD_FREE:
      case IDD_LOAD:
      			ntype = wParam;
			CheckRadioButton (hDlg, IDD_FREE, IDD_LOAD, wParam);
			break;

      default:		return FALSE;
      } /* end switch */
    break;

  default:      return FALSE;
  } /* end switch */
return TRUE;
} /* end of procedure AboutDlgProc() */
