//	CEntry.c

#ifndef __GNUC__
	#include "OSUtils.h"	//	DateToSeconds
#endif

#include "MemUtils.h"
#include "ADFS_Strings.h"
#include "ADFS_Icons.h"
#include "ADFS_Menus.h"
#include "ADFS_Prefs.h"
#include "ADFS_LogFile.h"
#include "ADFS_O_Callbacks.h"
#include "A2PixInterface.h"
#include "ProFileTypes.h"
#include "Pro_Utils.h"
#include "CDiskMapWindow.h"
#include "CDialogCopy.h"
#include "BasicTokenizer.h"
#include "Disassembly.h"
#include "AppleWorks.h"
#include "Carbon68kGlue.h"
#include "CCopyFile.h"
#include "CCopyTree.h"

#include "FSUtils.h"
#include "Utils.h"
#include "CDialogGetInfo.h"

#include "CDesktop.h"
#include "CDesktopWindow.h"
#include "CFolderWindow.h"

#include "CDisk.h"
#include "CEntry.h"

DateTimeRec		g_nullDateTime = { 2000, 1, 0, 0, 0, 0, 0 };
extern short	g_numQueuedErrors;

CEntry		*GetTopicEntry(O_CTopic *topic)
{
	CEntry	*thiz;
	
	topic->O_GetCustomData((void **)&thiz);
	
	return thiz;
}

O_CTopic	*GetEntryTopic(CEntry *entry)
{
	return entry->i_topicRef.cTopic 
		? entry->i_topicRef.cTopic 
		: entry->i_cDisk.gen->i_topicRef.cTopic;
}

RgnHandle		gRgn1 = NULL;
RgnHandle		gRgn2 = NULL;
RgnHandle		gRgn3 = NULL;
RgnHandle		gRgn4 = NULL;

OSErr		CEntry::IEntry(
	CDisk				*cDisk, 
	CFolder				*cParentFolder, 
	FSObjectType		type, 
	DiskLocSpecUnion	diskLoc, 
	EntryIndex			diskLocDirEntryIndex,	//	relative to cur dir sector
	EntryIndex			directoryIndex			//	relative to entire directory
) {
	OSErr				err		= noErr;
	O_TopicIndex		addTopicIndex;
	CFinderWindow		*window;
	Boolean				twirledB;
	
	if (cParentFolder) {
		addTopicIndex = cParentFolder->i_addTopicIndex;
		cParentFolder->i_addTopicIndex = O_TopicIndex_END;
	} else {
		addTopicIndex = O_TopicIndex_END;	//	 this is unused then?
	}
	
	i_cDisk.gen				= cDisk;
	i_type					= type;
	i_fileType				= ADFS_File_NONE;
	i_filePos				= 0;
	i_fileBufP				= NULL;
	i_basBufP				= NULL;
	i_diskLoc				= diskLoc;
	i_diskLocDirEntryIndex	= diskLocDirEntryIndex;
	i_directoryIndex		= directoryIndex;
	i_disposingB			= FALSE;
	i_myEntryCachedB		= FALSE;
	
	i_iconPoint.h			= ((directoryIndex - 1) % 5) * 64 + 32;
	i_iconPoint.v			= ((directoryIndex - 1) / 5) * 50 + 20;

	i_window				= NULL;
	i_windowRect			= gEmptyRect;

	i_topicRef.cOutline		= NULL;
	i_topicRef.cTopic		= NULL;
	i_addTopicIndex			= O_TopicIndex_END;
	i_hilightedB			= FALSE;
	i_entryRgnTimestamp		= 0;
	i_entryRgn				= NULL;
	i_ioType				= ADFS_IO_NONE;
	i_resForkB				= FALSE;
	i_eof					= 0;
	i_badPicB				= FALSE;
	
	i_physical_sizeL	= 0;
	i_logical_sizeL		= 0;

	if (gRgn1 == NULL) {
		gRgn1 = NewRgn();
		gRgn2 = NewRgn();
		gRgn3 = NewRgn();
		gRgn4 = NewRgn();

		if (!(gRgn1 && gRgn2 && gRgn3 && gRgn4)) {
			err = memFullErr;
		}
	}

	if (!err) {
		if (i_type != FSObject_DISK_ROOT_FOLDER) {
			O_CTopic		*topic;
			
			if (i_type == FSObject_ROOT_FOLDER) {
				err = gDesktop->i_cOutline->O_GetRoot(&topic);
			} else {
				NewObject(topic, O_CTopic, err);
				
				if (!err) err = topic->O_InitTopic();
			}
			
			if (!err) {
				O_CTopic		*recent;
				
				if (!err) err = topic->O_SetCallbackDispatch(S_EntryDispatchCB);
				if (!err) err = topic->O_SetCustomData(this);

				if (i_type != FSObject_ROOT_FOLDER) {
					if (!err) err = gDesktop->i_cOutline->O_GetRecent(&recent);
					if (!err) err = topic->O_Adopt(
						cDisk->i_desktop->i_cOutline, recent, addTopicIndex);
					if (!err) err = topic->O_Insert();
					if (!err) err = recent->O_SetRecent();
				}
			}
			
			if (!err) {
				char			buf[256];

				i_topicRef.cTopic	= topic;
				i_topicRef.cOutline	= gDesktop->i_cOutline;
				
				if (i_type == FSObject_ROOT_FOLDER) {
					twirledB = TRUE;
					i_topicRef.cTopic->O_IsTwirledDown(NULL, &twirledB);
				} else {
					(void)topic->O_SetName(GetName(buf));
				}

				if (
					i_type == FSObject_FOLDER
					|| i_type == FSObject_DISK
				) {
					twirledB = GetTwirled();
					i_topicRef.cTopic->O_IsTwirledDown(NULL, &twirledB);
				}
			}
		}
	}

	if (i_type != FSObject_ROOT_FOLDER) {
		window = GetEnclosingWindow();
		window->InvalWindow(WindowRect_INTERIOR);
		window->AdjustScrollbars();
	}

	return err;
}

OSErr			CEntry::UnDelete(Boolean recursiveB, CDialogCopy *copyP0)
{
	GetParentFolder()->UnCacheFolderSizes();
	InvalStat(ADFS_Stat_ICON);

	if (i_cDisk.gen->i_diskMapP) {
		i_cDisk.gen->i_diskMapP->Refresh(this, TRUE, TRUE);
	}

	if (copyP0) {
		copyP0->IncrementProgress(TRUE, NULL);
	}

	return noErr;
}

OSErr			CEntry::Delete(Boolean warnB, CDialogCopy *copyP0)
{
	if (copyP0) {
		copyP0->IncrementProgress(TRUE, NULL);
	}

	if (
		(
			i_type == FSObject_FILE
			|| i_type == FSObject_FOLDER
		) && i_cDisk.gen->i_show_deletedB
	) {
		CDialogGetInfo		*getInfoP	= GetGetInfo();
		CDiskMapWindow		*diskMapP	= i_cDisk.gen->i_diskMapP;

		InvalStat(ADFS_Stat_ICON);

		if (diskMapP) {
			diskMapP->Refresh(this, FALSE, TRUE);
		}
		
		if (
			getInfoP
			&& (
				getInfoP->i_entryP == this
				|| getInfoP->i_entryP->i_cDisk.gen == this
			)
		) {
			getInfoP->InvalDialogItem(ADFS_GetInfo_USER_ICON);
		}
	
		i_myEntryCachedB = FALSE;
	} else {
		Dispose();
	}

	return noErr;
}

void			CEntry::Dispose(void)
{
	if (!i_disposingB) {
		CDialogGetInfo		*getInfoP	= GetGetInfo();
		CDiskMapWindow		*diskMapP	= i_cDisk.gen->i_diskMapP;
		CFinderWindow		*window		= GetEnclosingWindow();
		CRenameTextEdit		*renameTE	= IsThisRename();
		
		if (renameTE) renameTE->Finish();
		
		if (i_type != FSObject_DISK_ROOT_FOLDER) {
			ASSERT(i_topicRef.cTopic);
		}
		
		if (i_entryRgn) {
			DisposeRgn(i_entryRgn);
			i_entryRgn = NULL;
		}
		
		if (
			getInfoP
			&& (
				getInfoP->i_entryP == this
				|| getInfoP->i_entryP->i_cDisk.gen == this
			)
		) {
			getInfoP->Dispose();
		}	

		i_disposingB = TRUE;
		
		if (diskMapP) {
			QuietErrors(TRUE);
			diskMapP->Refresh(this, FALSE, TRUE);
			QuietErrors(FALSE);
			g_numQueuedErrors = 0;
		}

		window->InvalWindow(WindowRect_INTERIOR);

		if (i_topicRef.cTopic) {
			i_topicRef.cTopic->O_Remove();
			i_topicRef.cTopic->O_DisposeTopic();
		}
	} else {
		delete this;
	}
}

