/*==LICENSE==*

CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011  Cyan Worlds, Inc.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

You can contact Cyan Worlds, Inc. by email legal@cyan.com
 or by snail mail at:
      Cyan Worlds, Inc.
      14617 N Newport Hwy
      Mead, WA   99021

*==LICENSE==*/
#include "HeadSpin.h"
#include "hsTypes.h"
#include <windows.h>
#include "res/resource.h"
#include <shlwapi.h>
#include <shlobj.h>
#include <commctrl.h>
#include <time.h>

#include "hsStream.h"
#include "hsResMgr.h"
#include "plFontFreeType.h"
#include "../plGImage/plFont.h"
#include "../plGImage/plMipmap.h"
#include "../pnKeyedObject/plUoid.h"
#include "../pnKeyedObject/plKeyImp.h"


extern HINSTANCE	gInstance;

// My global font that i'm working on
plFont	*gFont = nil;

// Preview bitmap
HDC		gPreviewHDC = nil;
HBITMAP	gPreviewBitmap = nil;

void	IMakeFontGoAway( void )
{
	if( gFont != nil )
	{
		plKeyImp *imp = (plKeyImp *)(gFont->GetKey());
		if( imp != nil )
			imp->SetObjectPtr( nil );
		gFont = nil;
	}
}

void	IMakeNewFont( void )
{
	IMakeFontGoAway();
	gFont = new plFont();
}

BOOL CALLBACK AboutDialogProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	if( msg == WM_COMMAND )
		EndDialog( hWnd, 0 );
	return 0;
}

bool	PromptForFile( HWND parent, const char *prompt, const char *filter, char *fileName, int fileNameMax, bool save )
{
	OPENFILENAME	openInfo;


	memset( &openInfo, 0, sizeof( OPENFILENAME ) );
	openInfo.hInstance = gInstance;
	openInfo.hwndOwner = parent;
	openInfo.lStructSize = sizeof( OPENFILENAME );
	openInfo.lpstrFile = fileName;
	openInfo.nMaxFile = fileNameMax;
	openInfo.lpstrFilter = filter;
	openInfo.lpstrTitle = prompt;
	openInfo.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
	if( !save )
		openInfo.Flags |= OFN_READONLY;

	if( save )
		return GetSaveFileName( &openInfo ) ? true : false;

	return GetOpenFileName( &openInfo ) ? true : false;
}

