// MultitronDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Multitron.h"
#include "MultitronDlg.h"
#include "MainFrm.h"
#include "TextureDoc.h"

#include <GameOs\TooLOS.hpp>
#include <imagelib\image.h>
#include <direct.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMultitronDlg dialog


CMultitronDlg::CMultitronDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMultitronDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CMultitronDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_pDocument = NULL;
	m_pNoteFile = NULL;
}


void CMultitronDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMultitronDlg)
	DDX_Control(pDX, IDC_PREVIEW_USED, m_wndPreviewUsed);
	DDX_Control(pDX, IDC_PREVIEW_UNUSED, m_wndPreviewUnused);
	DDX_Control(pDX, IDC_LIST_USED, m_wndUsed);
	DDX_Control(pDX, IDC_LIST_UNUSED, m_wndUnused);
	DDX_Control(pDX, IDC_USED_IMAGEPROP, m_wndUsedImageProp);
	DDX_Control(pDX, IDC_UNUSED_IMAGEPROP, m_wndUnusedImageProp);
	DDX_Control(pDX, IDC_CHECK_SHOWSEUDO, m_checkShowSeudo);
	DDX_Control(pDX, IDC_CHECK_SEARCHSUB, m_checkSearchSubDir);
	DDX_Control(pDX, IDC_CHECK_SHOWMIPMAP, m_checkShowMipmap);
	DDX_Control(pDX, IDC_CHECK_SHOWSOLID, m_checkShowSolid);
	DDX_Control(pDX, IDC_CHECK_SHOWALPHA, m_checkShowAlpha);
	DDX_Control(pDX, IDC_CHECK_PREVIEWALPHA, m_checkPreviewAlpha);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CMultitronDlg, CDialog)
	//{{AFX_MSG_MAP(CMultitronDlg)
	ON_WM_DRAWITEM()
	//ON_WM_CONTEXTMENU()
	ON_LBN_SELCHANGE(IDC_LIST_UNUSED, OnSelchangeListUnused)
	ON_LBN_SELCHANGE(IDC_LIST_USED, OnSelchangeListUsed)
	ON_BN_CLICKED(IDC_CHECK_PREVIEWALPHA, OnCheckPreviewAlpha)
	ON_BN_CLICKED(IDC_CHECK_SHOWSEUDO, UpdateUsedList)
	ON_BN_CLICKED(IDC_CHECK_SHOWMIPMAP, UpdateUsedList)
	ON_BN_CLICKED(IDC_CHECK_SHOWSOLID, UpdateUsedList)
	ON_BN_CLICKED(IDC_CHECK_SHOWALPHA, UpdateUsedList)
	ON_BN_CLICKED(IDC_CHECK_SEARCHSUB, FindAllTextures)
	ON_COMMAND(ID_DELETEFROMDISK, OnDeleteTextureFromDisk)
	ON_COMMAND(ID_ADD_MEGATEXTURE, OnAddMegatexture)
	ON_COMMAND(ID_ADD_TEXTUREHINT, OnAdd)
	ON_COMMAND(ID_REMOVE_TEXTUREHINT, OnRemove)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMultitronDlg message handlers

/*******************************************************************************
/* function name: OnInitialUpdate
/* description: Called when window is displayed for the first time, 
/*	set up window size and position
/*******************************************************************************/
BOOL CMultitronDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();

	m_checkShowSolid.SetCheck(true);
	m_checkShowAlpha.SetCheck(true);
	
	FindTextures("content\\textures\\");
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