OSErr		CEntry::CountRecurse(Boolean deletedB, ulong *totalL)
{
	ASSERT(i_type != FSObject_FOLDER);
	return noErr;
}

OSErr		CEntry::EntryPane_CB_EntryArray(
	TA_IterateType taType, TA_IterateData *cbData)
{
	OSErr		err = noErr;
	
	switch (taType) {

		case TA_Iterate_ADD_TO_DRAG: {
			AddToDragRef(&cbData->drag);
			break;
		}
		
		case TA_Iterate_SET_PENDING_COPY: {
			err = ADFS_SetPendingCopy(
				CCT_Copy_ENTRY, CCT_Copy_FSSPEC, 
				cbData->copy.folderSpecP);
			break;
		}
		
		case TA_Iterate_SELECT: {
			Select(cbData->select.select, cbData->select.draw);
			break;
		}
		
		case TA_Iterate_GET_DISKS_OF_SELECTION: {
			CEntryArray		*disksP = (CEntryArray *)cbData;
			
			if (!disksP->Member(i_cDisk.gen)) {
				err = disksP->Add(i_cDisk.gen);
			}
			break;
		}

		case TA_Iterate_FLUSH_MEM_DISK: {
			Boolean		*flushBP = (Boolean *)cbData;
			
			i_cDisk.gen->FlushMemDisk(*flushBP);
			break;
		}

		case TA_Iterate_DELETE: {
			CDialogCopy		*copyP = (CDialogCopy *)cbData;

			if (!IsDeleted()) {
				Delete(TRUE, copyP);
			}
			break;
		}
		
		case TA_Iterate_COUNT_RECURSE:
		case TA_Iterate_COUNT_RECURSE_DELETED: {
			Boolean		count_deletedB	= taType == TA_Iterate_COUNT_RECURSE_DELETED;
			Boolean		is_deletedB		= IsDeleted();
			ulong		*totalL			= (ulong *)cbData;
			CFolder		*folderP		= NULL;

			if (i_type == FSObject_DISK) {
				folderP = ((CDisk *)this)->i_rootDir.gen;
			} else {
				if (!IsAncestorSelected()) {
					if (i_type == FSObject_FOLDER && !is_deletedB) {
						folderP	= (CFolder *)this;
					}
				}
			}
			
			if (count_deletedB == is_deletedB) {
				(*totalL)++;
			}

			if (folderP) {
				err = folderP->CountRecurse(count_deletedB, totalL);
			}
			break;
		}

		case TA_Iterate_UNDELETE: {
			CDialogCopy		*copyP		= (CDialogCopy *)cbData;
			CFolder			*folderP	= NULL;

			if (i_type == FSObject_DISK) {
				folderP = ((CDisk *)this)->i_rootDir.gen;
			} else {
				if (!IsAncestorSelected()) {
					if (i_type == FSObject_FOLDER && !IsDeleted()) {
						folderP	= (CFolder *)this;
					}
				}
			}
			
			if (folderP) {
				folderP->UnDeleteFolderContents(TRUE, copyP);
			} else {
				UnDelete(FALSE, copyP);
			}
			break;
		}
		
		case TA_Iterate_DISPOSE: {
			Dispose();
			break;
		}
	}
	
	return err;
}

//	static
Err			CEntry::S_EntryDispatchCB(	
	O_TopicRefP	topicRef, 
	O_CBType				cbType, 
	O_CBDataP			cbData
) {
	CEntry	*thiz	= GetTopicEntry(topicRef->cTopic);
	Err		err		= noErr;
	
	if (thiz) {
		err = thiz->EntryDispatchCB(cbType, cbData);
	}
	
	return err;
}

Boolean			CEntry::IsAncestorSelected(void)
{
	Boolean		ancestorSelectedB	= FALSE;
	Boolean		doneB				= FALSE;
	CEntry		*parentP			= this;
	
	if (i_type != FSObject_DISK) do {
		parentP = parentP->GetParent();
		
		if (parentP->i_type == FSObject_DISK) {
			parentP	= i_cDisk.gen;
			doneB	= TRUE;
		}
		
		if (parentP->IsSelected()) {
			ancestorSelectedB	= TRUE;
			doneB				= TRUE;
		}
	} while (!doneB);
	
	return ancestorSelectedB;
}

Err		CEntry::EntryDispatchCB(
	O_CBType			cbType, 
	O_CBDataP			cbData
) {
	OSErr		err = noErr;
	
	switch (cbType) {
	
		case ADFS_O_CB_UPDATE_SORT: {
			UpdateSort(TRUE);
			break;
		}
		
		case ADFS_O_CB_COLLECT_BITMAP: {
			Gen_AllocMap		*blockBitMapP = (Gen_AllocMap *)cbData;
			Gen_EntryAlloc		*sectorsRecP;
			
			QuietErrors(TRUE);
			err = GetEntryAlloc(Gen_UseBlocks(blockBitMapP->allocSize), &sectorsRecP);
			QuietErrors(FALSE);
			g_numQueuedErrors = 0;
	
			if (!err) {
				err = i_cDisk.gen->AddSectorsToMap(
					this, sectorsRecP, blockBitMapP);
				
				DisposeEntryAlloc(sectorsRecP);
			}
			break;
		}
		
		case O_CB_DRAW: {
			Draw();
			break;
		}

		case O_CB_DRAG_REORDER: {
			break;
		}

		case O_CB_TWIRL: {
			break;
		}

		case O_CB_MARQUEE: {
			Point	thePoint  = { 0, 0 };
			
			SetEmptyRgn(gRgn4);
			GetNameAndIconRgn(gRgn4);
			
			//	GetNameAndIconRgn() is always in global coords, since it's
			//	mostly used for drag and drop, so re-localize it
			GlobalToLocal(&thePoint);
			OffsetRgn(gRgn4, thePoint.h, thePoint.v);
			
			RectRgn(gRgn3, &cbData->marquee.theRect);
			SectRgn(gRgn3, gRgn4, gRgn3);
			if (!EmptyRgn(gRgn3)) {
				if (cbData->marquee.toggleB) {
					Select(!IsSelected(), TRUE);
				} else {
					Select(TRUE, TRUE);
				}
			}
			break;
		}
		
		case O_CB_DUP_CUST_DATA: {
			cbData->dup_cust.dest_cust_data = cbData->dup_cust.source_cust_data;
			break;
		}
		
		case O_CB_HIT_TEST: {
			Boolean						*didHit = (Boolean *)&(cbData->hit_test.cTopic);
			ADFS_StatType				statType;

			statType	= HitTest(cbData->hit_test.hit_point, NULL);
			*didHit		= statType != ADFS_Stat_NONE;
			break;
		}

		case O_CB_DISPOSE_CUST_DATA: {
			if (i_window) {
				i_window->Dispose();
			}
			
			i_disposingB = TRUE;
			Dispose();
			break;
		}

		case ADFS_O_CB_PANE_ARRAY_GET_SEL_RGNS: {
			RgnHandle		theRgn = (RgnHandle)cbData;
			
			GetNameAndIconRgn(theRgn);
			break;
		}

		case ADFS_O_CB_PANE_ARRAY_GET_SEL_DRAG: {
			if (!IsAncestorSelected()) {
				CEntryArray		*arrayP = (CEntryArray *)cbData;
				
				arrayP->Add(this);
			}
			break;
		}

		case ADFS_O_CB_PANE_ARRAY_GET_SEL:
		case ADFS_O_CB_PANE_ARRAY_GET: {
			ADFS_O_CBData_GET_SEL		*getSelP = (ADFS_O_CBData_GET_SEL *)cbData;
			
			if (!getSelP->not_if_ancestor_selB || !IsAncestorSelected()) {
				getSelP->arrayP->Add(this);
			}
			break;
		}

		case ADFS_O_CB_COUNT_TYPES: {
			ADFS_O_CBData_COUNT_TYPES	*ct = (ADFS_O_CBData_COUNT_TYPES *)cbData;
			Boolean						saveThisB = TRUE;
			
			switch (i_type) {

				case FSObject_FILE: {
					if (IsDeleted()) {
						(ct->files_deleted)++;
					} else {
						(ct->files_normal)++;
					}
					break;
				}

				case FSObject_FOLDER: {
					if (IsDeleted()) {
						(ct->folders_deleted)++;
					} else {
						(ct->folders_normal)++;
					}
					break;
				}

				case FSObject_DISK: {
					(ct->disks)++;
					
					ct->show_deleted += i_cDisk.gen->i_show_deletedB;
					break;
				}

				default: {
					saveThisB = FALSE;
					(ct->errors)++;
					ReportErrorStr(0, "Strange object type!");
					break;
				}
			}
			
			if (saveThisB) {
				ct->entryP = this;
			}
			
			break;
		}
		
		case ADFS_O_CB_GET_INFO: {
//			Boolean			selected = IsSelected();

		 	/*
		 	if (selected) {
		 		if (i_getInfo) {
		 			SelectWindow(i_getInfo->i_dialog);
		 			ShowWindow(i_getInfo->i_dialog);
		 		} else if (NewObject(i_getInfo, CDialogGetInfo, err)) {
					i_getInfo->IGetInfo(this);
				}
		 	}
			*/
			break;
		}
		
		case ADFS_O_CB_DISPOSE: {
			ASSERT(FALSE);
			break;
		}
	}
	
	return err;
}

