#define	STRICT
#include	<windows.h>
#include	<windowsx.h>
#include	<commctrl.h>
#include	<tchar.h>
#include	"kctrl.h"
#include	"resource.h"
#include	"controls.h"
#include	"appmain.h"
#include	"dialog.h"
#include	"pobox.h"
#include	"jpconv.h"

#define		GawaroBaseKey	TEXT("Software\\Gawaro")
#define		VAR_USECTRL		TEXT("UseCtrl")
#define		VAR_BASEDIR		TEXT("BaseDir")
#define		VAR_PREWAIT		TEXT("PreWait")
#define		VAR_POSTWAIT	TEXT("PostWait")
#define		VAR_JIS			TEXT("JIS")
#define		VAR_SOFTKEY		TEXT("SoftKey")
#define		VAR_LEFTPOS		TEXT("LeftPos")
#define		VAR_SAVEDIC		TEXT("SaveDic")
#define		VAR_PREDICT		TEXT("Predict")
#define		VAR_SELCOLOR	TEXT("SelColor")
#define		VAR_HOTKEY		TEXT("HotKey")

#define		SOFTKEY_WIDTH	240
#define		SOFTKEY_HEIGHT	150
#define		NONEKEY_HEIGHT	70
#define		LINEKEY_HEIGHT	22

enum ShiftMode {
	KEY_NORMAL = 0, KEY_CAPSHIFT, KEY_SHIFT, KEY_CAPS
} ;

extern "C" {
	TCHAR	MessageBuf[ 512 ] ;
#ifdef	_WIN32_WCE
	TCHAR	g_szDictBase[ MAX_PATH ] = TEXT("\\Dic") ;
#else	/* _WIN32_WCE */
	TCHAR	g_szDictBase[ MAX_PATH ] = TEXT("Dic") ;
#endif	/* _WIN32_WCE */
	BOOL	g_fUseCtrl = FALSE ;
	DWORD	g_dwPreWait = 0 ;
	DWORD	g_dwPostWait = 0 ;
	DWORD	g_fJis = 0 ;				/* JISペーストフラグ */
	HWND	g_hWndDialog = NULL ;
	DWORD	g_dwFepMode = 0 ;
	DWORD	g_dwSoftKey = 1 ;			/* 0:NONE, 1:HIRA, 2:ROMA, 3:1LINE */
	BOOL	g_fLeftPos = FALSE ;		/* 左位置フラグ */
	BOOL	g_fSaveDic = FALSE ;		/* 辞書保存フラグ */
	BOOL	g_fPredict = TRUE ;			/* 予測表示フラグ */
	DWORD	g_dwSelColor = 0x00FFFFFF ;
	DWORD	g_dwHotKey = 0 ;
} ;

HINSTANCE	g_hLib = 0 ;
BOOL	InitHotkey() ;
void	ReleaseHotkey() ;
BOOL	(*g_pRegisterHotKey)( HWND hWnd, int id, UINT fsModifiers, UINT vk ) = 0 ;
BOOL	(*g_pUnregisterHotKey)( HWND hWnd, int id ) = 0 ;

RomaText	g_Roma ;
InputMode	inputmode = JAPANESE ;
LPCSTR		g_szPrevSel = 0 ;

#ifdef	_WIN32_WCE
#define	isalpha(c)	(((c)>='a'&&(c)<='z')||((c)>='A'&&(c)<='Z'))
#endif	/* _WIN32_WCE */

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

	void	CreateFep( LPRECT pos ) ;

public:
	MainWindow( MainApp *app ) ;

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

	BOOL	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() ;
	BOOL	CheckClose() ;
	BOOL	SaveDic() ;
	void	WMHotKey( int idHotKey, UINT fuModifiers, UINT uVirtKey ) ;
	BOOL	GetNoClose() const { return m_fNoClose ; }

	static	BOOL	RegisterClass( HINSTANCE hInst ) ;
	static	LPCTSTR	GetClassName() { return szClassName ; }
} ;

/*
 * FEP行ウィンドウ
 */
class FepWindow : public Window {
	MainApp		*m_pApp ;			/* アプリケーションへのポインタ */
	HWND		m_hwndParent ;
	HWND		m_hwndRoma ;
	HWND		m_hwndHira ;
	HWND		m_hwndNormal ;
	HWND		m_hwndShift ;
	HWND		m_hwndCand ;
	HWND		m_hwndText ;
	HWND		m_hwndCurrent ;
	BOOL		m_fSend ;
	DWORD		m_dwSendMode ;
	CHAR		m_sFixed[ 256 ] ;
	DWORD		m_dwMuhenkan ;
	enum ShiftMode	m_smShifted ;

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

	BOOL	Create( HWND hWndMain ) ;

	BOOL	WMCreate( HWND hDlg ) ;
	void	WMChar( TCHAR c, LONG keydata ) ;
	BOOL	WMSysChar( TCHAR c, LONG keydata ) ;
	LRESULT	WMCommand( HWND hDlg, UINT msg, WPARAM wp, LPARAM lp ) ;
	void	WMActivate( WORD fActive, BOOL fMinimize, HWND hWnd ) ;

	void	SendText( LPCSTR sjis ) ;
	BOOL	ConfirmInput() ;
	BOOL	ConfirmFixed() ;

	void	ChangeKeyMode() ;
	void	SetParent( HWND hWndParent ) ;
	void	SetCurrent( HWND hWnd ) ;
	BOOL	IsCurrent( HWND hWnd ) const ;
	BOOL	CommandKey( Key* key ) ;
	void	JpnKey( Key* key ) ;
	void	NormalKey( Key* key ) ;
	void	CandKey( Key* key ) ;
	void	KeyEnter() ;
	void	KeyESC( BOOL bFromKey ) ;
	void	KeyBS() ;
	void	KeyUp() ;
	void	KeyDown() ;
	void	KeySpace( BOOL fForceSpace ) ;

	BOOL	GetFromClipboard( LPTSTR unicode, DWORD dstsize ) ;
	void	CodeConvSub( LPCTSTR ptr ) ;
	BOOL	CopyToClipboard( LPCTSTR unicode ) ;
	void	Hide() const ;
	void	FepSetParent( HWND hWnd, BOOL bForce ) ;
	BOOL	AddDict() ;
	void	AltConv() ;
	DWORD	GetSelect() const ;
	void	ToMuhenkan() ;
	void	NextCand() ;
	void	PrevCand() ;
	void	ChangeMuhenkan( WORD id ) ;
} ;

/*-------------------------------------------------------------------------*
 * MainApp
 *-------------------------------------------------------------------------*/
MainApp	*MainApp::g_pApp = 0 ;

MainApp::MainApp()
{
	m_pMainWnd = 0 ;
	g_pApp = this ;
	InitHotkey() ;
}

MainApp::~MainApp()
{
	ReleaseHotkey() ;
}

