/********************************************************************
  FSR displays the percentage of free system resources in real time.
  Copyright (c) 1993 Jeff Prosise. First published in PC Magazine,
  U.S. Edition, April 13, 1993.
 ********************************************************************/

#include <windows.h>
#include <stdlib.h>

#define IDM_ALWAYSONTOP 100

extern DWORD FAR PASCAL GetHeapSpaces (HMODULE);
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG);
DWORD GetFSR (BOOL);

WORD wTimerID;						// Timer ID

/********************************************************************
  WinMain starts the program.
 ********************************************************************/

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
					LPSTR lpszCmdLine, int nCmdShow)
{
	static char szAppName[] = "Free System Resources";
	WNDCLASS wndclass;
	HWND hwnd;
	MSG msg;

 	if (hPrevInstance)
		return FALSE;

	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc = (WNDPROC) WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = NULL;
	wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
	wndclass.hbrBackground = GetStockObject (LTGRAY_BRUSH);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = szAppName;

	RegisterClass (&wndclass);

	hwnd = CreateWindow (szAppName, szAppName, WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, CW_USEDEFAULT, 384, 96, NULL, NULL,
			hInstance, NULL);

	if ((wTimerID = SetTimer (hwnd, 1, 1000, NULL)) == NULL) {
		MessageBox (hwnd, "Unable to allocate a timer", "Error",
			MB_ICONEXCLAMATION | MB_OK);
		return FALSE;
	}

 	ShowWindow (hwnd, nCmdShow);
	UpdateWindow (hwnd);

 	while (GetMessage (&msg, NULL, 0, 0))
			DispatchMessage (&msg);

 	return msg.wParam;
}

/********************************************************************
  WndProc processes messages to the main window.
 ********************************************************************/