CFinderWindow	*g_window;
short			g_rightEdge;
short			g_fontHeight;
short			g_smallFontOffset;
Boolean			g_isIconView;

void	CEntry::UpdateGlobals(void)
{
	Rect		portRect;
	
	g_window			= GetEnclosingWindow();

	GetPortBounds(GetWindowPort(g_window->GetWindowRef()), &portRect);
	
	g_rightEdge			= portRect.right - kScrollbarWidth + 1;
	g_fontHeight		= g_window->i_fontInfo.ascent + g_window->i_fontInfo.descent;
	g_smallFontOffset	= 1 - ((ADFS_MinCellHeight - g_fontHeight) / 2);
	g_isIconView		= g_window->i_header->i_viewAs == cmdViewAsIcons;
}

static		void	FixRectEdge(Rect *theRect, short edge)
{
	if (theRect->left >= edge) {
		theRect->left = theRect->right = edge;
	}

	if (theRect->right > edge) {
		theRect->right = edge;
	}
}

void			CEntry::GetStatRects(
	ADFS_StatType	statType, 
	Rect			*statRect, 
	Rect			*statItemRect,	//	ONLY for non strings!
	Rect			*statBufRect	//	just the buffer area (to the right)
) {
	if (g_isIconView) {
		statBufRect->left = 0;
		statBufRect->top = 0;
		statBufRect->right = 0;
		statBufRect->bottom = 0;

		if (statType == ADFS_Stat_ICON) {
			statRect->left = i_iconPoint.h;
			statRect->top = i_iconPoint.v;
			statRect->right = statRect->left + 32;
			statRect->bottom = statRect->top + 32;
		} else {
			*statRect = *statBufRect;
		}
		
		*statItemRect = *statRect;
	} else {
		short	offset;
		
		GetEntryTopic(this)->O_GetPaneFrame((M_Rect *)statRect);
		statRect->bottom--;
		offset = statRect->left;
		
		GetEnclosingWindow()->i_header->GetStatSize(statType, &statRect->left, &statRect->right);
		
		//	index, icon and name get indented
		if (statType >= ADFS_Stat_INDEX && statType <= ADFS_Stat_NAME) {
			OffsetRect(statRect, offset, 0);
		}
		
		//	the right side of the name does NOT get indented
		if (statType == ADFS_Stat_NAME) {
			statRect->right -= offset;
		}
		
		*statBufRect = *statItemRect = *statRect;
		
		statBufRect->left	= statBufRect->right;
		statBufRect->right	+= GetEnclosingWindow()->i_header->GetStatBorder(statType);
		
		switch (statType) {

			case ADFS_Stat_TWIRLIE: {
				statItemRect->left++;
				OffsetRect(statItemRect, 0, 2);
				statItemRect->bottom = statItemRect->top + 16;
				statBufRect->right += offset;
				break;
			}

			case ADFS_Stat_ICON: {
				OffsetRect(statItemRect, 0, 1);
				statItemRect->bottom	= statItemRect->top + 16;
				statItemRect->right		= statItemRect->left + 16;
				break;
			}

			case ADFS_Stat_LAST_ONE: {
				statBufRect->right = g_rightEdge;
				break;
			}
		}

		FixRectEdge(statRect, g_rightEdge);
		FixRectEdge(statItemRect, g_rightEdge);
		FixRectEdge(statBufRect, g_rightEdge);
	}
}


char			*CEntry::GetStatString(
	ADFS_StatType	statType, 
	char			*buf, 
	Rect			*statRect, 
	Rect			*statItemRect,	//	ONLY for non strings
	Rect			*statBufRect	//	just the buffer area (to the right)
) {	
	GetStatRects(statType, statRect, statItemRect, statBufRect);
	
	buf[0] = 0;
	
	switch (statType) {
		
		case ADFS_Stat_TWIRLIE: {
			strcpy(buf, "Twirlie");
			break;
		}
		
		case ADFS_Stat_ICON: {
			strcpy(buf, "Icon");
			break;
		}
		
		case ADFS_Stat_INDEX: {
			sprintf(buf, "%u", (unsigned int)i_directoryIndex);
			break;
		}

		case ADFS_Stat_NAME: {
			GetName(buf);
			break;
		}

		case ADFS_Stat_SIZE: {
			FormatSize(GetPhysicalSize(), buf);
			break;
		}

		case ADFS_Stat_USED: {
			FormatSize(GetLogicalSize(), buf);
			break;
		}

		case ADFS_Stat_KIND: {
			GetDescription(buf);
			break;
		}

		case ADFS_Stat_MOD_DATE: {
			GetModifiedTimeString(buf);
			break;
		}

		case ADFS_Stat_CRE_DATE: {
			GetCreatedTimeString(buf);
			break;
		}
	}
	
	if (!g_isIconView) {
		ShrinkCString(buf, statRect->right - statRect->left);
	}

	return buf;
}

char			*CEntry::GetStatStringInfo(
	ADFS_StatType	statType, 
	char			*buf, 
	Rect			*statRect, 
	Rect			*statStrRect,
	Rect			*statLeftBufRect, 
	Rect			*statRightBufRect
) {
	GetStatString(statType, buf, statRect, statStrRect, statRightBufRect);
	
	if (!g_isIconView) {
		*statLeftBufRect = *statRect;
		
		//	at this time, statStrRect == statRect
		
		switch (statType) {

			case ADFS_Stat_INDEX:
			case ADFS_Stat_NAME:
			case ADFS_Stat_SIZE:
			case ADFS_Stat_USED:
			case ADFS_Stat_KIND:
			case ADFS_Stat_CRE_DATE:
			case ADFS_Stat_MOD_DATE: {
				short			width;
				
				width = TextWidth(buf, 0, strlen(buf));
							
				if (GetEnclosingWindow()->i_header->GetStatJustify(statType) == ADFS_Justify_RIGHT) {
					statStrRect->left = statStrRect->right - width;
				} else {
					statStrRect->right = statStrRect->left + width;
					statRightBufRect->left = statStrRect->right;
				}

				statLeftBufRect->right = statStrRect->left;

				InsetRect(statStrRect, -2, 1);
				
				statStrRect->top = statStrRect->bottom - g_fontHeight;
				
				if (g_fontHeight < ADFS_MinCellHeight) {
					OffsetRect(statStrRect, 0, g_smallFontOffset);
				}
				
				if (statType == ADFS_Stat_NAME) {
					CRenameTextEdit		*renameTE = IsThisRename();
					
					if (renameTE) {
						statStrRect->right = statRightBufRect->right - 2;
						statStrRect->top++;
						statStrRect->left++;
					}
				}
				break;
			}
		}
	} else {
		*statLeftBufRect = *statRightBufRect;
		
		if (statType == ADFS_Stat_NAME) {
			short			width;
			
			width = TextWidth(buf, 0, strlen(buf));

			statRect->top = i_iconPoint.v + 33;
			statRect->bottom = statRect->top + g_fontHeight;
			
			statRect->left = i_iconPoint.h + 14 - (width >> 1);
			statRect->right = statRect->left + width + 4;
			
			*statStrRect = *statRect;
		}
	}
	
	return buf;
}