/*******************************************************************************
/* function name: OnDrawItem
/* description: Draw the preview bitmaps for selected textures
/*******************************************************************************/
void CMultitronDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	switch (lpDrawItemStruct->CtlID)
	{
	case IDC_PREVIEW_UNUSED:
		{
			HBITMAP hBitmap = m_bmUnused;
			if (hBitmap)
			{
				CDC  memDC;
				int res;
				
				BITMAP bmp;
				res=m_bmUnused.GetBitmap(&bmp);
				Verify(res);
				
				BOOL bres;
				CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
				bres=memDC.CreateCompatibleDC(pDC);
				Verify(bres);
				memDC.SelectObject(&m_bmUnused);
				CRect hfrct;
				m_wndPreviewUnused.GetClientRect(&hfrct);

				pDC->SetStretchBltMode(COLORONCOLOR);
				bres=pDC->StretchBlt(0,0,hfrct.Width(),hfrct.Height(),&memDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);

				//bres=pDC->BitBlt(0,0,hfrct.Width(),hfrct.Height(),NULL,0,0,BLACKNESS);
				//bres=pDC->BitBlt(0,0,hfrct.Width(),hfrct.Height(),&memDC,0,0,SRCCOPY);
				Verify(bres);
				memDC.DeleteDC();
			}
			return;
		}
	case IDC_PREVIEW_USED:
		{
			HBITMAP hBitmap = m_bmUsed;
			if (hBitmap)
			{
				CDC  memDC;
				int res;
				
				BITMAP bmp;
				res=m_bmUsed.GetBitmap(&bmp);
				Verify(res);
				
				BOOL bres;
				CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
				bres=memDC.CreateCompatibleDC(pDC);
				Verify(bres);
				memDC.SelectObject(&m_bmUsed);
				CRect hfrct;
				m_wndPreviewUnused.GetClientRect(&hfrct);

				pDC->SetStretchBltMode(COLORONCOLOR);
				bres=pDC->StretchBlt(0,0,hfrct.Width(),hfrct.Height(),&memDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);

				//bres=pDC->BitBlt(0,0,hfrct.Width(),hfrct.Height(),NULL,0,0,BLACKNESS);
				//bres=pDC->BitBlt(0,0,hfrct.Width(),hfrct.Height(),&memDC,0,0,SRCCOPY);
				Verify(bres);
				memDC.DeleteDC();
			}
			return;
		}
	}
	CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
}

/*******************************************************************************
/* function name: OnSelchangeListUnused
/* description: Selection changed in the unused texture list, load the texture
/*	and update the preview bitmap
/*******************************************************************************/
void CMultitronDlg::OnSelchangeListUnused() 
{
	m_wndPreviewUnused.Invalidate();

	int count = m_wndUnused.GetSelCount();
	GetDlgItem(ID_ADD_MEGATEXTURE)->EnableWindow(count>1);
	if (count == 0) {
		GetDlgItem(ID_ADD_TEXTUREHINT)->EnableWindow(false);
		GetDlgItem(ID_DELETEFROMDISK)->EnableWindow(false);
		return;
	}
	GetDlgItem(ID_ADD_TEXTUREHINT)->EnableWindow(true);
	GetDlgItem(ID_DELETEFROMDISK)->EnableWindow(true);


	int *items = new int[count];
	m_wndUnused.GetSelItems(count,items);
	
	int x = count-1;
	CString name;
	m_wndUnused.GetText(items[x],name);
	name.TrimLeft();
	name = "content\\textures\\"+name;
	
	Image image;
	CString fullname = name+".png";
	if (gos_DoesFileExist(fullname))
	{
		image.Load((char *)(LPCTSTR)fullname);
	}
	else
	{
		fullname = name+".tga";
		if (gos_DoesFileExist(fullname))
		{
			image.Load((char *)(LPCTSTR)fullname);
		}
		else
		{
			delete[] items;
			return;
		}
	}

	delete[] items;

	bool bPreviewAlpha = m_checkPreviewAlpha.GetCheck()?true:false;
	UpdateImageBitmap(&m_bmUnused, &image, bPreviewAlpha);
	UpdateImageProp(&m_wndUnusedImageProp, &image);
}

/*******************************************************************************
/* function name: OnSelchangeListUsed
/* description: Selection changed in the used texture list, load the texture
/*	and update the preview bitmap
/*******************************************************************************/
void CMultitronDlg::OnSelchangeListUsed() 
{
	m_wndPreviewUsed.Invalidate();

	int count = m_wndUsed.GetSelCount();
	if (count == 0) {
		GetDlgItem(ID_REMOVE_TEXTUREHINT)->EnableWindow(false);
		return;
	}
	GetDlgItem(ID_REMOVE_TEXTUREHINT)->EnableWindow(true);

	OnEditTextureHint();

	bool bPreviewAlpha = m_checkPreviewAlpha.GetCheck()?true:false;
	CDocument* pDoc = m_pDocument->GetTextureDoc();
	if (pDoc) {
		CTextureDoc* pTextureDoc = (CTextureDoc*) pDoc;
		Image* pImage = pTextureDoc->GetImage(0);
		
		int *items = new int[count];
		m_wndUsed.GetSelItems(count,items);
		Stuff::Page *page = (Stuff::Page *)m_wndUsed.GetItemData(items[0]);
		Check_Object(page);
		
		UpdateImageBitmap(&m_bmUsed, pImage, bPreviewAlpha);
		UpdateImageProp(&m_wndUsedImageProp, pImage, page);
		delete[] items;
	}
}