BOOL
MainApp::Create( HINSTANCE hInstance )
{
	DWORD	fReadDict ;

	m_hInst = hInstance ;

	if ( !ConfirmRegisterClass( m_hInst ) ) {
		return FALSE ;
	}
	if ( !SoftKeyRegisterClass( 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 */

	GetReg() ;

	SetCursor( LoadCursor(NULL, IDC_WAIT) ) ;
	fReadDict = readphrases() ;
	SetCursor( (HCURSOR) NULL ) ;
	if ( fReadDict ) {
		MessageBox( NULL, TEXT("Can't read dictionary"), TEXT("Error"), MB_OK|MB_ICONASTERISK ) ;
	}

	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 ;
	}

	if ( fReadDict ) {
		PostMessage( m_pMainWnd->get_hwnd(), WM_COMMAND, IDM_SETUP, 0 ) ;
	} else {
		PostMessage( m_pMainWnd->get_hwnd(), WM_COMMAND, IDM_ACTIVATE, (LPARAM) GetCenterWindow() ) ;
	}

	return TRUE ;
}

int
MainApp::Run()
{
	MSG		msg ;

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

BOOL
MainApp::GetReg()
{
	HKEY	hk ;
	LONG	lret ;
	LPCTSTR	name ;
	LPBYTE	lpData ;
	TCHAR	sValue[ 256 ] ;
	DWORD	dwType, cbData, dwValue = 0 ;

	/* レジストリキーをオープンする */
	lret = RegOpenKeyEx( HKEY_CURRENT_USER, GawaroBaseKey, 0,
						 KEY_QUERY_VALUE, &hk ) ;
	if ( lret == ERROR_SUCCESS ) {
		/* CTRL/ALT切り替え */
		name = VAR_USECTRL ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			g_fUseCtrl = dwValue ;
		}
		/* レジストリクローズ */
		RegCloseKey( hk ) ;
	}
	_tcscpy( sValue, GawaroBaseKey ) ;
	_tcscat( sValue, TEXT("\\") ) ;
	_tcscat( sValue, szTitleName ) ;
	/* レジストリキーをオープンする */
	lret = RegOpenKeyEx( HKEY_CURRENT_USER, sValue, 0,
						 KEY_QUERY_VALUE, &hk ) ;
	if ( lret == ERROR_SUCCESS ) {
		/* BaseDir */
		name = VAR_BASEDIR ;
		dwType = REG_SZ ;
		lpData = (LPBYTE) sValue ;
		cbData = sizeof sValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			_tcscpy( g_szDictBase, sValue ) ;
		}
		/* ペースト前の待ち秒数 */
		name = VAR_PREWAIT ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			g_dwPreWait = dwValue ;
		}
		/* ペースト後の待ち秒数 */
		name = VAR_POSTWAIT ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			g_dwPostWait = dwValue ;
		}
		/* JIS送信フラグ */
		name = VAR_JIS ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			g_fJis = dwValue ;
		}
		/* ソフトキーモード */
		name = VAR_SOFTKEY ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			g_dwSoftKey = dwValue ;
		}
		/* 左位置モード */
		name = VAR_LEFTPOS ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			g_fLeftPos = dwValue ;
		}
		/* 辞書保存モード */
		name = VAR_SAVEDIC ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			g_fSaveDic = dwValue ;
		}
		/* 予測表示モード */
		name = VAR_PREDICT ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			g_fPredict = dwValue ;
		}
		/* SelColor */
		name = VAR_SELCOLOR ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			g_dwSelColor = dwValue ;
		}
		/* HotKey */
		name = VAR_HOTKEY ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			g_dwHotKey = dwValue ;
		}
		/* レジストリクローズ */
		RegCloseKey( hk ) ;
	}
	return TRUE ;
}

void
MainApp::SetReg() const
{
	HKEY	hk ;
	LONG	lret ;
	LPTSTR	name ;
	LPBYTE	lpData ;
	TCHAR	sValue[ 256 ] ;
	DWORD	ret, dwType, cbData, dwValue ;

	_tcscpy( sValue, GawaroBaseKey ) ;
	_tcscat( sValue, TEXT("\\") ) ;
	_tcscat( sValue, szTitleName ) ;
	/* レジストリキーを作成する */
	lret = RegCreateKeyEx( HKEY_CURRENT_USER, sValue, 0, TEXT(""), 0,
#ifdef	_WIN32_WCE
						   0,
#else	/* _WIN32_WCE */
						   KEY_ALL_ACCESS,
#endif	/* _WIN32_WCE */
						   NULL, &hk, &ret ) ;
	if ( lret == ERROR_SUCCESS ) {
		/* 辞書ファイルパス名 */
		name = VAR_BASEDIR ;
		dwType = REG_SZ ;
		lpData = (LPBYTE) g_szDictBase ;
		cbData = (_tcslen(g_szDictBase) + 1) * sizeof (*g_szDictBase) ;
		lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
		/* ペースト前の待ち秒数 */
		name = VAR_PREWAIT ;
		dwType = REG_DWORD ;
		dwValue = g_dwPreWait ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
		/* ペースト後の待ち秒数 */
		name = VAR_POSTWAIT ;
		dwType = REG_DWORD ;
		dwValue = g_dwPostWait ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
		/* JIS送信フラグ */
		name = VAR_JIS ;
		dwType = REG_DWORD ;
		dwValue = g_fJis ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
		/* ソフトキーフラグ */
		name = VAR_SOFTKEY ;
		dwType = REG_DWORD ;
		dwValue = g_dwSoftKey ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
		/* 左位置フラグ */
		name = VAR_LEFTPOS ;
		dwType = REG_DWORD ;
		dwValue = g_fLeftPos ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
		/* 辞書保存モード */
		name = VAR_SAVEDIC ;
		dwType = REG_DWORD ;
		dwValue = g_fSaveDic ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
		/* 予測表示モード */
		name = VAR_PREDICT ;
		dwType = REG_DWORD ;
		dwValue = g_fPredict ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
		/* SelColor */
		name = VAR_SELCOLOR ;
		dwType = REG_DWORD ;
		dwValue = g_dwSelColor ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
		/* HotKey */
		name = VAR_HOTKEY ;
		dwType = REG_DWORD ;
		dwValue = g_dwHotKey ;
		lpData = (LPBYTE) &dwValue ;
		cbData = sizeof dwValue ;
		RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
		/* レジストリクローズ */
		RegCloseKey( hk ) ;
	}
}

void
MainApp::DeleteReg() const
{
	TCHAR	sValue[ 256 ] ;

	_tcscpy( sValue, GawaroBaseKey ) ;
	_tcscat( sValue, TEXT("\\") ) ;
	_tcscat( sValue, szTitleName ) ;
	RegDeleteKey( HKEY_CURRENT_USER, sValue ) ;
}

BOOL
MainApp::check_next_key() const
{
	BOOL	ret ;
	MSG		msg ;

	if ( g_dwSoftKey == 1 || g_dwSoftKey == 2 ) {
		ret = PeekMessage( &msg, NULL, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE ) ;
	} else {
		ret = PeekMessage( &msg, NULL, WM_KEYDOWN, WM_KEYDOWN, PM_NOREMOVE ) ;
	}
	if ( !ret ) {
		return FALSE ;
	}
	return TRUE ;
}

int
strwidth( LPCSTR str )
{
	return strlen( str ) * GetFontHW() ;
}

BOOL
havealpha( LPCSTR s )
{
	for ( ; *s ; s ++ ) {
		if ( isalpha( *s ) ) {
			return 1 ;
		}
	}
	return 0 ;
}

BOOL
check_next_key()
{
	static	int		count = 0 ;

	count ++ ;
	count %= 10 ;
	if ( count ) {
		return FALSE ;
	}
	if ( MainApp::g_pApp ) {
		return MainApp::g_pApp->check_next_key() ;
	}
	return FALSE ;
}

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

BOOL
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() ;
	/* ホットキーを登録する */
	if ( g_pRegisterHotKey && g_dwHotKey ) {
#ifdef	_WIN32_WCE
		(*g_pRegisterHotKey)( hWnd, 0x0000, HIWORD(g_dwHotKey), LOWORD(g_dwHotKey) ) ;
#endif
	} else {
		g_dwHotKey = 0 ;
	}
	return FALSE ;
}

/*
 * タスクバーに通知アイコンを登録する
 */
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 ;

	g_dwFepMode = index ;
	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()
{
#ifdef	_WIN32_WCE
	if ( g_pUnregisterHotKey ) {
		/* ホットキーを解除する */
		(*g_pUnregisterHotKey)( m_hWnd, 0x0000 ) ;
	}
#endif
	/* タスクバーアイコンを削除する */
	DeleteTaskBarIcon() ;
	if ( m_hIcon ) {
		::DeleteObject( m_hIcon ) ;
		m_hIcon = 0 ;
	}
	PostQuitMessage( 0 ) ;
}

BOOL
MainWindow::WMClose()
{
	if ( !CheckClose() ) {
		return TRUE ;
	}
	if ( m_fUninstall ) {
		m_pApp->DeleteReg() ;
	} else {
		m_pApp->SetReg() ;
	}
	return FALSE ;
}

BOOL
MainWindow::CheckClose()
{
	BOOL	ret = SaveDic() ;
	if ( m_fUninstall ) {
		ret = TRUE ;
	}
	return ret ;
}