void	CEntry::LogName(void)
{
	char	buf[256];

	ADFS_Log(GetDescription(buf));
	ADFS_Log(" '");
	ADFS_Log(GetName(buf));
	ADFS_Log("'");
}

void	CEntry::Draw(void)
{
	ADFS_StatType	statType;
	
	UpdateGlobals();

	if ((**gPrefsH).log_updatesB) {
		ADFS_Log("------ Drawing Entry: ");
		LogName();
		ADFS_Log("\n");
	}
	
	ADFS_Stat_FOR_EACH(statType) {
		DrawStat(statType);
	}
	
	if ((**gPrefsH).log_updatesB) {
		ADFS_Log("|\n");
	}
}

void	CEntry::Hilight(Boolean hilightedB)
{
	i_hilightedB = hilightedB;
	Draw();
}

Boolean	CEntry::IsHilighted(void)
{
	return i_hilightedB;
}

void	CEntry::Select(Boolean selectedB, Boolean drawB)
{
	CDiskMapWindow		*diskMapP	= i_cDisk.gen->i_diskMapP;

	GetEntryTopic(this)->O_Select(selectedB, drawB);
	
	if (diskMapP) {
		if (selectedB) {
			diskMapP->HiliteEntry(this);
		} else {
			diskMapP->HiliteEntry(NULL);
		}
	}
}

void	CEntry::SelectAll(Boolean selectedB, Boolean drawB)
{
	GetEntryTopic(this)->O_SelectAll(selectedB, drawB);
}

Boolean	CEntry::IsSelected(void)
{
	Boolean selectedB;
	
	GetEntryTopic(this)->O_IsSelected(&selectedB, NULL);

	return selectedB;
}

void	CEntry::InvalStat(ADFS_StatType statType)
{
	CFinderWindow	*windowP = GetEnclosingWindow();
	Boolean			prepared = windowP->i_prepared;
	Rect			statRect, statItemRect, statBufRect;
	GrafPtr			savePort;
	
	if (!prepared) {
		GetPort(&savePort);
		windowP->Prepare();
	}
	
	GetStatRects(statType, &statRect, &statItemRect, &statBufRect);
	InvalWindowRect(windowP->GetWindowRef(), &statRect);
	
	if (!prepared) {
		windowP->UnPrepare();
		SetPort(savePort);
	}
}

static	void	DrawHilight(Rect *theRect)
{
	PenSize(2, 2);
	PenMode(patXor);
	InsetRect(theRect, -1, -1);
	FrameRect(theRect);
	InsetRect(theRect, 1, 1);
	PenMode(patCopy);
	PenSize(1, 1);
}

void	CEntry::DrawStat(ADFS_StatType statType)
{
	Rect			theRect, statRect, statItemRect, leftBuf, rightBuf; 
	char			buf[256];
	
	switch (statType) {
		
		case ADFS_Stat_TWIRLIE: {
			strcpy(buf, "Twirlie");
			break;
		}
		
		case ADFS_Stat_ICON: {
			strcpy(buf, "Icon");
			break;
		}
		
		case ADFS_Stat_INDEX: {
			strcpy(buf, "Index");
			break;
		}
		
		default: {
			CopyPascalStringToC(GetEnclosingWindow()->i_header->i_stats[statType].name, buf);
			break;
		}
	}

	if ((**gPrefsH).log_updatesB) {
		ADFS_Log("|");
		ADFS_Log(buf);
	}
	
	GetStatStringInfo(statType, buf, &statRect, &statItemRect, &leftBuf, &rightBuf);			

	if (!EmptyRect(&statRect)) {
		Boolean			selected = IsSelected();
		
		if (g_isIconView) {
			if (buf[0] != 0) {
				EraseRect(&statItemRect);
			}
		} else {
			if (!g_window->i_usingOffscreens) {
				if (g_window->i_usingEraseRgns) {
					theRect = statRect;
					theRect.right = rightBuf.right;

					RectRgn(gRgn1, &theRect);

					theRect = statItemRect;
					
					if (buf[0] != 0) {
						InsetRect(&theRect, 2, 0);
					}
					
					RectRgn(gRgn2, &theRect);
					
					DiffRgn(gRgn1, gRgn2, gRgn1);
					EraseRgn(gRgn1);
				} else {
					EraseRect(&leftBuf);
					EraseRect(&rightBuf);
				}
			}
		}

		switch (statType) {

			case ADFS_Stat_TWIRLIE: {
				Boolean		noDaughters = FALSE;
				
				if (i_type == FSObject_FILE) {
					EraseRect(&statItemRect);
				} else {
					if (O_TopicFirstChild(GetEntryTopic(this)) == NULL) {
						noDaughters = TRUE;
						O_TopicFirstChild(GetEntryTopic(this)) = O_Fake_Topic;
					}
					
					GetEntryTopic(this)->O_DrawTwirlieArrow((M_Rect *)&statItemRect);
					
					if (noDaughters) {
						O_TopicFirstChild(GetEntryTopic(this)) = NULL;
					}
				}
				break;
			}
			
			case ADFS_Stat_ICON: {
				IconTransformType	transform	= kTransformNone;
				
				if (i_window) {
					transform |= kTransformOpen;
				}
				
				if (selected) {
					transform |= kTransformSelected;
				}

				DrawIcon(transform, &statItemRect);
								
				if (i_hilightedB) {
					DrawHilight(&statItemRect);
				}
				break;
			}
			
			case ADFS_Stat_LOCK: {
				//GetEntryStatIcon(statType);
				EraseRect(&statItemRect);
				FrameRect(&statItemRect);
				break;
			}

			case ADFS_Stat_INDEX:
			case ADFS_Stat_NAME:
			case ADFS_Stat_SIZE:
			case ADFS_Stat_USED:
			case ADFS_Stat_KIND:
			case ADFS_Stat_CRE_DATE:
			case ADFS_Stat_MOD_DATE: {
				MoveTo(statItemRect.left + 2, statItemRect.bottom - g_window->i_fontInfo.descent);
				
				DrawCString(buf);

				if (statType == ADFS_Stat_NAME) {
					CRenameTextEdit		*renameTE = IsThisRename();
					
					if (renameTE) {
						renameTE->Draw();
					} else {
						if (selected) {
							InvertRect(&statItemRect);
						}
						
						if (i_hilightedB) {
							DrawHilight(&statItemRect);
						}
					}
				}
				break;
			}
		}
	}
}

void		CEntry::DrawIcon(IconTransformType transform, Rect *theRect)
{
	if (IsDeleted()) {
		transform |= kTransformDeleted;
	}
	
	if (IsLocked()) {
		transform |= kTransformLocked;
	}
	
	EraseRect(theRect);
	ADFS_DrawIcon(GetIconType(), theRect, transform);
}


void		CEntry::GetBlitRgn(RgnHandle theRgn)
{
	if (g_isIconView) {
		SetEmptyRgn(gRgn4);
		GetNameAndIconRgn(gRgn4);
		UnionRgn(theRgn, gRgn4, theRgn);
	} else {
		Rect	statRect;
		
		UpdateGlobals();
		
		GetEntryTopic(this)->O_GetPaneFrame((M_Rect *)&statRect);
		statRect.bottom--;
		statRect.left = 0;
		
		RectRgn(gRgn1, &statRect);
		UnionRgn(theRgn, gRgn1, theRgn);
	}
}

//	GetNameAndIconRgn() is always in global coords, since it's
//	mostly used for drag and drop
void		CEntry::GetNameAndIconRgn(RgnHandle theRgn)
{
	Rect				statRect, statItemRect, leftBuf, rightBuf; 
	char				buf[256];
	Point				thePoint = { 0, 0 };
	
	UpdateGlobals();

	GetStatStringInfo(ADFS_Stat_NAME, buf, &statRect, &statItemRect, &leftBuf, &rightBuf);
	RectRgn(gRgn1, &statItemRect);
	CopyRgn(gRgn1, gRgn2);
	InsetRgn(gRgn2, 2, 2);
	DiffRgn(gRgn1, gRgn2, gRgn3);

	GetStatStringInfo(ADFS_Stat_ICON, buf, &statRect, &statItemRect, &leftBuf, &rightBuf);
	RectRgn(gRgn1, &statItemRect);
	CopyRgn(gRgn1, gRgn2);
	InsetRgn(gRgn2, 2, 2);

	DiffRgn(gRgn1, gRgn2, gRgn1);
	UnionRgn(gRgn3, gRgn1, gRgn3);
	LocalToGlobal(&thePoint);
	OffsetRgn(gRgn3, thePoint.h, thePoint.v);
	
	UnionRgn(gRgn3, theRgn, theRgn);
}

