#define	STRICT
#include	<windows.h>
#include	<windowsx.h>
#include	<commctrl.h>
#include	<tchar.h>
#include	"resource.h"
#include	"fepbox.h"
#include	"appmain.h"
#include	"dialog.h"
#include	"setup.h"

TCHAR	MessageBuf[ 512 ] ;
DWORD	PreWait = 10 ;
DWORD	PostWait = 10 ;
DWORD	F_QuickSend = 0 ;
DWORD	F_JIS = 1 ;			/* JISペーストフラグ */
TCHAR	DictPath[ MAX_PATH ] = TEXT("") ;
DWORD	g_dFepMode = 0 ;
HWND	g_hWndDialog = NULL ;
BOOL	g_fUninst = FALSE ;

class MainWindow : public Window {
private:
	MainApp		*m_pApp ;			/* アプリケーションへのポインタ */
	HICON		m_hIcon ;			/* アプリアイコンのハンドル */
	BOOL		m_fLoadNotify ;		/* タスクバー格納フラグ */
	BOOL		m_fFepLine ;		/* FEP行表示フラグ */
	BOOL		m_fNoMenu ;			/* メニュー非表示フラグ */

	void	CreateFep( LPRECT pos ) ;

public:
	MainWindow( MainApp *app ) ;

	BOOL	Create() ;
	void	CreateFepWnd( LPRECT pos ) ;

	void	WMCreate( HWND hWnd ) ;
	BOOL	AddTaskBarIcon() const ;
	BOOL	DeleteTaskBarIcon() const ;
	BOOL	ModifyTaskBarIcon( DWORD index ) const ;

	void	WMDestroy() ;
	LRESULT	WMCommand( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp ) ;
	void	WMNotify( HWND hWnd, int idCtrl, LPNMHDR pnmh ) ;
	BOOL	WMClose() ;

	static	BOOL	RegisterClass( HINSTANCE hInst ) ;
	static	LPCTSTR	GetClassName() { return TEXT("KANJIIN") ; }
} ;

/*
 * FEP行ウィンドウ
 */
class FepWindow : public Window {
	MainApp		*m_pApp ;			/* アプリケーションへのポインタ */
	HWND		m_hWndFep ;

public:
	FepWindow( MainApp *pApp ) ;
	~FepWindow() ;

	BOOL	Create( HWND hWndMain ) ;
	void	PutChar( TCHAR c ) ;

	void	WMCreate( HWND hDlg ) ;
	LRESULT	WMCommand( HWND hDlg, UINT msg, WPARAM wp, LPARAM lp ) ;
	void	WMActivate( WORD fActive, BOOL fMinimize, HWND hWnd ) ;
} ;

/*-------------------------------------------------------------------------*
 * MainApp
 *-------------------------------------------------------------------------*/
MainApp::MainApp()
{
}

MainApp::~MainApp()
{
}

BOOL
MainApp::Create( HINSTANCE hInstance, HWND hWndParent, TCHAR ch )
{
	m_hInst = hInstance ;

	if ( !FepBoxRegisterClass( m_hInst ) ) {
		return FALSE ;
	}
	if ( !MainWindow::RegisterClass( m_hInst ) ) {
		return FALSE ;
	}

#ifdef	_WIN32_WCE
	m_hAccl = LoadAccelerators( m_hInst,
								MAKEINTRESOURCE(IDR_ACCELERATOR1) ) ;
#else	/* _WIN32_WCE */
	m_hAccl = LoadAccelerators( GetModuleHandle(NULL),
								MAKEINTRESOURCE(IDR_ACCELERATOR1) ) ;
#endif	/* _WIN32_WCE */

	m_pMainWnd = new MainWindow( this ) ;
	if ( !m_pMainWnd ) {
		return FALSE ;
	}
	m_pFepWnd = new FepWindow( this ) ;
	if ( !m_pFepWnd ) {
		delete m_pMainWnd ;
		return FALSE ;
	}
	if ( !m_pMainWnd->Create() ) {
		delete m_pFepWnd ;
		delete m_pMainWnd ;
		return FALSE ;
	}
	if ( !m_pFepWnd->Create( m_pMainWnd->get_hwnd() ) ) {
		delete m_pFepWnd ;
		delete m_pMainWnd ;
		return FALSE ;
	}

	HWND	hWnd = m_pMainWnd->get_hwnd() ;

	if ( !get_reg() ) {
		goto setup ;
	}

	SetCursor( (HCURSOR) IDC_WAIT ) ;
	/* 辞書を読み込む */
	if ( !FepSetDict( DictPath ) ) {
		SetCursor( NULL ) ;
		goto setup ;
	}
	if ( hWndParent ) {
		PostMessage( hWnd, WM_COMMAND, MAKEWPARAM( IDM_ACTIVATE_HWND, ch ), (LPARAM) hWndParent ) ;
	} else {
		hWndParent = GetCenterWindow() ;
		PostMessage( hWnd, WM_COMMAND, IDM_ACTIVATE, (LPARAM) hWndParent ) ;
	}
	SetCursor( NULL ) ;
	return TRUE ;

setup:
	/* セットアップダイアログを開く */
	SendMessage( hWnd, WM_COMMAND, IDM_SETUP, 0 ) ;
	if ( g_fUninst ) {
		delete_reg() ;
	} else {
		set_reg() ;
	}
	m_pMainWnd->DeleteTaskBarIcon() ;
	delete m_pMainWnd ;
	return FALSE ;
}

