#if 1
//	OTLN_CTopic.c

#include "O_p.h"
#include "string.h"

//#include "OTLN_COutline.h"
//#include "OTLN_CTopic.h"

//IMPLEMENT_RTTC(OTLN_CTopic);

Err			OTLNg_GetCTopic(OTLN_TopicH topic, OTLN_CTopic **ctopic)
{
	ASSERT(ctopic);
	*ctopic = NULL;
	
	return OTLN_GetTopicCustomData(topic, (void **)ctopic);
}

/********  Initialize  **********/
Err						OTLN_CTopic::OTLNm_ITopic(
			Err				*operator_err, 
			OTLN_TopicH		topicH0, 	//	if passed, then name0 is ignored
	const	char			*name0
) {
	Err				err = Err_NONE;
	OTLN_TopicH		topicH;
	
	OTLNpi_operator_err				= operator_err;
	OTLNpi_user_cb_dispatch_proc	= NULL;
	OTLNpi_custom_data				= NULL;
	OTLNpi_disposing				= FALSE;
	OTLNpi_cOutline					= NULL;
	OTLNpi_parent0					= NULL;
	OTLNpi_index					= 0;
	
	if (topicH0) {
		topicH = topicH0;
	} else {
		if (!err) err = OTLN_NewTopic(name0, &topicH);
	}
	
	if (!err) err = OTLN_SetTopicCallbacks(
		topicH, 
		NULL, 
		NULL, 
		this, 
		OTLNspm_DuplicateSelfCB, 
		OTLNspm_DisposeSelfCB);
	
	if (!err) {
		OTLNpi_topicH	= topicH;
	}
	
	return err;
}

/********  Duplicate  **********/
Err						OTLN_CTopic::OTLNspm_DuplicateSelfCB(
	OTLN_OutlineAndTopic	*to_source0, 		//	always passed out, but may be ignored
	void					*custom_source, 
	OTLN_OutlineAndTopic	*to_dest0, 			//	always passed out, but may be ignored
	void 					**custom_dest
) {
	Err					err		= Err_NONE;
	OTLN_CTopic			*thiz	= (OTLN_CTopic *)custom_source;
	
	err = thiz->OTLNpm_DuplicateSelf(to_source0, to_dest0, (OTLN_CTopic **)custom_dest);
	
	return err;
}	

//	[202]
Err						OTLN_CTopic::OTLNpm_DuplicateSelf(
	OTLN_OutlineAndTopic	*source_ot, 
	OTLN_OutlineAndTopic	*dest_ot, 
	OTLN_CTopic				**duplicate
) {
	Err					err		= Err_NONE;

	*duplicate = new(OTLN_CTopic);
	
	if (*duplicate == NULL) {
		err = memFullErr;
		//	out of memory while duplicating an outline topic
		//OTLNp_PROB_S(202, OTLNp_STR(21));
	} else {
		
		if (!err) err = (*duplicate)->OTLNm_ITopic(OTLNpi_operator_err, dest_ot->topicH, NULL);
		
		if (!err && OTLNpi_user_cb_dispatch_proc) {
			OTLN_COutlineAndCTopic		source_cot;
			OTLN_CBData					cb_data;
			
			cb_data.dup_cust.source_cust_data	= OTLNpi_custom_data;
			cb_data.dup_cust.dest_cust_data		= NULL;

			if (!err) err = OTLNpg_OT_2_COT(source_ot, &source_cot);
			if (!err) err = OTLNpg_OT_2_COT(dest_ot, &cb_data.dup_cust.dest_cot);
			if (!err) err = (*OTLNpi_user_cb_dispatch_proc)(
				&source_cot, OTLN_CB_DUP_CUST_DATA, &cb_data
			);
			
			if (!err) {
				(*duplicate)->OTLNpi_user_cb_dispatch_proc	= OTLNpi_user_cb_dispatch_proc;
				(*duplicate)->OTLNpi_custom_data			= cb_data.dup_cust.dest_cust_data;
			}
		}

		if (err) {
			(void)(*duplicate)->OTLNm_DisposeTopic();
			*duplicate = NULL;
		}
	}
	
	return err;
}
		
Err						OTLN_CTopic::OTLNm_Duplicate(OTLN_CTopic **duplicate)
{
	Err					err			= Err_NONE;
	OTLN_TopicH			topicH;
	
	if (!err) err = OTLN_DupTopic(OTLNpi_topicH, &topicH);
	if (!err) err = OTLNg_GetCTopic(topicH, duplicate);
	
	return err;
}

/********  Dispose  **********/
Err				OTLN_CTopic::OTLNspm_DisposeSelfCB(void *custom_data)
{
	OTLN_CTopic		*thiz	= (OTLN_CTopic *)custom_data;
	Err				err		= Err_NONE;
		
	if (!err) err = thiz->OTLNpm_DisposeSelf();
	
	return err;
}

Err				OTLN_CTopic::OTLNpm_DisposeSelf(void)
{
	Err					err = Err_NONE;

	if (OTLNpi_user_cb_dispatch_proc) {
		OTLN_COutlineAndCTopic		cot;
		OTLN_CBData					cb_data;
		
		cot.cOutline	= OTLNpi_cOutline;	//	may be NULL?  when?
		cot.cTopic		= this;
		
		cb_data.dispose_cust.cust_data	= OTLNpi_custom_data;
		err = (*OTLNpi_user_cb_dispatch_proc)(
			&cot, OTLN_CB_DISPOSE_CUST_DATA, &cb_data
		);
	}

	delete this;
	
	return err;
}