ADFS_StatType	CEntry::HitTest(
	Point		thePoint, 
	Rect		*theRect0
) {
	ADFS_StatType	statType;
	Rect			statRect, statItemRect, leftBuf, rightBuf; 
	char			buf[256];
	
	UpdateGlobals();

	ADFS_Stat_FOR_EACH(statType) {
		GetStatStringInfo(statType, buf, &statRect, &statItemRect, &leftBuf, &rightBuf);
		if (PtInRect(thePoint, &statItemRect)) {
			break;
		}
	}
	
	if (statType == ADFS_Stat_NUMTYPES) {
		statType = ADFS_Stat_NONE;
	}
	
	if (statType && theRect0)
		*theRect0 = statItemRect;
	
	return statType;
}

//	gets native file type
ushort			CEntry::GetFileType(void)
{
	return 0;
}

void			CEntry::SetFileType(Byte fileType)
{
}

//	gets prodos equivalent file type
ushort			CEntry::GetFileType_ProEquiv(void)
{
	return 0;
}

void			CEntry::SetFileType_ProEquiv(Byte proType)
{
}

ushort			CEntry::GetAuxType(void)
{
	return 0;
}

void			CEntry::SetAuxType(ushort auxType)
{
}

void			CEntry::GetMacTypeAndCreator(
	OSType	*fileType, 
	OSType	*fileCreator)
{
	Pro_To_Mac_FileType((Byte)GetFileType_ProEquiv(), GetAuxType(), fileType, fileCreator);
	
	if (IsGraphic()) {
		*fileCreator = A2Pix_Creator;
	}
}


ulong		CEntry::ADFS_GetBufSize(void)
{
	return 0;
}

OSErr		CEntry::ADFS_Open(
	ADFS_IOType	ioType, 
	Boolean		resForkB, 
	char		**bufferP, 
	ulong		*bufSize)
{
	OSErr		err	= noErr;
	
	i_ioType	= ioType;
	i_resForkB	= resForkB;
	i_filePos	= 0;
	*bufSize	= ADFS_GetBufSize();
	
	if (*bufSize) {
		i_fileBufP = *bufferP = TrackNewPtr("entry file buf", *bufSize);
		
		if (!i_fileBufP) {
			err = memFullErr;
		}

		if (!err && ioType == ADFS_IO_READ) {
			Size	bufSizeL = *bufSize;
			
			if (
				i_fileType == ADFS_File_BASIC
				|| i_fileType == ADFS_File_INTBASIC
			) {
				bufSizeL = (*bufSize) * kBasBufSizeMultiplier;
				
			} else if (i_fileType == ADFS_File_AWP) {
				bufSizeL = (*bufSize) * kAwpBufSizeMultiplier;

			} else if (i_fileType == ADFS_File_BINARY) {
				bufSizeL = (*bufSize) * kBinBufSizeMultiplier;
			}

			i_basBufP = TrackNewPtr("detokenize file buf", bufSizeL);

			if (!i_basBufP) {
				ReportError(err = memFullErr);
			}
		}
	} else {
		*bufferP = NULL;
		ReportError(err = memFullErr);
	}
	
	if (!err) {
		i_cDisk.gen->FlushMemDisk(FALSE);
	}
	
	return err;
}

OSErr		CEntry::ADFS_Read(ushort *bytesRead)
{
	OSErr		err	= noErr;

	i_filePos += *bytesRead;
	
	if (i_fileType == ADFS_File_TEXT) {
		ushort	loop;
		
		for (loop = 0; loop < *bytesRead; loop++) {
			i_fileBufP[loop] = i_fileBufP[loop] & 0x7F;
		}
	}

	return err;
}	

OSErr		CEntry::ADFS_Write(ushort *bytesWritten)
{
	OSErr		err	= noErr;

	i_filePos += *bytesWritten;
	
	if (i_fileType == ADFS_File_TEXT) {
		ushort	loop;
		
		for (loop = 0; loop < *bytesWritten; loop++) {
			i_fileBufP[loop] = i_fileBufP[loop] | 0x80;
		}
	}

	return err;
}	

OSErr		CEntry::ADFS_Close(void)
{
	CDiskMapWindow		*diskMapP	= i_cDisk.gen->i_diskMapP;

	if (i_fileBufP) {
		TrackDisposePtr((Ptr)i_fileBufP);
		i_fileBufP = NULL;
	}

	if (i_basBufP) {
		TrackDisposePtr((Ptr)i_basBufP);
		i_basBufP = NULL;
	}
	
	i_filePos = 0;
	i_cDisk.gen->FlushMemDisk(TRUE);

	if (i_ioType == ADFS_IO_WRITE) {
		CFolder	*folderP = (CFolder *)GetParentFolder();
	
		//	we've written the last block
		folderP->UnCacheFolderSizes();

		i_logical_sizeL		= 0;
		i_physical_sizeL	= 0;

		if (i_resForkB) {
			i_eof = GetLogicalSize();
		}

		if (diskMapP) {
//	why call it here when i'm going to call it from 
//	CCopyFile_Entry::CopySelfTo() -> SetFileInfo?
//	perhaps cuz if I get a disk full error, it will know to 
//	un-map those blocks?
//			diskMapP->Refresh(this, TRUE, TRUE);
		}

		folderP->UpdateSort();
	}
	
	i_resForkB	= FALSE;
	i_ioType	= ADFS_IO_NONE;
	
	return noErr;
}

/******************************************/
CCopyTree	*g_pendingCopyTree = NULL;
Boolean		g_copyHappeningB	= FALSE;

OSErr	CEntry::ADFS_SetPendingCopy(
	CCT_CopyType	sourceType, 
	CCT_CopyType	destType, 
	void			*opDataP)
{
	OSErr		err = noErr;
	
	if (destType == CCT_Copy_FSSPEC) {
		//	dest is a folder FSSpec in the finder

		if (!g_pendingCopyTree) {
			err = GetNewCopyTree(
				destType, (Ptr)opDataP, 
				&g_pendingCopyTree);
		}
		
		ASSERT(sourceType == CCT_Copy_ENTRY);
		if (!err) err = g_pendingCopyTree->AddEntry(
			NULL, sourceType, (Ptr)this, NULL);
	} else {
		ASSERT(destType == CCT_Copy_ENTRY);
		//	dest is a CFolder
		
		if (!g_pendingCopyTree) {
			err = GetNewCopyTree(
				destType, (Ptr)this, 
				&g_pendingCopyTree);
		}
		
		if (!err) err = g_pendingCopyTree->AddEntry(
			NULL, sourceType, (Ptr)opDataP, NULL);
	}
	
	if (err && g_pendingCopyTree) {
		g_pendingCopyTree->Dispose();
		g_pendingCopyTree = NULL;
	}
	
	return err;
}

