/*************************************************
 **************   commodgad.c   ******************
 *************************************************/

#define INTUI_V36_NAMES_ONLY

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

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

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

#include "stickit2.h"

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

extern prj_p prj;

/*
Function : void commodlistview(int number,ULONG seconds,ULONG micros)
Purpose : The user has clicked on the listview gadget, number number. If there
	is already a note in the gadgets, this info is copied out. The selected
	note is then shown.
*/

void commodlistview(int number,ULONG seconds,ULONG micros)
{
	/* If there is no current note on display, de-ghost the gadgets */

	if (!prj->curr_note) {
		GT_SetGadgetAttrs(commodGadgets[commod_title],commod,NULL,
GA_Disabled,FALSE,TAG_END);
		GT_SetGadgetAttrs(commodGadgets[commod_cyccolour],commod,NULL,
GA_Disabled,FALSE,TAG_END);
		GT_SetGadgetAttrs(commodGadgets[commod_palette],commod,NULL,
GA_Disabled,FALSE,TAG_END);
		GT_SetGadgetAttrs(commodGadgets[commod_font],commod,NULL,
GA_Disabled,FALSE,TAG_END);
		GT_SetGadgetAttrs(commodGadgets[commod_pubscreen],commod,NULL,
GA_Disabled,FALSE,TAG_END);
	}
	else
		commodtonote(prj->curr_note);

	prj->curr_note = prj->notes[number];

	if (!prj->curr_note)
		error("Can't find listview note",ERR_FATAL,__LINE__,__FILE__);

	notetocommod(prj->curr_note);

	/* If timings are zero, selected from menu */

	if ((!seconds) && (!micros))
		return;

	/* Did the user double-click on the gadget ? */

	if ((DoubleClick(prj->doubleclickseconds,prj->doubleclickmicros,
seconds,micros)) && (prj->lastclicked == number)) {
		note_open(prj->curr_note);
		note_refresh(prj->curr_note);
	}

	/* Copy double click values */

	prj->lastclicked = number;
	prj->doubleclickseconds = seconds;
	prj->doubleclickmicros = micros;
}

/*
Function : void commodcyccolour(int number)
Purpose : The user has clicked on the cycle gadget. Store the number in the
	prj structure.
*/

void commodcyccolour(int number)
{
	note_p curr_note;

	prj->commodcolour = number;

	if (!prj->curr_note)
		return;

	curr_note = prj->curr_note;

	/* Find out which colour to show */

	switch (prj->commodcolour) {
		case COLOUR_BACKGROUND:
			GT_SetGadgetAttrs(commodGadgets[commod_palette],commod,
NULL,GTPA_Color,curr_note->backcolour,TAG_END);
			break;
		case COLOUR_TEXT:
			GT_SetGadgetAttrs(commodGadgets[commod_palette],commod,
NULL,GTPA_Color,curr_note->textcolour,TAG_END);
			break;
		case COLOUR_CARAT:
			GT_SetGadgetAttrs(commodGadgets[commod_palette],commod,
NULL,GTPA_Color,curr_note->caratcolour,TAG_END);
			break;
		default:
			break;
	}
}

/*
Function : void commodpalette(int number)
Purpose : The user has clicked on the palette gadget. Refresh the note and
	carat colours as appropriate.
*/

void commodpalette(int number)
{
	note_p curr_note;

	if (!prj->curr_note)
		return;

	curr_note = prj->curr_note;

	switch (prj->commodcolour) {
		case COLOUR_BACKGROUND:
			if (curr_note->backcolour == number)
				break;

			curr_note->backcolour = number;

			if (curr_note->win)
				note_refresh(curr_note);
			break;
		case COLOUR_TEXT:
			if (curr_note->textcolour == number)
				break;

			curr_note->textcolour = number;

			if (curr_note->win)
				note_refresh(curr_note);
			break;
		case COLOUR_CARAT:
			if (curr_note->caratcolour == number)
				break;

			if (!curr_note->carat.text) {
				curr_note->caratcolour = number;
				break;
			}
			break;
		default:
			break;
	}

	/* Colour probably changed */

	prj->projectchanged = TRUE;
}