int
MainApp::Run()
{
	MSG		msg ;

	while ( GetMessage( &msg, NULL, 0, 0 ) ) {
		if ( !TranslateAccelerator( m_pMainWnd->get_hwnd(), m_hAccl, &msg ) ) {
			TranslateMessage( &msg ) ;
		}
		DispatchMessage( &msg ) ;
	}

	if ( g_fUninst ) {
		delete_reg() ;
	} else {
		set_reg() ;
	}

	return msg.wParam ;
}

/*-------------------------------------------------------------------------*
 * MainWindow
 *-------------------------------------------------------------------------*/
MainWindow::MainWindow( MainApp *pApp )
{
	m_pApp = pApp ;
	m_hIcon = 0 ;
	m_fFepLine = FALSE ;
	m_fNoMenu = FALSE ;
}

void
MainWindow::WMCreate( HWND hWnd )
{
	m_hWnd = hWnd ;
	/* アイコンを作成しタスクバーに登録する */
	m_hIcon = (HICON) LoadImage( m_pApp->get_inst(), MAKEINTRESOURCE(IDI_APPICON),
								 IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR ) ;
	if ( m_hIcon ) {
		SendMessage( hWnd, WM_SETICON, FALSE, (LPARAM) m_hIcon ) ;
	}
	/* タスクバーに登録する */
	m_fLoadNotify = AddTaskBarIcon() ;
}

/*
 * タスクバーに通知アイコンを登録する
 */
BOOL
MainWindow::AddTaskBarIcon() const
{
	NOTIFYICONDATA	tnid ;
	HICON			hIcon ;

	/* 通知エリア用のアイコンを作成する */
	hIcon = (HICON) LoadImage( m_pApp->get_inst(), MAKEINTRESOURCE(IDI_KANJI),
							   IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR ) ;
	memset( &tnid, 0, sizeof tnid ) ;
	tnid.cbSize = sizeof (NOTIFYICONDATA) ;
	tnid.hWnd = m_hWnd ;
	tnid.uID = IDM_NOTIFY ;
	tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP ;
	tnid.uCallbackMessage = WM_COMMAND ;
	tnid.hIcon = hIcon ;
	_tcscpy( tnid.szTip, szTitleName ) ;
	return Shell_NotifyIcon( NIM_ADD, &tnid ) ;
}

/*
 * 通知アイコンを削除する
 */
BOOL
MainWindow::DeleteTaskBarIcon() const
{
	NOTIFYICONDATA	tnid ;

	memset( &tnid, 0, sizeof tnid ) ;
	tnid.cbSize = sizeof (NOTIFYICONDATA) ;
	tnid.hWnd = m_hWnd ;
	tnid.uID = IDM_NOTIFY ;
	return Shell_NotifyIcon( NIM_DELETE, &tnid ) ;
}

/*
 * 通知アイコンを変更する
 */
BOOL
MainWindow::ModifyTaskBarIcon( DWORD index ) const
{
	NOTIFYICONDATA	tnid ;
	HICON			hIcon ;
	WORD			idCtrl = index ? IDI_DIRECT : IDI_KANJI ;

	hIcon = (HICON) LoadImage( m_pApp->get_inst(), MAKEINTRESOURCE(idCtrl),
							   IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR ) ;
	memset( &tnid, 0, sizeof tnid ) ;
	tnid.cbSize = sizeof (NOTIFYICONDATA) ;
	tnid.hWnd = m_hWnd ;
	tnid.uID = IDM_NOTIFY ;
	tnid.uFlags = NIF_ICON ;
	tnid.hIcon = hIcon ;
	return Shell_NotifyIcon( NIM_MODIFY, &tnid ) ;
}