/*******************************************************************************
/* function name: OnAdd
/* description: Add seleted textures from the unused list to hint file, and update
/*	used and unused texture lists
/*******************************************************************************/
void CMultitronDlg::OnAdd() 
{
	int count = m_wndUnused.GetSelCount();
	if (count == 0)
		return;

	int *items = new int[count];
	CString *strings = new CString[count];
	CPtrList listNewPages;

	m_wndUnused.GetSelItems(count,items);

	for (int x=0;x<count;x++)
	{
		m_wndUnused.GetText(items[x], strings[x]);
	}

	// Delete the textures from the unused list
	for (x=0;x<count;x++)
	{
		m_wndUnused.DeleteString(m_wndUnused.FindStringExact(items[0], strings[x]));
	}

	// Add the textures the hint file
	Stuff::NotationFile *pFile = m_pNoteFile;		
	for (x=0;x<count;x++)
	{
		Stuff::Page *page = pFile->AddPage(strings[x]);
		Check_Object(page);
		listNewPages.AddTail((LPVOID)page);

		// If the texture's name ends with a number, 
		// then it is most likely an explicit mipmap
		if (strings[x].GetAt(strings[x].GetLength()-1) <= '9' &&
			strings[x].GetAt(strings[x].GetLength()-1) >= '0')
			page->SetEntry("mipmap", "explicit");
	}
	
	// Update the used list
	m_pDocument->UpdateAllViews(NULL, 0, NULL);

	// Select the first hint in the list that has just been added
	int index = m_wndUsed.FindStringExact(0, strings[0]);
	if (index>=0) {
		m_wndUsed.SetSel(-1, false);
		m_wndUsed.SetSel(index, true);
		OnSelchangeListUsed();
	}

	// Update selection in the unused list
	m_wndUnused.SetSel(items[0], true);
	OnSelchangeListUnused();
	
	delete[] items;
	delete[] strings;
}

/*******************************************************************************
/* function name: OnRemove
/* description: Remove seleted texture hints from the to hint file, and update
/*	used and unused texture lists
/*******************************************************************************/
void CMultitronDlg::OnRemove() 
{
	int count = m_wndUsed.GetSelCount();
	if (count == 0)
		return;

	int *items = new int[count];
	CString *strings = new CString[count];

	m_wndUsed.GetSelItems(count,items);

	// Remove the textures from the used list, and the hint file
	for (int x=0;x<count;x++)
	{
		m_wndUsed.GetText(items[x], strings[x]);
		Stuff::Page *page = (Stuff::Page *)m_wndUsed.GetItemData(items[x]);
		if (page) {
			Check_Object(page);
			CString name = m_pDocument->RemoveTexture(page);
			m_wndUsed.SetItemData(items[x], NULL);
		}
	}

	// Update the used list and the unused list
	m_pDocument->UpdateAllViews(NULL, 0, NULL);
	m_pDocument->UpdateAllViews(NULL, 1, NULL);

	// Update selection in the unused list
	int index = m_wndUnused.FindStringExact(0, strings[0]);
	if (index>=0) {
		m_wndUnused.SetSel(-1, false);
		m_wndUnused.SetSel(index, true);
		OnSelchangeListUnused();
	}

	// Update selection in the used list
	m_wndUsed.SetSel(items[0], true);
	OnSelchangeListUsed();

	delete[] items;
	delete[] strings;
}