void	IUpdateInfo( HWND hDlg )
{
	const int TEST_STRING_SIZE = 512;
	static wchar_t testString[ TEST_STRING_SIZE ] = L"The quick brown fox jumped over the lazy dog! ABCabc012345;,.";

	if( gFont == nil )
	{
		SetDlgItemText( hDlg, IDC_FACE, "" );
		SetDlgItemText( hDlg, IDC_FSIZE, "" );
		SetDlgItemText( hDlg, IDC_STARTG, "" );
		SetDlgItemText( hDlg, IDC_GCOUNT, "" );

		SetDlgItemText( hDlg, IDC_WIDTH, "" );
		SetDlgItemText( hDlg, IDC_HEIGHT, "" );
		SetDlgItemText( hDlg, IDC_BPP, "" );

		CheckDlgButton( hDlg, IDC_BOLD, false );
		CheckDlgButton( hDlg, IDC_ITALIC, false );
		return;
	}

	SetDlgItemText( hDlg, IDC_FACE, gFont->GetFace() );
	SetDlgItemInt( hDlg, IDC_FSIZE, gFont->GetSize(), false );
	SetDlgItemInt( hDlg, IDC_STARTG, gFont->GetFirstChar(), false );
	SetDlgItemInt( hDlg, IDC_GCOUNT, gFont->GetNumChars(), false );

	SetDlgItemInt( hDlg, IDC_WIDTH, gFont->GetBitmapWidth(), false );
	SetDlgItemInt( hDlg, IDC_HEIGHT, gFont->GetBitmapHeight(), false );
	SetDlgItemInt( hDlg, IDC_BPP, gFont->GetBitmapBPP(), false );

	CheckDlgButton( hDlg, IDC_BOLD, gFont->IsFlagSet( plFont::kFlagBold ) );
	CheckDlgButton( hDlg, IDC_ITALIC, gFont->IsFlagSet( plFont::kFlagItalic ) );

	if( gPreviewHDC != nil )
	{
		DeleteObject( gPreviewHDC );
		DeleteObject( gPreviewBitmap );
		gPreviewHDC = nil;
		gPreviewBitmap = nil;
	}

	// Get the size of our preview
	RECT r;
	GetClientRect( GetDlgItem( hDlg, IDC_PREVIEW ), &r );
	MapWindowPoints( GetDlgItem( hDlg, IDC_PREVIEW ), hDlg, (POINT *)&r, 2 );

	InvalidateRect( hDlg, &r, false );

	if( gFont->GetNumChars() == 0 )
		return;

	// Our preview bitmap
	HDC deskDC = GetDC( nil );
	gPreviewHDC = CreateCompatibleDC( deskDC );
	gPreviewBitmap = CreateCompatibleBitmap( deskDC, r.right - r.left, r.bottom - r.top );
	SelectObject( gPreviewHDC, gPreviewBitmap );
	ReleaseDC( nil, deskDC );

	::GetDlgItemTextW( hDlg, IDC_PREVTEXT, testString, TEST_STRING_SIZE );

	// Create us a mipmap to render onto, render onto it, then copy that to our DC
	plMipmap *mip = new plMipmap( r.right - r.left, r.bottom - r.top, plMipmap::kARGB32Config, 1 );
	memset( mip->GetImage(), 0xff, mip->GetWidth() * mip->GetHeight() * 4 );

	gFont->SetRenderColor( 0xff000000 );
	gFont->SetRenderFlag( plFont::kRenderClip, true );
	gFont->SetRenderClipRect( 0, 0, (Int16)(r.right - r.left), (Int16)(r.bottom - r.top) );
	UInt16 w, h, a, lastX, lastY;
	UInt32 firstCC;
	gFont->CalcStringExtents( testString, w, h, a, firstCC, lastX, lastY );

	int cY = ( ( ( r.bottom - r.top ) - h ) >> 1 ) + a;

	if( cY < 0 )
		cY = 0;
	else if( cY > r.bottom - r.top - 1 )
		cY = r.bottom - r.top - 1;

	memset( mip->GetAddr32( 8, cY ), 0xc0, ( r.right - r.left - 8 ) * 4 );

	gFont->RenderString( mip, 8, cY, testString );

	int x, y;
	for( y = 0; y < r.bottom - r.top; y++ )
	{
		for( x = 0; x < r.right - r.left; x++ )
		{
			UInt32 color = *mip->GetAddr32( x, y );
			hsColorRGBA   rgba;
			rgba.FromARGB32( color );

			if( color != 0xffffffff && color != 0xff000000 )
			{
				int q = 0;
			}
			SetPixel( gPreviewHDC, x, y, RGB( rgba.r * 255.f, rgba.g * 255.f, rgba.b * 255.f) );
		}
	}

	delete mip;
}

class plSetKeyObj : public hsKeyedObject
{
	public:
		void	SetMyKey( const plKey &key )
		{
			SetKey( key );
		}
};

class plMyBDFCallback : public plBDFConvertCallback
{
	protected:
		HWND	fDlg;
		clock_t	fLastTime;
		UInt16	fPoint;

		void	IPumpMessageQueue( void )
		{
			MSG	msg;
			while( PeekMessage( &msg, fDlg, 0, 0, PM_REMOVE ) )
			{
				TranslateMessage( &msg );
				DispatchMessage( &msg );
			}
		}

	public:
		plMyBDFCallback( HWND dlg ) : fDlg( dlg ) {}

