//	OTLNp.c

#include "OTLNp.h"

/********************************************************/
Err			OTLN_CheckOutlineMagic(int rtn, OTLN_OutlineH outline)
{
	Err		err = Err_NONE;
	
	if (!(outline && *outline)) {
		//	"magic outline handle or master pointer is null."
		OTLNp_FATAL_S(rtn, OTLNp_STR(15));
		err = Err_PARAMETER;
	} else if (!((**outline).magic1 == OTLN_MAGIC && (**outline).magic2 == OTLN_MAGIC)) {
		//	"magic spell failed on an outline."
		OTLNp_FATAL_S(rtn, OTLNp_STR(13));
		err = Err_MAGIC;
	}

	return err;
}


Err			OTLN_CheckTopicMagic(int rtn, OTLN_TopicH topic)
{
	Err		err = Err_NONE;
	
	if (!(topic && *topic)) {
		//	"magic topic handle or master pointer is null."
		OTLNp_FATAL_S(rtn, OTLNp_STR(16));
		err = Err_PARAMETER;
	} else if (!((**topic).magic1 == OTLN_MAGIC && (**topic).magic2 == OTLN_MAGIC)) {
		//	"magic spell failed on an topic."
		OTLNp_FATAL_S(rtn, OTLNp_STR(14));
		err = Err_MAGIC;
	}

	return err;
}


Err			OTLN_CheckOutlineRootMagic(int rtn, OTLN_OutlineH outline)
{
	Err				err = Err_NONE;
	
	err = OTLN_CheckOutlineMagic(rtn, outline);

	if (!err) {
		err = OTLN_CheckTopicMagic(rtn, DH(outline)->outline_root);
	}
		
	return err;
}


/** OTLN_GetCellRect
**/
M_Rect		OTLN_GetCellRect(OTLN_OutlineP ol, OTLN_CellRectType type, M_Rect *cellRect)
{
	M_Rect	returnRect;
	short	width;
	
	returnRect	= *cellRect;
	width		= returnRect.bottom - returnRect.top;
	
	switch (type)
	{
		case OTLN_CellRect_CELL:
			returnRect.left		= ol->bounds.left;
			returnRect.right	= ol->bounds.right;
			break;
			
		case OTLN_CellRect_LEFT:
			returnRect.left		= ol->bounds.left;
			returnRect.right	= ol->outline_left;
			break;
			
		case OTLN_CellRect_RIGHT:
			returnRect.left		= ol->outline_right + 2;
			returnRect.right	= ol->bounds.right;
			InsetRect(&returnRect, 0, 2);
			break;
			
		case OTLN_CellRect_TWIRLY_ARROW:
			M_InsetRect(&returnRect, 3, 3);
			returnRect.right	= returnRect.left + 10;
			returnRect.bottom	= returnRect.top + 10;			
			break;
			
		case OTLN_CellRect_ICON:
			returnRect.top		+= 3;
			returnRect.left		+= ol->cell_height + 1;
			returnRect.right	= returnRect.left + 9;
			returnRect.bottom	= returnRect.top + 9;			
			break;
			
		case OTLN_CellRect_NAME:
			returnRect.left += ol->cell_height;
			M_InsetRect(&returnRect, 1, 2);
			break;
		
		case OTLN_CellRect_CENTER:
			returnRect.left		= ol->outline_left;
			returnRect.right	= ol->outline_right;
			M_InsetRect(&returnRect, 0, 2);
			break;
			
		case OTLN_CellRect_NAME_NUMBER:
		case OTLN_CellRect_NAME_NUMBER_ICON:
			DebugStr("\pImplement GetCellRect: Name/Number, Name/Number/Icon");
			SysBeep(1);
			break;
		
		case OTLN_CellRect_NAME_ICON:
			returnRect.left += ol->cell_height + 14;
			M_InsetRect(&returnRect, 1, 2);
			break;
	}
	
	return(returnRect);
}

/*	OTLNp_RecurseDupTopic [63]
	assume that topic is valid, non null
	and dupTopic has ALREADY been allocated!!!
*/
Err		OTLNp_RecurseDupTopic(	
	OTLN_TopicH		topic, 
	OTLN_TopicH		dupTopic, 
	OTLN_TopicH		dupTopicMother, 
	OTLN_TopicH		dupTopicPrevSister
) {
	Err				err			= Err_NONE;
	OTLN_TopicH		newTopic	= NULL;
	
	err = OTLN_CheckTopicMagic(63, topic);
	if (!err) {
		err = OTLN_CheckTopicMagic(63, dupTopic);
	}

	if (!err) {
		void					*dup;
		
		*DH(dupTopic) = *DH(topic);
		
		if (DH(dupTopic)->dup_custom_data) {
			OTLN_OutlineAndTopic	source;
			OTLN_OutlineAndTopic	dest;
			
			source.topicH	= topic;
			dest.topicH		= dupTopic;
			
			if (!err) err = OTLN_GetTopicOutline(source.topicH, &source.outlineH);
			if (!err) err = OTLN_GetTopicOutline(dest.topicH, &dest.outlineH);
			if (!err) err = (*DH(dupTopic)->dup_custom_data)(
				&source, DH(dupTopic)->custom_data, 
				&dest, &dup
			);
			if (!err) DH(dupTopic)->custom_data = dup;
		} else {
			DH(dupTopic)->custom_data = DH(topic)->custom_data;
		}
	}
	
	if (!err) {	
		DH(dupTopic)->mother		= dupTopicMother;
		DH(dupTopic)->prev_sister	= dupTopicPrevSister;
		DH(dupTopic)->self			= dupTopic;
		
		if (DH(topic)->daughters) {
			err = OTLN_NewTopic(NULL, &newTopic);
			
			if (!err) {
				DH(dupTopic)->daughters = newTopic;
				newTopic = NULL;
				
				err = OTLNp_RecurseDupTopic(
					DH(topic)->daughters, 
					DH(dupTopic)->daughters, 
					dupTopic, NULL
				);
			}
		} else {
			DH(dupTopic)->daughters = NULL;
		}

		if (!err) {
			if (DH(topic)->next_sister) {
				err = OTLN_NewTopic(NULL, &newTopic);
				
				if (!err) {
					DH(dupTopic)->next_sister = newTopic;
					newTopic = NULL;
	
					err = OTLNp_RecurseDupTopic(
						DH(topic)->next_sister, 
						DH(dupTopic)->next_sister, 
						dupTopicMother, dupTopic
					);
				}
			} else {
				DH(dupTopic)->next_sister = NULL;
			}
		}
	}
	
	if (err) {
		if (newTopic) {
			(void)OTLN_DisposeTopic(newTopic);
		}
	}
	
	return err;
}