/*
Function : void commodtitle()
Purpose : The user has clicked on the title gadget. Copy the new title text
	to the window's title bar.
*/

void commodtitle()
{
	struct Window *curr_win;
	struct Gadget *curr_gad;

	note_p curr_note;

	if (!prj->curr_note)
		return;

	curr_note = prj->curr_note;

	curr_win = curr_note->win;

	if (!curr_win)
		return;

	curr_gad = commodGadgets[commod_title];

	strncpy(curr_note->title,
((struct StringInfo *)curr_gad->SpecialInfo)->Buffer,STRLEN_NOTETITLE);

	SetWindowTitles(curr_win,curr_note->title,(UBYTE *)-1);

	/* Data has probably changed */

	prj->projectchanged = TRUE;
}

/*
Function : void commodfont()
Purpose : The user has clicked on the font... gadget, so pop up a font
	requester.
*/

void commodfont()
{
	struct FontRequester *fontreq;
	struct Window *curr_win;
	struct RastPort *curr_rport;

	note_p curr_note;

	if (!prj->curr_note)
		return;

	curr_note = prj->curr_note;
	curr_win = curr_note->win;
	curr_rport = curr_win->RPort;

	if (curr_note->fontname[0] != '\0')
		fontreq = (struct FontRequester *)AllocAslRequestTags(
ASL_FontRequest,ASL_FontName,prj->curr_note->fontname,ASL_FontHeight,
prj->curr_note->textattr.ta_YSize,ASL_FontStyles,
prj->curr_note->textattr.ta_Style,ASL_HookFunc,(ULONG)hookfunc,
ASL_FuncFlags,FONF_STYLES|FONF_DOMSGFUNC,ASL_Window,commod,TAG_DONE);
	else
		fontreq = (struct FontRequester *)AllocAslRequestTags(
ASL_FontRequest,ASL_FontName,"topaz.font",ASL_FontHeight,8,ASL_FontStyles,
prj->curr_note->textattr.ta_Style,ASL_HookFunc,(ULONG)hookfunc,
ASL_FuncFlags,FONF_STYLES|FONF_DOMSGFUNC,ASL_Window,commod,TAG_DONE);

	if (!fontreq)
		return;

	/* Block mouse input to all open windows */

	note_blockall();
	commod_block();

	if (AslRequest(fontreq,NULL)) {
		/* If existing font open, close it */

		if (curr_note->font) {
			CloseFont(curr_note->font);
			curr_note->font = NULL;
		}

		/* Copy new font details to note */

		strncpy(curr_note->fontname,fontreq->fo_Attr.ta_Name,STRLEN_FONTNAME);
		curr_note->textattr.ta_Name = curr_note->fontname;
		curr_note->textattr.ta_YSize = fontreq->fo_Attr.ta_YSize;
		curr_note->textattr.ta_Style = fontreq->fo_Attr.ta_Style;
		curr_note->textattr.ta_Flags = prj->prefs.textattr.ta_Flags;

		/* Open new font */

		curr_note->font = OpenDiskFont(&curr_note->textattr);

		if (!curr_note->font)
			curr_note->fontname[0] = '\0';

		if ((curr_note->win) && (curr_note->font)) {
			/* Add any font styles */

			SetFont(curr_rport,curr_note->font);
			SetSoftStyle(curr_rport,
curr_note->textattr.ta_Style ^ curr_note->font->tf_Style,
(FSF_BOLD | FSF_UNDERLINED | FSF_ITALIC));
		}

		/* If default font */

		if ((curr_note->win) && (!curr_note->font)) {
			note_close(curr_note,FALSE);
			note_open(curr_note);
		}

		/* Only do the rest if the window is open */

		if (curr_note->win)
			note_refresh(curr_note);

		/* Update text string */

		build_fontstring(curr_note);
		GT_SetGadgetAttrs(commodGadgets[commod_fontstr],commod,
NULL,GTTX_Text,curr_note->fontstring,TAG_END);

		/* Data has probably changed */

		prj->projectchanged = TRUE;
	}

	/* Clear input to all open windows */

	note_blockclearall();
	commod_blockclear();

	FreeAslRequest(fontreq);
}