void
MainWindow::WMDestroy()
{
	DeleteTaskBarIcon() ;
	if ( m_hIcon ) {
		::DeleteObject( m_hIcon ) ;
		m_hIcon = 0 ;
	}
	PostQuitMessage( 0 ) ;
}

LRESULT
MainWindow::WMCommand( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	DWORD	ret ;
	HMENU	hMenu ;
	HWND	hWndParent ;
	WORD	notifyCode = HIWORD(wParam), cmd = LOWORD(wParam) ;

	switch ( cmd ) {
	case IDM_EXIT:
		SendMessage( hWnd, WM_CLOSE, 0, 0 ) ;
		break ;
	case IDM_NOTIFY:
		if ( lParam == WM_LBUTTONDOWN ) {
			if ( GetAsyncKeyState( VK_MENU ) & 0x8000 ) {
				SendMessage( hWnd, WM_CLOSE, 0, 0 ) ;
			} else {
				if ( m_fNoMenu ) {
					if ( g_hWndDialog ) {
						SetForegroundWindow( g_hWndDialog ) ;
					}
					break ;
				} else if ( m_fFepLine ) {
					break ;
				}
				SetForegroundWindow( hWnd ) ;
				/* ポップアップメニューを作成する */
				hMenu = CreatePopupMenu() ;
				if ( hMenu ) {
					::AppendMenu( hMenu, MF_STRING | (F_JIS ? MF_CHECKED : MF_UNCHECKED), IDM_JIS, TEXT("JIS") ) ;
					::AppendMenu( hMenu, MF_SEPARATOR, 0, 0 ) ;
					::AppendMenu( hMenu, MF_STRING, IDM_SETUP, TEXT("Setup") ) ;
					::AppendMenu( hMenu, MF_SEPARATOR, 0, 0 ) ;
					::AppendMenu( hMenu, MF_STRING, IDM_EXIT, TEXT("Exit") ) ;
					::TrackPopupMenu( hMenu,
							TPM_BOTTOMALIGN|TPM_RIGHTALIGN,
							GetSystemMetrics( SM_CXSCREEN ),
							GetSystemMetrics( SM_CYSCREEN ) - 30,
							0,
							hWnd,
							NULL ) ;
					::DestroyMenu( hMenu ) ;
				}
			}
		}
		break ;
	case IDM_JIS:
		F_JIS = F_JIS ? 0 : 1 ;
		break ;
	case IDM_FEPLINE:
		SendMessage( hWnd, WM_COMMAND, IDM_FEPSETMODE, 0 ) ;
		m_pApp->get_fep()->PutChar( (TCHAR) lParam ) ;
		break ;
	case IDM_ACTIVATE:
		if ( m_fNoMenu ) {
			break ;
		}
		hWndParent = (HWND) lParam ;
		if ( !hWndParent ) {
			hWndParent = GetCenterWindow() ;
		}
		FepSetParent( hWndParent, FALSE ) ;
		PostMessage( hWnd, WM_COMMAND, IDM_FEPLINE, 0 ) ;
		break ;
	case IDM_ACTIVATE_HWND:
		if ( m_fNoMenu ) {
			break ;
		}
		hWndParent = (HWND) lParam ;
		if ( notifyCode ) {
			FepSetParent( hWndParent, TRUE ) ;
			PostMessage( hWnd, WM_COMMAND, IDM_FEPLINE, (LPARAM) notifyCode ) ;
		} else {
			SendMessage( hWnd, WM_COMMAND, IDM_FEPSETMODE, 0 ) ;
			SetForegroundWindow( hWndParent ) ;
		}
		break ;
	case IDM_FEPGETMODE:
		return g_dFepMode ;
		break ;
	case IDM_FEPSETMODE:
		ret = (DWORD) lParam ;
		if ( g_dFepMode != ret && ret < 2 ) {
			g_dFepMode = ret ;
			ModifyTaskBarIcon( g_dFepMode ) ;
		}
		break ;
	case IDM_SETUP:
		/* セットアップ */
		if ( m_fNoMenu ) {
			break ;
		}
		m_fNoMenu = TRUE ;
		ret = SetupDialogExec( m_pApp->get_inst(), hWnd ) ;
		m_fNoMenu = FALSE ;
		if ( ret & DIALOG_RET_EXIT ) {
			SendMessage( hWnd, WM_CLOSE, 0, 0 ) ;
			break ;
		} else if ( ret & DIALOG_RET_UNINSTALL ) {
			g_fUninst = TRUE ;
			SendMessage( hWnd, WM_CLOSE, 0, 0 ) ;
			break ;
		} else if ( ret & DIALOG_RET_CHANGEDICT ) {
			FepSetDict( DictPath ) ;
		}
		break ;
	}
	return 0 ;
}

