#include <exec/types.h>
#include <exec/execbase.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/dos.h>
#include <intuition/intuition.h>
#include <stdio.h>
#include <string.h>
#include "xferq.h"
#include "xferqint.h"
#include "xferq_pragmas.h"


#define	NOLIB			1
#define	BADLIB		2
#define	ACTIVE		3

struct Library *XferqBase;
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;

struct meter {
	long numobj;
	long *used;
	long *free;
	char **names;
};

struct TextAttr Topaz = {
	"topaz.font",
	8, 0, 0
};


int main(void)
{
struct Node *node;
struct Window *win;
struct meter meter, *pmeter;
int state, active;
int height;
int i, y, ticks, renderOK;
int cheight, ctop, cleft, cwidth;
struct RastPort *rp;
struct MsgPort *idcmp;
struct IntuiMessage *im;
char buffer[8];

	XferqBase = NULL;
	GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37);
	IntuitionBase = (struct IntuitionBase *)
		OpenLibrary("intuition.library", 37);
	win = NULL;
	if (!GfxBase || !IntuitionBase) {
		goto cleanup;
	}
	
	win = OpenWindowTags(NULL,
		WA_Left, 0,
		WA_Top, 0,
		WA_InnerWidth, 28*8 + 2,
		WA_InnerHeight, 8 + 2,
		WA_AutoAdjust, TRUE,
		WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_CHANGEWINDOW,
		WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
					WFLG_SMART_REFRESH | WFLG_NOCAREREFRESH,
		WA_Title, "XferQ Memory Meter",
		TAG_DONE);
	if (!win) {
		goto cleanup;
	}
	cheight = win->BorderTop + win->BorderBottom + 2;
	cwidth = win->BorderLeft + win->BorderRight + 2;
	ctop = win->BorderTop + 1;
	cleft = win->BorderLeft + 1;
	rp = win->RPort;
	idcmp = win->UserPort;

	state = NOLIB;
	XferqBase = NULL;
	renderOK = TRUE;
	active = TRUE;
	
	while (active) {
		Forbid();
		node = FindName(&SysBase->LibList, "xferq.library");
		Permit();
	
		if (!node) {
			state = NOLIB;
		}
		else {
			XferqBase = OpenLibrary("xferq.library", 1);
			if (!XferqBase) {
				state = NOLIB;
			}
			else {
				pmeter = XfqHookTags(
					XQ_Meter, &meter,
					TAG_DONE);
				if (!pmeter) {
					CloseLibrary(XferqBase);
					XferqBase = NULL;
					state = BADLIB;
				}
				else {
					state = ACTIVE;
				}
			}
		}
		
		/*
		 *		Compute new height and set it.
		 */
		height = cheight + 8;
		if (state == ACTIVE) {
			for (i = 0; i < pmeter->numobj; i++) {
				if (pmeter->names[i]) {
					height += 8;
				}
			}
		}
		
		if (renderOK) {
			if (height != win->Height) {
				ChangeWindowBox(win, win->LeftEdge, win->TopEdge,
					cwidth + 28 * 8, height);
				renderOK = FALSE;
				ticks = 10;
			}
			else {
				ticks = 100;
			}
		}
		
		/*
		 *		Render.
		 */
		if (renderOK) {
			switch (state) {
			case ACTIVE:
				Move(rp, cleft, ctop + 6);
				SetAPen(rp, 3);
				Text(rp, "Name            Used    Free", 28);
				SetAPen(rp, 1);
				y = ctop + 14;
				for (i = 0; i < pmeter->numobj; i++) {
					if (pmeter->names[i]) {
						Move(rp, cleft, y);
						Text(rp, pmeter->names[i], strlen(pmeter->names[i]));
					
						sprintf(buffer, " %7d", pmeter->used[i]);
						Move(rp, cleft + 8 * 12, y);
						Text(rp, buffer, strlen(buffer));

						sprintf(buffer, " %7d", pmeter->free[i]);
						Text(rp, buffer, strlen(buffer));
						
						y += 8;
					}
				}
				break;
			case NOLIB:
				SetAPen(rp, 1);
				Move(rp, cleft, ctop + 6);
				Text(rp, " (xferq.library not loaded) ", 28);
				break;
			case BADLIB:
				SetAPen(rp, 1);
				Move(rp, cleft, ctop + 6);
				Text(rp, " (meter info not available) ", 28);
				break;
			}
		}
		
		if (XferqBase) {
			CloseLibrary(XferqBase);
			XferqBase = NULL;
		}
		
		/*
		 *		Check IDCMP
		 */
		im = (struct IntuiMessage *)GetMsg(idcmp);
		if (im) {
			switch (im->Class) {
			case IDCMP_CLOSEWINDOW:
				active = FALSE;
				break;
			case IDCMP_CHANGEWINDOW:
				renderOK = TRUE;
				SetAPen(rp, 0);
				RectFill(rp, win->BorderLeft, win->BorderTop,
					win->Width - win->BorderRight - 1,
					win->Height - win->BorderBottom - 1);
				break;
			}
			ReplyMsg(im);
		}
		
		/*
		 *		Delay
		 */
		if (active) {
			Delay(ticks);
		}
	}
	
cleanup:
	if (win) {
		CloseWindow(win);
	}
	if (XferqBase) {
		CloseLibrary(XferqBase);
	}
	if (IntuitionBase) {
		CloseLibrary((struct Library *)IntuitionBase);
	}
	if (GfxBase) {
		CloseLibrary((struct Library *)GfxBase);
	}
	return 0;
}