//	static
void	CEntry::ADFS_DoPendingCopyCB(void)
{
	if (g_pendingCopyTree && !g_copyHappeningB) {
		CDisk		*srcDiskP = NULL, *dstDiskP = NULL;
		CCopyTree	*copyTreeP = g_pendingCopyTree;
		OSErr		err = noErr, err2;
		Boolean		flushSrcB = FALSE;
		Boolean		flushDstB = FALSE;
		Boolean		show_deletedB = FALSE;
		
		SetStandardCursor(watchCursor);
		g_pendingCopyTree = NULL;
		
		if (copyTreeP->i_sourceP->i_copyType == CCT_Copy_ENTRY) {
			srcDiskP = ((CEntry *)copyTreeP->i_sourceP->i_myData)->i_cDisk.gen;
		}
		
		if (copyTreeP->i_destP->i_copyType == CCT_Copy_ENTRY) {
			dstDiskP = ((CEntry *)copyTreeP->i_destP->i_myData)->i_cDisk.gen;
		}
		
		if (srcDiskP) {
			err = srcDiskP->FlushMemDisk(FALSE);
			if (!err) flushSrcB = TRUE;
		}
		
		if (!err && dstDiskP) {
			err = dstDiskP->FlushMemDisk(FALSE);
			if (!err) flushDstB = TRUE;
			
			if (!err && dstDiskP->i_show_deletedB) {
				err = dstDiskP->ToggleDeletedFiles();
				show_deletedB = TRUE;
			}
		}
		
		if (!err) {
			g_copyHappeningB = TRUE;
			err = copyTreeP->Copy(TRUE);
			copyTreeP->Dispose();
			g_copyHappeningB = FALSE;
		}
		
		if (flushSrcB) {
			err2 = srcDiskP->FlushMemDisk(TRUE);
			if (!err) err = err2;
		}

		if (flushDstB) {
			err2 = dstDiskP->FlushMemDisk(TRUE);
			if (!err) err = err2;			
		}

		if (dstDiskP && show_deletedB) {
			err2 = dstDiskP->ToggleDeletedFiles();
			if (!err) err = err2;			
		}
	}
}

OSErr		CEntry::ADFS_DragSendDataProc(
	DragRef			theDrag, 
	DragItemRef		itemRef, 
	FlavorType		flavorType)
{
	OSErr		err = noErr;

	if (flavorType == kDragPromisedFlavor) {
		Str32		nameBuf;
		HFSFlavor	hfsFlavor;
		FSSpec		destFolderSpec;
		
		GetMacTypeAndCreator(&hfsFlavor.fileType, &hfsFlavor.fileCreator);
		hfsFlavor.fdFlags			= kHasNoINITs;
		
		GetName((char *)nameBuf);
		CopyCStringToPascal((char *)nameBuf, nameBuf);

		err = FSSpecFromDragRef(theDrag, nameBuf, &hfsFlavor.fileSpec);
		
		if (err == dupFNErr) {
			ReportErrorStr(-1, "Can't replace duplicates.  (Yet!)");
		}
		
		if (!err) err = FSpGetParentFolder(&hfsFlavor.fileSpec, &destFolderSpec);

		if (!err) err = FSpCreateFileOrFolder(
			&hfsFlavor.fileSpec, 
			hfsFlavor.fileType, 
			hfsFlavor.fileCreator, 
			FSObject_IS_FOLDER(i_type));
		
		if (!err) {
			err = FSpSetMagicBusyDate(&hfsFlavor.fileSpec);

			if (!err) {
				err = ADFS_SetPendingCopy(
					CCT_Copy_ENTRY, CCT_Copy_FSSPEC, &destFolderSpec);

				if (!err) err = SetDragItemFlavorData(
					theDrag, itemRef, flavorType, 
					&hfsFlavor.fileSpec, sizeof(FSSpec), 0L);
			}
								
			if (err) (void)FSpDelete(&hfsFlavor.fileSpec);
		}
	}

	return err;
}

static	pascal	OSErr		ADFS_DragSendDataProcCB(
	FlavorType		theType, 
	void			*dragSendRefCon, 
	DragItemRef		theItemRef, 
	DragRef			theDrag)
{
	CEntry		*thiz = (CEntry *)theItemRef;
	
	return thiz->ADFS_DragSendDataProc(theDrag, theItemRef, theType);
}

OSErr		CEntry::AddToDragRef(TA_Iterate_ADD_TO_DRAG_Data *dragData)
{
	OSErr				err = noErr;
	CEntry				*thiz = this;
	PromiseHFSFlavor	promiseFlavor;
	
	GetMacTypeAndCreator(&promiseFlavor.fileType, &promiseFlavor.fileCreator);
	promiseFlavor.fdFlags			= kHasNoINITs;
	promiseFlavor.promisedFlavor	= kDragPromisedFlavor;
	
	//	using "this" as drag item ref

	if (!err) err = AddDragItemFlavor(
		dragData->dragRef, (DragItemRef)this,
		kDragFlavorTypePromiseHFS, &promiseFlavor, 
		sizeof(PromiseHFSFlavor), flavorNotSaved);
			
	if (!err) err = AddDragItemFlavor(
		dragData->dragRef, (DragItemRef)this, 
		kDragPromisedFlavor, NULL, 0,
		flavorNotSaved);
			
	if (!err) err = AddDragItemFlavor(
		dragData->dragRef, (DragItemRef)this, 
		kDragFlavorTypeADFS, &thiz, sizeof(Ptr), 
		flavorSenderOnly | flavorNotSaved);

	if (!err) {
		GetNameAndIconRgn(dragData->dragRgn);
	}
	
	return err;
}

OSErr		CEntry::DragItem(EventRecord *theEvent)
{
	OSErr							err = noErr;
	TA_Iterate_ADD_TO_DRAG_Data		dragData;
	
	dragData.dragRef = 0;
	dragData.dragRgn = NewRgn();

	if (dragData.dragRgn) {
		err = NewDrag(&dragData.dragRef);

		if (!err) {
			DragSendDataUPP		sendDataUPP;
			
			sendDataUPP = NewDragSendDataUPP(ADFS_DragSendDataProcCB);
			if (sendDataUPP == NULL) err = memFullErr;
			
			if (!err) {
				CFinderWindow	*window = GetEnclosingWindow();
				CEntryArray		*selectionP;
				
				if (!err) err = SetDragSendProc(dragData.dragRef, sendDataUPP, this);
				
				if (!err) {
					selectionP = window->GetDragSelection();
					err = selectionP == NULL;
				}
				
				if (!err) {
					err = window->Prepare();
					
					if (!err) {
						
						if (!err) err = window->GetSelectionRgn(dragData.dragRgn);
						if (!err) {
							if (!selectionP->Member(this)) {
								err = 1;
							} else {
								err = selectionP->Iterate(TA_Iterate_ADD_TO_DRAG, &dragData);
							}
						}

						window->UnPrepare();
					}

					selectionP->Dispose();
				}
				
				
				if (!err) {
					SetDragging(TRUE);
					err = TrackDrag(dragData.dragRef, theEvent, dragData.dragRgn);
					SetDragging(FALSE);
				}
				
				if (!err) {
					Boolean		inTrashB;
					
					err = DragWentToTrash(dragData.dragRef, &inTrashB);
					
					if (!err && inTrashB) {
						SysBeep(1);
						//	do something nice
					}
				}

			    DisposeDragSendDataUPP(sendDataUPP);
			}
			
			DisposeDrag(dragData.dragRef);
		}
		
		DisposeRgn(dragData.dragRgn);
	}
	
	return err;
}

OSErr		CEntry::CanAcceptFlavor(
	DragReference	theDrag, 
	ItemReference	itemRef, 
	FlavorType		flavorType, 
	Boolean			*goodFlavorB)
{
	OSErr		err = noErr;

	return err;
}

OSErr		CEntry::DragReceiveFlavor(
	DragReference	theDrag, 
	ItemReference	itemRef, 
	FlavorType		flavorType, 
	void			*data)
{
	OSErr		err = dragNotAcceptedErr;

	return err;
}