/*
	Err			err = Err_NONE, err2;

	if (!err && !OTLNpi_disposing) {
		OTLNpi_disposing = TRUE;
		if (!err) err = OTLN_DisposeTopic(OTLNpi_topicH);
		OTLNpi_disposing = FALSE;
		err2 = OTLNpm_DisposeSelf();
		
		if (!err) err = err2;
	}
	
	return err;
*/
Err				OTLN_CTopic::OTLNm_DisposeTopic(void)
{
	Err					err	= Err_NONE;

	err = OTLN_DisposeTopic(OTLNpi_topicH);
	
	return err;
}

void				OTLN_CTopic::Dispose(void)
{
	/*
		you should never call this 
		cuz it does NOT return an error.
		you should call DisposeObject directly
	*/
	
	(void)OTLNm_DisposeTopic();
}

/********  Hit Test  **********/
Err						OTLN_CTopic::OTLNm_HitTest(Point hit_point, Boolean *hit)
{
	Err					err = Err_NONE;
	Rect				frame;
	
	*hit = FALSE;
	
	frame = OTLN_Topic_RECENT_CELL(OTLNpi_topicH);

	if (!EmptyRect(&frame)) {
		OTLN_COutline		*coutline;

		if (!err) err = OTLNm_GetOutline(&coutline);
		if (!err && OTLNpi_user_cb_dispatch_proc) {
			OTLN_CBData_HIT_TEST		ht;
			OTLN_COutlineAndCTopic		cot;
			Boolean						*didHit = (Boolean *)&ht.cTopic;
			
			cot.cOutline	= coutline;
			cot.cTopic		= this;
			
			ht.hit_point	= hit_point;
			*didHit			= FALSE;
			
			err = (*OTLNpi_user_cb_dispatch_proc)(
				&cot, OTLN_CB_HIT_TEST, (OTLN_CBData *)&ht
			);
			
			if (!err) {
				*hit = *didHit;
			}
		}
	}
	
	return err;
}

/*
{
	Rect		rect = OTLN_Topic_RECENT_CELL(OTLNpi_topicH);
	
	//	watchout!  $$$  you may not want this in AE
	rect.left = 0;
	
	*hit = M_PtInRect(&hit_point, &rect);
	
	return Err_NONE;
}
*/
			
/********  Draw  **********/
Err						OTLN_CTopic::OTLNm_Draw(Boolean scrub)
{
	Err					err = Err_NONE;
	Rect				frame;
	
	frame = OTLN_Topic_RECENT_CELL(OTLNpi_topicH);

	if (!EmptyRect(&frame)) {
		OTLN_COutline		*coutline;

		if (!err) err = OTLNm_GetOutline(&coutline);
		if (!err && OTLNpi_user_cb_dispatch_proc) {
			OTLN_COutlineAndCTopic		cot;
			
			cot.cOutline	= coutline;
			cot.cTopic		= this;
			
			err = (*OTLNpi_user_cb_dispatch_proc)(
				&cot, OTLN_CB_DRAW, (OTLN_CBData *)&scrub
			);
		}
	}
	
	return err;
}

Boolean		gGoDeep = TRUE;

Err			OTLN_CTopic::OTLNm_DrawFromHere(long *bottom)
{
	Err					err = Err_NONE;
	OTLN_SaveFontInfo	sfi;
	OTLN_COutline		*coutline;

	if (!err) err = OTLNm_GetOutline(&coutline);
	if (!err) err = OTLN_SaveSetFontInfo(coutline->OTLNi_outlineH, &sfi);
	if (!err) err = coutline->OTLNm_ClearRects();
	if (!err) err = coutline->OTLNm_UpdateBounds();

	if (!err) err = OTLNm_ApplyToItems(
		OTLN_COutlineIterate_ONSCREEN, 
		OTLN_CB_DRAW, 
		this, 
		TRUE, gGoDeep
	);
	
	gGoDeep = TRUE;
	
	//	even if the iterate fails, we still need to re-set the font info
	(void)OTLN_RestoreFontInfo(&sfi);
	
	*bottom = coutline->i_v_bottom;
	
	return err;
}
		
Err			OTLN_CTopic::OTLNm_CountVisibleCellsFromHere(long *pixels)
{
	Err				err = Err_NONE;
	OTLN_CBData		cb_data;
	
	*pixels = 0;

	cb_data.count.count_cells = TRUE;
	cb_data.count.count = 0;
	
	if (!err) err = OTLNm_ApplyToItems(
		OTLN_COutlineIterate_VISIBLE, 
		OTLN_CB_COUNT, 
		&cb_data, 
		TRUE, TRUE
	);

	if (!err) {
		*pixels = cb_data.count.count;
	}
	
	return err;
}

Err			OTLN_CTopic::OTLNm_HitTestFromHere(Point hit_point, OTLN_CTopic **cTopic)
{
	Err							err = Err_NONE;
	OTLN_CBData_HIT_TEST		hit_test;
	
	*cTopic				= NULL;
	hit_test.hit_point	= hit_point;
	hit_test.cTopic 	= NULL;
	
	if (!err) err = OTLNm_ApplyToItems(
		OTLN_COutlineIterate_ONSCREEN, 
		OTLN_CB_HIT_TEST, 
		&hit_test, 
		TRUE, gGoDeep
	);
	
	gGoDeep = TRUE;
	
	if (!err) {
		*cTopic = hit_test.cTopic;
	}
	
	return err;
}

Err			OTLN_CTopic::OTLNm_GetPaneFrame(Rect *rect)
{
	*rect = OTLN_Topic_RECENT_CELL(OTLNpi_topicH);

	return Err_NONE;
}