		virtual void	NumChars( UInt16 chars )
		{
			::SendDlgItemMessage( fDlg, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM( 0, chars ) );
			IPumpMessageQueue();
			fLastTime = clock();
			fPoint = 0;
		}

		virtual void	CharDone( void )
		{
			fPoint++;
			if( clock() - fLastTime > CLOCKS_PER_SEC / 16 )
			{
				::SendDlgItemMessage( fDlg, IDC_PROGRESS, PBM_SETPOS, fPoint, 0 );
				IPumpMessageQueue();
				fLastTime = clock();
			}
		}
};

BOOL CALLBACK ProgressWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	return 0;
}
	
void	IImportFNT( HWND hWnd, const char *path )
{
	IMakeNewFont();
	if( !gFont->LoadFromFNT( path ) )
		MessageBox( hWnd, "Failure converting FNT file", "ERROR", MB_OK | MB_ICONEXCLAMATION );
	IUpdateInfo( hWnd );
}

void	IImportBDF( HWND hWnd, const char *path )
{
	IMakeNewFont();
	HWND dialog = CreateDialog( gInstance, MAKEINTRESOURCE( IDD_PROGRESS ), hWnd, ProgressWndProc );
	ShowWindow( dialog, SW_SHOW );
	EnableWindow( hWnd, false );
	plMyBDFCallback	callback( dialog );

	if( !gFont->LoadFromBDF( path, &callback ) )
		MessageBox( hWnd, "Failure converting BDF file", "ERROR", MB_OK | MB_ICONEXCLAMATION );

	DestroyWindow( dialog );
	EnableWindow( hWnd, true );

	IUpdateInfo( hWnd );
}

void	IOpenP2F( HWND hWnd, const char *path )
{
	IMakeNewFont();
	if( !gFont->LoadFromP2FFile( path ) )
		MessageBox( hWnd, "Failure opening P2F file", "ERROR", MB_OK | MB_ICONEXCLAMATION );

	IUpdateInfo( hWnd );
}

struct ResRecord
{
	HRSRC	fHandle;
	char	fName[ 512 ];

	ResRecord() { fHandle = nil; fName[ 0 ] = 0; }
	ResRecord( HRSRC h, const char *n ) { fHandle = h; strncpy( fName, n, sizeof( fName ) ); }
};

BOOL CALLBACK	ResEnumProc( HMODULE module, LPCTSTR type, LPTSTR name, LONG_PTR lParam )
{
	HRSRC res = FindResource( module, name, type );
	if( res != nil )
	{
		hsTArray<ResRecord *>	*array = (hsTArray<ResRecord *> *)lParam;
		array->Append( new ResRecord( res, name ) );
	}

	return true;
}

BOOL CALLBACK ResListWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	switch( message )
	{
		case WM_INITDIALOG:
			{
				SendDlgItemMessage( hWnd, IDC_RESLIST, LB_RESETCONTENT, 0, 0 );
				hsTArray<ResRecord *> *array = (hsTArray<ResRecord *> *)lParam;
				for( UInt32 i = 0; i < array->GetCount(); i++ )
				{
					ResRecord *rec = array->Get( i );
					int idx = SendDlgItemMessage( hWnd, IDC_RESLIST, LB_ADDSTRING, 0, (LPARAM)rec->fName );
					SendDlgItemMessage( hWnd, IDC_RESLIST, LB_SETITEMDATA, idx, (LPARAM)rec );
				}
			}
			return 0;

		case WM_COMMAND:
			if( wParam == IDCANCEL )
				EndDialog( hWnd, nil );
			else
			{
				int idx = SendDlgItemMessage( hWnd, IDC_RESLIST, LB_GETCURSEL, 0, 0 );
				if( idx == LB_ERR )
					EndDialog( hWnd, nil );
				else
				{
					ResRecord *rec = (ResRecord *)SendDlgItemMessage( hWnd, IDC_RESLIST, LB_GETITEMDATA, idx, 0 );
					EndDialog( hWnd, (int)rec );
				}
			}
			return true;
	}

	return 0;
}