/*******************************************************************************
/* function name: OnDeleteTextureFromDisk
/* description: Delete the select textures from hard disk
/*******************************************************************************/
void CMultitronDlg::OnDeleteTextureFromDisk() 
{
	m_bmUnused.DeleteObject();
	m_wndPreviewUnused.Invalidate();
	int count = m_wndUnused.GetSelCount();
	if (count == 0)
		return;

	if (IDNO == MessageBox("Are you sure you want to DELETE selected files from the DISK?","Confirm File Deletion",MB_ICONWARNING | MB_YESNO))
	{
		return;
	}

	int *items = new int[count];
	m_wndUnused.GetSelItems(count,items);

	for (int x=0;x<count;x++)
	{
		CString name;
		m_wndUnused.GetText(items[x],name);

		name.MakeLower();
		POSITION pos = m_listTextures.Find(name);
		if (pos)
		{
			m_listTextures.RemoveAt(pos);
		}

		name = "content\\textures\\"+name;

		CString fullname = name+".png";
		if (gos_DoesFileExist(fullname))
		{
			gos_DeleteFile(fullname);
		}

		fullname = name+".tga";
		if (gos_DoesFileExist(fullname))
		{
			gos_DeleteFile(fullname);
		}
	}
	delete[] items;
	
	// Update the unused list
	m_pDocument->UpdateAllViews(NULL, 1, NULL);
}

/*******************************************************************************
/* function name: OnEditTextureHint
/* description: Update texture views
/*******************************************************************************/
void CMultitronDlg::OnEditTextureHint() 
{
	int count = m_wndUsed.GetSelCount();
	int *items = new int[count];
	m_wndUsed.GetSelItems(count,items);

	if (m_pDocument->GetTextureDoc()) {
		m_pDocument->GetTextureDoc()->SetPathName(NULL);
	}

	for (int x=0;x<count;x++)
	{
		DWORD data = m_wndUsed.GetItemData(items[x]);
		if (0==x)
			m_pDocument->OpenTexture((Stuff::Page *)data);
		else
			m_pDocument->GetTextureDoc()->SetPathName((LPCTSTR)data);
	}
	delete[] items;
	if (m_pDocument->GetTextureDoc()) {
		m_pDocument->GetTextureDoc()->UpdateAllViews(NULL,0,NULL);
	}
}

/*******************************************************************************
/* function name: UpdateUnusedList
/* description: 
/*******************************************************************************/
void CMultitronDlg::UpdateUnusedList(CObject* pHint)
{
	m_wndUnused.ResetContent();
	POSITION pos = m_listTextures.GetHeadPosition();
	while (pos)
	{
		CString str = m_listTextures.GetNext(pos);

		if (!m_listUsed.Find(str)) {
			m_wndUnused.AddString(str);
		}
	}

	int count = m_wndUnused.GetSelCount();
	if (count == 0) {
		m_wndUnused.SetSel(0, true);
		OnSelchangeListUnused();
	}
}

