/*======================================*/
/*																			*/
/* Simple window manager V1.0						*/
/*																			*/
/* © J.Tyberghein.											*/
/*		Sun Sep 23 21:05:52 1990					*/
/*																			*/
/*======================================*/


#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfx.h>
#include <graphics/gfxmacros.h>
#include <intuition/intuitionbase.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/wb.h>
#include <proto/dos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/wb_protos.h>
#include <workbench/workbench.h>
#include <string.h>

/*** Menu ID's ***/
#define MENU_QUIT		1000
#define MENU_MAX		1001
#define MENU_MIN		1002
#define MENU_CASC		1003
#define MENU_HTILE	1004
#define MENU_VTILE	1005
#define MENU_ABOUT	1100

/*** Error codes ***/
#define ERR_OPENLIB	-1
#define ERR_PORT		-2
#define ERR_APMENU	-3


struct MsgPort *port = NULL;

extern APTR DOSBase;
struct IntuitionBase *IntuitionBase = NULL;
APTR WorkbenchBase = NULL;
APTR am1 = NULL,am2 = NULL,am3 = NULL,am4 = NULL,am5 = NULL,am6 = NULL,am7 = NULL;


void __regargs CloseStuff (int rc)
{
	switch (rc)
		{
			case -1 : PutStr ("Error opening library !\n"); break;
			case -2 : PutStr ("Error creating message port !\n"); break;
			case -3 : PutStr ("Error adding menu to workbench !\n"); break;
		}

	if (am7) RemoveAppMenuItem (am7);
	if (am6) RemoveAppMenuItem (am6);
	if (am5) RemoveAppMenuItem (am5);
	if (am4) RemoveAppMenuItem (am4);
	if (am3) RemoveAppMenuItem (am3);
	if (am2) RemoveAppMenuItem (am2);
	if (am1) RemoveAppMenuItem (am1);

	if (port) DeleteMsgPort (port);
	if (IntuitionBase) CloseLibrary ((struct Library *)IntuitionBase);
	if (WorkbenchBase) CloseLibrary ((struct Library *)WorkbenchBase);
	XCEXIT (rc);
}


void OpenStuff ()
{
	if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary ("intuition.library",36L)))
		{
			Write (Output (),"You need AmigaDOS 2.0\n",22);
			CloseStuff (0);
		}

	if (!(WorkbenchBase = (APTR )OpenLibrary ("workbench.library",0L)))
		CloseStuff (ERR_OPENLIB);

	if (!(port = (struct MsgPort *)CreateMsgPort ()))
		CloseStuff (ERR_PORT);

	if (!(am1 = (APTR)AddAppMenuItemA (MENU_QUIT,0,"WM: Quit",port,NULL)))
		CloseStuff (ERR_APMENU);
	if (!(am7 = (APTR)AddAppMenuItemA (MENU_ABOUT,0,"WM: About",port,NULL)))
		CloseStuff (ERR_APMENU);
	if (!(am2 = (APTR)AddAppMenuItemA (MENU_MAX,0,"WM: Maximize",port,NULL)))
		CloseStuff (ERR_APMENU);
	if (!(am3 = (APTR)AddAppMenuItemA (MENU_MIN,0,"WM: Minimize",port,NULL)))
		CloseStuff (ERR_APMENU);
	if (!(am4 = (APTR)AddAppMenuItemA (MENU_CASC,0,"WM: Cascade",port,NULL)))
		CloseStuff (ERR_APMENU);
	if (!(am5 = (APTR)AddAppMenuItemA (MENU_HTILE,0,"WM: Horiz Tile",port,NULL)))
		CloseStuff (ERR_APMENU);
	if (!(am6 = (APTR)AddAppMenuItemA (MENU_VTILE,0,"WM: Vert Tile",port,NULL)))
		CloseStuff (ERR_APMENU);

}


