/**********************************************
 **************   commod.c   ******************
 **********************************************/

#define INTUI_V36_NAMES_ONLY

#include <libraries/commodities.h>
#include <exec/exec.h>
#include <intuition/intuition.h>

#include <clib/commodities_protos.h>
#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>	/* For printf calls, remove when finished */

#include "stickit2.h"

#include "consts.h"
#include "structs.h"
#include "proto.h"

#define EVT_HOTKEY		1L

extern prj_p prj;

#ifdef _DCC
extern __chip UWORD WaitPointer[];
#else
extern UWORD __chip WaitPointer[];
#endif

/*
Function : void commod_startup(void)
Purpose : Sets up the program as a commodity.
*/

void commod_startup(void)
{
	struct NewBroker newbroker = {
		NB_VERSION,
		"StickIt2",
		"StickIt2",
		"Sticky Note Reminder - © Andy Dean 1993",
		0,
		COF_SHOW_HIDE,
		0,
		0,
		0
	};

	newbroker.nb_Port = prj->broker_msg_port;
	newbroker.nb_Pri = prj->prefs.cx_priority;

	/* Set up main broker */

	prj->broker = CxBroker(&newbroker,NULL);

	if (!prj->broker)
		error("Can't define broker",ERR_FATAL,__LINE__,__FILE__);

	/* Set up filter */

	prj->filter = CxFilter(prj->prefs.cx_popkey);

	if (!prj->filter)
		error("Can't define filter",ERR_FATAL,__LINE__,__FILE__);

	/* Add filter to broker's personal list */

	AttachCxObj(prj->broker,prj->filter);

	/* Set up sender (wow this is tedious) */

	prj->sender = CxSender(prj->broker_msg_port,EVT_HOTKEY);

	if (!prj->sender)
		error("Can't define sender",ERR_FATAL,__LINE__,__FILE__);

	AttachCxObj(prj->filter,prj->sender);

	/* Finally, the translater */

	prj->translate = CxTranslate(NULL);

	if (!prj->translate)
		error("Can't define translate",ERR_FATAL,__LINE__,__FILE__);

	AttachCxObj(prj->filter,prj->translate);

	/* Test the commodities error of the whole object */

	if (CxObjError(prj->filter))
		error("Can't build commodities object",ERR_FATAL,__LINE__,
__FILE__);

	/* Activate the object (YEAH!) */

	ActivateCxObj(prj->broker,1L);
}

/*
Function : BOOL commod_event()
Purpose : Handles a commodity event. Returns TRUE if a CXCMD_KILL is received,
	else FALSE.
*/

BOOL commod_event()
{
	struct EasyStruct quitreq = {
		sizeof(struct EasyStruct),
		0,
		"StickIt2",
		"Data has changed, continue with quit ?",
		"Okay|Cancel"
	};

	CxMsg *cxmsg;

	ULONG msg_type,msg_id;
	BOOL done = FALSE;

	/* Get message from port */

	while (cxmsg = (CxMsg *)GetMsg(prj->broker_msg_port)) {
		msg_id = CxMsgID(cxmsg);
		msg_type = CxMsgType(cxmsg);
		ReplyMsg((struct Message *)cxmsg);

		switch (msg_type) {
			case CXM_IEVENT:
				switch(msg_id) {
					case EVT_HOTKEY:
						openwindowcommod();
						break;
					default:
						break;
				}
				break;
			case CXM_COMMAND:
				switch (msg_id) {
					case CXCMD_APPEAR:
						/* Who cares if it opens! */
						openwindowcommod();
						break;

					case CXCMD_DISAPPEAR:
						/* Will only close if open */
						closewindowcommod();
						break;

					case CXCMD_DISABLE:
						ActivateCxObj(prj->broker,0L);
						break;

					case CXCMD_ENABLE:
						ActivateCxObj(prj->broker,1L);
						break;

					case CXCMD_KILL:
						if (prj->projectchanged) {
							if (EasyRequest(
commod,&quitreq,NULL,TAG_END))
								done = TRUE;
						}
						else
							done = TRUE;

						break;

					default:
						break;
				}
			default:
				break;
		}
	}

	return(done);
}