bool g_bWarnDuplicateAlias = true;
/*******************************************************************************
/* function name: UpdateUsedList
/* description: 
/*******************************************************************************/
void CMultitronDlg::UpdateUsedList(CObject* pHint)
{	
	Stuff::NotationFile *pFile = m_pNoteFile;
	m_wndUsed.ResetContent();
	m_listUsed.RemoveAll();

	m_mapAliasNames.RemoveAll();
	
	CMapStringToOb listMipmaps;

	bool bShowSeudo = m_checkShowSeudo.GetCheck()?true:false;
	bool bShowSolid = m_checkShowSolid.GetCheck()?true:false;
	bool bShowAlpha = m_checkShowAlpha.GetCheck()?true:false;

	Stuff::NotationFile::PageIterator *pages = pFile->MakePageIterator();
	Stuff::Page *page;
	while (NULL != (page = pages->ReadAndNext()))
	{
		CString pagename = page->GetName();
		pagename.MakeLower();

		const char *entry = NULL;

		// Mipmaps are going to be added differently
		// So for now, add them to a table to use later
		if (page->GetEntry("mipmap",&entry)) {
			if (stricmp(entry, "explicit") == 0) {
		        CObject *value;
				if (listMipmaps.Lookup(pagename.Left(pagename.GetLength()-1), value))
				{
					bool bAdded = false;
					CStringList* pMipmaps = (CStringList*)value;

					CString mipmapName = pMipmaps->GetHead();
					if (mipmapName>pagename) {
						bAdded = true;
						pMipmaps->AddHead(pagename);
					}

					POSITION pos = pMipmaps->GetHeadPosition();
					while(pos) {
						if (bAdded)
							break;

						CString mipmapName = pMipmaps->GetNext(pos);
						if (mipmapName>pagename) {
							bAdded = true;
							if (!pos) {
								POSITION temp = pMipmaps->GetTailPosition();
								pMipmaps->InsertBefore(temp, pagename);
							}
							else {
								POSITION temp = pos;
								pMipmaps->GetPrev(temp);
								pMipmaps->InsertBefore(temp, pagename);
							}
						}
					}
					if (!bAdded)
						pMipmaps->AddTail(pagename);
				}
				else
				{
					CStringList* pMipmaps = new CStringList;
					pMipmaps->AddTail(pagename);
					listMipmaps[pagename.Left(pagename.GetLength()-1)] = pMipmaps;
				}				
			}
		}

		// If it has an alias, then add it to a alias list that'll be used later
		if (page->GetEntry("Alias",&entry))
		{
			CString aliasName(entry);
			aliasName.MakeLower();

			CString originalName;
			if (m_mapAliasNames.Lookup(aliasName,originalName) && g_bWarnDuplicateAlias)
				MessageBox(CString("Two or more textures are using the same alias ")+entry, "Error!", MB_OK);

			m_mapAliasNames[aliasName]=pagename;
		}

		// Could be a megatexture
		else {
			Stuff::Page::NoteIterator *noteIt = page->MakeNoteIterator();
			Stuff::Note *note;
			
			while ((note = noteIt->ReadAndNext()) != NULL)
			{
				const char *name = NULL;
				const char *entry = NULL;
				note->GetEntry(&entry);
				name = note->GetName();
				int x, y;
				int param_count = sscanf(entry, "%d %d", &x, &y);
				if (param_count==2 && stricmp(name, "PageSize")) {
					CString originalName;
					if (m_mapAliasNames.Lookup(entry,originalName))
						MessageBox(CString("Two or more textures are using the same alias ")+entry, "Error!", MB_OK);
					m_mapAliasNames[pagename]=name;
					break;
				}
			}
			delete noteIt;
		}
	}

	delete pages;
	pages = pFile->MakePageIterator();
	while (NULL != (page = pages->ReadAndNext()))
	{
		CString pagename = page->GetName();
		pagename.MakeLower();
		m_listUsed.AddTail(pagename);

		// Add explicit mipmaps later
		const char *entry = NULL;
		if (page->GetEntry("mipmap",&entry)) {
			if (stricmp(entry, "explicit") == 0)
				continue;
		}

		if (page->GetEntry("Resourcify",&entry))
		{
			// If a non-resourcified / seudo texture
			if (!bShowSeudo && ::stricmp(entry, "false")==0)
				continue;
		}

		if (page->GetEntry("Format",&entry))
		{
			// If a solid texture
			if (::stricmp(entry, "solid")==0) {
				if (!bShowSolid)
					continue;
			}
			// Else if an alpha texture
			else {
				if (!bShowAlpha)
					continue;
			}
		}
		else {
			if (!bShowSolid)
				continue;
		}

		CString textureInfo = pagename;
		CString originalName;
		if (m_mapAliasNames.Lookup(pagename,originalName) && originalName.GetLength())
			textureInfo += "("+originalName+")";

		int index = m_wndUsed.AddString(textureInfo);

		m_wndUsed.SetItemData(index,(DWORD)page);

	}

	// Add the head of explicit mipmaps
    POSITION pos = listMipmaps.GetStartPosition();
    while (pos)
    {
        CObject *pObj;
        CString name;
        listMipmaps.GetNextAssoc(pos,name,pObj);
        
        CStringList *pMipmaps = (CStringList*)pObj;		
		CString mipmapName = pMipmaps->GetHead();
		mipmapName.MakeLower();

		Stuff::Page *page = pFile->FindPage(mipmapName);
		if (page) {

			const char *entry = NULL;
			if (page->GetEntry("Resourcify",&entry))
			{
				// If a non-resourcified / seudo texture
				if (!bShowSeudo && ::stricmp(entry, "false")==0)
					continue;
			}
			
			if (page->GetEntry("Format",&entry))
			{
				// If a solid texture
				if (::stricmp(entry, "solid")==0) {
					if (!bShowSolid)
						continue;
				}
				// Else if an alpha texture
				else {
					if (!bShowAlpha)
						continue;
				}
			}
			else {
				if (!bShowSolid)
					continue;
			}

			CString textureInfo = mipmapName;
			CString originalName;
			if (m_mapAliasNames.Lookup(mipmapName,originalName) && originalName.GetLength())
				textureInfo += "("+originalName+")";

			int index = m_wndUsed.AddString(textureInfo);
			Check_Object(page);
			m_wndUsed.SetItemData(index,(DWORD)page);
		}
	}

	// Add the rest of the mipmaps, which will be indented after the first one
    pos = listMipmaps.GetStartPosition();
    while (pos)
    {
        CObject *pObj;
        CString name;
        listMipmaps.GetNextAssoc(pos,name,pObj);
        
        CStringList *pMipmaps = (CStringList*)pObj;
		int index = m_wndUsed.FindString(0, pMipmaps->RemoveHead());
		if (index >= 0)
			ListExplicitMipmaps(pMipmaps, index);
		delete pMipmaps;
	}

	delete pages;

	int count = m_wndUsed.GetSelCount();
	if (count == 0) {
		m_wndUsed.SetSel(0, true);
		OnSelchangeListUsed();
	}

	g_bWarnDuplicateAlias = false;
}