void	IImportFON( HWND hWnd, const char *path )
{
	// FON files are really just resource modules
	IMakeNewFont();
	HMODULE file = LoadLibraryEx( path, nil, LOAD_LIBRARY_AS_DATAFILE | DONT_RESOLVE_DLL_REFERENCES );
	if( file == nil )
	{
		char msg[ 512 ], msg2[ 1024 ];

		FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
						nil, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)msg, sizeof( msg ), nil );

		sprintf( msg2, "Failure importing FON file: can't open as resource library (%s)", msg );
		MessageBox( hWnd, msg2, "Error", MB_OK | MB_ICONEXCLAMATION );
	}
	else
	{
		hsTArray<ResRecord *>	resList;
		
		if( EnumResourceNames( file, "Font", ResEnumProc, (LPARAM)&resList ) )
		{
			// Put up a list of the resources so the user can choose which one
			ResRecord *res = (ResRecord *)DialogBoxParam( gInstance, MAKEINTRESOURCE( IDD_FONCHOOSER ), hWnd, 
															ResListWndProc, (LPARAM)&resList );
			if( res != nil )
			{
				// Load the resource into a ram stream
				hsRAMStream	stream;

				HGLOBAL glob = LoadResource( file, res->fHandle );
				if( glob != nil )
				{
					void *data = LockResource( glob );
					if( data != nil )
					{
						stream.Write( SizeofResource( file, res->fHandle ), data );
						stream.Rewind();

						if( !gFont->LoadFromFNTStream( &stream ) )
							MessageBox( hWnd, "Failure importing FON file: can't parse resource as FNT",
												"Error", MB_OK | MB_ICONEXCLAMATION );

					}
				}
			}
		}
		else
		{
			char msg[ 512 ], msg2[ 1024 ];

			FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
							nil, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)msg, sizeof( msg ), nil );

			sprintf( msg2, "Failure importing FON file: can't enumerate resources (%s)", msg );
			MessageBox( hWnd, msg2, "Error", MB_OK | MB_ICONEXCLAMATION );
		}

		UInt32 i;
		for( i = 0; i < resList.GetCount(); i++ )
			delete resList[ i ];
		resList.Reset();

		FreeLibrary( file );
	}

	IUpdateInfo( hWnd );
}

BOOL CALLBACK FreeTypeDlgProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	static plFontFreeType::Options	*info;

	switch( message )
	{
		case WM_INITDIALOG:
			info = (plFontFreeType::Options *)lParam;
			SetDlgItemInt( hWnd, IDC_PSIZE, info->fSize, false );
			SetDlgItemInt( hWnd, IDC_RES, info->fScreenRes, false );
			SetDlgItemInt( hWnd, IDC_MAXCHAR, info->fMaxCharLimit, false );
			CheckRadioButton( hWnd, IDC_BITDEPTH, IDC_BITDEPTH2, info->fBitDepth == 1 ? IDC_BITDEPTH : IDC_BITDEPTH2 );
			return 0;

		case WM_COMMAND:
			if( wParam == IDOK || wParam == IDCANCEL || wParam == IDC_BATCH )
			{
				info->fSize = GetDlgItemInt( hWnd, IDC_PSIZE, nil, false );
				info->fScreenRes = GetDlgItemInt( hWnd, IDC_RES, nil, false );
				info->fMaxCharLimit = GetDlgItemInt( hWnd, IDC_MAXCHAR, nil, false );
				
				if( IsDlgButtonChecked( hWnd, IDC_BITDEPTH ) )
					info->fBitDepth = 1;
				else
					info->fBitDepth = 8;

				EndDialog( hWnd, wParam );
			}
			return 1;
	}
	return 0;
}

void	IBatchFreeType( HWND hWnd, const char *path );