/*
Function : BOOL commodwin_event(struct IntuiMessage *curr_msg)
Purpose : Handles a commodity window event. Returns TRUE if a user selects
	Quit from the menus, else FALSE.
*/

BOOL commodwin_event(struct IntuiMessage *curr_msg)
{
	BOOL done = FALSE;

	done = processwindowcommod(curr_msg);

	return (done);
}

/*
Function : BOOL processwindowcommod(struct IntuiMessage *curr_msg)
Purpose : A clone of Designer's event handler. The function returns TRUE if the
	user selects Quit, else returns FALSE. If curr_msg->Class ==
	IDCMP_CLOSEWINDOW, the window is closed here.
*/

BOOL processwindowcommod(struct IntuiMessage *curr_msg)
{
	BOOL done = FALSE;

	switch (curr_msg->Class) {
		case IDCMP_REFRESHWINDOW:
			GT_BeginRefresh(commod);
			GT_EndRefresh(commod,TRUE);
			break;
		case IDCMP_CLOSEWINDOW:
			done = commodclose();
			break;
		case IDCMP_MENUPICK:
			done = processwindowmenucommod(curr_msg);
			break;
		case IDCMP_GADGETUP:
			processwindowgadcommod(curr_msg);
			break;
		case IDCMP_VANILLAKEY:
			/* Don't need a curr_note for "Add" */

			switch (curr_msg->Code) {
				case 'N':
				case 'n':
					commodnew();
					break;
				default:
					break;
			}

			if (!prj->curr_note)
				break;

			switch (curr_msg->Code) {
				case 'L':
				case 'l':
					commoddel();
					break;
				case 'U':
				case 'u':
					commodup();
					break;
				case 'D':
				case 'd':
					commoddown();
					break;
				case 'T':
				case 't':
					ActivateGadget(
commodGadgets[commod_title],commod,NULL);
					break;
				case 'F':
				case 'f':
					commodfont();
					break;
				case 'S':
				case 's':
					ActivateGadget(
commodGadgets[commod_pubscreen],commod,NULL);
					break;
				default:
					break;
			}
			break;
		default:
			break;
	}

	return (done);
}

/*
Function : BOOL processwindowmenucommod(struct IntuiMessage *curr_msg)
Purpose : Processes all menu events (a clone of The Designer routine).
*/

BOOL processwindowmenucommod(struct IntuiMessage *curr_msg)
{
	struct EasyStruct aboutreq = {
		sizeof(struct EasyStruct),
		0,
		"StickIt2",
		"%s\n\n%s\n\nCX_POPKEY = \"%s\"",
		"Okay"
	};

	struct EasyStruct quitreq = {
		sizeof(struct EasyStruct),
		0,
		"StickIt2",
		"Data has changed, continue with quit ?",
		"Okay|Cancel"
	};

	struct MenuItem *menuitem;

	extern char *versionstring;

	UWORD menunumber;
	UWORD menunum;
	UWORD itemnumber;
	UWORD subnumber;

	BOOL done = FALSE;

	int l;

	menunumber = curr_msg->Code;

	while ((menunumber != MENUNULL) && (!done)) {
		menuitem = ItemAddress(commodMenu,menunumber);
		menunum = MENUNUM(menunumber);
		itemnumber = ITEMNUM(menunumber);
		subnumber = SUBNUM(menunumber);

		switch (menunum) {
			case NOMENU:
				break;

			case commodMenu_project:
				switch (itemnumber) {
					case NOITEM:
						break;
					case commodMenu_project_save:
						file_writenotes();
						break;
					case commodMenu_project_about:
						note_blockall();
						commod_block();

						EasyRequest(commod,&aboutreq,
NULL,&versionstring[6],VERSION_STRING2,prj->prefs.cx_popkey);
						note_blockclearall();
						commod_blockclear();

						break;
					case commodMenu_project_hide:
						done = commodclose();
						break;
					case commodMenu_project_quit:
						/* Store data */

						if (prj->curr_note)
							commodtonote(
prj->curr_note);
						if (prj->projectchanged) {
							if (EasyRequest(
commod,&quitreq,NULL,TAG_END)) {
								done = TRUE;
								prj->abouttoquit = TRUE;
							}
						}
						else {
							done = TRUE;
							prj->abouttoquit = TRUE;
						}

						break;
					default:
						break;
				}
				break;
			case commodMenu_notes:
				switch(itemnumber) {
					case NOITEM:
						break;
					case commodMenu_notes_new:
						commodnew();
						break;
					case commodMenu_notes_delete:
						commoddel();
						break;
					case commodMenu_notes_redraw:
						/* Close all */

						for (l = 0; l < NO_NOTES; l++) {
							if (prj->notes[l])
								note_close(
prj->notes[l],FALSE);
						}

						/* Open all */

						for (l = NO_NOTES -1; l >= 0; l--) {
							if (prj->notes[l]) {
								note_open(
prj->notes[l]);
								note_refresh(
prj->notes[l]);
							}
						}
						break;
					default:
						break;
				}
				break;
			default:
				break;
		}

	menunumber = menuitem->NextSelect;
	}

	return(done);
}