void
MainWindow::WMNotify( HWND hWnd, int idCtrl, LPNMHDR pnmh )
{
}

BOOL
MainWindow::WMClose()
{
	return FALSE ;
}

BOOL
MainWindow::Create()
{
	HWND	hWnd = CreateWindowEx( 0,
						GetClassName(),
						szTitleName,
						WS_BORDER,
						0, 0, 10, 10,
						NULL,
						NULL,
						m_pApp->get_inst(),
						this ) ;
	if ( hWnd == 0 ) {
		return FALSE ;
	}
	ShowWindow( hWnd, SW_HIDE ) ;
    UpdateWindow( hWnd ) ;
    return TRUE ;
}

BOOL
MainWindow::RegisterClass( HINSTANCE hInst )
{
	WNDCLASS	wc ;

	wc.style         = NULL ;
	wc.lpfnWndProc   = (WNDPROC) WndProc ;
	wc.cbClsExtra    = 0 ;
	wc.cbWndExtra    = 4 ;
	wc.hInstance     = hInst ;
	wc.hIcon         = NULL ;
	wc.hCursor       = NULL ;
	wc.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH ) ;
	wc.lpszMenuName  = 0 ;
	wc.lpszClassName = 	GetClassName() ;
	return ::RegisterClass( &wc ) ;
}

/*-------------------------------------------------------------------------*
 * FepWindow
 *-------------------------------------------------------------------------*/
FepWindow::FepWindow( MainApp *pApp )
{
	m_pApp = pApp ;
}

FepWindow::~FepWindow()
{
}

BOOL
FepWindow::Create( HWND hWndMain )
{
	HWND	hWnd ;

	hWnd = CreateDialogParam( m_pApp->get_inst(),
					MAKEINTRESOURCE(IDD_DLG_FEP),
					hWndMain,
					DlgProc,
					(LPARAM) this ) ;
	ShowWindow( hWnd, SW_HIDE ) ;
	UpdateWindow( hWnd ) ;
	return TRUE ;
}

void
FepWindow::PutChar( TCHAR c )
{
	ShowWindow( m_hWnd, SW_SHOW ) ;
	SetForegroundWindow( m_hWnd ) ;
	SendMessage( m_hWndFep, WM_CHAR, (WPARAM) c, 0 ) ;
	SetFocus( m_hWndFep ) ;
}

void
FepWindow::WMCreate( HWND hDlg )
{
	OSVERSIONINFO	os ;
	DWORD			x, y, bw, bh ;
	BOOL			bVer10 = TRUE ;

	m_hWnd = hDlg ;

	memset( &os, 0, sizeof os ) ;
	os.dwOSVersionInfoSize = sizeof os ;
	if ( GetVersionEx( &os ) && os.dwMajorVersion > 1 ) {
		bVer10 = FALSE ;
	}

#ifdef	_WIN32_WCE
	bh = GetFontH() + 8 ;
#else	/* _WIN32_WCE */
	bh = GetFontH() + 8 ;
#endif	/* _WIN32_WCE */
	bw = GetSystemMetrics( SM_CXSCREEN ) - GetSystemMetrics( SM_CXVSCROLL ) - 8 ;

	x = 2 ;
	y = GetSystemMetrics( SM_CYSCREEN ) - bh - 2 ;

	if ( bVer10 ) {
		MoveWindow( hDlg, x, y, bw, bh, FALSE ) ;
	} else {
		SetWindowPos( hDlg, (HWND)-1, x, y, bw, bh, 0 ) ;
	}

	m_hWndFep = ::CreateWindow( CTRL_FEPBOX,
						TEXT(""),
						WS_CHILD|WS_BORDER|WS_VISIBLE,
						0, 0, bw - 2, bh - 2,
						hDlg,
						0,
						m_pApp->get_inst(), 0 ) ;
}

LRESULT
FepWindow::WMCommand( HWND hDlg, UINT msg, WPARAM wp, LPARAM lp )
{
	WORD	notifyCode = HIWORD(wp), cmd = LOWORD(wp) ;

	switch ( cmd ) {
	case IDM_FEPSETMODE:
		SendMessage( m_pApp->get_main()->get_hwnd(), msg, wp, lp ) ;
		return 1 ;
	}
	return 0 ;
}

void
FepWindow::WMActivate( WORD fActive, BOOL fMinimize, HWND hWnd )
{
	if ( fActive != WA_INACTIVE ) {
		return ;
	} else if ( SendMessage( m_hWndFep, FEP_ISSENDING, 0, 0 ) ) {
		return ;
	}
	ShowWindow( m_hWnd, SW_HIDE ) ;
}