void	IImportFreeType( HWND hWnd, const char *path )
{
	static plFontFreeType::Options info;

	int ret = DialogBoxParam( gInstance, MAKEINTRESOURCE( IDD_FREETYPE ), hWnd, FreeTypeDlgProc, (LPARAM)&info );
	if( ret == IDCANCEL )
		return;
	else if( ret == IDC_BATCH )
	{
		IBatchFreeType( hWnd, path );
		return;
	}

	IMakeNewFont();
	HWND dialog = CreateDialog( gInstance, MAKEINTRESOURCE( IDD_PROGRESS ), hWnd, ProgressWndProc );
	ShowWindow( dialog, SW_SHOW );
	EnableWindow( hWnd, false );
	plMyBDFCallback	callback( dialog );

	plFontFreeType *ft2Convert = (plFontFreeType *)gFont;
	if( !ft2Convert->ImportFreeType( path, &info, &callback ) )
		MessageBox( hWnd, "Failure converting TrueType file", "ERROR", MB_OK | MB_ICONEXCLAMATION );

	DestroyWindow( dialog );
	EnableWindow( hWnd, true );

	IUpdateInfo( hWnd );
}

static UInt8	sNumSizes = 0;
static UInt8	sSizeArray[ 256 ];
static char		sFontName[ 256 ]; // desired font name for FreeType conversions

BOOL CALLBACK FreeTypeBatchDlgProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	static plFontFreeType::Options	*info;

	switch( message )
	{
		case WM_INITDIALOG:
			info = (plFontFreeType::Options *)lParam;
			SetDlgItemText( hWnd, IDC_PSIZE, "12" );
			SetDlgItemText( hWnd, IDC_FONTNAME, "Untitled" );
			SetDlgItemInt( hWnd, IDC_RES, info->fScreenRes, false );
			SetDlgItemInt( hWnd, IDC_MAXCHAR, info->fMaxCharLimit, false );
			CheckRadioButton( hWnd, IDC_BITDEPTH, IDC_BITDEPTH2, info->fBitDepth == 1 ? IDC_BITDEPTH : IDC_BITDEPTH2 );
			return 0;

		case WM_COMMAND:
			if( wParam == IDOK || wParam == IDCANCEL )
			{
				sNumSizes = 0;

				char *c, *lastC, str[ 1024 ];
				GetDlgItemText( hWnd, IDC_PSIZE, str, sizeof( str ) );
				lastC = str;
				while( ( c = strchr( lastC, ',' ) ) != nil && sNumSizes < 255 )
				{
					*c = 0;
					sSizeArray[ sNumSizes++ ] = atoi( lastC );
					lastC = c + 1;			
				}

				sSizeArray[ sNumSizes++ ] = atoi( lastC );

				info->fScreenRes = GetDlgItemInt( hWnd, IDC_RES, nil, false );
				info->fMaxCharLimit = GetDlgItemInt( hWnd, IDC_MAXCHAR, nil, false );
				
				if( IsDlgButtonChecked( hWnd, IDC_BITDEPTH ) )
					info->fBitDepth = 1;
				else
					info->fBitDepth = 8;
				
				GetDlgItemText( hWnd, IDC_FONTNAME, sFontName, sizeof(sFontName) );

				EndDialog( hWnd, wParam );
			}
			return 1;
	}
	return 0;
}