BOOL
MainWindow::SaveDic()
{
	DWORD	ret ;

	SetCursor( LoadCursor(NULL, IDC_WAIT) ) ;
	ret = writephrases() ;
	SetCursor( (HCURSOR) NULL ) ;
	if ( ret ) {
		wsprintf( MessageBuf, TEXT("Can't save dictionary.\r\nerror = %d"), ret ) ;
		MessageBox( m_hWnd, MessageBuf, szTitleName, MB_OK|MB_ICONHAND ) ;
		return FALSE ;
	}
	return TRUE ;
}

void
MainWindow::WMHotKey( int idHotKey, UINT fuModifiers, UINT uVirtKey )
{
	SendMessage( m_hWnd, WM_COMMAND, (WPARAM) IDM_ACTIVATE, 0 ) ;
}

LRESULT
MainWindow::WMCommand( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	TCHAR	c ;
	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_COMMAND, IDM_ACTIVATE, 0 ) ;
				break ;
			}
		} else if ( lParam != WM_LBUTTONDBLCLK ) {
			break ;
		}
		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 | (g_fJis ? 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:
		g_fJis = g_fJis ? 0 : 1 ;
		break ;
	case IDM_ACTIVATE:
		lParam = 0 ;
		if ( g_dwFepMode ) {
			/* 漢字モードでなければ漢字モードにする */
			ModifyTaskBarIcon( 0 ) ;
		}
		//
	case IDM_ACTIVATE_HWND:
		if ( m_fNoMenu ) {
			break ;
		}
		m_fNoClose = cmd == IDM_ACTIVATE ;
		c = notifyCode ;
		hWndParent = (HWND) lParam ;
		if ( !hWndParent ) {
			hWndParent = GetCenterWindow() ;
		}
		m_pApp->get_fep()->SetParent( hWndParent ) ;
		if ( c ) {
			m_pApp->get_fep()->WMChar( c, 0 ) ;
		}
		break ;
	case IDM_FEPGETMODE:
		return g_dwFepMode ;
	case IDM_FEPSETMODE:
		ret = (DWORD) lParam ;
		if ( g_dwFepMode != ret && ret < 2 ) {
			ModifyTaskBarIcon( ret ) ;
		}
		break ;
	case IDM_ADDDICT:
	case IDM_ENTER:
	case IDM_ESCAPE:
	case IDM_BACKSPACE:
	case IDM_UP:
	case IDM_DOWN:
	case IDM_TAB:
	case IDM_NEXT:
	case IDM_PREV:
	case IDM_ZENHIRA:
	case IDM_ZENKATA:
	case IDM_HAN:
	case IDM_ROMA:
		SendMessage( m_pApp->get_fep()->get_hwnd(), msg, wParam, lParam ) ;
		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_UNINSTALL ) {
			m_fUninstall = TRUE ;
			SendMessage( hWnd, WM_CLOSE, 0, 0 ) ;
			break ;
		} else if ( ret & DIALOG_RET_CHANGEKEY ) {
			m_pApp->get_fep()->ChangeKeyMode() ;
		} else if ( ret & DIALOG_RET_CHANGEDICT ) {
			SetCursor( LoadCursor(NULL, IDC_WAIT) ) ;
			ret = readphrases() ;
			SetCursor( (HCURSOR) NULL ) ;
			if ( ret ) {
				MessageBox( NULL, TEXT("Can't read dictionary"), TEXT("Error"), MB_OK|MB_ICONASTERISK ) ;
				PostMessage( hWnd, WM_COMMAND, IDM_SETUP, 0 ) ;
			}
		}
		break ;
	}
	return 0 ;
}

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 ;
	m_hwndParent = 0 ;
	m_fSend = FALSE ;
	m_dwSendMode = 0 ;
	m_hwndCurrent = 0 ;
	m_dwMuhenkan = ROMA_NORMAL ;
	m_smShifted = KEY_NORMAL ;
	m_sFixed[ 0 ] = 0 ;
}

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 ;
}

BOOL
FepWindow::WMCreate( HWND hDlg )
{
	HINSTANCE		hInst = m_pApp->get_inst() ;

	m_hWnd = hDlg ;
	m_hwndText = ::CreateWindow( CTRL_CONFIRM,
						TEXT(""),
						WS_CHILD|WS_VISIBLE,
						0, 0, 240, 20,
						m_hWnd,
						(HMENU) IDC_TEXT,
						hInst, 0 ) ;
	SendMessage( m_hwndText, CONFIRM_SETCOLSEL, 0, (LPARAM) g_dwSelColor ) ;

	m_hwndCand = ::CreateWindow( CTRL_SOFTKEY,
						TEXT(""),
						WS_CHILD|WS_VISIBLE,
						0, 25, 240, 44,
						m_hWnd,
						(HMENU) IDC_CANDKEY,
						hInst, 0 ) ;
	SendMessage( m_hwndCand, SOFTKEY_SETLIST, 0, (LPARAM) candkey ) ;
	SendMessage( m_hwndCand, SOFTKEY_SETCOLSEL, 0, (LPARAM) g_dwSelColor ) ;

	m_hwndRoma = ::CreateWindow( CTRL_SOFTKEY,
						TEXT(""),
						WS_CHILD|WS_VISIBLE,
						0, 70, 240, 80,
						m_hWnd,
						(HMENU) IDC_ROMAKEY,
						hInst, 0 ) ;
	SendMessage( m_hwndRoma, SOFTKEY_SETLIST, 0, (LPARAM) g_KeyRoma ) ;
	SendMessage( m_hwndRoma, SOFTKEY_SETBITMAP, 0,
				 (LPARAM) LoadBitmap( hInst, MAKEINTRESOURCE(IDB_ROMAKEY) ) ) ;
	SendMessage( m_hwndRoma, SOFTKEY_SETCOLSEL, 0, (LPARAM) g_dwSelColor ) ;
	ShowWindow( m_hwndRoma, SW_HIDE ) ;

	m_hwndHira = ::CreateWindow( CTRL_SOFTKEY,
						TEXT(""),
						WS_CHILD|WS_VISIBLE,
						0, 70, 240, 80,
						m_hWnd,
						(HMENU) IDC_HIRAKEY,
						hInst, 0 ) ;
	SendMessage( m_hwndHira, SOFTKEY_SETLIST, 0, (LPARAM) g_KeyHira ) ;
	SendMessage( m_hwndHira, SOFTKEY_SETBITMAP, 0,
				 (LPARAM) LoadBitmap( hInst, MAKEINTRESOURCE(IDB_HIRAKEY) ) ) ;
	SendMessage( m_hwndHira, SOFTKEY_SETCOLSEL, 0, (LPARAM) g_dwSelColor ) ;
	ShowWindow( m_hwndHira, SW_HIDE ) ;

	m_hwndNormal = ::CreateWindow( CTRL_SOFTKEY,
						TEXT(""),
						WS_CHILD|WS_VISIBLE,
						0, 70, 240, 80,
						m_hWnd,
						(HMENU) IDC_NORMALKEY,
						hInst, 0 ) ;
	SendMessage( m_hwndNormal, SOFTKEY_SETLIST, 0, (LPARAM) g_KeyNormal ) ;
	SendMessage( m_hwndNormal, SOFTKEY_SETBITMAP, 0,
				 (LPARAM) LoadBitmap( hInst, MAKEINTRESOURCE(IDB_NORMALKEY) ) ) ;
	SendMessage( m_hwndNormal, SOFTKEY_SETCOLSEL, 0, (LPARAM) g_dwSelColor ) ;
	ShowWindow( m_hwndNormal, SW_HIDE ) ;

	m_hwndShift = ::CreateWindow( CTRL_SOFTKEY,
						TEXT(""),
						WS_CHILD|WS_VISIBLE,
						0, 70, 240, 80,
						m_hWnd,
						(HMENU) IDC_SHIFTKEY,
						hInst, 0 ) ;
	SendMessage( m_hwndShift, SOFTKEY_SETLIST, 0, (LPARAM) g_KeyShift ) ;
	SendMessage( m_hwndShift, SOFTKEY_SETBITMAP, 0,
				 (LPARAM) LoadBitmap( hInst, MAKEINTRESOURCE(IDB_SHIFTKEY) ) ) ;
	SendMessage( m_hwndShift, SOFTKEY_SETCOLSEL, 0, (LPARAM) g_dwSelColor ) ;
	ShowWindow( m_hwndShift, SW_HIDE ) ;

	ChangeKeyMode() ;

	return FALSE ;
}