CPTR hookfunc(LONG type,CPTR obj,struct FontRequester *fontreq)
{
	struct IntuiMessage *curr_msg;

	note_p curr_note;

	curr_msg = (struct IntuiMessage *)obj;

	switch(type) {
		case FONF_DOMSGFUNC:
			switch (curr_msg->Class) {
				case IDCMP_REFRESHWINDOW:
					if (curr_msg->IDCMPWindow == commod)
						break;

					/* Must be a note message */

					curr_note = note_from_window(
curr_msg->IDCMPWindow);

					if (!curr_note)
						break;

					BeginRefresh(curr_msg->IDCMPWindow);
					note_refresh(curr_note);
					EndRefresh(curr_msg->IDCMPWindow,TRUE);

					break;
				default:
					break;
			}
		default:
			break;
	}

	return (obj);
}

/*
Function : void commodpubscreen()
Purpose : The user has clicked on the pubscreen gadget. When the presses
	on ENTER, we try and open the note on the new window.
*/

void commodpubscreen()
{
	struct Window *curr_win;
	struct Gadget *curr_gad;

	note_p curr_note;

	if (!prj->curr_note)
		return;

	curr_note = prj->curr_note;

	curr_win = curr_note->win;

	if (!curr_win)
		return;

	curr_gad = commodGadgets[commod_pubscreen];

	strncpy(curr_note->pubscreen,
((struct StringInfo *)curr_gad->SpecialInfo)->Buffer,STRLEN_PUBSCREEN);

	if (curr_win) {
		note_close(curr_note,FALSE);
		note_open(curr_note);
		note_refresh(curr_note);
	}

	/* Data has probably changed */

	prj->projectchanged = TRUE;
}

/*
Function : void commodnew()
Purpose : The user has clicked on the "New" in the listview or "New note" from
	the commod menu. If there is room, a note is created and added at the
	head of the list.
*/

void commodnew()
{
	int l;

	/* Is there any space in the notes array? */

	if (next_free_note() == NO_FREE_NOTES) {
		error("Maximum number of notes in use",ERR_WARNING,__LINE__,
__FILE__);
		return;
	}

	/* Copy the stuff from the gadgets into the current selected note */

	if ((commod) && (prj->curr_note))
		commodtonote(prj->curr_note);

	/* Shift all the notes in the array up one to make space at [0] */

	/* Temporarily disconnect then list */

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

	for (l = (NO_NOTES - 2); l >= 0; l--) {
		prj->notes[l + 1] = prj->notes[l];
		prj->notes[l + 1]->node.ln_Pri = - (BYTE)(l + 1);
	}

	/* Re-connect with new priorities */

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

	prj->notes[0] = NULL;

	/* Create the note */

	note_create(0);

	/* Open the note */

	note_open(prj->notes[0]);
	note_refresh(prj->notes[0]);

	/* If the listview is selected, copy the stuff into it */

	if ((commod) && (prj->curr_note)) {
		prj->curr_note = prj->notes[0];
		notetocommod(prj->curr_note);

		GT_SetGadgetAttrs(commodGadgets[commod_listview],commod,NULL,
GTLV_Selected,0,TAG_END);
	}

	/* Data changed */

	prj->projectchanged = TRUE;
}

/*
Function : void commoddel()
Purpose : Removes the prj->curr_note from the array and shifts the rest around.
*/