void	IBatchFreeType( HWND hWnd, const char *path )
{
	static plFontFreeType::Options info;

	if( DialogBoxParam( gInstance, MAKEINTRESOURCE( IDD_FREETYPEBATCH ), hWnd, FreeTypeBatchDlgProc, (LPARAM)&info ) == IDCANCEL )
		return;

	BROWSEINFO		bInfo;
	LPITEMIDLIST	itemList;
	LPMALLOC		shMalloc;
	static char		destPath[ MAX_PATH ] = "";

	memset( &bInfo, 0, sizeof( bInfo ) );
	bInfo.hwndOwner = hWnd;
	bInfo.pidlRoot = NULL;
	bInfo.pszDisplayName = destPath;
	bInfo.lpszTitle = "Select a path to write the P2F fonts to:";
	bInfo.ulFlags = BIF_EDITBOX;

	itemList = SHBrowseForFolder( &bInfo );
	if( itemList != NULL )
	{
		SHGetPathFromIDList( itemList, destPath );
		SHGetMalloc( &shMalloc );
		shMalloc->Free( itemList );
		shMalloc->Release();
	}
	else
		return;

	HWND dialog = CreateDialog( gInstance, MAKEINTRESOURCE( IDD_PROGRESS ), hWnd, ProgressWndProc );
	ShowWindow( dialog, SW_SHOW );
	EnableWindow( hWnd, false );
	plMyBDFCallback	callback( dialog );

	callback.NumChars( sNumSizes );
	UInt8 i;
	for( i = 0; i < sNumSizes; i++ )
	{
		IMakeNewFont();
		plFontFreeType *ft2Convert = (plFontFreeType *)gFont;

		info.fSize = sSizeArray[ i ];
		if( !ft2Convert->ImportFreeType( path, &info, nil ) )
		{
			MessageBox( hWnd, "Failure converting TrueType file", "ERROR", MB_OK | MB_ICONEXCLAMATION );
			continue;
		}

		gFont->SetFace(sFontName);
		char fileName[ MAX_PATH ];
		sprintf( fileName, "%s\\%s-%d.p2f", destPath, gFont->GetFace(), gFont->GetSize() );
		hsUNIXStream stream;
		if( !stream.Open( fileName, "wb" ) )
			MessageBox( hWnd, "Can't open file for writing", "Error", MB_OK | MB_ICONEXCLAMATION );
		else
		{
			gFont->WriteRaw( &stream );
			stream.Close();
		}

		callback.CharDone();
	}

	DestroyWindow( dialog );
	EnableWindow( hWnd, true );
	IUpdateInfo( hWnd );
}