/*
Function : int openwindowcommod()
Purpose : Calls the Designer's OpenWindowcommod() function then attaches the
	list to the listview gadget.
*/

int openwindowcommod()
{
	BOOL alreadyopen = FALSE;

	int failed;

	alreadyopen = commod ? TRUE : FALSE;

	failed = OpenWindowcommod(prj->main_msg_port);

	/* If the window is open, push its screen to the front */

	if (commod)
		ScreenToFront(commod->WScreen);

	if ((!failed) && (!alreadyopen)) {
		/* Don't want bloody IDCMP_INTUITICKS */

		ModifyIDCMP(commod,commod->IDCMPFlags &= ~IDCMP_INTUITICKS);

		GT_SetGadgetAttrs(commodGadgets[commod_listview],commod,NULL,
GTLV_Labels,&prj->commodlist,TAG_END);
	}

	return(failed);
}

/*
Function : void closewindowcommod()
Purpose : Like Designer's CloseWindowcommod(), but cleans up a few extra things
	as well.
*/

void closewindowcommod()
{
	/* First detatch list view (not really needed, but neat) */

	if (commod)
		GT_SetGadgetAttrs(commodGadgets[commod_listview],commod,NULL,
GTLV_Labels,NULL,TAG_END);

	CloseWindowcommod();

	prj->curr_note = NULL;
}

/*
Function : void processwindowgadcommod(struct IntuiMessage *curr_msg)
Purpose : Handles all the gadget presses in the commodities window.
*/

void processwindowgadcommod(struct IntuiMessage *curr_msg)
{
	struct Gadget *curr_gad;

	curr_gad = (struct Gadget *)curr_msg->IAddress;

	switch (curr_gad->GadgetID) {
		case commod_listview:
			commodlistview(curr_msg->Code,curr_msg->Seconds,
curr_msg->Micros);
			break;
		case commod_cyccolour:
			commodcyccolour(curr_msg->Code);
			break;
		case commod_palette:
			commodpalette(curr_msg->Code);
			break;
		case commod_title:
			commodtitle();
			break;
		case commod_font:
			commodfont();
			break;
		case commod_pubscreen:
			commodpubscreen();
			break;
		case commod_new:
			commodnew();
			break;
		case commod_del:
			commoddel();
			break;
		case commod_up:
			commodup();
			break;
		case commod_down:
			commoddown();
			break;
		default:
			break;
	}
}

/*
Function : void commod_block()
Purpose : Blocks the current note to mouse input and puts up a wait pointer.
*/

void commod_block()
{
	/* Only do it if window open */

	if (!commod)
		return;

	InitRequester(&prj->blockreq);

	if (Request(&prj->blockreq,commod))
		SetPointer(commod,WaitPointer,16,16,-6,0);
}

/*
Function : void commod_blockclear()
Purpose : Clears the commodities win for mouse input and returns to the normal
	pointer.
*/

void commod_blockclear()
{
	/* Only do it if window open */

	if (!commod)
		return;

	ClearPointer(commod);
	EndRequest(&prj->blockreq,commod);
}