Err			OTLN_CTopic::OTLNm_GetTopicRect(OTLN_CellRectType cellType, Rect *the_rect)
{
	Err							err		= Err_NONE;
	OTLN_COutline				*coutline;
	Boolean						use_indent = cellType == OTLN_CellRect_NAME
											|| cellType == OTLN_CellRect_ICON;
	
	if (
		cellType == OTLN_CellRect_NAME
		&& OTLN_IS_TopicFlag_SET(
			OTLN_GET_TopicH_FLAGS(OTLNpi_topicH), 
			OTLN_TopicFlags_HAS_ICON
		)
	) {
		cellType = OTLN_CellRect_NAME_ICON;
	}

	err = OTLNm_GetOutline(&coutline);
	
	if (!err) {
		OTLN_OutlineH		outline = coutline->OTLNi_outlineH;
		
		*the_rect = OTLN_Topic_RECENT_CELL(OTLNpi_topicH);

		if (cellType != OTLN_CellRect_INDENTED_CELL) {
			HLock((Handle)outline);
			*the_rect = OTLN_GetCellRect(*outline, cellType, the_rect);
			HUnlock((Handle)outline);
		}
		
		if (use_indent && coutline->OTLNpi_indent_width0) {
			short	height = (*outline)->cell_height;
			
			the_rect->left = (
				(the_rect->left - height) 
				+ (height * coutline->OTLNpi_indent_width0)
			);
		}
	}
	
	return err;
}

Err			OTLN_CTopic::OTLNm_DrawTwirlieArrow(Rect *the_rect)
{
	Err		err		= Err_NONE;

	if (
		(*OTLNpi_topicH)->daughters != NULL 
		&& OTLN_IS_TopicFlag_EXPANDABLE(OTLNpi_topicH)
	) {
		err = O_BlitTwirly(
			OTLN_IS_TopicFlag_COLLAPSED(OTLNpi_topicH)
				?	O_kTwirl_UP
				:	O_kTwirl_DOWN, 
			the_rect
		);
	}
	
	return err;
}

Err			OTLN_CTopic::OTLNm_DrawName(Rect *the_rect)
{
	Err				err		= Err_NONE;
	OTLN_TopicP		to;
	
	HLock((Handle)OTLNpi_topicH);
	to = *OTLNpi_topicH;
	
	if (OTLN_IS_TopicFlag_SET(OTLN_GET_TopicP_FLAGS(to), OTLN_TopicFlags_HAS_NUMBER)) {
		OTLN_CTopicIndex		index;
		
		err = OTLNm_GetTopicIndex(&index);
		
		to->topicNumber = index + 1;
	}
	
	if (!err) err = OTLN_DrawName(NULL, to, the_rect);
	
	HUnlock((Handle)OTLNpi_topicH);
	
	return err;
}

Err			OTLN_CTopic::OTLNm_DrawTopicDefault(void)
{
	Err							err		= Err_NONE;
	OTLN_COutline				*coutline;
	OTLN_Hit_n_Draw_Record		hdr;
	
	err = OTLNm_GetOutline(&coutline);
	
	if (!err) {
		hdr.outline	= coutline->OTLNi_outlineH;
		hdr.topic	= OTLNpi_topicH;
		hdr.rect	= OTLN_Topic_RECENT_CELL(hdr.topic);
		
		HLock((Handle)hdr.outline);
		HLock((Handle)hdr.topic);
		
		err = OTLN_DrawTopicDefault(&hdr);

		HUnlock((Handle)hdr.topic);
		HUnlock((Handle)hdr.outline);
	}
	
	return err;
}


/********  User Callbacks, Custom Data  **********/
Err				OTLN_CTopic::OTLNm_SetCallbackDispatch(OTLN_CBDispatchProc user_cb_dispatch_proc)
{
	OTLNpi_user_cb_dispatch_proc = user_cb_dispatch_proc;
	
	return Err_NONE;
}

Err				OTLN_CTopic::OTLNm_GetCallbackDispatch(OTLN_CBDispatchProc *user_cb_dispatch_proc)
{
	*user_cb_dispatch_proc = OTLNpi_user_cb_dispatch_proc;
	
	return Err_NONE;
}

Err				OTLN_CTopic::OTLNm_SetCustomData(void *custom_data)
{
	OTLNpi_custom_data = custom_data;
	
	return Err_NONE;
}

Err				OTLN_CTopic::OTLNm_GetCustomData(void **custom_data)
{
	*custom_data = OTLNpi_custom_data;
	
	return Err_NONE;
}

/********  set/get specs  **********/
Err			OTLN_CTopic::OTLNm_SetSpecs(
	const	char				*name0,
			short				cell_height_multiple0, 
			OTLN_TopicFlags		*flags0
) {
	return OTLN_SetTopicSpecs(
		OTLNpi_topicH, name0, 
		cell_height_multiple0, 
		flags0 ? *flags0 : NULL, NULL, NULL
	);
}
		
Err			OTLN_CTopic::OTLNm_GetSpecs(
	char				*name0,
	short				*cell_height_multiple0, 
	OTLN_TopicFlags		*flags0
) {
	if (name0) {
		strcpy(name0, (*OTLNpi_topicH)->name);
	}
	
	if (cell_height_multiple0) {
		*cell_height_multiple0 = (*OTLNpi_topicH)->cell_height_multiple;
	}
	
	if (flags0) {
		*flags0 = (*OTLNpi_topicH)->flags;
	}

	return Err_NONE;
}

