void CPrefabsDlg::OnExportobject() 
{
	int iIndex = m_Objects.GetNextItem(-1, LVNI_SELECTED);
	while(iIndex != -1)
	{
		CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(iIndex));
		if(pPrefab)
		{
			// export it
			CString strFilename;
			strFilename = pPrefab->GetName();
			CFileDialog dlg(FALSE, "map", strFilename, OFN_HIDEREADONLY | 
				OFN_OVERWRITEPROMPT, "Map files|*.map;*.rmf|", this);
			if(dlg.DoModal() == IDCANCEL)
				return;	// nevermind
			strFilename = dlg.GetPathName();

			int iPos = strFilename.Find('.');
			DWORD dwFlags = CPrefab::lsRMF;
			if(iPos != -1)
			{
				char *p = strFilename.GetBuffer(0);
				if(!strnicmp(p+iPos+1, "map", 3))
					dwFlags = CPrefab::lsMAP;
			}

			pPrefab->Save(strFilename, dwFlags);
		}
		// get next item
		iIndex = m_Objects.GetNextItem(iIndex, LVNI_SELECTED);
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pPrefab - 
//-----------------------------------------------------------------------------
void CPrefab::AddMRU(CPrefab *pPrefab)
{
	if(!bCacheEnabled)
		return;

	POSITION p = MRU.Find(pPrefab);
	if(p)
	{
		// remove there and add to head
		MRU.RemoveAt(p);
	}
	else if(MRU.GetCount() == 5)
	{
		// uncache tail object
		p = MRU.GetTailPosition();
		if(p)	// might not be any yet
		{
			CPrefab *pUncache = MRU.GetAt(p);
			pUncache->FreeData();
			MRU.RemoveAt(p);
		}
	}

	// add to head
	MRU.AddHead(pPrefab);
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CPrefab::FreeAllData()
{
	// free all prefab data memory
	POSITION p = PrefabList.GetHeadPosition();
	while(p)
	{
		CPrefab *pPrefab = PrefabList.GetNext(p);
		pPrefab->FreeData();
	}
}
void CPrefabsDlg::OnEndlabeleditObjects(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
	LV_ITEM &item = pDispInfo->item;
	
	*pResult = 0;

	if(item.pszText == NULL)
		return;

	CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(item.iItem));
	pPrefab->SetName(item.pszText);
	m_Objects.SetItemText(item.iItem, 0, item.pszText);
	bCurLibraryModified = TRUE;
}
void CPrefabsDlg::SetCurObject(int iItem)
{
	iCurObject = iItem;

	if(iCurObject == -1)
	{
		m_ObjectNotes.SetWindowText("");
		return;
	}

	// update data..
	CPrefab *pPrefab = CPrefab::FindID(m_Objects.GetItemData(iCurObject));
	Assert(pPrefab);

	m_ObjectNotes.SetWindowText(pPrefab->GetNotes());
}
void CPrefabsDlg::EditObjectInfo()
{
	int iSel;
	CPrefab *pPrefab = GetCurrentObject(&iSel);

	CEditPrefabDlg dlg;
	dlg.m_strName = pPrefab->GetName();
	dlg.m_strDescript = pPrefab->GetNotes();

	dlg.SetRanges(500, -1);

	if(dlg.DoModal() == IDCANCEL)
		return;

	pPrefab->SetName(dlg.m_strName);
	pPrefab->SetNotes(dlg.m_strDescript);

	AddToObjectList(pPrefab, iSel, TRUE);
	bCurLibraryModified = TRUE;
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pszFilename - 
//			bIndexOnly - 
// Output : int
//-----------------------------------------------------------------------------
int CPrefabLibraryRMF::Save(LPCTSTR pszFilename, BOOL bIndexOnly)
{
	// temp storage
	static char szFile[MAX_PATH];

	// if only saving index, special code -
	if(bIndexOnly && m_file.is_open())
	{
		// close file, reopen in binary write
		m_file.close();
		if(Prefabs.GetCount())
		{
			// change size of file first
			int iHandle = _open(m_strOpenFileName, _O_BINARY | _O_WRONLY);
			_chsize(iHandle, m_dwDirOffset);
			_close(iHandle);
		}

		fstream file(m_strOpenFileName, ios::binary | ios::out);

		// write string header
		file << pLibHeader;
		// write binary header (in case notes have changed)
		PrefabLibraryHeader plh;
		plh.dwNumEntries = Prefabs.GetCount();
		plh.fVersion = fLibVersion;
		plh.dwDirOffset = m_dwDirOffset;
		strcpy(plh.szNotes, szNotes);
		file.write((char*)&plh, sizeof plh);

		// recreate a directory and write it
		PrefabHeader *ph = new PrefabHeader[Prefabs.GetCount()];
		int iCur = 0;

		POSITION p = Prefabs.GetHeadPosition();
		while(p)
		{
			CPrefab *pPrefab = Prefabs.GetNext(p);

			// setup this dir entry
			ph[iCur].dwOffset = pPrefab->dwFileOffset;
			ph[iCur].dwSize = pPrefab->dwFileSize;
			strcpy(ph[iCur].szName, pPrefab->GetName());
			strcpy(ph[iCur].szNotes, pPrefab->GetNotes());
			ph[iCur].iType = pPrefab->GetType();

			++iCur;	// increase current directory entry
		}

		// write directory
		file.seekp(m_dwDirOffset);
		file.write((char*)ph, sizeof(*ph) * Prefabs.GetCount());
		file.close();

		// re-open
		m_file.open(m_strOpenFileName, ios::in | ios::binary | ios::nocreate);
		return 1;
	}

	if(pszFilename == NULL)
	{
		pszFilename = szFile;

		if(m_strOpenFileName.IsEmpty())
		{
			char szNewFilename[MAX_PATH];
			CWorldcraft *pApp = (CWorldcraft*) AfxGetApp();
			pApp->GetDirectory(DIR_PREFABS, szNewFilename);

			sprintf(szNewFilename + strlen(szNewFilename), "\\%s.ol", m_szName);

			// make a name
			m_strOpenFileName = szNewFilename;
		}

		strcpy(szFile, m_strOpenFileName);
	}
	else
	{
		strcpy(szFile, pszFilename);
		SetNameFromFilename(pszFilename);
	}

	// open temp file to save to.. then delete & rename old one.
	CString strTempFileName = "Temporary Prefab Library.$$$";
	fstream file;
	file.open(strTempFileName, ios::binary | ios::out);

	// write string header
	file << pLibHeader;

	// write binary header
	// save current position so we can seek back and rewrite it
	DWORD dwBinaryHeaderOffset = file.tellp();
	PrefabLibraryHeader plh;
	plh.dwNumEntries = Prefabs.GetCount();
	plh.fVersion = fLibVersion;
	strcpy(plh.szNotes, szNotes);
	file.write((char*)&plh, sizeof plh);

	// allocate memory for directory
	PrefabHeader *ph = new PrefabHeader[plh.dwNumEntries];
	int iCur = 0;

	char *pCopyBuf = new char[64000];

	// write each prefab
	POSITION p = Prefabs.GetHeadPosition();
	while (p)
	{
		CPrefabRMF *pPrefab = (CPrefabRMF *)Prefabs.GetNext(p);

		// setup this dir entry
		ph[iCur].dwOffset = file.tellp();
		strcpy(ph[iCur].szName, pPrefab->GetName());
		strcpy(ph[iCur].szNotes, pPrefab->GetNotes());
		ph[iCur].iType = pPrefab->GetType();

		if(pPrefab->IsLoaded())
		{
			// it's loaded - save in native method
			pPrefab->Save(file, CPrefab::lsUpdateFilePos);
		}
		else
		{
			// it's not loaded - save with quick method by copying
			// bytes directly from the existing file
			ASSERT(m_file.is_open());
			m_file.seekg(pPrefab->dwFileOffset);
			DWORD dwToRead = 64000, dwCopied = 0;
			while(dwToRead == 64000)
			{
				if(dwCopied + dwToRead > pPrefab->dwFileSize)
					dwToRead = pPrefab->dwFileSize - dwCopied;
				m_file.read(pCopyBuf, dwToRead);
				file.write(pCopyBuf, dwToRead);
				dwCopied += dwToRead;
			}
		}

		// set offset info HERE because we might use it above
		pPrefab->dwFileOffset = ph[iCur].dwOffset;

		// set size info
		ph[iCur].dwSize = pPrefab->dwFileSize = 
			file.tellp() - ph[iCur].dwOffset;

		++iCur;	// increase current directory entry
	}

	// delete copy buf
	delete[] pCopyBuf;

	// rewrite binary header
	plh.dwDirOffset = m_dwDirOffset = file.tellp();
	file.seekp(dwBinaryHeaderOffset);
	file.write((char*)&plh, sizeof(plh));
	file.seekp(0, ios::end);

	// write directory
	file.write((char*)ph, sizeof(*ph) * plh.dwNumEntries);
	file.close();	// close temp file
	
	// delete original and rename
	m_file.close();	// might already be open.. might not.
	remove(m_strOpenFileName);

	m_strOpenFileName = szFile;
	int iRvl = rename(strTempFileName, m_strOpenFileName);
	
	// reopen original
	m_file.open(m_strOpenFileName, ios::in | ios::binary | ios::nocreate);

	return 1;
}