/*******************************************************************************
/* function name: OnAddMegatexture
/* description: Add a megatexture from multiple unused textures
/*******************************************************************************/
void CMultitronDlg::OnAddMegatexture() 
{
	int nCount = m_wndUnused.GetSelCount();
	if (0==nCount)
		return;
	
	Check_Object(m_pNoteFile);
	
	// Add the hint for the seudo textures
	int *items = new int[nCount];
	CPtrList list;

	m_wndUnused.GetSelItems(nCount,items);
	for (int x=0;x<nCount;x++)
	{
		CString name;
		m_wndUnused.GetText(items[x],name);
		Stuff::Page *page = m_pNoteFile->AddPage(name);
		Check_Object(page);
		page->SetEntry("resourcify","false");
		list.AddTail((LPVOID)page);
	}
	delete[] items;
	
	// Now add the megatexture hint
	Stuff::Page *page = (Stuff::Page *)list.GetHead();
	Check_Object(page);
	
	// Create a megatexture with the name of the first item with underscore first character
	CString meganame = CString("_")+page->GetName();
	meganame.MakeLower();
	if (m_pNoteFile->FindPage(meganame)) {
		MessageBox(meganame + "already exists", "Rename", MB_OK);
	}
	
	// Put all of the textures at 0 0 and let the TextureView arrange them
	Stuff::Page *megapage = m_pNoteFile->AddPage(meganame);
	
	megapage->AppendEntry("PageSize","512 512");
	POSITION pos = list.GetHeadPosition();
	while (pos)
	{
		Stuff::Page *page = (Stuff::Page *)list.GetNext(pos);
		Check_Object(page);
		
		CString name = page->GetName();
		const char *entry;
		if (page->GetEntry("Alias",&entry))
		{
			name = entry;
		}
		megapage->AppendEntry(name,"");
	}
	
	CPtrList listNewPages;
	listNewPages.AddHead((LPVOID)megapage);
	m_pDocument->UpdateAllViews(NULL, 0, NULL);

	int index = m_wndUsed.FindStringExact(0, meganame);
	if (index>=0) {
		m_wndUsed.SetSel(-1, false);
		m_wndUsed.SetSel(index, true);
		OnSelchangeListUsed();
	}
}

/*******************************************************************************
/* function name: OnCheckPreviewAlpha
/* description: 
/*******************************************************************************/
void CMultitronDlg::OnCheckPreviewAlpha()
{
	OnSelchangeListUsed();
	OnSelchangeListUnused();
}

/*******************************************************************************
/* function name: SetDocument
/* description: 
/*******************************************************************************/
CDocument *CMultitronDlg::SetDocument(CMultitronDoc *pDoc)
{
	CMultitronDoc *pBack = m_pDocument;
	if (-1 != (DWORD)pDoc)
		m_pDocument = pDoc;

	m_pNoteFile = m_pDocument->GetHintFile();

	UpdateUsedList();
	UpdateUnusedList();
	return pBack;
}