void __regargs Minimize (struct Screen *scr)
{
	struct Window *win;

	for (win=scr->FirstWindow ; win ; win=win->NextWindow)
		if (win->Flags & WINDOWSIZING) ChangeWindowBox (win,win->LeftEdge,win->TopEdge,win->MinWidth,win->MinHeight);
}



void __regargs Maximize (struct Screen *scr)
{
	struct Window *win;

	for (win=scr->FirstWindow ; win ; win=win->NextWindow)
		if (win->Flags & WINDOWSIZING) ChangeWindowBox (win,0,0,scr->Width,scr->Height);
}


void __regargs Cascade (struct Screen *scr)
{
	struct Window *win;
	int wd,x,y,w,h,cx,cy;

	for (win=scr->FirstWindow,wd=0 ; win ; win=win->NextWindow)
		if ((win->Flags & WINDOWDRAG) || (win->Flags & WINDOWSIZING)) wd++;

	cx = cy = (wd-1)*20;

	for (win=scr->FirstWindow ; win ; win=win->NextWindow)
		{
			x = win->LeftEdge;
			y = win->TopEdge;
			w = win->Width;
			h = win->Height;
			if (win->Flags & WINDOWDRAG) { x = cx; y = cy; }
			if (win->Flags & WINDOWSIZING) { w = scr->Width-x; h = scr->Height-y; }
			if ((win->Flags & WINDOWDRAG) || (win->Flags & WINDOWSIZING))
				{
					ChangeWindowBox (win,x,y,w,h);
					WindowToBack (win);
					cx -= 20;
					cy -= 20;
					if (cx>scr->Width-20 || cy>scr->Height-20) return;
				}
		}
}


void __regargs HorizTile (struct Screen *scr)
{
	struct Window *win;
	int wd,cx,cw;

	for (win=scr->FirstWindow,wd=0 ; win ; win=win->NextWindow)
		if ((win->Flags & WINDOWDRAG) && (win->Flags & WINDOWSIZING)) wd++;

	cx = 0;
	if (wd) cw = scr->Width/wd;

	for (win=scr->FirstWindow ; win ; win=win->NextWindow)
		if ((win->Flags & WINDOWDRAG) && (win->Flags & WINDOWSIZING))
			{
				ChangeWindowBox (win,cx,0,cw,scr->Height);
				cx += cw;;
			}
}


void __regargs VertTile (struct Screen *scr)
{
	struct Window *win;
	int wd,cy,ch;

	for (win=scr->FirstWindow,wd=0 ; win ; win=win->NextWindow)
		if ((win->Flags & WINDOWDRAG) && (win->Flags & WINDOWSIZING)) wd++;

	cy = 0;
	if (wd) ch = scr->Height/wd;

	for (win=scr->FirstWindow ; win ; win=win->NextWindow)
		if ((win->Flags & WINDOWDRAG) && (win->Flags & WINDOWSIZING))
			{
				ChangeWindowBox (win,0,cy,scr->Width,ch);
				cy += ch;;
			}
}


void argmain ()
{
	unsigned int x,y;
	struct Screen *scr;
	struct AppMessage *apm;
	ULONG ID;

	OpenStuff ();

	Requester ("Window manager","","Installed",0);

	x = y = 50;
	do
		{
			WaitPort (port);
			apm = (struct AppMessage *)GetMsg (port);
			ID = apm->am_ID;
			ReplyMsg ((struct Message *)apm);

			Forbid ();
			scr = IntuitionBase->FirstScreen;
			switch (ID)
				{
					case MENU_MAX		: Maximize (scr); break;
					case MENU_MIN		: Minimize (scr); break;
					case MENU_CASC	: Cascade (scr); break;
					case MENU_HTILE	: HorizTile (scr); break;
					case MENU_VTILE	: VertTile (scr); break;
					case MENU_ABOUT	: Requester ("Window manager V1.0","Written by J.Tyberghein","23 Sep 1990",0); break;
				}
			Permit ();
		}
	while (ID != MENU_QUIT);

	CloseStuff (0);
}