void
FepWindow::ChangeKeyMode()
{
	OSVERSIONINFO	os ;
	BOOL			bVer10 = TRUE ;
	DWORD			x, y ;
	DWORD			bw, bh ;
	DWORD			bx1, by1, bw1, bh1 ;
	DWORD			bx2, by2, bw2, bh2 ;

	inputmode = JAPANESE ;
	if ( m_hwndCurrent ) {
		ShowWindow( m_hwndCurrent, SW_HIDE ) ;
	}
	switch ( g_dwSoftKey ) {
	case 1:
		/* かなキーボード */
		m_hwndCurrent = m_hwndHira ;
		ShowWindow( m_hwndCurrent, SW_SHOW ) ;
		/* FEP画面の調整 */
		bw = SOFTKEY_WIDTH, bh = SOFTKEY_HEIGHT ;
		x = g_fLeftPos ? 0 : GetSystemMetrics( SM_CXSCREEN ) - bw ;
		y = GetSystemMetrics( SM_CYSCREEN ) - bh - 26 ;
		/* 確定表示領域の位置調整 */
		bx1 = 0, by1 = 0, bw1 = 240, bh1 = 20 ;
		/* 候補表示領域の位置調整 */
		bx2 = 0, by2 = 25, bw2 = 240, bh2 = 44 ;
		break ;
	case 2:
		/* ローマ字キーボード */
		m_hwndCurrent = m_hwndRoma ;
		ShowWindow( m_hwndCurrent, SW_SHOW ) ;
		/* FEP画面の調整 */
		bw = SOFTKEY_WIDTH, bh = SOFTKEY_HEIGHT ;
		x = g_fLeftPos ? 0 : GetSystemMetrics( SM_CXSCREEN ) - bw ;
		y = GetSystemMetrics( SM_CYSCREEN ) - bh - 26 ;
		/* 確定表示領域の位置調整 */
		bx1 = 0, by1 = 0, bw1 = 240, bh1 = 20 ;
		/* 候補表示領域の位置調整 */
		bx2 = 0, by2 = 25, bw2 = 240, bh2 = 44 ;
		break ;
	case 3:
		/* 1行モード */
		m_hwndCurrent = 0 ;
		/* FEP画面の調整 */
		bw = GetSystemMetrics( SM_CXSCREEN ) - GetSystemMetrics( SM_CXVSCROLL ) - 8 ;
		bh = LINEKEY_HEIGHT ;
		x = 2 ;
		y = GetSystemMetrics( SM_CYSCREEN ) - bh - 2 ;
		/* 確定表示領域の位置調整 */
		bx1 = 0, by1 = 0, bw1 = bw / 2, bh1 = LINEKEY_HEIGHT ;
		/* 候補表示領域の位置調整 */
		bx2 = bw1, by2 = 0, bw2 = bw / 2, bh2 = LINEKEY_HEIGHT ;
		break ;
	default:
		/* ソフトキーボードなし */
		m_hwndCurrent = 0 ;
		/* FEP画面の調整 */
		bw = GetSystemMetrics( SM_CXSCREEN ) ;
		if ( bw >= 480 ) {
			bw /= 2 ;
		}
		bh = NONEKEY_HEIGHT ;
		x = g_fLeftPos ? 0 : GetSystemMetrics( SM_CXSCREEN ) - bw ;
		y = GetSystemMetrics( SM_CYSCREEN ) - bh - 26 ;
		/* 確定表示領域の位置調整 */
		bx1 = 0, by1 = 0, bw1 = bw, bh1 = 20 ;
		/* 候補表示領域の位置調整 */
		bx2 = 0, by2 = 25, bw2 = bw, bh2 = 44 ;
		break ;
	}
	memset( &os, 0, sizeof os ) ;
	os.dwOSVersionInfoSize = sizeof os ;
	if ( GetVersionEx( &os ) && os.dwMajorVersion > 1 ) {
		SetWindowPos( m_hWnd, (HWND)-1, x, y, bw, bh, 0 ) ;
	} else {
		MoveWindow( m_hWnd, x, y, bw, bh, FALSE ) ;
	}
	MoveWindow( m_hwndText, bx1, by1, bw1, bh1, FALSE ) ;
	g_CandPos.width = bw2, g_CandPos.height = bh2 ;
	MoveWindow( m_hwndCand, bx2, by2, bw2, bh2, FALSE ) ;
}

void
FepWindow::WMChar( TCHAR c, LONG keydata )
{
	CHAR	buf[ 2 ] ;

	if ( c == TEXT(' ') ) {
		if ( g_fUseCtrl && (GetKeyState( VK_CONTROL) & 0x80) ) {
			/* Ctrl+SPACEが押された場合 */
			ToMuhenkan() ;
		} else {
			KeySpace( GetKeyState( VK_SHIFT ) & 0x80 ) ;
		}
	} else if ( c > TEXT(' ') ) {
		if ( GetSelect() ) {
			Key*	key = (Key*) SendMessage( m_hwndCand, SOFTKEY_GETCURCAND, 0, 0 ) ;
			if ( key ) {
				CandKey( key ) ;
			} else {
				SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
			}
		}
		if ( m_dwMuhenkan ) {
			g_Roma.getmuhenkan( m_dwMuhenkan, &m_sFixed[ strlen( m_sFixed ) ] ) ;
			SendMessage( m_hwndText, CONFIRM_SETFIXED, 0, (LPARAM) m_sFixed ) ;
			m_dwMuhenkan = ROMA_NORMAL ;
			g_Roma.clear() ;
		}
		buf[0] = (CHAR) c ;
		buf[1] = 0 ;
		if ( inputmode == JAPANESE ) {
			m_dwMuhenkan = ROMA_NORMAL ;
			if ( g_dwSoftKey == 1 ) {
				g_Roma.addstr( buf ) ;
			} else {
				g_Roma.addromachar( *buf ) ;
			}
			g_Roma.getkana( hstr ) ;
			makecand( NEWCAND, FALSE ) ;
			SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
		} else {
			ConfirmInput() ;
			strcat( m_sFixed, buf ) ;
			ConfirmFixed() ;
		}
		SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
		InvalidateRect( m_hwndCand, NULL, TRUE ) ;
	}
}

BOOL
FepWindow::WMSysChar( TCHAR c, LONG keydata )
{
	if ( c == TEXT(' ') ) {
		if ( !g_fUseCtrl && (keydata & 0x20000000) ) {
			/* ALT+SPACEが押された場合 */
			ToMuhenkan() ;
			return TRUE ;
		}
	}
	return FALSE ;
}

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

void
FepWindow::SetParent( HWND hWndParent )
{
	FepSetParent( hWndParent, FALSE ) ;
	ShowWindow( m_hWnd, SW_SHOW ) ;
	SetForegroundWindow( m_hWnd ) ;
}

/*
 * 入力対象となるウィンドウを設定する
 */