BOOL CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	char		fileName[ MAX_PATH ];
	PAINTSTRUCT	paintInfo;
	HDC			myDC;
	RECT		r;


	switch( message )
	{
		case WM_PAINT:
			myDC = BeginPaint( hWnd, &paintInfo );

			GetClientRect( GetDlgItem( hWnd, IDC_PREVIEW ), &r );
			MapWindowPoints( GetDlgItem( hWnd, IDC_PREVIEW ), hWnd, (POINT *)&r, 2 );

			if( gPreviewHDC != nil )
				BitBlt( myDC, r.left, r.top, r.right - r.left, r.bottom - r.top, gPreviewHDC, 0, 0, SRCCOPY );
			else
				FillRect( myDC, &r, GetSysColorBrush( COLOR_3DFACE ) );

			DrawEdge( myDC, &r, EDGE_SUNKEN, BF_RECT );

			EndPaint( hWnd, &paintInfo );
			return 0;

		case WM_INITDIALOG:
			SendMessage( hWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon( gInstance, MAKEINTRESOURCE( IDI_APPICON ) ) );
			SetDlgItemTextW( hWnd, IDC_PREVTEXT, L"The quick brown fox jumped over the lazy dog! ABCabc012345;,." );
			return 0;

		case WM_COMMAND:
			if( wParam == ID_FILE_ABOUT )
			{
				DialogBox( gInstance, MAKEINTRESOURCE( IDD_ABOUT ), hWnd, AboutDialogProc );
			}
			else if( wParam == ID_FILE_EXIT )
				PostQuitMessage( 0 );
			else if( wParam == ID_FILE_FNT )
			{
				fileName[ 0 ] = 0;
				if( PromptForFile( hWnd, "Choose a FNT file to convert", "Windows FNT files\0*.fnt\0All files\0*.*\0", fileName, sizeof( fileName ), false ) )
					IImportFNT( hWnd, fileName );
			}
			else if( wParam == ID_FILE_P2F )
			{
				fileName[ 0 ] = 0;
				if( PromptForFile( hWnd, "Choose a P2F file to open", "Plasma 2 font files\0*.p2f\0All files\0*.*\0", fileName, sizeof( fileName ), false ) )
					IOpenP2F( hWnd, fileName );
			}
			else if( wParam == ID_FILE_FON )
			{
				fileName[ 0 ] = 0;
				if( PromptForFile( hWnd, "Choose a FON file to convert", "Windows FON files\0*.fon\0All files\0*.*\0", fileName, sizeof( fileName ), false ) )
					IImportFON( hWnd, fileName );
			}
			else if( wParam == ID_FILE_TRUETYPE )
			{
				fileName[ 0 ] = 0;
				if( PromptForFile( hWnd, "Choose a TrueType font to convert", "TrueType files\0*.ttf\0TrueType Collections\0*.ttc\0All files\0*.*\0", fileName, sizeof( fileName ), false ) )
					IBatchFreeType( hWnd, fileName );
			}
			else if( wParam == ID_FILE_EXPORT )
			{
				// Grab updated values for the font
				GetDlgItemText( hWnd, IDC_FACE, fileName, sizeof( fileName ) );
				gFont->SetFace( fileName );
				gFont->SetSize( GetDlgItemInt( hWnd, IDC_FSIZE, nil, false ) );
				gFont->SetFlag( plFont::kFlagBold, IsDlgButtonChecked( hWnd, IDC_BOLD ) == BST_CHECKED );
				gFont->SetFlag( plFont::kFlagItalic, IsDlgButtonChecked( hWnd, IDC_ITALIC ) == BST_CHECKED );

				// Write out
				sprintf( fileName, "%s-%d.p2f", gFont->GetFace(), gFont->GetSize() );
				if( PromptForFile( hWnd, "Specify a file to export to", "Plasma 2 font files\0*.p2f\0", fileName, sizeof( fileName ), true ) )
				{
					hsUNIXStream stream;
					if( !stream.Open( fileName, "wb" ) )
						MessageBox( hWnd, "Can't open file for writing", "Error", MB_OK | MB_ICONEXCLAMATION );
					else
					{
/*						sprintf( fileName, "%s-%d", gFont->GetFace(), gFont->GetSize() );

						if( gFont->GetKey() == nil )
							hsgResMgr::ResMgr()->NewKey( fileName, gFont, plLocation::kGlobalFixedLoc );

*/						
						gFont->WriteRaw( &stream );
						stream.Close();
					}
				}
			}
			else if( LOWORD( wParam ) == IDC_PREVTEXT && HIWORD( wParam ) == EN_CHANGE )
			{
				IUpdateInfo( hWnd );
			}
			return true;

		case WM_CLOSE:
			PostQuitMessage( 0 );
			return true;

		case WM_DROPFILES:
			{
				int		i, fileCount = DragQueryFile( (HDROP)wParam, -1, nil, nil );
				char	path[ MAX_PATH ];


				for( i = 0; i < fileCount; i++ )
				{
					if( DragQueryFile( (HDROP)wParam, i, path, sizeof( path ) ) > 0 )
					{
						char *ext = PathFindExtension( path );
						if( stricmp( ext, ".fnt" ) == 0 )
							IImportFNT( hWnd, path );
						else if( stricmp( ext, ".bdf" ) == 0 )
							IImportBDF( hWnd, path );
						else if( stricmp( ext, ".fon" ) == 0 )
							IImportFON( hWnd, path );
						else if( stricmp( ext, ".exe" ) == 0 )
							IImportFON( hWnd, path );
						else if(( stricmp( ext, ".ttf" ) == 0 ) || ( stricmp( ext, ".ttc" ) == 0 ))
							IImportFreeType( hWnd, path );
						else if( stricmp( ext, ".p2f" ) == 0 )
							IOpenP2F( hWnd, path );
						else
							// Try using our freeType converter
							IImportFreeType( hWnd, path );
					}
				}

				IUpdateInfo( hWnd );
			}
			break;

	}
	return 0;//DefWindowProc( hWnd, message, wParam, lParam );
}