void commoddel()
{
	int notepos;
	int l;

	/* If there's no current note, can't do anything */

	if (!prj->curr_note) {
		error("No note selected",ERR_WARNING,__LINE__,__FILE__);
		return;
	}

	/* Ghost out all the gadgets */

	if (commod) {
		GT_SetGadgetAttrs(commodGadgets[commod_title],commod,NULL,
GA_Disabled,TRUE,TAG_END);
		GT_SetGadgetAttrs(commodGadgets[commod_cyccolour],commod,NULL,
GA_Disabled,TRUE,TAG_END);
		GT_SetGadgetAttrs(commodGadgets[commod_palette],commod,NULL,
GA_Disabled,TRUE,TAG_END);
		GT_SetGadgetAttrs(commodGadgets[commod_font],commod,NULL,
GA_Disabled,TRUE,TAG_END);
		GT_SetGadgetAttrs(commodGadgets[commod_pubscreen],commod,NULL,
GA_Disabled,TRUE,TAG_END);
	}

	/* Deselect it from the list */

	GT_SetGadgetAttrs(commodGadgets[commod_listview],commod,NULL,
GTLV_Selected,~0,TAG_END);

	note_close(prj->curr_note,TRUE);

	/* Where abouts in the array is it ? */

	notepos = positionfromnote(prj->curr_note);

	prj->curr_note = NULL;

	if (notepos == NOT_IN_ARRAY)
		error("Can't find deleted note in array",ERR_FATAL,__LINE__,
__FILE__);

	/* Shift the rest of the array, disconnect first */

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

	for (l = notepos; l < (NO_NOTES - 1); l++) {
		prj->notes[l] = prj->notes[l + 1];
		prj->notes[l]->node.ln_Pri = - (BYTE)(l);
	}

	prj->notes[NO_NOTES - 1] = NULL;

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

	/* Data changed */

	prj->projectchanged = TRUE;
}

/*
Function : void commodup()
Purpose : Moves the prj->curr_note up in the listview.
*/

void commodup()
{
	note_p temp_note;

	int notepos;

	/* If no note selected */

	if (!prj->curr_note)
		return;

	notepos = positionfromnote(prj->curr_note);

	if (notepos == NOT_IN_ARRAY)
		error("Can't find note in array",ERR_FATAL,__LINE__,__FILE__);

	/* Can't move top note up */

	if (notepos == 0)
		return;

	/* Disconnect the list */

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

	/* Swap priorities first */

	prj->notes[notepos]->node.ln_Pri = - (BYTE)(notepos - 1);
	prj->notes[notepos - 1]->node.ln_Pri = - (BYTE)(notepos);

	/* Swap positions notepos and notepos - 1 */

	temp_note = prj->notes[notepos];
	prj->notes[notepos] = prj->notes[notepos - 1];
	prj->notes[notepos - 1] = temp_note;

	/* Remove both from the list and re-enque */

	Remove(&prj->notes[notepos]->node);
	Remove(&prj->notes[notepos - 1]->node);

	Enqueue(&prj->commodlist,&prj->notes[notepos]->node);
	Enqueue(&prj->commodlist,&prj->notes[notepos - 1]->node);

	/* Reconnect list */

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

	/* Select the next one */

	GT_SetGadgetAttrs(commodGadgets[commod_listview],commod,NULL,
GTLV_Selected,notepos - 1,TAG_END);

	/* Data changed */

	prj->projectchanged = TRUE;
}

/*
Function : void commoddown()
Purpose : Moves the prj->curr_note down in the listview.
*/

void commoddown()
{
	note_p temp_note;

	int notepos;

	/* If no note selected */

	if (!prj->curr_note)
		return;

	notepos = positionfromnote(prj->curr_note);

	if (notepos == NOT_IN_ARRAY)
		error("Can't find note in array",ERR_FATAL,__LINE__,__FILE__);

	/* Can't move bottom note down */

	if ((notepos == (NO_NOTES - 1)) || !(prj->notes[notepos + 1]))
		return;

	/* Disconnect the list */

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

	/* Swap priorities first */

	prj->notes[notepos]->node.ln_Pri = - (BYTE)(notepos + 1);
	prj->notes[notepos + 1]->node.ln_Pri = - (BYTE)(notepos);

	/* Swap positions notepos and notepos + 1 */

	temp_note = prj->notes[notepos];
	prj->notes[notepos] = prj->notes[notepos + 1];
	prj->notes[notepos + 1] = temp_note;

	/* Remove both from the list and re-enque */

	Remove(&prj->notes[notepos]->node);
	Remove(&prj->notes[notepos + 1]->node);

	Enqueue(&prj->commodlist,&prj->notes[notepos]->node);
	Enqueue(&prj->commodlist,&prj->notes[notepos + 1]->node);

	/* Reconnect list */

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

	/* Select the next one */

	GT_SetGadgetAttrs(commodGadgets[commod_listview],commod,NULL,
GTLV_Selected,notepos + 1,TAG_END);

	/* Data changed */

	prj->projectchanged = TRUE;
}