void
FepWindow::FepSetParent( HWND hWnd, BOOL bForce )
{
	TCHAR	tmpbuf[ 128 ] ;
	BOOL	bUnknown = FALSE ;
	HWND	hWndTmp, hWndPrev = hWnd ;

	m_hwndParent = hWnd ;
	if ( !bForce ) {
		while ( 1 ) {
			*tmpbuf = 0 ;
			GetClassName( m_hwndParent, tmpbuf, 128 ) ;
			if ( !_tcsicmp( tmpbuf, TEXT("BOOKWIN") ) ) {
				m_dwSendMode = IDM_PEXCEL ;
				return ;
			} else if ( !_tcsicmp( tmpbuf, TEXT("Pocket Word") ) ) {
				m_dwSendMode = 0 ;
				return ;
			} else if ( !_tcsicmp( tmpbuf, TEXT("Explore") ) ) {
				m_dwSendMode = 1 ;
				return ;
			} else if ( !_tcsicmp( tmpbuf, TEXT("Calendar") ) ) {
				m_dwSendMode = 0 ;
				return ;
			} else if ( !_tcsicmp( tmpbuf, TEXT("Dialog") ) ) {
				*tmpbuf = 0 ;
				GetWindowText( m_hwndParent, tmpbuf, 128 ) ;
				if ( !_tcsicmp( tmpbuf, TEXT("Confirm Name") ) ) {
					m_dwSendMode = 0 ;
					return ;
				} else if ( !*tmpbuf ) {
					goto next ;
				}
//				MessageBox( NULL, tmpbuf, TEXT("(2)"), MB_OK ) ;
				hWndTmp = GetParent( m_hwndParent ) ;
				if ( hWndTmp ) {
					*tmpbuf = 0 ;
					GetClassName( hWndTmp, tmpbuf, 128 ) ;
					if ( !_tcsicmp( tmpbuf, TEXT("Calendar") ) ) {
						m_dwSendMode = 0 ;
						m_hwndParent = bUnknown ? hWndPrev : m_hwndParent ;
						return ;
					} else if ( !_tcsicmp( tmpbuf, TEXT("Tasks Application") ) ) {
						m_dwSendMode = 0 ;
						m_hwndParent = bUnknown ? hWndPrev : m_hwndParent ;
						return ;
					} else if ( !_tcsicmp( tmpbuf, TEXT("Contacts") ) ) {
						m_dwSendMode = 0 ;
						return ;
					} else if ( !_tcsicmp( tmpbuf, TEXT("Dialog") ) ) {
						bUnknown = TRUE ;
					} else if ( !_tcsicmp( tmpbuf, TEXT("BOOKWIN") ) ) {
						/* Pocket Excel Find Dialog */
						m_dwSendMode = 0 ;
						return ;
					} else {
//						MessageBox( NULL, tmpbuf, TEXT("(1)"), MB_OK ) ;
					}
				}
			} else if ( !_tcsicmp( tmpbuf, TEXT("ASForm") ) ) {
			} else if ( !_tcsncmp( tmpbuf, TEXT("ATL:"), 4 ) ) {
			} else {
//				MessageBox( NULL, tmpbuf, TEXT("(4)"), MB_OK ) ;
			}
next:
			hWndPrev = m_hwndParent ;
			m_hwndParent = GetParent( m_hwndParent ) ;
			if ( !m_hwndParent ) {
				if ( !_tcsicmp( tmpbuf, TEXT("static") ) ) {
					m_dwSendMode = IDM_UNKNOWN ;
				} else {
					m_dwSendMode = 0 ;
				}
				m_hwndParent = hWndPrev ;
				break ;
			}
		}
	}
	m_dwSendMode = SendMessage( hWnd, WM_COMMAND, IDM_FEPOK, 0 ) ;
	if ( m_dwSendMode ) {
		m_hwndParent = hWnd ;
	}
}

/*
 * 文字列を入力対象ウィンドウに送る
 */
void
FepWindow::SendText( LPCSTR sjis )
{
	COPYDATASTRUCT	cds ;
	HWND			hWnd ;
	TCHAR			unicode[ 128 ], c, *ptr ;
	BOOL			fNoClose = m_pApp->get_main()->GetNoClose() ;

	if ( !m_hwndParent ) {
		return ;
	}
	sjis2unicode( (LPBYTE) sjis, unicode, sizeof unicode ) ;
	/* 送信中はHIDEしない */
	m_fSend = TRUE ;
	if ( m_dwSendMode == IDM_UNKNOWN ) {
		FepSetParent( GetCenterWindow(), FALSE ) ;
		if ( m_dwSendMode == IDM_UNKNOWN ) {
			m_dwSendMode = 0 ;
		}
	}
	/* 送信方法に応じて送信を行う */
	if ( m_dwSendMode == IDM_FEPOK ) {
		/* WM_COPYDATAで送信する場合 */
		cds.dwData = 0 ;
		cds.cbData = (_tcslen( unicode ) + 1) * sizeof (TCHAR) ;
		cds.lpData = (PBYTE) unicode ;
		SendMessage( m_hwndParent, WM_COPYDATA, (WPARAM) m_hWnd, (LPARAM) &cds ) ;
	} else if ( m_dwSendMode == IDM_FEPCHAR ) {
		/* IDM_FEPCHARで送信する場合 */
		ptr = unicode ;
		while ( c = *ptr++ ) {
			SendMessage( m_hwndParent, WM_COMMAND, (WPARAM) IDM_FEPCHAR, (LPARAM) c ) ;
		}
	} else if ( m_dwSendMode == IDM_WMCHAR ) {
		/* WM_CHARで送信する場合 */
		ptr = unicode ;
		while ( c = *ptr++ ) {
			SendMessage( m_hwndParent, WM_CHAR, (WPARAM) c, 0 ) ;
		}
	} else if ( m_dwSendMode != IDM_UNKNOWN ) {
		/* クリップボードにコピーする */
		CopyToClipboard( unicode ) ;
		/* 送信先のウィンドウをアクティブにする */
		hWnd = GetForegroundWindow() ;
		SetForegroundWindow( m_hwndParent ) ;
		SetActiveWindow( m_hwndParent ) ;
		if ( m_dwSendMode == IDM_EXPLORE ) {
			Sleep( 100 ) ;
			SetForegroundWindow( hWnd ) ;
			SetActiveWindow( m_hWnd ) ;
			Sleep( 100 ) ;
			SetForegroundWindow( m_hwndParent ) ;
			SetActiveWindow( m_hwndParent ) ;
		}
		Sleep( g_dwPreWait * 100 ) ;
		if ( GetForegroundWindow() == hWnd ) {
			MessageBeep( MB_ICONASTERISK ) ;
		}
		if ( !*unicode || !_tcscmp( unicode, TEXT("\n") ) ) {
			keybd_event( VK_RETURN, 0, 0, 0 ) ;
			keybd_event( VK_RETURN, 0, KEYEVENTF_KEYUP, 0 ) ;
		} else {
			/* ペースト用のキーコードを送信する */
			keybd_event( VK_CONTROL, 0, 0, 0 ) ;
			keybd_event( 0x56, 0, 0, 0 ) ;
			keybd_event( 0x56, 0, KEYEVENTF_KEYUP, 0 ) ;
			keybd_event( VK_CONTROL, 0, KEYEVENTF_KEYUP, 0 ) ;
		}
		Sleep( g_dwPostWait * 100 ) ;
		if ( fNoClose ) {
			/* FEPウィンドウをアクティブにする */
			SetForegroundWindow( hWnd ) ;
			SetActiveWindow( m_hWnd ) ;
		}
	}
	m_fSend = FALSE ;
	if ( !fNoClose ) {
		Hide() ;
	}
}

/*
 * 入力中の未確定文字列を確定する
 */
BOOL
FepWindow::ConfirmInput()
{
	if ( !strlen( hstr ) ) {
		return FALSE ;
	}
	g_Roma.getmuhenkan( m_dwMuhenkan, &m_sFixed[ strlen( m_sFixed ) ] ) ;
	m_dwMuhenkan = ROMA_NORMAL ;
	g_Roma.clear() ;
	g_Roma.getkana( hstr ) ;
	makecand( NEWCAND, FALSE ) ;
	SendMessage( m_hwndText, CONFIRM_SETFIXED, 0, (LPARAM) m_sFixed ) ;
	return TRUE ;
}

/*
 * 入力中の確定文字列を送信する
 */