Err				OTLN_CTopic::OTLNm_SetName(const char *name)
{
	return OTLNm_SetSpecs(name, NULL, NULL);
}

Err				OTLN_CTopic::OTLNm_GetName(char *name)
{
	return OTLNm_GetSpecs(name, NULL, NULL);
}

Err				OTLN_CTopic::OTLNm_SetFontStyle(short style)
{
	Style	font_style = style;
	
	return OTLN_SetTopicSpecs(OTLNpi_topicH, NULL, 0, 0, NULL, &font_style);
}

/********  creating the outline  **********/
Err			OTLN_CTopic::OTLNm_SetRecent(void)
{
	Err					err = Err_NONE;
	OTLN_COutline		*coutline;
	
	err = OTLNm_GetOutline(&coutline);
	
	if (!err) {
		coutline->OTLNm_SetRecent(this);
	}

	return err;
}

Err			OTLN_CTopic::OTLNm_Adopt(
	OTLN_COutline		*cOutline, 
	OTLN_CTopic			*parent0, 
	OTLN_CTopicIndex	index
) {
	OTLNpi_cOutline	= cOutline;
	OTLNpi_parent0	= parent0;	//	NULL means Root
	OTLNpi_index	= index;
	
	return Err_NONE;
}

Err			OTLN_CTopic::OTLNm_Orphan(void)
{
	OTLNm_Adopt(NULL, NULL, OTLN_CTopicIndex_NONE);

	return Err_NONE;
}


//	[203]
Err			OTLN_CTopic::OTLNm_Insert(void)
{
	Err						err = Err_NONE;
	OTLN_AddTopicAsType		where;
	OTLN_CTopic				*ctopic_ref;
	
	if (!OTLNpi_parent0) {
		err = OTLNpi_cOutline->OTLNm_GetRootTopic(&ctopic_ref);
	} else {
		ctopic_ref = OTLNpi_parent0;
	}
	
	if (!err) switch (OTLNpi_index) {

		case OTLN_CTopicIndex_NONE: {
//			OTLNp_PROB_S(203, OTLNp_STR(22));
			err = OTLN_Err_BAD_INSERT_INDEX;
			break;
		}
		
		case OTLN_CTopicIndex_START: {
			where = OTLN_AddTopicAs_FIRST_DAUGHTER;
			break;
		}
		
		default:
		case OTLN_CTopicIndex_END: {
			where = OTLN_AddTopicAs_LAST_DAUGHTER;
			break;
		}
		
//			where	= OTLN_AddTopicAs_SISTER;
//			err		= ctopic_ref->OTLNm_GetIndTopic(OTLNpi_index - 1, &ctopic_ref);
//			break;
//		}
	}

	if (!err) err = OTLN_AddTopic(
		OTLNpi_cOutline->OTLNi_outlineH, 
		OTLNpi_topicH, 
		ctopic_ref->OTLNpi_topicH, where
	);
	
	if (!err) err = OTLNm_Orphan();
	
	return err;
}

Err			OTLN_CTopic::OTLNm_Remove(void)
{
	Err					err			= Err_NONE;
	OTLN_CTopic			*recentP	= NULL;
	
	//	performs adoption magically
	if (!err) err = OTLNm_GetOutline(&OTLNpi_cOutline);
	if (!err) err = OTLNm_GetParent(&OTLNpi_parent0);
	if (!err) err = OTLNm_GetTopicIndex(&OTLNpi_index);
	if (!err) err = OTLNpi_cOutline->O_GetRecent(&recentP);
	
	if (recentP == this) {
		if (!err) err = OTLNpi_parent0->O_SetRecent();
	}

	if (!err) err = OTLN_RemoveTopic(
		OTLNpi_cOutline->OTLNi_outlineH, 
		OTLNpi_topicH);
	
	return err;
}

/********  drag reorder stuff, operates on children  **********/
//	static
Err		OTLN_CTopic::OTLNspm_DragReorderMessageCB(
	OTLN_DragReorderCBMessageType	message, 
	OTLN_DragReorderDataRec			*drag_data, 
	void							*user_data
) {
	Err					err = Err_NONE;
	OTLN_CTopic			*thiz;
	OTLN_COutline		*coutline;
	OTLN_CBData			cb_data;

	thiz = (OTLN_CTopic *)user_data;

	err = thiz->OTLNm_GetOutline(&coutline);

	if (!err && thiz->OTLNpi_user_cb_dispatch_proc) {
		OTLN_COutlineAndCTopic		cot;
		
		cot.cOutline	= coutline;
		cot.cTopic		= thiz;
		
		cb_data.drag.message	= message;
		
		if (!err) err = coutline->OTLNm_GetOutlineFrame(&cb_data.drag.min_frame);

		if (!err) err = OTLN_DragReorderAutoscrollSetup(
			message, drag_data->u.p.pixels, 
			&cb_data.drag.min_frame, &cb_data.drag.max_frame, 
			&cb_data.drag.the_point
		);

		if (!err) err = (*thiz->OTLNpi_user_cb_dispatch_proc)(
			&cot, OTLN_CB_DRAG_REORDER, &cb_data
		);
		
		if (!err) {
			if (!cb_data.drag.scrolled) {
				drag_data->u.p.pixels;
			}

			err = coutline->OTLNm_GetOutlineFrame(drag_data->u.p.frame_rect);
		}
	}
	
	return err;
}