void		CEntry::DoClick(Point thePoint, long modifiers)
{
	Rect			statItemRect;
	ADFS_StatType	statType = HitTest(thePoint, &statItemRect);
	CFinderWindow	*window = GetEnclosingWindow();

	if (statType != ADFS_Stat_NAME) {
		CRenameTextEdit::FinishRename();
	}

	switch (statType) {

		case ADFS_Stat_TWIRLIE: {
			Boolean		down;
			
			GetEntryTopic(this)->O_IsTwirledDown(&down, NULL);
			down = !down;
			
			if (TrackMouse1(&statItemRect, O_HiliteTwirly, NULL, &down)) {
				O_TwirlArrow(&statItemRect, down);
				GetEntryTopic(this)->O_IsTwirledDown(NULL, &down);
				SetTwirled(down);
				window->InvalWindow(WindowRect_HEADER);
				window->InvalWindow(WindowRect_INTERIOR);
				window->AdjustScrollbars();
				
				if (down && i_window) {
					i_window->Dispose();
				}
			}
			break;
		}

		case ADFS_Stat_NAME:
			CRenameTextEdit		*renameTE = IsThisRename();
			
			if (renameTE) {
				renameTE->DoClick(thePoint, modifiers, 0);
				return;
			}
			
		case ADFS_Stat_ICON: {
			extern	Boolean		gDoubleClick;
			Err			err = noErr;
			Boolean		selected = FALSE;
			Boolean		toggle = FALSE;//, extend = FALSE;
			
			toggle = (modifiers & (cmdKey | shiftKey)) != 0;
			
			selected = IsSelected();
			
			if (!err && !toggle && !selected) {
				CDialogGetInfo		*getInfoP = GetGetInfo();

				GetEnclosingWindow()->DeSelectAll();
				
				if (getInfoP) {
					getInfoP->SetGetInfoEntry(this, getInfoP->i_showPreviewB);
				}
			}
			
			selected = toggle ? !selected : TRUE;
			
			//	nops out if already selected
			Select(selected, FALSE);
			
			window->InvalWindow(WindowRect_INTERIOR);
						
			if (selected) {
				if (gDoubleClick) {
					Open();
				} else {
					window->UnPrepare();
					window->Update();
					window->Prepare();

					if (StillDown() && MouseMoved(kTrackAll)) {
						extern		EventRecord		gEvent;
						Boolean		copyTranslateB	= (**gPrefsH).detokenizeB;
						
						window->UnPrepare();
						
						if (check_key_down(option_key)) {
							copyTranslateB = !copyTranslateB;
						}
						
						SetCopyTranslated(copyTranslateB);
						
						if (DragItem(&gEvent) != noErr) {
							SetCopyTranslated((**gPrefsH).detokenizeB);
						}
					}
				}
			}
			break;
		}
		
		default: {
			window->MarqueeSelect(thePoint, modifiers);
			break;
		}
	}
}

CFinderWindow		*CEntry::GetMyWindow(void)
{
	CFinderWindow	*window = NULL;
	
	switch (i_type) {

		case FSObject_ROOT_FOLDER: {
			window = gDesktop->i_window;
			break;
		}

		case FSObject_FOLDER:
		case FSObject_DISK: {
			window = i_window;
			break;
		}

		case FSObject_DISK_ROOT_FOLDER: {
			window = i_cDisk.gen->i_window;
			break;
		}
	}
		
	if (!window) {
		window = GetEnclosingWindow();
	}
	
	return window;
}

CFinderWindow		*CEntry::GetEnclosingWindow(void)
{
	CFinderWindow	*window = NULL;
	
	switch (i_type) {

		case FSObject_ROOT_FOLDER: {
			window = gDesktop->i_window;
			break;
		}

		case FSObject_DISK: {
			window = i_cDisk.gen->i_desktop->i_window;
			break;
		}

		case FSObject_DISK_ROOT_FOLDER: {
			if (i_cDisk.gen->i_window) {
				window = i_cDisk.gen->i_window;
			} else {
				window = i_cDisk.gen->GetEnclosingWindow();
			}
			break;
		}

		default: {
			CFolder		*folderP = GetParentFolder();
			
			if (folderP) {
				if (folderP->i_window) {
					window = folderP->i_window;
				} else {
					window = folderP->GetEnclosingWindow();
				}
			}
			break;
		}
	}
		
	if (!window) {
		ReportError(IC_Err_YOU_WILL_CRASH);
	}
	
	return window;
}

char			*CEntry::GetName(char *buf)
{
	GetEntryTopic(this)->O_GetName(buf);
	return buf;
}

void			CEntry::SetName(char *buf)
{
	ASSERT(GetEntryTopic(this));
	(void)GetEntryTopic(this)->O_SetName(buf);
}

char			*CEntry::GetDescription(char *buf)
{
	if (IsGraphic()) {
		strcpy(buf,
			ADFS_Str((ADFS_StrType)
				(ADFS_Str_HGR + (i_fileType - ADFS_File_HGR))));
	} else {
		strcpy(buf, "An interesting file");
	}
	
	return buf;
}

Boolean			CEntry::IsTrashed(void)
{
	return FALSE;
}

void			CEntry::SetTrashed(Boolean trash)
{
}

Boolean			CEntry::IsLocked(void)
{
	Boolean		isLockedB	= TRUE;
	
	if (IS_ImageRec_PHYSICAL(i_cDisk.gen->i_imageRec)) {
		isLockedB = ImageRec_VolRec(i_cDisk.gen->i_imageRec).phys.lockedB;
	} else if (IS_ImageRec_URL(i_cDisk.gen->i_imageRec)) {
		isLockedB = TRUE;
	} else {
		Gen_AccessBits		bits;
		
		GetAccessBits(&bits);
		
		if (bits.writeEnable) {
			(void)FSpGetFileLock(&ImageRec_VolRec(i_cDisk.gen->i_imageRec).image.fileSpec, &isLockedB);
		}
	}
	
	return isLockedB;
}

void			CEntry::SetLocked(Boolean lock)
{
}

char		*GetTimeString(
	DateTimeRec		*dtP,
	char			*buf, 
	DateForm		form = abbrevDate);

char		*GetTimeString(
	DateTimeRec		*dtP,
	char			*buf, 
	DateForm		form)
{
	unsigned long	dateSecs;
	Str255			dateStr, timeStr;
	char			*dateStrC = (char *)&dateStr, *timeStrC = (char *)&timeStr;
	
	DateToSeconds(dtP, &dateSecs);
	
	if (DateIsNull(dtP)) {
		CopyString(c2p("-"), dateStr);
	} else {
		DateString(dateSecs, form, dateStr, NULL);
	}

	if (TimeIsNull(dtP)) {
		CopyString(c2p("-"), timeStr);
	} else {
		TimeString(dateSecs, FALSE, timeStr, NULL);
	}
	
	CopyPascalStringToC(dateStr, dateStrC);
	CopyPascalStringToC(timeStr, timeStrC);
	
	if (dateStrC[0] == '-') {
		sprintf(buf, "%s", timeStrC);
	} else if (timeStrC[0] == '-') {
		sprintf(buf, "%s", dateStrC);
	} else {
		sprintf(buf, "%s, %s", dateStrC, timeStrC);
	}
	
	return buf;
}

DateTimeRec		*CEntry::GetCreatedTime(DateTimeRec *dt)
{
	*dt = g_nullDateTime;
	
	return dt;
}

char			*CEntry::GetCreatedTimeString(char *buf)
{
	DateTimeRec		dt;

	GetCreatedTime(&dt);
	return GetTimeString(&dt, buf);
}

void			CEntry::SetCreatedTime(DateTimeRec *dt)
{
}

DateTimeRec		*CEntry::GetModifiedTime(DateTimeRec *dt)
{
	*dt = g_nullDateTime;
	
	return dt;
}

char			*CEntry::GetModifiedTimeString(char *buf)
{
	DateTimeRec		dt;

	GetModifiedTime(&dt);
	return GetTimeString(&dt, buf);
}

void			CEntry::SetModifiedTime(DateTimeRec *dt)
{
}

void			CEntry::SetTimeStamps(DateTimeRec *creDate, DateTimeRec *modDate)
{
	SetCreatedTime(creDate);
	SetModifiedTime(creDate);
}

void			CEntry::GetTimeStamps(DateTimeRec *creDate, DateTimeRec *modDate)
{
	GetCreatedTime(creDate);
	GetModifiedTime(creDate);
}

ulong			CEntry::GetLogicalSize(void)
{
	return 0;
}

void			CEntry::SetLogicalSize(ulong size)
{
}
	
ulong			CEntry::GetPhysicalSize(void)
{
	return 0;
}

void			CEntry::SetPhysicalSize(ulong size)
{
}

ADFS_IconType			CEntry::GetIconType(void)
{
	return 0;
}

/*
	Also defined:
	
	#define	ApplyToSelection(_ct, _cd)		ApplyToItems(O_Iterate_SELECTED, _ct, _cd)
	#define	ApplyToOnScreenItems(_ct, _cd)	ApplyToItems(O_Iterate_ONSCREEN, _ct, _cd)
*/
void			CEntry::ApplyToItems(
	O_IterateType	iterateType, 
	O_CBType		cbType, 
	void			*cbData
) {
	UpdateGlobals();

	GetEntryTopic(this)->O_ApplyToItems(
		iterateType, 
		cbType, 
		(O_CBDataP *)cbData, 
		TRUE, !g_isIconView);
}