BOOL
FepWindow::ConfirmFixed()
{
	if ( !strlen( m_sFixed ) ) {
		return FALSE ;
	}
	SendText( m_sFixed ) ;
	strcpy( m_sFixed, "" ) ;
	SendMessage( m_hwndText, CONFIRM_SETFIXED, 0, (LPARAM) m_sFixed ) ;
	return TRUE ;
}

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

	switch ( cmd ) {
	case IDC_ROMAKEY:
	case IDC_HIRAKEY:
		JpnKey( (Key*) lParam ) ;
		break ;
	case IDC_NORMALKEY:
		NormalKey( (Key*) lParam ) ;
		break ;
	case IDC_SHIFTKEY:
		NormalKey( (Key*) lParam ) ;
		break ;
	case IDC_CANDKEY:
		CandKey( (Key*) lParam ) ;
		break ;
	case IDM_NOTIFY:
		SetForegroundWindow( m_hWnd ) ;
		break ;
	case IDC_TEXT:
		if ( notifyCode == CONFIRMN_CHAR ) {
			WMChar( (TCHAR) lParam, 0 ) ;
		}
		break ;
	case IDM_ENTER:
		KeyEnter() ;
		break ;
	case IDM_ESCAPE:
		KeyESC( TRUE ) ;
		break ;
	case IDM_BACKSPACE:
		KeyBS() ;
		break ;
	case IDM_UP:
		KeyUp() ;
		break ;
	case IDM_DOWN:
		KeyDown() ;
		break ;
	case IDM_ADDDICT:
		/* 登録 */
		AddDict() ;
		break ;
	case IDM_TAB:
		/* 異体字 */
		AltConv() ;
		break ;
	case IDM_NEXT:
		/* 次候補 */
		NextCand() ;
		break ;
	case IDM_PREV:
		/* 前候補 */
		PrevCand() ;
		break ;
	case IDM_ZENHIRA:
	case IDM_ZENKATA:
	case IDM_HAN:
	case IDM_ROMA:
		ChangeMuhenkan( cmd ) ;
		break ;
	}
	return 0 ;
}

void
FepWindow::SetCurrent( HWND hWnd )
{
	if ( !hWnd || hWnd == m_hwndCurrent ) {
		return ;
	}
	ShowWindow( hWnd, SW_SHOW ) ;
	if ( m_hwndCurrent ) {
		ShowWindow( m_hwndCurrent, SW_HIDE ) ;
	}
	m_hwndCurrent = hWnd ;
}

BOOL
FepWindow::IsCurrent( HWND hWnd ) const
{
	return m_hwndCurrent == hWnd ;
}

BOOL
FepWindow::CommandKey( Key* key )
{
	if ( !strcmp( key->str, ENTERSTR ) ) {
		/* 改行 */
		KeyEnter() ;
	} else if ( !strcmp( key->str, MODSTR ) ) {
		/* 登録 */
		AddDict() ;
	} else if ( !strcmp( key->str, DELSTR ) ) {
		/* 削除 */
		KeyBS() ;
	} else if ( !strcmp( key->str, CANSTR ) ) {
		/* 取消 */
		KeyESC( FALSE ) ;
	} else if ( !strcmp( key->str, ALTSTR ) ) {
		/* 異体字 */
		AltConv() ;
	} else if ( !strcmp( key->str, PREVSTR ) ) {
		/* 前候補 */
		PrevCand() ;
	} else if ( !strcmp( key->str, NEXTSTR ) ) {
		/* 次候補 */
		NextCand() ;
	} else {
		return FALSE ;
	}
	SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
	InvalidateRect( m_hwndCand, NULL, TRUE ) ;
	return TRUE ;
}

void
FepWindow::JpnKey( Key* key1 )
{
	if ( CommandKey( key1 ) ) {
		return ;
	}
	if ( !strcmp( key1->str, UPSTR ) ) {
		if ( strlen( hstr ) || strlen( m_sFixed ) ) {
			PrevCand() ;
		} else {
//			SendVirtualKey( VK_UP, KEYEVENTF_SILENT ) ;
		}
	} else if ( !strcmp( key1->str, DOWNSTR ) ) {
		if ( strlen( hstr ) || strlen( m_sFixed ) ) {
			NextCand() ;
		} else {
//			SendVirtualKey( VK_DOWN, KEYEVENTF_SILENT ) ;
		}
	} else if ( !strcmp( key1->str, LEFTSTR ) ) {
		if ( strlen( hstr ) || strlen( m_sFixed ) ) {
			KeyUp() ;
		} else {
//			SendVirtualKey( VK_LEFT, KEYEVENTF_SILENT ) ;
		}
	} else if ( !strcmp( key1->str, RIGHTSTR ) ) {
		if ( strlen( hstr ) || strlen( m_sFixed ) ) {
			KeyDown() ;
		} else {
//			SendVirtualKey( VK_RIGHT, KEYEVENTF_SILENT ) ;
		}
	} else if ( !strcmp( key1->str, HANSTR ) ) {
		ChangeMuhenkan( IDM_HAN ) ;
		return ;
	} else if ( !strcmp( key1->str, ZENSTR ) ) {
		ChangeMuhenkan( IDM_ROMA ) ;
		return ;
	} else if ( !strcmp( key1->str, KATASTR ) ) {
		ChangeMuhenkan( IDM_ZENKATA ) ;
		return ;
	} else if ( !strcmp( key1->str, ENGSTR ) ) {
		inputmode = ENGLISH ;
		m_smShifted = KEY_NORMAL ;
		SetCurrent( m_hwndNormal ) ;
		SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
		InvalidateRect( m_hwndCand, NULL, TRUE ) ;
		return ;
	} else if ( inputmode == JAPANESE ) {
		m_dwMuhenkan = ROMA_NORMAL ;
		if ( g_dwSoftKey == 1 ) {
			g_Roma.addstr( key1->yomi ) ;
		} else {
			g_Roma.addromachar( (CHAR) *key1->yomi ) ;
		}
		g_Roma.getkana( hstr ) ;
		makecand( NEWCAND, FALSE ) ;
		SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
	} else {
		ConfirmInput() ;
		strcat( m_sFixed, key1->yomi ) ;
		ConfirmFixed() ;
	}
	SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
	InvalidateRect( m_hwndCand, NULL, TRUE ) ;
}

void
FepWindow::NormalKey( Key* key )
{
	if ( CommandKey( key ) ) {
		return ;
	}
	if ( !strcmp( key->str, UPSTR ) ) {
//		SendVirtualKey( VK_UP, KEYEVENTF_SILENT ) ;
	} else if ( !strcmp( key->str, DOWNSTR ) ) {
//		SendVirtualKey( VK_DOWN, KEYEVENTF_SILENT ) ;
	} else if ( !strcmp( key->str, LEFTSTR ) ) {
//		SendVirtualKey( VK_LEFT, KEYEVENTF_SILENT ) ;
	} else if ( !strcmp( key->str, RIGHTSTR ) ) {
//		SendVirtualKey( VK_RIGHT, KEYEVENTF_SILENT ) ;
	} else if ( !strcmp( key->str, TABSTR ) ) {
		SendText( "\t" ) ;
	} else if ( !strcmp( key->str, JPNSTR ) ) {
		inputmode = JAPANESE ;
		m_smShifted = KEY_NORMAL ;
		SetCurrent( g_dwSoftKey == 1 ? m_hwndHira : m_hwndRoma ) ;
		SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
		InvalidateRect( m_hwndCand, NULL, TRUE ) ;
		return ;
	} else if ( !strcmp( key->str, SFTSTR ) ) {
		switch ( m_smShifted ) {
		case KEY_NORMAL:	m_smShifted = KEY_SHIFT ;		break ;
		case KEY_CAPSHIFT:	m_smShifted = KEY_CAPS ;		break ;
		case KEY_SHIFT:		m_smShifted = KEY_NORMAL ;		break ;
		case KEY_CAPS:		m_smShifted = KEY_CAPSHIFT ;	break ;
		}
		SetCurrent( m_smShifted == KEY_SHIFT || m_smShifted == KEY_CAPS ? m_hwndShift : m_hwndNormal ) ;
		return ;
	} else if ( !strcmp( key->str, CAPSTR ) ) {
		switch ( m_smShifted ) {
		case KEY_NORMAL:	m_smShifted = KEY_CAPS ;		break ;
		case KEY_CAPSHIFT:	m_smShifted = KEY_SHIFT ;		break ;
		case KEY_SHIFT:		m_smShifted = KEY_CAPSHIFT ;	break ;
		case KEY_CAPS:		m_smShifted = KEY_NORMAL ;		break ;
		}
		SetCurrent( m_smShifted == KEY_SHIFT || m_smShifted == KEY_CAPS ? m_hwndShift : m_hwndNormal ) ;
		return ;
	} else {
		JpnKey( key ) ;
		switch ( m_smShifted ) {
		case KEY_SHIFT:
			m_smShifted = KEY_NORMAL ;
			SetCurrent( m_hwndNormal ) ;
			break ;
		case KEY_CAPSHIFT:
			m_smShifted = KEY_CAPS ;
			SetCurrent( m_hwndShift ) ;
			break ;
		}
	}
}