Err			OTLN_CTopic::OTLNm_DragReorder(
	Point					hit_point, 
	long					cell_height0, 
	OTLN_CTopicIndex		oldIndex, 		//	must pass this in
	OTLN_CTopicIndex		*newIndex
) {
	Err						err = Err_NONE;
	OTLN_Hit_n_Draw_Record	hitDrawRec;
	OTLN_COutline			*coutline;
	OTLN_CTopic				*ctopic_exclude;
	Rect					frame;
	
	if (!err) err = OTLNm_GetOutline(&coutline);
	if (!err) err = coutline->OTLNm_GetOutlineFrame(&frame);
	if (!err) err = OTLNm_GetIndTopic(oldIndex, &ctopic_exclude);

	if (!err) {
		hitDrawRec.hit_point	= hit_point;
		hitDrawRec.outline		= coutline->OTLNi_outlineH;
		hitDrawRec.topic		= ctopic_exclude->OTLNpi_topicH;
		
		err = OTLN_DragReorderTopic(
			&hitDrawRec, 
			OTLNspm_DragReorderMessageCB, 
			this, 
			&frame, 
			cell_height0, 
			&oldIndex, 
			newIndex
		);
	}
	
	return err;
}

//	make reorder a callback so it happens magically
Err			OTLN_CTopic::OTLNm_ReOrder(
	OTLN_CTopicIndex	oldIndex,
	OTLN_CTopicIndex	newIndex
) {
	Err						err = Err_NONE;
	
	if (oldIndex != newIndex) {
		OTLN_COutline			*coutline;
		
		err = OTLNm_GetOutline(&coutline);

		if (!err) err = OTLN_ReorderTopics(
			coutline->OTLNi_outlineH, OTLNpi_topicH, NULL, oldIndex, newIndex
		);
	}
	
	return err;
}


/********  access  **********/
Err			OTLN_CTopic::OTLNm_GetOutline(OTLN_COutline **coutline)
{
	Err					err = Err_NONE;
	OTLN_OutlineH		outlineH;
	
	err = OTLN_GetTopicOutline(OTLNpi_topicH, &outlineH);
	if (!err) err = OTLNg_GetCOutline(outlineH, coutline);
	
	return err;
}

Err			OTLN_CTopic::OTLNm_IsRootTopic(Boolean *is_root)
{
	Err					err = Err_NONE;
	OTLN_COutline		*coutline;
	OTLN_CTopic			*croot;
	
	err = OTLNm_GetOutline(&coutline);
	
	if (!err) err = coutline->OTLNm_GetRootTopic(&croot);
	
	*is_root = croot == this;
	
	return err;
}

Err			OTLN_CTopic::OTLNm_IsFirstTopic(Boolean *is_first)
{
	Err					err = Err_NONE;
	OTLN_COutline		*coutline;
	OTLN_CTopic			*cfirst;
	
	err = OTLNm_GetOutline(&coutline);
	
	if (!err) err = coutline->OTLNm_GetRootTopic(&cfirst);
	
	*is_first = cfirst == this;
	
	return err;
}

Err			OTLN_CTopic::OTLNm_GetParent(OTLN_CTopic **ctopic)
{
	Err					err = Err_NONE;
	OTLN_TopicH			topicH;
	
	*ctopic = NULL;
	
	if (!err) err = OTLN_GetMother(OTLNpi_topicH, &topicH);
	if (!err && topicH) {
		err = OTLNg_GetCTopic(topicH, ctopic);
	}

	return err;
}

Err			OTLN_CTopic::OTLNm_GetFirstSister(OTLN_CTopic **ctopic)
{
	Err					err = Err_NONE;
	OTLN_TopicH			topicH;
	
	*ctopic = NULL;
	
	if (!err) err = OTLN_GetFirstSister(OTLNpi_topicH, &topicH);
	if (!err && topicH) {
		err = OTLNg_GetCTopic(topicH, ctopic);
	}

	return err;
}

Err			OTLN_CTopic::OTLNm_GetPrevSister(OTLN_CTopic **ctopic)
{
	Err					err = Err_NONE;
	OTLN_TopicH			topicH;
	
	*ctopic = NULL;
	
	if (!err) err = OTLN_GetPrevSister(OTLNpi_topicH, &topicH);
	if (!err && topicH) {
		err = OTLNg_GetCTopic(topicH, ctopic);
	}
	
	return err;
}

Err			OTLN_CTopic::OTLNm_GetNextSister(OTLN_CTopic **ctopic)
{
	Err					err = Err_NONE;
	OTLN_TopicH			topicH;
	
	*ctopic = NULL;

	if (!err) err = OTLN_GetNextSister(OTLNpi_topicH, &topicH);
	if (!err && topicH) {
		err = OTLNg_GetCTopic(topicH, ctopic);
	}
	
	return err;
}

Err			OTLN_CTopic::OTLNm_GetLastSister(OTLN_CTopic **ctopic)
{
	Err					err = Err_NONE;
	OTLN_TopicH			topicH;
	
	*ctopic = NULL;
	
	if (!err) err = OTLN_GetLastSister(OTLNpi_topicH, &topicH);
	if (!err && topicH) {
		err = OTLNg_GetCTopic(topicH, ctopic);
	}
	
	return err;
}

Err			OTLN_CTopic::OTLNm_TwirledDown(Boolean *cur_setting0, Boolean *new_setting0)
{
	Err					err = Err_NONE;
	
	if (cur_setting0) {
		*cur_setting0 = !OTLN_IS_TopicFlag_COLLAPSED(OTLNpi_topicH);
	}
	
	if (new_setting0) {
		OTLN_ResetTopicFlag_COLLAPSED(OTLNpi_topicH, !(*new_setting0));
	}
	
	return err;
}