CFolder		*CEntry::GetParentFolder(void)
{
	CEntry		*parentP = GetParent();
	
	if (parentP && parentP->i_type == FSObject_DISK) {
		parentP = ((CDisk *)parentP)->i_rootDir.gen;
		ASSERT(parentP->i_type == FSObject_DISK_ROOT_FOLDER);
	}
	
	return (CFolder *)parentP;
}

CEntry		*CEntry::GetParent(void)
{
	CEntry			*entryP = NULL;
	
	if (i_topicRef.cTopic) {
		OSErr			err;
		O_CTopic		*cTopic;
		
		err = i_topicRef.cTopic->O_GetParent(&cTopic);
		if (err) {
			ReportError(err);
		} else if (cTopic) {
			entryP = GetTopicEntry(cTopic);
			ASSERT(entryP->i_type == FSObject_DISK
				|| entryP->i_type == FSObject_ROOT_FOLDER
				|| entryP->i_type == FSObject_FOLDER);
		}
	}

	return entryP;
}

Gen_AccessBits		Gen_kAccess_UNLOCKED	= { 1, 1, 0, 0, 1, 1 };

void			CEntry::GetAccessBits(Gen_AccessBits *bits)
{
	//	override me
	*bits = Gen_kAccess_UNLOCKED;
}

void			CEntry::SetAccessBits(Gen_AccessBits *bits)
{
	InvalStat(ADFS_Stat_ICON);
}

void			CEntry::SetTwirled(Boolean twirledB)
{
	if (twirledB) {
		UpdateSort(TRUE);
	}
}

Boolean			CEntry::GetTwirled(void)
{
	return FALSE;
}

char	gSeparatorAC[5] = ": ";

char		*CEntry::GetWhereString(char *buf256)
{
	char	whereBuf[256], myBuf[256];
	
	if (i_type == FSObject_DISK_ROOT_FOLDER) {
		i_cDisk.gen->GetWhereString(whereBuf);
	} else {
		GetParent()->GetWhereString(whereBuf);
	}
	
	GetName(myBuf);
	
	sprintf(buf256, "%s%s%s", whereBuf, gSeparatorAC, myBuf);
	return buf256;
}

char		*CEntry::GetStorageStr(char *buf256)
{
	strcpy(buf256, "n/a");
	return buf256;
}

void		CEntry::DisposeEntryAlloc(Gen_EntryAlloc *sectorListP)
{
	if (sectorListP) {
		ushort				sectorTypeS;
		
		for (
			sectorTypeS = Gen_Alloc_NONE; 
			sectorTypeS < Gen_Alloc_NUMTYPES;
			sectorTypeS++
		) {
			if (sectorListP->type[sectorTypeS].u.ptr) {
				// must drive list, dispose of entry sectors == Gen_Alloc_MULTI
				TrackDisposePtr(sectorListP->type[sectorTypeS].u.ptr);
			}
		}

		TrackDisposePtr((Ptr)sectorListP);
	}
}

OSErr		CEntry::GetEntryAlloc(
	Boolean			getAsBlocksB, 
	Gen_EntryAlloc	**sectorListH)
{
	return memFullErr;
}

CRenameTextEdit		*CEntry::IsThisRename(void)
{
	CRenameTextEdit		*renameTE;
	CEntry				*renameEntryP = NULL;
	long				nothingL;
	
	renameTE = CRenameTextEdit::GetCurTextEdit();
	
	if (renameTE) {
		renameTE->GetCBData((void **)&renameEntryP, &nothingL);
	}
	
	if (renameEntryP != this) {
		renameTE = NULL;
	}
	
	return renameTE;
}

Boolean		CEntry::CanRename(void)
{
	return TRUE;
}

void		CEntry::Rename(void)
{
	if (IsLocked() || !CanRename()) {
		SysBeep(1);
	} else {
		char				bufAC[256];
		Rect				statRect, statItemRect, leftBuf, rightBuf; 
		CFinderWindow		*finderWindowP = GetEnclosingWindow();
		
		finderWindowP->Prepare();
		
		UpdateGlobals();

		GetStatStringInfo(
			ADFS_Stat_NAME, bufAC, &statRect, 
			&statItemRect, &leftBuf, &rightBuf);
		
		statItemRect.right = rightBuf.right - 2;
		statItemRect.top++;
		statItemRect.left++;
		
		GetName(bufAC);
		finderWindowP->i_renameTE = GetNewRenameTextEdit(
			bufAC, &statItemRect, 256, 	//	get max name len
			CEntry_S_CB_FinishRename, 
			this, 0);
		
		finderWindowP->UnPrepare();
	}
}

//	static
void		CEntry::CEntry_S_CB_FinishRename(void *cbData)
{
	CEntry	*thiz = (CEntry *)cbData;
	
	thiz->FinishRename();
}

void		CEntry::FinishRename(void)
{
	CRenameTextEdit		*renameTE	= GetEnclosingWindow()->i_renameTE;
	
	ASSERT(renameTE);
	if (!renameTE) {
		renameTE = CRenameTextEdit::GetCurTextEdit();
	}
	
	if (renameTE) {
		Rect				theRect		= renameTE->GetViewRectFrame();
		char				bufAC[256];
		
		GetEnclosingWindow()->i_renameTE = NULL;
		
		InvalWindowRect(
			GetEnclosingWindow()->GetWindowRef(), 
			&theRect);
		
		renameTE->GetText(bufAC);
		SetName(bufAC);

		renameTE->Dispose();
	}
}

OSErr		CEntry::Duplicate(void)
{
	return noErr;
}

CEntry		*CEntry::NextEntry(void)
{
	OSErr		err = noErr;
	CEntry		*nextEntryP = NULL;
	O_CTopic *topicP;
	
	topicP = GetEntryTopic(this);
	err = topicP == NULL;
	
	if (!err && topicP) err = topicP->O_GetNextSister(&topicP);
	if (!err && topicP) {
		nextEntryP = GetTopicEntry(topicP);
	}
	
	return nextEntryP;
}

Boolean		CEntry::IsForked(void)
{
	return FALSE;
}

OSErr		CEntry::GetForkInfo(CCT_ForkInfo *forkInfoP)
{
	return ASSERT(IsForked());
}

OSErr		CEntry::SetForkInfo(CCT_ForkInfo *forkInfoP)
{
	return ASSERT(IsForked());
}

void		CEntry::GetPreview(ADFS_PreviewRec *previewRecP)
{
	structclr(*previewRecP);
}

Boolean		CEntry::IsDeleted(void)
{
	return FALSE;
}

Boolean		CEntry::IsGraphic(void)
{
	return i_fileType == ADFS_File_HGR
		|| i_fileType == ADFS_File_DHGR_DAZ
		|| i_fileType == ADFS_File_DHGR_BEAGLE;
}

Boolean		CEntry::IsTranslatable(void)
{
	return i_fileType == ADFS_File_TEXT
		|| i_fileType == ADFS_File_BASIC
		|| i_fileType == ADFS_File_INTBASIC
		|| i_fileType == ADFS_File_AWP
		|| i_fileType == ADFS_File_BINARY;
}

void		CEntry::Open(void)
{
	if (i_type == FSObject_FILE) {
		ASSERT("missing override" == NULL);
	} else {
		if (!i_window) {
			//	changes the port!!
			i_window = MakeNewFolderWindow(&i_topicRef);
			
			SetPortWindowPort(GetEnclosingWindow()->GetWindowRef());

			if (!i_window) {
				ReportError(IC_Err_OUT_OF_MEMORY);
			} else {
				Boolean		down = FALSE;
				
				GetEntryTopic(this)->O_IsTwirledDown(NULL, &down);
			}
		}

		if (i_window) {
			i_window->Show(TRUE);
		}
	}
}

OSErr		CEntry::ToggleDeletedFiles(void)
{
	return noErr;
}

O_TopicIndex		CEntry::GetEntryIndex(void)
{
	O_TopicIndex	indexL;
	
	(void)GetEntryTopic(this)->O_GetTopicIndex(&indexL);
	
	return indexL;
}

OSErr		CEntry::UpdateSort(Boolean recursiveB)
{
	return noErr;
}

OSErr		CEntry::Reorder(
	O_TopicIndex	oldIndex,
	O_TopicIndex	newIndex)
{
	OSErr		err = noErr;
	
	err = GetEntryTopic(this)->O_Reorder(oldIndex, newIndex);

	GetMyWindow()->InvalWindow(WindowRect_INTERIOR);
	
	return err;
}