void
FepWindow::CandKey( Key* key1 )
{
	strcat( outstr, key1->str ) ;
	if ( inputmode == ENGLISH ) {
		strcat( m_sFixed, " " ) ;
	}
	havealpha( key1->str ) ;
	g_Roma.clear() ;
	g_Roma.getkana( hstr ) ;
	g_szPrevSel = addphrase( g_szPrevSel, key1->str, key1->yomi, FALSE ) ;
	strcat( m_sFixed, key1->str ) ;
	makecand( NEWCAND, FALSE ) ;
	SendMessage( m_hwndText, CONFIRM_SETFIXED, 0, (LPARAM) m_sFixed ) ;
	SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
	SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
	InvalidateRect( m_hwndCand, NULL, TRUE ) ;
}

/*
 * 改行
 */
void
FepWindow::KeyEnter()
{
	if ( g_dwNumCand && GetSelect() ) {
		Key*	key = (Key*) SendMessage( m_hwndCand, SOFTKEY_GETCURCAND, 0, 0 ) ;
		if ( key ) {
			CandKey( key ) ;
			return ;
		}
		SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
	}
	if ( ConfirmInput() ) {
	} else if ( ConfirmFixed() ) {
	} else {
		SendText( "\n" ) ;
	}
	SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
	InvalidateRect( m_hwndCand, NULL, TRUE ) ;
}

/*
 * 取消
 */
void
FepWindow::KeyESC( BOOL bFromKey )
{
	if ( g_dwNumCand && GetSelect() ) {
		/* 取消(候補の取消) */
		SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
		return ;
	}
	if ( strlen( hstr ) ) {
		m_dwMuhenkan = ROMA_NORMAL ;
		g_Roma.clear() ;
		g_Roma.getkana( hstr ) ;
	} else if ( strlen( m_sFixed ) ) {
		strcpy( m_sFixed, "" ) ;
		SendMessage( m_hwndText, CONFIRM_SETFIXED, 0, (LPARAM) m_sFixed ) ;
	} else if ( bFromKey ) {
		/* キーボード入力の場合はウィンドウを隠す */
		Hide() ;
		return ;
	} else {
		/* 取消キーを送る */
		SendText( "\x1B" ) ;
		return ;
	}
	makecand( NEWCAND, FALSE ) ;
	SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
	InvalidateRect( m_hwndCand, NULL, TRUE ) ;
}

/*
 * 削除
 */
void
FepWindow::KeyBS()
{
	int		len ;
	TCHAR	unicode[ 256 ] ;

	if ( *hstr ) {
		if ( GetSelect() ) {
			SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
			return ;
		}
		/* 入力中の文字を削除する */
		m_dwMuhenkan = ROMA_NORMAL ;
		g_Roma.backspace() ;
		g_Roma.getkana( hstr ) ;
		makecand( NEWCAND, FALSE ) ;
	} else {
		sjis2unicode( (LPBYTE) m_sFixed, unicode, sizeof unicode ) ;
		len = _tcslen( unicode ) ;
		if ( len ) {
			/* 入力済の文字を削除する */
			unicode[ -- len ] = 0 ;
			unicode2sjis( unicode, (LPBYTE) m_sFixed, sizeof m_sFixed ) ;
			SendMessage( m_hwndText, CONFIRM_SETFIXED, 0, (LPARAM) m_sFixed ) ;
		} else {
			/* BSキーを送る */
			SendText( "\x08" ) ;
		}
	}
	SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
	InvalidateRect( m_hwndCand, NULL, TRUE ) ;
}

/*
 * 上キー
 */
void
FepWindow::KeyUp()
{
	DWORD	ret = GetSelect() ;

	if ( ret > 1 ) {
		SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, ret - 1 ) ;
	} else {
		if ( g_dwCandIndex ) {
			makecand( PREVCAND, FALSE ) ;
			SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, g_dwNumCand ) ;
		} else if ( ret ) {
			SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
		}
	}
}

/*
 * 下キー
 */
void
FepWindow::KeyDown()
{
	int		ret = GetSelect() + 1 ;

	if ( check_abort() ) {
		makecand( NEWCAND, TRUE ) ;
	}
	if ( !g_dwNumCand ) {
		return ;
	} else if ( ret > g_dwNumCand ) {
		makecand( NEXTCAND, FALSE ) ;
		ret = 1 ;
	}
	SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, ret ) ;
}

/*
 * 候補選択
 */
void
FepWindow::KeySpace( BOOL fForceSpace )
{
	int		len ;

	if ( !g_dwNumCand || fForceSpace ) {
		/* 空白文字列を追加する場合 */
		if ( strlen( hstr ) ) {
			g_Roma.getmuhenkan( m_dwMuhenkan, &m_sFixed[ strlen( m_sFixed ) ] ) ;
			m_dwMuhenkan = ROMA_NORMAL ;
			g_Roma.clear() ;
			g_Roma.getkana( hstr ) ;
		}
		len = strlen( m_sFixed ) ;
		if ( len && m_sFixed[ len - 1 ] == ' ' ) {
			strcpy( &m_sFixed[ len - 1 ], "　" ) ;
		} else {
			m_sFixed[ len ++ ] = ' ' ;
			m_sFixed[ len ] = 0 ;
		}
		makecand( NEWCAND, FALSE ) ;
		SendMessage( m_hwndText, CONFIRM_SETFIXED, 0, (LPARAM) m_sFixed ) ;
		SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
		SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
		InvalidateRect( m_hwndCand, NULL, TRUE ) ;
	} else {
		KeyDown() ;
	}
}

BOOL
FepWindow::AddDict()
{
	TCHAR	unicode[ 128 ] ;

	if ( !*hstr ) {
		/* 読みを入力していない場合 */
		MessageBeep( MB_ICONHAND ) ;
		return FALSE ;
	} else if ( !*m_sFixed ) {
		/* 登録文字列がない場合はクリップボードを参照 */
		if ( !GetFromClipboard( unicode, sizeof unicode ) ) {
			MessageBeep( MB_ICONHAND ) ;
		} else {
			/* クリップボード内の文字列を入力済文字列に移す */
			unicode2sjis( unicode, (LPBYTE) m_sFixed, sizeof m_sFixed ) ;
			SendMessage( m_hwndText, CONFIRM_SETFIXED, 0, (LPARAM) m_sFixed ) ;
		}
		return FALSE ;
	}
	g_szPrevSel = addphrase( g_szPrevSel, m_sFixed, hstr, TRUE ) ;
	makecand( NEWCAND, FALSE ) ;
	/* 辞書登録の後は読みを消す */
	m_dwMuhenkan = ROMA_NORMAL ;
	g_Roma.clear() ;
	g_Roma.getkana( hstr ) ;
	SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
	SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
	InvalidateRect( m_hwndCand, NULL, TRUE ) ;
	MessageBeep( MB_ICONINFORMATION ) ;
	return TRUE ;
}

void
FepWindow::AltConv()
{
	if ( !*hstr ) {
		return ;
	}
	itaiconv( hstr, hstr ) ;
	g_Roma.setkana( hstr ) ;
	SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
	InvalidateRect( m_hwndCand, NULL, TRUE ) ;
}

DWORD
FepWindow::GetSelect() const
{
	return SendMessage( m_hwndCand, SOFTKEY_GETCUR, 0, 0 ) ;
}