/*** Utility routines (not direct gadget presses) *****************************/

/*
Function : void commodtonote(note_p curr_note)
Purpose : Copies all the info in the gadgets in the commodities window into
	curr_note.
*/

void commodtonote(note_p curr_note)
{
	struct Gadget *curr_gad;
	struct Window *curr_win;

	curr_win = curr_note->win;

	if (!curr_win)
		return;

	/* Copy title text from gadget to note */

	curr_gad = commodGadgets[commod_title];

	/* See if data changed */

	if (strncmp(curr_note->title,
((struct StringInfo *)curr_gad->SpecialInfo)->Buffer,STRLEN_NOTETITLE))
		prj->projectchanged = TRUE;

	strncpy(curr_note->title,
((struct StringInfo *)curr_gad->SpecialInfo)->Buffer,STRLEN_NOTETITLE);

	SetWindowTitles(curr_win,curr_note->title,(UBYTE *)-1);

	/* Copy pub screen name into note and refresh if needed */

	curr_gad = commodGadgets[commod_pubscreen];

	if (strcmp(((struct StringInfo *)curr_gad->SpecialInfo)->Buffer,
curr_note->pubscreen)) {
		strncpy(curr_note->pubscreen,
((struct StringInfo *)curr_gad->SpecialInfo)->Buffer,STRLEN_PUBSCREEN);

		note_close(curr_note,FALSE);
		note_open(curr_note);
		note_refresh(curr_note);

		prj->projectchanged = TRUE;
	}
}

/*
Function : void notetocommod(note_p curr_note)
Purpose : Copies all the info in the curr_note into the commodities window.
*/

void notetocommod(note_p curr_note)
{
	/* Copy title bar text */

	GT_SetGadgetAttrs(commodGadgets[commod_title],commod,NULL,
GTST_String,curr_note->title,TAG_END);

	/* Copy fontname */

	if (curr_note->fontname[0] == '\0')
		GT_SetGadgetAttrs(commodGadgets[commod_fontstr],commod,NULL,
GTTX_Text,"Default font",TAG_END);
	else
		GT_SetGadgetAttrs(commodGadgets[commod_fontstr],commod,NULL,
GTTX_Text,curr_note->fontstring,TAG_END);

	/* Find out which colour to show */

	switch (prj->commodcolour) {
		case COLOUR_BACKGROUND:
			GT_SetGadgetAttrs(commodGadgets[commod_palette],commod,
NULL,GTPA_Color,curr_note->backcolour,TAG_END);
			break;
		case COLOUR_TEXT:
			GT_SetGadgetAttrs(commodGadgets[commod_palette],commod,
NULL,GTPA_Color,curr_note->textcolour,TAG_END);
			break;
		case COLOUR_CARAT:
			GT_SetGadgetAttrs(commodGadgets[commod_palette],commod,
NULL,GTPA_Color,curr_note->caratcolour,TAG_END);
			break;
		default:
			break;
	}

	/* Copy pub screen name */

	GT_SetGadgetAttrs(commodGadgets[commod_pubscreen],commod,NULL,
GTST_String,curr_note->pubscreen,TAG_END);
}

/*
Function : BOOL commodclose()
Purpose : If the user clicks on the close gadget or selects "hide" from the
	menu, this function is called. If the tooltype HIDEWARN=YES then
	a requester is popped up if the data has been changed. Returns TRUE
	if the window is to close.
*/

BOOL commodclose()
{
	struct EasyStruct hidereq = {
		sizeof(struct EasyStruct),
		0,
		"StickIt2",
		"Data has changed, continue with hide ?",
		"Okay|Cancel"
	};

	if (!commod)
		return (FALSE);

	if ((prj->prefs.hidewarn) && (prj->projectchanged)) {
		if (EasyRequest(commod,&hidereq,NULL,TAG_END))
			return (TRUE);
		else
			return (FALSE);
	}
	else
		return (TRUE);
}