long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
	static char szSection[] = "Options";
	static char szEntry[] = "AlwaysOnTop";
	static char szIniFile[] = "FSR.INI";

	static HPEN hGrayPen;
	static HBRUSH hPinkBrush, hRedBrush;
	RECT rect, rectUsed, rectFree;
	static DWORD dwPercentFree;
	DWORD dwVersion, dwTotal;
	static BOOL bWin31Flag;
	static HMENU hSysMenu;
	char szBuffer[4];
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message) {

	case WM_CREATE:
		dwVersion = GetVersion ();
		if ((LOBYTE (LOWORD (dwVersion)) >= 3) &&
			(HIBYTE (LOWORD (dwVersion)) >= 10))
			bWin31Flag = TRUE;
		else
			bWin31Flag = FALSE;

		hGrayPen = CreatePen (PS_SOLID, 1, RGB (128, 128, 128));
		hPinkBrush = CreateSolidBrush (RGB (192, 0, 192));
		hRedBrush = CreateSolidBrush (RGB (192, 0, 0));

		dwPercentFree = GetFSR (bWin31Flag);

		if (bWin31Flag) {
			hSysMenu = GetSystemMenu (hwnd, FALSE);
			AppendMenu (hSysMenu, MF_SEPARATOR, 0, NULL);
			AppendMenu (hSysMenu, MF_STRING, IDM_ALWAYSONTOP,
				"Always on &Top");
			if (GetPrivateProfileInt (szSection, szEntry, 0, szIniFile)) {
				CheckMenuItem (hSysMenu, IDM_ALWAYSONTOP, MF_CHECKED);
				SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0,
					SWP_NOMOVE | SWP_NOSIZE);
			}
		}
		return 0;

	case WM_PAINT:
		hdc = BeginPaint (hwnd, &ps);
		SetBkMode (hdc, TRANSPARENT);
		GetClientRect (hwnd, &rect);

		if (IsIconic (hwnd)) {
			FillRect (hdc, &rect, GetStockObject (LTGRAY_BRUSH));
			SetTextColor (hdc, RGB (0, 0, 192));
			DrawText (hdc, _itoa ((int) dwPercentFree, szBuffer, 10),
				-1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
		}
		else {
			if ((--rect.bottom < 16) || (--rect.right < 32))
				return 0;
			InflateRect (&rect, -4, -4);

			SelectObject (hdc, hGrayPen);
			MoveTo (hdc, rect.left, rect.bottom);
			LineTo (hdc, rect.left, rect.top);
			LineTo (hdc, rect.right+1, rect.top);
			MoveTo (hdc, rect.right-1, rect.top+1);
			LineTo (hdc, rect.left+1, rect.top+1);
			LineTo (hdc, rect.left+1, rect.bottom);

			SelectObject (hdc, GetStockObject (WHITE_PEN));
			MoveTo (hdc, rect.left+1, rect.bottom);
			LineTo (hdc, rect.right, rect.bottom);
			LineTo (hdc, rect.right, rect.top);
			MoveTo (hdc, rect.right-1, rect.top+2);
			LineTo (hdc, rect.right-1, rect.bottom-1);
			LineTo (hdc, rect.left+1, rect.bottom-1);

			InflateRect (&rect, -2, -2);
			rect.right++;
			rect.bottom++;
			CopyRect (&rectUsed, &rect);
			CopyRect (&rectFree, &rect);
			dwTotal = (DWORD) (rect.right - rect.left);
			rectFree.right = rectFree.left +
				((int) ((dwTotal * dwPercentFree) / 100));
			rectUsed.left = rectFree.right;

			if (dwPercentFree >= 25)
				FillRect (hdc, &rectFree, hPinkBrush);
			else
				FillRect (hdc, &rectFree, hRedBrush);
			FillRect (hdc, &rectUsed, GetStockObject (LTGRAY_BRUSH));
			SetTextColor (hdc, RGB (255, 255, 255));
			DrawText (hdc, _itoa ((int) dwPercentFree, szBuffer, 10),
				-1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
		}

		EndPaint (hwnd, &ps);
		return 0;

	case WM_TIMER:
		dwPercentFree = GetFSR (bWin31Flag);
		GetClientRect (hwnd, &rect);
		InflateRect (&rect, -6, -6);
		InvalidateRect (hwnd, &rect, FALSE);
		return 0;

	case WM_SYSCOMMAND:
		if (wParam == 100) {
			if ((GetMenuState (hSysMenu, IDM_ALWAYSONTOP, MF_BYCOMMAND) &
				MF_CHECKED)) {
				CheckMenuItem (hSysMenu, IDM_ALWAYSONTOP, MF_UNCHECKED);
				SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
					SWP_NOMOVE | SWP_NOSIZE);
				WritePrivateProfileString (szSection, szEntry, "0",
					szIniFile);
			}
			else {
				CheckMenuItem (hSysMenu, IDM_ALWAYSONTOP, MF_CHECKED);
				SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0,
					SWP_NOMOVE | SWP_NOSIZE);
				WritePrivateProfileString (szSection, szEntry, "1",
					szIniFile);
			}
			return 0;
		}
		break;

	case WM_DESTROY:
		KillTimer (hwnd, wTimerID);
		DeleteObject (hPinkBrush);
		DeleteObject (hRedBrush);
		DeleteObject (hGrayPen);
		PostQuitMessage (0);
		return 0;
	}
	return DefWindowProc (hwnd, message, wParam, lParam);
}

/********************************************************************
  GetFSR returns a value between 0 and 100 that quantifies the
  percentage of free system resources.
 ********************************************************************/

DWORD GetFSR (BOOL bWin31)
{
	DWORD dwHeapSpaces;
	WORD wUSERPercentFree, wGDIPercentFree;

	if (bWin31)
		return ((DWORD) GetFreeSystemResources (GFSR_SYSTEMRESOURCES));
	else {
		dwHeapSpaces = GetHeapSpaces (GetModuleHandle ("USER"));
		wUSERPercentFree = (WORD) (((DWORD) (LOWORD (dwHeapSpaces)) * 100) /
			((DWORD) (HIWORD (dwHeapSpaces))));
		dwHeapSpaces = GetHeapSpaces (GetModuleHandle ("GDI"));
		wGDIPercentFree = (WORD) (((DWORD) (LOWORD (dwHeapSpaces)) * 100) /
			((DWORD) (HIWORD (dwHeapSpaces))));
		return ((DWORD) min (wUSERPercentFree, wGDIPercentFree));
	}
}