void
FepWindow::ToMuhenkan()
{
	SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 0 ) ;
	g_Roma.clear() ;
	g_Roma.getkana( hstr ) ;
	strcpy( m_sFixed, "" ) ;
	SendMessage( m_hwndText, CONFIRM_SETFIXED, 0, (LPARAM) m_sFixed ) ;
	makecand( NEWCAND, FALSE ) ;
	SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) hstr ) ;
	Hide() ;
	m_pApp->get_main()->ModifyTaskBarIcon( 1 ) ;
}

void
FepWindow::NextCand()
{
	makecand( NEXTCAND, FALSE ) ;
	SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 1 ) ;
}

void
FepWindow::PrevCand()
{
	makecand( PREVCAND, FALSE ) ;
	SendMessage( m_hwndCand, SOFTKEY_SETCUR, 0, 1 ) ;
}

void
FepWindow::ChangeMuhenkan( WORD id )
{
	CHAR	buf[ 128 ] ;
	DWORD	muhenkan = m_dwMuhenkan ;

	switch ( id ) {
	case IDM_ZENHIRA:
		if ( *hstr ) {
			muhenkan = ROMA_ZENHIRA ;
		}
		break ;
	case IDM_ZENKATA:
		if ( *hstr ) {
			muhenkan = ROMA_ZENKATA ;
		}
		break ;
	case IDM_HAN:
		if ( *hstr ) {
			if ( muhenkan == ROMA_ZENROMA || muhenkan == ROMA_HANROMA ) {
				muhenkan = ROMA_HANROMA ;
			} else {
				muhenkan = ROMA_HANKATA ;
			}
		}
		break ;
	case IDM_ROMA:
		if ( *hstr ) {
			muhenkan = ROMA_ZENROMA ;
		}
		break ;
	}
	if ( muhenkan != m_dwMuhenkan ) {
		m_dwMuhenkan = muhenkan ;
		g_Roma.getmuhenkan( m_dwMuhenkan, buf ) ;
		SendMessage( m_hwndText, CONFIRM_SETINPUT, 0, (LPARAM) buf ) ;
	}
}

/*
 * クリップボードからUnicode文字列を取得する
 */
BOOL
FepWindow::GetFromClipboard( LPTSTR unicode, DWORD dstsize )
{
	TCHAR	c ;
	DWORD	cbsize ;
	LPCTSTR	cbptr, src ;
	BOOL	ret = FALSE ;

	/* 格納先の領域サイズを文字数に変換する */
	dstsize /= sizeof (TCHAR) ;
	if ( dstsize -- <= 1 ) {
		return FALSE ;
	}
	/* クリップボードをオープンする */
	if ( !OpenClipboard( m_hWnd ) ) {
		return FALSE ;
	}
#ifdef	_WIN32_WCE
	HLOCAL	hGMem = GetClipboardData( CF_UNICODETEXT ) ;
	cbsize = LocalSize( hGMem ) ;
	cbptr = (LPCTSTR) hGMem ;
#else	/* _WIN32_WCE */
	HGLOBAL	hGMem = GetClipboardData( CF_UNICODETEXT ) ;
	cbsize = GlobalSize( hGMem ) ;
	cbptr = (LPCTSTR) GlobalLock( hGMem ) ;
#endif	/* _WIN32_WCE */
	if ( !cbsize ) {
		goto exit ;
	}
	/* コード変換開始 */
	setup_codeconv( unicode ) ;
	src = cbptr ;
	cbsize /= sizeof (TCHAR) ;
	do {
		c = *src++ ;
		jis_unicode_char( c ) ;
	} while ( -- cbsize && -- dstsize && c ) ;
	jis_unicode_char( 0 ) ;
	putchar_codeconv( 0 ) ;
	ret = TRUE ;

exit:
#ifndef	_WIN32_WCE
	GlobalUnlock( hGMem ) ;
#endif	/* _WIN32_WCE */
	CloseClipboard() ;
	return ret ;
}

/*
 * コード変換用のサブルーチン
 */
void
FepWindow::CodeConvSub( LPCTSTR ptr )
{
	TCHAR	c ;

	while ( c = *ptr++ ) {
		unicode_jis_char( c ) ;
	}
	unicode_jis_char( 0 ) ;
}

/*
 * SJIS文字列をコード変換してクリップボードに格納する
 */
BOOL
FepWindow::CopyToClipboard( LPCTSTR unicode )
{
	LPTSTR		ptr ;
	DWORD		size ;

	if ( g_fJis ) {
		/* コード変換に必要なメモリ数を得る */
		setup_codeconv( 0 ) ;
		CodeConvSub( unicode ) ;
		size = getcount_codeconv() ;
		if ( !size ) {
			/* 変換対象がない場合 */
			return FALSE ;
		}
	} else {
		size = _tcslen( unicode ) + 1 ;
	}
	size *= sizeof (TCHAR) ;
	/* クリップボードオープン */
	if ( !OpenClipboard( m_hWnd ) ) {
		return FALSE ;
	} else if ( !EmptyClipboard() ) {
		CloseClipboard() ;
		return FALSE ;
	}
	/* 必要な分だけメモリ確保を行う */
#ifdef	_WIN32_WCE
	HLOCAL	hGMem = LocalAlloc( LMEM_FIXED, size ) ;
	ptr = (LPTSTR) hGMem ;
#else	/* _WIN32_WCE */
	HGLOBAL	hGMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, size ) ;
	ptr = (LPTSTR) GlobalLock( hGMem ) ;
#endif	/* _WIN32_WCE */

	if ( g_fJis ) {
		/* UNICODE->JIS変換し結果をメモリに書き込む */
		setup_codeconv( ptr ) ;
		CodeConvSub( unicode ) ;
	} else {
		_tcscpy( ptr, unicode ) ;
	}
	/* クリップボードに結果をセットする */
	SetClipboardData( CF_UNICODETEXT, hGMem ) ;
#ifndef	_WIN32_WCE
	GlobalUnlock( hGMem ) ;
#endif	/* _WIN32_WCE */
	/* クリップボードクローズ */
	CloseClipboard() ;
	return TRUE ;
}

void
FepWindow::Hide() const
{
	HWND	hWndApp ;

	if ( m_dwSendMode >= IDM_FEPOK ) {
		hWndApp = GetParent( m_hwndParent ) ;
		if ( !hWndApp ) {
			hWndApp = m_hwndParent ;
		}
	} else {
		hWndApp = m_hwndParent ;
	}
	SetForegroundWindow( hWndApp ) ;
	SetActiveWindow( hWndApp ) ;
	ShowWindow( m_hWnd, SW_HIDE ) ;
}

BOOL
InitHotkey()
{
	g_pRegisterHotKey = 0 ;
	g_pUnregisterHotKey = 0 ;
#ifdef	_WIN32_WCE
	g_hLib = LoadLibrary( TEXT("COREDLL.DLL") ) ;
#else	/* _WIN32_WCE */
	g_hLib = LoadLibrary( TEXT("USER32.DLL") ) ;
#endif	/* _WIN32_WCE */
	if ( g_hLib == NULL ) {
		return FALSE ;
	}
#ifdef	_WIN32_WCE
	g_pRegisterHotKey = (BOOL (*)(HWND,int,UINT,UINT)) GetProcAddress( g_hLib, TEXT("RegisterHotKey") ) ;
#else	/* _WIN32_WCE */
	g_pRegisterHotKey = (BOOL (*)(HWND,int,UINT,UINT)) GetProcAddress( g_hLib, "RegisterHotKey" ) ;
#endif	/* _WIN32_WCE */
	if ( !g_pRegisterHotKey ) {
		return FALSE ;
	}
#ifdef	_WIN32_WCE
	g_pUnregisterHotKey = (BOOL (*)(HWND,int)) GetProcAddress( g_hLib, TEXT("UnregisterHotKey") ) ;
#else	/* _WIN32_WCE */
	g_pUnregisterHotKey = (BOOL (*)(HWND,int)) GetProcAddress( g_hLib, "UnregisterHotKey" ) ;
#endif	/* _WIN32_WCE */
	if ( !g_pUnregisterHotKey ) {
		g_pRegisterHotKey = 0 ;
		return FALSE ;
	}
	return TRUE ;
}

void
ReleaseHotkey()
{
	if ( g_hLib ) {
		FreeLibrary( g_hLib ) ;
	}
}