/*******************************************************************************
/* function name: FindTextures
/* description: 
/*******************************************************************************/
void CMultitronDlg::FindTextures(CString dir)
{
	CFileFind find;
	int icount = 0;
	
	// Find all png texture
	bool bmore = find.FindFile(dir+"*.png")?true:false;
	while (bmore)
	{
		bmore = find.FindNextFile()?true:false;
		CString str = find.GetFilePath();
		str.MakeLower();
		str = str.Left(str.Find("."));
		CString gamePath = str.Left(str.Find("content\\textures\\"));
		if (str.Find("content\\textures\\")>=0)
			str = str.Right(str.GetLength()-strlen(gamePath+"content\\textures\\"));
		m_listTextures.AddTail(str);
		icount++;
	}
	find.Close();

	// Find all tga textures
	bmore = find.FindFile(dir + "*.tga")?true:false;
	while (bmore)
	{
		bmore = find.FindNextFile()?true:false;
		CString str = find.GetFilePath();
		str.MakeLower();
		str = str.Left(str.Find("."));
		CString gamePath = str.Left(str.Find("content\\textures\\"));
		if (str.Find("content\\textures\\")>=0)
			str = str.Right(str.GetLength()-strlen(gamePath+"content\\textures\\"));
		if (!m_listTextures.Find(str))
		{
			m_listTextures.AddTail(str);
		}
		icount++;
	}
	find.Close();

	// Look in sub directories if needed
	if (!m_checkSearchSubDir.GetCheck())
		return;

    HANDLE hfl;
    WIN32_FIND_DATA fd;
    
    if(dir[dir.GetLength()-1]=='\\')
    {
        dir=dir.Left(dir.GetLength()-1);
    }
    
    fd.dwFileAttributes=NULL;
    hfl=FindFirstFile(dir+"\\*.*",&fd);
    
    if(INVALID_HANDLE_VALUE!=hfl)
    {
        do
        {
            if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
            {
                if(strcmp(fd.cFileName,".") && strcmp(fd.cFileName,"..") )
                {
                    FindTextures(dir+"\\"+fd.cFileName+"\\"); 
                }
            }
            
        } while(FindNextFile(hfl,&fd));
    }    
}

/*******************************************************************************
/* function name: FindAllTextures
/* description: 
/*******************************************************************************/
void CMultitronDlg::FindAllTextures()
{
	m_listTextures.RemoveAll();	
	FindTextures("content\\textures\\");
	UpdateUnusedList();
}

/*******************************************************************************
/* function name: ListExplicitMipmaps
/* description: List explicit mipmaps in the used list, ie,
/*	mipmap0
/*		mipmap1
/*		mipmap2
/*		mipmap3
/*******************************************************************************/
void CMultitronDlg::ListExplicitMipmaps(CStringList* pMipmaps, int index)
{
	bool bShowSeudo = m_checkShowSeudo.GetCheck()?true:false;
	bool bShowSolid = m_checkShowSolid.GetCheck()?true:false;
	bool bShowAlpha = m_checkShowAlpha.GetCheck()?true:false;

	POSITION pos = pMipmaps->GetHeadPosition();
	while (pos)
	{
		CString mipmapName = pMipmaps->GetNext(pos);
		Stuff::Page *page = m_pNoteFile->FindPage(mipmapName);
		if (page) {
			
			const char* entry = NULL;
			if (page->GetEntry("Resourcify",&entry))
			{
				// If a non-resourcified / seudo texture
				if (!bShowSeudo && ::stricmp(entry, "false")==0)
					continue;
			}
			
			if (page->GetEntry("Format",&entry))
			{
				// If a solid texture
				if (::stricmp(entry, "solid")==0) {
					if (!bShowSolid)
						continue;
				}
				// Else if an alpha texture
				else {
					if (!bShowAlpha)
						continue;
				}
			}
			else {
				if (!bShowSolid)
					continue;
			}

			if (m_checkShowMipmap.GetCheck()) {
				
				CString textureInfo = CString("   ")+mipmapName;				
				m_wndUsed.InsertString(++index, textureInfo);				
				Check_Object(page);
				m_wndUsed.SetItemData(index,(DWORD)page);
			}
		}
	}
}