Err			OTLN_CTopic::OTLNm_FamilyVisible(Boolean *cur_setting0, Boolean *new_setting0)
{
	Err					err = Err_NONE;
	
	if (cur_setting0) {
		*cur_setting0 = !OTLN_IS_TopicFlag_FAMILY_INVISABLE(OTLNpi_topicH);
	}
	
	if (new_setting0) {
		OTLN_ResetTopicFlag_FAMILY_INVISABLE(OTLNpi_topicH, !(*new_setting0));
	}

	return err;
}

Err			OTLN_CTopic::OTLNm_TopicOnscreen(Boolean *onscreen)
{
	Err					err = Err_NONE;
	OTLN_COutline		*coutline;
	
	if (!err) err = OTLNm_GetOutline(&coutline);
	if (!err) err = OTLN_IsVisible(coutline->OTLNi_outlineH, OTLNpi_topicH, onscreen);
	
	return err;
}

Err			OTLN_CTopic::OTLNm_TopicVisible(Boolean *cur_setting0, Boolean *new_setting0)
{
	Err					err = Err_NONE;
	
	if (cur_setting0) {
		*cur_setting0 = !OTLN_IS_TopicFlag_TOPIC_INVISABLE(OTLNpi_topicH);
	}
	
	if (new_setting0) {
		OTLN_ResetTopicFlag_TOPIC_INVISABLE(OTLNpi_topicH, !(*new_setting0));
	}

	return err;
}

Err			OTLN_CTopic::OTLNm_Solo(Boolean *cur_setting0, Boolean *new_setting0)
{
	Err					err = Err_NONE;
	
	if (cur_setting0) {
		*cur_setting0 = OTLN_IS_TopicFlag_TOPIC_SOLO(OTLNpi_topicH);
	}
	
	if (new_setting0) {
		OTLN_ResetTopicFlag_TOPIC_SOLO(OTLNpi_topicH, *new_setting0);
	}

	return err;
}

Err			OTLN_CTopic::OTLNm_HasSeparator(Boolean *cur_setting0, Boolean *new_setting0)
{
	Err					err = Err_NONE;
	
	if (cur_setting0) {
		*cur_setting0 = OTLN_IS_TopicFlag_SET(
			OTLN_GET_TopicH_FLAGS(OTLNpi_topicH), 
			OTLN_TopicFlags_HAS_SEPARATOR
		);
	}
	
	if (new_setting0) {
		OTLN_TopicFlag_RESET(
			OTLN_GET_TopicH_FLAGS(OTLNpi_topicH), 
			OTLN_TopicFlags_HAS_SEPARATOR, 
			*new_setting0
		);
	}

	return err;
}

Err			OTLN_CTopic::OTLNm_HasNumber(Boolean *cur_setting0, Boolean *new_setting0)
{
	Err					err = Err_NONE;
	
	if (cur_setting0) {
		*cur_setting0 = OTLN_IS_TopicFlag_SET(
			OTLN_GET_TopicH_FLAGS(OTLNpi_topicH), 
			OTLN_TopicFlags_HAS_NUMBER
		);
	}
	
	if (new_setting0) {
		OTLN_TopicFlag_RESET(
			OTLN_GET_TopicH_FLAGS(OTLNpi_topicH), 
			OTLN_TopicFlags_HAS_NUMBER, 
			*new_setting0
		);
	}

	return err;
}

Err			OTLN_CTopic::OTLNm_CountTopics(OTLN_CTopicIndex *count)
{
	Err					err = Err_NONE;
	OTLN_CTopic			*cTopic;
	
	*count = 0;
	
	err = OTLNm_GetIndTopic(0, &cTopic);
	
	if (cTopic) {
		if (!err) err = cTopic->OTLNm_GetLastSister(&cTopic);
		
		if (!err && cTopic) {
			err = cTopic->OTLNm_GetTopicIndex(count);
			(*count)++;
		}
	}
	
	return err;
}

//	selects self unless == OTLNpi_selectionException
//	returns MY index
Err			OTLN_CTopic::OTLNm_GetTopicIndex(OTLN_CTopicIndex *index)
{
	Err					err = Err_NONE;
	OTLN_COutline		*coutline;
	
	if (!err) err = OTLNm_GetOutline(&coutline);
	if (!err) err = OTLN_GetTopicIndex(coutline->OTLNi_outlineH, OTLNpi_topicH, index);
	
	return err;
}

//	gets child[index]	may return NULL
Err			OTLN_CTopic::OTLNm_GetIndTopic(OTLN_CTopicIndex index, OTLN_CTopic **ctopic)
{
	Err					err = Err_NONE;
	OTLN_COutline		*coutline;
	OTLN_TopicH			topicH;
	
	*ctopic = NULL;
	
	if (!err) err = OTLNm_GetOutline(&coutline);
	
	if (!err) err = OTLN_GetIndTopic(
		coutline->OTLNi_outlineH, OTLNpi_topicH, index, &topicH
	);
	
	if (!err && topicH) err = OTLNg_GetCTopic(topicH, ctopic);

	return err;
}

/********  selection  **********/
Err			OTLN_CTopic::OTLNm_SelectAll(
	Boolean		select, 
	Boolean		draw
) {
	Err					err = Err_NONE;
	OTLN_CTopic			*cTopic;
	OTLN_CTopicIndex	topic_index;
	
	OTLN_FOR_EACH_OBJECT(this, topic_index, cTopic, err) {
		err = cTopic->OTLNm_Select(select, draw);
	} OTLN_END_EACH_OBJECT(topic_index, err);
	
	return err;
}

Err			OTLN_CTopic::OTLNm_Select(
	Boolean		select, 
	Boolean		draw
) {
	Err			err = Err_NONE;
	Boolean		selected;
	
	if (!err) err = OTLNm_Selected(&selected, NULL);
	
	if (!err) {
		if (selected ^ select) {
			if (!err) err = OTLNm_Selected(NULL, &select);
			
			if (!err && draw) {
				err = OTLNm_Draw(FALSE);
			}
		}
	}
	
	return err;
}

Err			OTLN_CTopic::OTLNm_Selected(Boolean *cur_setting0, Boolean *new_setting0)
{
	Err					err = Err_NONE;
	
	if (cur_setting0) {
		*cur_setting0 = OTLN_IS_TopicFlag_SELECTED(OTLNpi_topicH);
	}
	
	if (new_setting0) {
		OTLN_ResetTopicFlag_SELECTED(OTLNpi_topicH, *new_setting0);
	}

	return err;
}

Err			OTLN_CTopic::OTLNm_CountSelectedTopics(OTLN_CTopicIndex *count)
{
	Err					err = Err_NONE;
	OTLN_TopicH			topicH;
	OTLN_CTopicIndex	topic_index;
	
	*count = 0;
	
	OTLN_FOR_EACH(OTLNpi_topicH, topic_index, topicH, err) {
		
		if (OTLN_IS_TopicFlag_SELECTED(topicH)) {
			(*count)++;
		}
		
	} OTLN_END_EACH(topic_index, topicH, err);
	
	return err;
}

Err			OTLN_CTopic::OTLNm_GetIndSelectedTopic(
	OTLN_CTopicIndex	index, 
	OTLN_CTopic			**ctopic
) {
	Err					err = Err_NONE;
	OTLN_CTopicIndex	topic_index, sel_index = -1;
	OTLN_TopicH			topicH;
	
	*ctopic = NULL;
	
	OTLN_FOR_EACH(OTLNpi_topicH, topic_index, topicH, err) {
		
		if (OTLN_IS_TopicFlag_SELECTED(topicH)) {
			sel_index++;
			
			if (sel_index == index) {
				err = OTLNg_GetCTopic(topicH, ctopic);
				if (!err) err = OTLN_Err_BREAK_FROM_LOOP;
			}
		}
		
	} OTLN_END_EACH(topic_index, topicH, err);
	
	if (err == OTLN_Err_BREAK_FROM_LOOP)
		err = Err_NONE;
	
	return err;
}

/********  iterate  **********/

Err		OTLN_CTopic::OTLNpm_ApplyToItemsR(
	OTLN_IterateVarsP	gvars, 
	short				h_pos, 
	Boolean				hidden
) {
	OTLN_CTopic			*next_topic;
	Err					err				= Err_NONE;
	Boolean				do_callback		= TRUE, 
						do_iterateDeep	= TRUE, 
						incr_vertical	= TRUE, 
						familyVisible, topicVisible, twirled_down;
	

	if (!err) err = OTLNm_FamilyVisible(&familyVisible, NULL);
	if (!err) err = OTLNm_TopicVisible(&topicVisible, NULL);
	if (!err) err = OTLNm_TwirledDown(&twirled_down, NULL);

	if (!err) {
		familyVisible	= familyVisible || !gvars->ol->honor_family_invisable;
		topicVisible	= topicVisible && !hidden;
	}
	
	//	decide wether to call back to front end code
	if (!err) switch (gvars->iterate_type) {
		
		default:
		
		case OTLN_COutlineIterate_CHILDREN: {
			incr_vertical	= FALSE;
			do_callback		= FALSE;
			break;
		}


		case OTLN_COutlineIterate_ALL: {
			do_callback = TRUE;
			break;
		}
		
		case OTLN_COutlineIterate_SELECTED: {
			err = OTLNm_Selected(&do_callback, NULL);
			break;
		}

		case OTLN_COutlineIterate_TWIRLED_DOWN: {
			//	only for children
			break;
		}
		
		case OTLN_COutlineIterate_UNSHY: {
			if (!familyVisible) {
				incr_vertical	= FALSE;
				do_callback		= FALSE;
			}
			break;
		}
		
		case OTLN_COutlineIterate_VISIBLE: {
			if (!familyVisible || !topicVisible) {
				incr_vertical	= FALSE;
				do_callback		= FALSE;
			}
			break;
		}
		
		case OTLN_COutlineIterate_ONSCREEN: {
			short	vBottom	= gvars->v_pos + 1
								+ (
									gvars->ol->cell_height
									* (*OTLNpi_topicH)->cell_height_multiple
								);
			
			if (!err) {
				if (!familyVisible || !topicVisible) {
					do_callback		= FALSE;
					incr_vertical	= FALSE;
				} else if (vBottom < gvars->outline_frame.top) {
					do_callback		= FALSE;
				} else if (gvars->v_pos > gvars->outline_frame.bottom) {
					do_callback		= FALSE;
					err				= OTLN_Err_BREAK_FROM_LOOP;
				}
			}
			break;
		}
	}
	
	if (!err) {
		Rect		rect;
		
		if (hidden) {
			rect.top		= 0;
			rect.left		= 0;
			rect.bottom		= 0;
			rect.right		= 0;
		} else {
			rect.top		= gvars->v_pos;
			rect.left		= h_pos;	//	+ gvars->ol->outline_left
			rect.bottom		= (gvars->ol->cell_height * (*OTLNpi_topicH)->cell_height_multiple) + 1 + gvars->v_pos;
			rect.right		= gvars->ol->outline_right;		
		}
		
		(*OTLNpi_topicH)->recent_cell = rect;
	}

	if (!err && do_callback) {
		if (OTLNpi_user_cb_dispatch_proc) {
			OTLN_COutlineAndCTopic		cot;
			
			cot.cOutline	= gvars->cOutline;
			cot.cTopic		= this;
			
			if (!err) {
				if (gvars->cb_type > OTLN_CB_INTERNAL) {
					err = cot.cOutline->OTLNm_InternalCBDispatchProc(
						&cot, gvars->cb_type, (OTLN_CBData *)gvars->data
					);
				} else {
					err = (*OTLNpi_user_cb_dispatch_proc)(
						&cot, gvars->cb_type, (OTLN_CBData *)gvars->data
					);
				}
			}
		}
	}
	
	if (!err && !hidden && incr_vertical)
		gvars->v_pos += gvars->ol->cell_height * (*OTLNpi_topicH)->cell_height_multiple;
	
	//	now decide if you want to iterate on children
	do_iterateDeep = TRUE;
	
	if (!err) switch (gvars->iterate_type) {
		
		default:
		case OTLN_COutlineIterate_CHILDREN:
		case OTLN_COutlineIterate_ALL: {
			//	yeah...
			break;
		}
		
		case OTLN_COutlineIterate_SELECTED: {
			//	only for self
			break;
		}

		case OTLN_COutlineIterate_UNSHY: {
			do_iterateDeep = familyVisible;
			break;
		}
		
		case OTLN_COutlineIterate_TWIRLED_DOWN: {
			do_iterateDeep = twirled_down;
			break;
		}
		
		case OTLN_COutlineIterate_VISIBLE: {
			//	only for self
			break;
		}
		
		case OTLN_COutlineIterate_ONSCREEN: {
			do_iterateDeep = familyVisible && twirled_down;
			break;
		}
	}
	
	if (!err && gvars->go_deep && do_iterateDeep) {
		Boolean		oldHidden = hidden;
		
		if (!twirled_down)
			hidden = TRUE;
		
		//	iterate over children
		err = OTLNm_GetIndTopic(OTLN_CTopicIndex_START, &next_topic);
		
		if (!err && next_topic) {
			Boolean		was_childrenB = gvars->iterate_type == OTLN_COutlineIterate_CHILDREN;
			
			if (was_childrenB) {
				gvars->iterate_type = OTLN_COutlineIterate_ALL;
				gvars->go_deep		= FALSE;
			}
			
			err = next_topic->OTLNpm_ApplyToItemsR(
				gvars, 
				h_pos + (gvars->cOutline->OTLNpi_indent_width0
					? gvars->ol->cell_height * gvars->cOutline->OTLNpi_indent_width0
					: gvars->ol->cell_height
				), hidden
			);

			if (was_childrenB) {
				gvars->go_wide = FALSE;
			}
		}
		
		hidden = oldHidden;
	}
	
	if (!err && gvars->go_wide) {
	
		//	then iterate over next sisters in line
		err = OTLNm_GetNextSister(&next_topic);

		if (!err && next_topic) {
			err = next_topic->OTLNpm_ApplyToItemsR(gvars, h_pos, hidden);
		}
	}

	return err;
}