/*******************************************************************************
/* function name: UpdateImageProp
/* description: Update image properties in under the preview window
/*******************************************************************************/
void CMultitronDlg::UpdateImageProp(CListBox *pList, Image* pImage, Stuff::Page* pPage)
{
	pList->ResetContent();
	
	if (pImage)
	{
		//Fill in the image properties list
		{
			CString str;
			char title[MAX_PATH];
			char ext[MAX_PATH];
			if (strlen(pImage->GetFileName())) {
				_splitpath(pImage->GetFileName(),NULL,NULL,title,ext);
				str.Format("Filename: %s%s",title,ext);
			}
			else if (pPage) {
				str.Format("Filename: %s%s",pPage->GetName(),".png");
			}
			
			pList->AddString(str);
			
			DWORD dwSize = pImage->GetWidth()*pImage->GetHeight()*pImage->GetBpp();
			dwSize = dwSize>>3;
			//DWORD dwSize = ::gos_FileSize(pImage->GetFileName());
			str.Format("Size: %d bytes",dwSize);
			pList->AddString(str);
			
			str.Format("Res: %dx%dx%dbpp",pImage->GetWidth(),pImage->GetHeight(),pImage->GetBpp());
			switch (pImage->GetIType())
			{
			case ITYPE_RGB:
				{
					str += " RGB";
					break;
				}
			case ITYPE_INDEXED:
				{
					str += " INDEXED";
					break;
				}
			}
			pList->AddString(str);
			
			str.Format("Has Alpha: %s",pImage->HasAlpha()?"true":"false");
			pList->AddString(str);
		}
	}
}

/*******************************************************************************
/* function name: UpdateImageBitmap
/* description: Update image bitmap for the preview window
/*******************************************************************************/
void CMultitronDlg::UpdateImageBitmap(CBitmap* pBitmap, Image* pImage, bool bPreviewAlpha)
{
	if (!pImage || !pBitmap)
		return;

	RGBMask mask;
	if(pImage->GetBpp()==32)
		mask.Set(0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
	else
		mask.Set(0x00ff0000,0x0000ff00,0x000000ff);
	
	pImage->MaskTo(mask);
	
	CDC  memDC,*hfDC;
	hfDC=GetDC();
	
	pBitmap->DeleteObject();
	BOOL bres;
	bres=pBitmap->CreateCompatibleBitmap(hfDC,pImage->GetWidth(),pImage->GetHeight());
	Verify(bres);
	
	memDC.CreateCompatibleDC(hfDC);
	memDC.SelectObject(pBitmap);
	
	BITMAPINFOHEADER bhd;
	BITMAPINFO       binf;
	bhd.biSize=sizeof(BITMAPINFOHEADER);
	bhd.biWidth=pImage->GetWidth(); bhd.biHeight=-pImage->GetHeight();
	bhd.biPlanes=1;
	bhd.biBitCount=(unsigned short)pImage->GetBpp();
	bhd.biCompression=BI_RGB;
	bhd.biSizeImage=0;
	bhd.biClrImportant=0;
	binf.bmiHeader=bhd;
	
	BYTE *imgdat=(BYTE *)(pImage->Lock());

	// If this is an alpha image, and Preview Alpha is checked
	// then write out RGB values with the alpha value, so that the
	// bitmap becomes a gray-scale image show the alpha channel
	if (pImage->GetBpp()==32 && bPreviewAlpha) {
		for (int i=0; i<pImage->GetWidth()*pImage->GetHeight(); ++i)
		{
			*(imgdat+i*4+0) = *(imgdat+i*4+3);
			*(imgdat+i*4+1) = *(imgdat+i*4+3);
			*(imgdat+i*4+2) = *(imgdat+i*4+3);
		}
	}
	
	SetDIBitsToDevice(memDC,
		0,0,pImage->GetWidth(),	pImage->GetHeight(),
		0,0,0,pImage->GetHeight(),
		imgdat,	&binf,DIB_RGB_COLORS);  
	pImage->UnLock();
	
	memDC.DeleteDC();
	ReleaseDC(hfDC);
}