Err		OTLN_CTopic::OTLNm_ApplyToItems(
	OTLN_COutlineIterateType	iterate_type, 
	OTLN_CBType					cb_type, 
	void						*data, 
	Boolean						go_wide, 
	Boolean						go_deep
) {
	Err					err = Err_NONE;
	OTLN_IterateVars	gvars;
	OTLN_COutline		*coutline;

	if (!err) err = OTLNm_GetOutline(&coutline);
	if (!err) err = coutline->OTLNm_GetOutlineFrame(&gvars.outline_frame);

	if (!err) {
		if (iterate_type == OTLN_COutlineIterate_CHILDREN) {
			gvars.go_wide		= TRUE;
			gvars.go_deep		= TRUE;
		} else {
			gvars.go_wide		= go_wide;
			gvars.go_deep		= go_deep;
		}
		
		gvars.cOutline		= coutline;
		HLock((Handle)coutline->OTLNi_outlineH);
		gvars.ol			= *(coutline->OTLNi_outlineH);
		gvars.iterate_type	= iterate_type;
		gvars.cb_type		= cb_type;
		gvars.data			= data;
		gvars.v_pos			= 0;
		
		err = OTLNpm_ApplyToItemsR(&gvars, 0, FALSE);
		
		HUnlock((Handle)coutline->OTLNi_outlineH);
		
		coutline->i_v_bottom = gvars.v_pos;
	}
	
	if (err == OTLN_Err_BREAK_FROM_LOOP)
		err = Err_NONE;
	
	return err;
}

//****************************************************
Err		OTLN_CTopic::OTLNm_MoveChildren(
	OTLN_CTopic	*srcParentP, 
	OTLN_CTopic	*dstParentP)
{
	Err					err = Err_NONE;
	
	if (srcParentP != dstParentP) {
		OTLN_CTopic			*curTopicP;
		OTLN_CTopicIndex	index, maxTopics;

		err = srcParentP->OTLNm_CountTopics(&maxTopics);
		if (!err) {
			
			for (index = maxTopics - 1; !err && index >= 0; index--) {
				err = srcParentP->OTLNm_GetIndTopic(index, &curTopicP);
				
				if (!err) err = curTopicP->OTLNm_Remove();
				if (!err) err = curTopicP->OTLNm_Adopt(
					curTopicP->OTLNpi_cOutline, dstParentP, 0);
				if (!err) err = curTopicP->OTLNm_Insert();
			}
		}
	}
	
	return err;
}

#endif