#define	STRICT
#include	<windows.h>
#include	<windowsx.h>
#include	<commctrl.h>
#include	<commdlg.h>
#include	<tchar.h>
#include	"kctrl.h"
#include	"resource.h"
#include	"basewin.h"
#include	"controls.h"
#include	"cetools.h"
#include	"fileopen.h"
#include	"appmain.h"
#include	"dialog.h"
#include	"log.h"

enum {
	MODE_FILE, MODE_LOG
} ;
typedef enum {
	MESSAGE_POST, MESSAGE_REPLY, MESSAGE_MAIL
} MESSAGEMODE ;

#define		WM_USER_VIEW	(WM_USER+1)
#define		MAX_FN			128
#define		is_kanji(x)		(((x)>=0x81 && (x)<=0x9F)||((x)>=0xE0 && (x)<=0xFC))

extern "C" {
	TCHAR		MessageBuf[ 512 ] ;
	BOOL		g_bDeleteReg = FALSE ;		/* レジストリを削除する場合*真* */
	TCHAR		g_szFilePath[ MAX_PATH ] = TEXT("") ;
	TCHAR		g_szBaseDir[ MAX_PATH ] = TEXT("\\") ;
	DWORD		g_dwTabSize = 8 ;
	DWORD		g_dwHMargin = 1 ;
	BOOL		g_bUseClipboard = FALSE ;
	DWORD		g_dwSeparatorPos = 0 ;
	TCHAR		g_szEditor[ MAX_PATH ] = TEXT("KPAD.EXE") ;
	TCHAR		g_szPadRepl[ MAX_PATH ] = TEXT("") ;
	TCHAR		g_szPadNew[ MAX_PATH ] = TEXT("") ;
	TCHAR		g_szPadMail[ MAX_PATH ] = TEXT("") ;
	TCHAR		g_szFindStr[ 128 ] = TEXT("") ;
	BOOL		g_bFindDirNext = TRUE ;
	BOOL		g_bIgnoreCase = TRUE ;
} ;

static	LPTSTR	g_szFilename[ MAX_FN ] ;
static	DWORD	g_dwFilesize[ MAX_FN ] ;
static	BOOL	g_bIsDir[ MAX_FN ] ;
static	BOOL	g_bIsSelected[ MAX_FN ] ;
static	DWORD	g_dwNumFilename = 0 ;
static	BYTE	g_szContent[ 1024 ] ;
static	BOOL	g_bRefMode = TRUE ;

KeyMapInfo	g_NarrowKeyMapInfo[] = {
	{ VK_RETURN, 0, MV_FUNC_ENTER },
	{ VK_ESCAPE, 0, MV_FUNC_ESC },
	{ VK_UP,     0, MV_FUNC_CHAR|'\b' },
	{ VK_DOWN,   0, MV_FUNC_CHAR|' ' },
	{ VK_LEFT,   0, MV_FUNC_PRIOR },
	{ VK_RIGHT,  0, MV_FUNC_NEXT },
	{ VK_PRIOR,  0, MV_FUNC_PRIOR },
	{ VK_NEXT,   0, MV_FUNC_NEXT },
	{ VK_HOME,   0, MV_FUNC_HOME },
	{ VK_END,    0, MV_FUNC_END },
	{ 0,         0, 0 }
} ;

KeyMapInfo	g_WideKeyMapInfo[] = {
	{ VK_RETURN, 0, MV_FUNC_ENTER },
	{ VK_ESCAPE, 0, MV_FUNC_ESC },
	{ VK_UP,     0, MV_FUNC_UP },
	{ VK_DOWN,   0, MV_FUNC_DOWN },
	{ VK_LEFT,   0, MV_FUNC_PRIOR },
	{ VK_RIGHT,  0, MV_FUNC_NEXT },
	{ VK_PRIOR,  0, MV_FUNC_PRIOR },
	{ VK_NEXT,   0, MV_FUNC_NEXT },
	{ VK_HOME,   0, MV_FUNC_HOME },
	{ VK_END,    0, MV_FUNC_END },
	{ 0,         0, 0 }
} ;

DWORD
CalcStrCols( LPCTSTR text )
{
	TCHAR	c ;
	DWORD	col ;

	col = 0 ;
	while ( c = *text++ ) {
		if ( is_hankaku( c ) ) {
			col ++ ;
		} else {
			col += 2 ;
		}
	}
	return col ;
}

void
ScreenToClientRect( HWND hwnd, LPRECT rect )
{
	POINT	point ;

	point.x = rect->left ;
	point.y = rect->top ;
	ScreenToClient( hwnd, &point ) ;
	rect->left = point.x ;
	rect->top  = point.y ;
	point.x = rect->right ;
	point.y = rect->bottom ;
	ScreenToClient( hwnd, &point ) ;
	rect->right  = point.x ;
	rect->bottom = point.y ;
}

void
clear_filename()
{
	DWORD		i ;

	for ( i = 0 ; i < g_dwNumFilename ; i ++ ) {
		if ( g_szFilename[ i ] ) {
			LocalFree( g_szFilename[ i ] ) ;
		}
	}
	for ( i = 0 ; i < MAX_FN ; i ++ ) {
		g_szFilename[ i ] = 0 ;
	}
	g_dwNumFilename = 0 ;
}

void
add_filename( LPCTSTR fn, DWORD size, BOOL bIsDir )
{
	int		ret ;
	DWORD	i, j, len = _tcslen( fn ) ;

	if ( g_dwNumFilename >= MAX_FN ) {
		return ;
	}
	for ( i = 0 ; i < g_dwNumFilename ; i ++ ) {
		ret = - ((bIsDir ? 0 : 1) - (g_bIsDir[ i ] ? 0 : 1)) ;
		if ( !ret ) {
			ret = _tcsicmp( fn, g_szFilename[ i ] ) ;
		}
		if ( ret < 0 ) {
			for ( j = g_dwNumFilename ; j > i ; j -- ) {
				g_szFilename[ j ] = g_szFilename[ j - 1 ] ;
				g_dwFilesize[ j ] = g_dwFilesize[ j - 1 ] ;
				g_bIsDir[ j ] = g_bIsDir[ j - 1 ] ;
			}
			break ;
		}
	}
	g_szFilename[ i ] = (LPTSTR) LocalAlloc( LPTR, (len + 1) * sizeof (TCHAR) ) ;
	_tcscpy( g_szFilename[ i ], fn ) ;
	g_dwFilesize[ i ] = size ;
	g_bIsDir[ i ] = bIsDir ;
	g_dwNumFilename ++ ;
}

/*
 * ファイルの一覧を取得する
 */
BOOL
GetFilenames( LPCTSTR dir )
{
	WIN32_FIND_DATA	find ;
	HANDLE			hFind ;
	BOOL			bIsDir ;
	TCHAR			findPath[ MAX_PATH ], *ptr ;

	clear_filename() ;
	/* ファイル検索用のワイルドカードを作成する */
	_tcscpy( findPath, dir ) ;
	catdir( findPath, TEXT("*.*"), NULL ) ;
	/* ルートフォルダ以外の時に「..」を追加する */
	if ( *dir && _tcscmp( dir, TEXT("\\") ) ) {
		add_filename( TEXT(".."), 0, TRUE ) ;
	}
	/* ファイルを検索する */
	hFind = FindFirstFile( findPath, &find ) ;
	if ( hFind != INVALID_HANDLE_VALUE ) {
		do {
			if ( !_tcscmp( find.cFileName, TEXT(".") ) ) {
				continue ;
			} else if ( !_tcscmp( find.cFileName, TEXT("..") ) ) {
				continue ;
#ifdef	_WIN32_WCE
			} else if ( find.dwFileAttributes & FILE_ATTRIBUTE_INROM ) {
				continue ;
			} else if ( find.dwFileAttributes & FILE_ATTRIBUTE_ROMSTATICREF ) {
				continue ;
			} else if ( find.dwFileAttributes & FILE_ATTRIBUTE_ROMMODULE ) {
				continue ;
#endif	/* _WIN32_WCE */
			}
			bIsDir = find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ;
			if ( !bIsDir ) {
				/* バイナリファイルは除外 */
				ptr = _tcsrchr( find.cFileName, TEXT('.') ) ;
				if ( !ptr ) {
					continue ;
				} else if ( !_tcsicmp( ptr, TEXT(".LOG") ) ) {
				} else {
					continue ;
				}
			}
			_tcscpy( findPath, dir ) ;
			catdir( findPath, find.cFileName, NULL ) ;
			add_filename( find.cFileName, find.nFileSizeLow, bIsDir ) ;
		} while ( FindNextFile( hFind, &find ) ) ;
		FindClose( hFind ) ;
	}
	if ( g_dwNumFilename ) {
		return TRUE ;
	}
	add_filename( TEXT("<No Files>"), 0, FALSE ) ;
	return FALSE ;
}

/*
 * ファイルの一部内容を取得する
 */
BOOL
GetFileContent( LPCTSTR path, DWORD pos, DWORD size )
{
	DWORD	nRead ;
	HANDLE	hFile ;

	hFile = CreateFile( path,
				GENERIC_READ,
				FILE_SHARE_READ,
				NULL,
				OPEN_EXISTING,
				FILE_ATTRIBUTE_NORMAL,
				NULL ) ;
	if ( hFile == INVALID_HANDLE_VALUE ) {
		return FALSE ;
	}
	memset( g_szContent, 0, sizeof g_szContent ) ;
	if ( pos ) {
		SetFilePointer( hFile, pos, NULL, FILE_BEGIN ) ;
	}
	if ( !size ) {
		size = sizeof g_szContent ;
	}
	ReadFile( hFile, g_szContent, size, &nRead, NULL ) ;
	g_szContent[ sizeof g_szContent - 1 ] = 0 ;
	CloseHandle( hFile ) ;
	return TRUE ;
}

/*
 * フォルダ内のファイル一覧を取得する
 */
BOOL
GetFolderContent( LPCTSTR dir, DWORD maxLine )
{
	LPBYTE			dst ;
	WIN32_FIND_DATA	find ;
	HANDLE			hFind ;
	DWORD			count = 0 ;
	BYTE			sjis[ MAX_PATH ] ;
	TCHAR			findPath[ MAX_PATH ], *ptr ;

	dst = g_szContent ;
	*dst = 0 ;
	if ( !*g_szFilePath ) {
		return FALSE ;
	}
	/* ファイル検索用のワイルドカードを作成する */
	_tcscpy( findPath, dir ) ;
	catdir( findPath, TEXT("*.*"), NULL ) ;
	/* ファイルを検索する */
	hFind = FindFirstFile( findPath, &find ) ;
	if ( hFind == INVALID_HANDLE_VALUE ) {
		return FALSE ;
	}
	do {
		if ( !_tcscmp( find.cFileName, TEXT(".") ) ) {
			continue ;
		} else if ( !_tcscmp( find.cFileName, TEXT("..") ) ) {
			continue ;
#ifdef	_WIN32_WCE
		} else if ( find.dwFileAttributes & FILE_ATTRIBUTE_INROM ) {
			continue ;
		} else if ( find.dwFileAttributes & FILE_ATTRIBUTE_ROMSTATICREF ) {
			continue ;
		} else if ( find.dwFileAttributes & FILE_ATTRIBUTE_ROMMODULE ) {
			continue ;
#endif	/* _WIN32_WCE */
		}
		if ( !(find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
			/* バイナリファイルは除外 */
			ptr = _tcsrchr( find.cFileName, TEXT('.') ) ;
			if ( !ptr ) {
				continue ;
			} else if ( !_tcsicmp( ptr, TEXT(".LOG") ) ) {
			} else {
				continue ;
			}
		}
		unicode2sjis( find.cFileName, sjis, sizeof sjis ) ;
		if ( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
			*dst++ = '[' ;
			strcpy( (LPSTR) dst, (LPSTR) sjis ) ;
			dst += strlen( (LPSTR) dst ) ;
			*dst++ = ']' ;
		} else {
			strcpy( (LPSTR) dst, (LPSTR) sjis ) ;
			dst += strlen( (LPSTR) dst ) ;
		}
		*dst++ = '\n' ;
		if ( ++ count >= maxLine ) {
			break ;
		}
	} while ( FindNextFile( hFind, &find ) ) ;
	FindClose( hFind ) ;
	*dst = 0 ;
	return TRUE ;
}

BOOL
ReadAllFiles()
{
	DWORD		i ;
	TCHAR		szFilePath[ MAX_PATH ] ;

	for ( i = 0 ; i < g_dwNumFilename ; i ++ ) {
		if ( g_bIsDir[ i ] ) {
			continue ;
		} else if ( !g_bIsSelected[ i ] ) {
			continue ;
		}
		_tcscpy( szFilePath, g_szBaseDir ) ;
		catdir( szFilePath, g_szFilename[ i ], NULL ) ;
		if ( !ReadLogFile( szFilePath ) ) {
			return FALSE ;
		}
	}
	return TRUE ;
}

/*
 * ログの一覧を取得する
 */
BOOL
GetLogs()
{
	FreeLogInfo() ;
	FreeRefList() ;
	FreeNormList() ;
	SetCursor( LoadCursor( NULL, IDC_WAIT ) ) ;
	if ( !ReadAllFiles() ) {
		goto error ;
	}
	if ( !MakeRefList() ) {
		goto error ;
	}
	if ( !MakeNormList() ) {
		goto error ;
	}
	SetCursor( NULL ) ;
	return TRUE ;

error:
	SetCursor( NULL ) ;
	FreeLogInfo() ;
	FreeRefList() ;
	FreeNormList() ;
	return FALSE ;
}

BOOL
ExecProgram( LPCTSTR fn )
{
#ifdef	_WIN32_WCE
	if ( *g_szEditor ) {
		PROCESS_INFORMATION		pi ;

		if ( CreateProcess( g_szEditor, fn,
							NULL, NULL, FALSE,
							0,
							NULL, NULL, NULL,
							&pi ) ) {
			CloseHandle( pi.hProcess ) ;
			CloseHandle( pi.hThread ) ;
			return TRUE ;
		}
	} else {
		SHELLEXECUTEINFO		sei ;

		memset( &sei, 0, sizeof sei ) ;
		sei.cbSize = sizeof sei ;
		sei.fMask = 0 ;
		sei.hwnd = NULL ;
		sei.lpVerb = TEXT("Open") ;
		sei.lpFile = fn ;
		sei.lpParameters = NULL ;
		sei.lpDirectory = NULL ;
		sei.nShow = SW_SHOW ;
		if ( ShellExecuteEx( &sei ) ) {
			return TRUE ;
		}
	}
#endif	/* _WIN32_WCE */
	return FALSE ;
}

/*
 * メインウィンドウ
 */
class MainWindow : public Window {
private:
	MainApp		*m_pApp ;		/* アプリケーションへのポインタ */
	HWND		m_hwndCB ;		/* CommandBarのハンドル */
	HICON		m_hIcon ;		/* アプリアイコンのハンドル */
	HWND		m_hwndFile ;	/* 一覧領域のハンドル */
	HWND		m_hwndContent ;	/* 内容領域のハンドル */
	HWND		m_hwndDetail ;	/* 詳細内容領域のハンドル */
	DWORD		m_dwTopPos ;	/* 一番上のコントロールのY座標 */
	TCHAR		m_szCurDir[ MAX_PATH ] ;
	BOOL		m_bNarrow ;		/* 画面が狭い場合*真* */
	DWORD		m_dwMode ;		/* 現在の画面モード */
	DWORD		m_dwLogPos ;
	DWORD		m_dwLogSize ;
	LPBYTE		m_szFileBuf ;
	LPCSTR		m_szForumID ;
	DWORD		m_dwRoomNo ;
	LPCSTR		m_szRoomName ;
	HWND		m_hwndSeparator ;
	BOOL		m_bMouseDown ;
	RECT		m_rectFile ;
	RECT		m_rectContent ;
	DWORD		m_dwListIndex ;	/* 一覧領域の現在行 */

	DWORD	CreateCommandBar() ;
	void	FreeFileBuf() ;
	BOOL	GetLogContent() ;

public:
	MainWindow( MainApp * ) ;
	~MainWindow() ;

	BOOL	Create() ;
	void	WMCreate( HWND hWnd ) ;
	void	WMDestroy() ;
	LRESULT	WMCommand( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp ) ;
	void	WMSetFocus() ;
	BOOL	WMClose() ;
	LRESULT	WMWndProc( HWND hWnd,  UINT msg, WPARAM wParam, LPARAM lParam, BOOL *bDefault ) ;
	void	WMInitMenuPopup( HMENU hmenuPopup, UINT uPos, BOOL fSystemMenu ) ;
	void	WMMouseDown( WPARAM wParam, LPARAM lParam ) ;
	void	WMMouseMove( WPARAM wParam, LPARAM lParam ) ;
	void	WMMouseUp( WPARAM wParam, LPARAM lParam ) ;
	void	DrawSeparator() const ;
	void	OneKeyMessage( TCHAR chCharCode ) const ;
	void	UpdateSelected( BOOL bAll ) const ;
	void	OpenLogView() ;
	void	CloseLogView() ;
	BOOL	MakeMessage( MESSAGEMODE dwMessageMode ) ;
	BOOL	SaveAs() ;
	BOOL	FindString() ;
	BOOL	FindStringForwardLog( DWORD dwStartIndex, LPDWORD pFoundIndex ) ;

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

	static	int		file_proc( int index, const BYTE **ptr, int *len ) ;
	static	int		title_proc( int index, const BYTE **ptr, int *len ) ;

	static	DWORD	m_dwMaxFileCol ;
} ;

/*-------------------------------------------------------------------------*
 * MainApp
 *-------------------------------------------------------------------------*/
MainApp::MainApp()
{
	m_pMainWnd = 0 ;
	clear_filename() ;
}

MainApp::~MainApp()
{
	FreeLogInfo() ;
	FreeRefList() ;
	FreeNormList() ;
	clear_filename() ;
}

BOOL
MainApp::Create( HINSTANCE hInstance )
{
	m_hInst = hInstance ;

	if ( !MainWindow::RegisterClass( m_hInst ) ) {
		return FALSE ;
	}
	if ( !BigListRegisterClass( m_hInst ) ) {
		return FALSE ;
	}
	if ( !MemViewRegisterClass( 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() ;

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

	/* 画面を前面にする */
	SetForegroundWindow( m_pMainWnd->get_hwnd() ) ;
	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 ;
}

#define		REG_BASEKEY		TEXT("Software\\Gawaro\\")
#define		VAR_EDITOR		TEXT("Editor")
#define		VAR_BASEDIR		TEXT("InitDir")
#define		VAR_TABSIZE		TEXT("TabSize")
#define		VAR_HMARGIN		TEXT("HMargin")
#define		VAR_QUOTE		TEXT("Quote")
#define		VAR_PADDIR		TEXT("PadDir")
#define		VAR_PADREPL		TEXT("PadRepl")
#define		VAR_PADNEW		TEXT("PadNew")
#define		VAR_PADMAIL		TEXT("PadMail")
#define		VAR_MAILPADFN	TEXT("MailPadFn")
#define		VAR_FORUMPADFN	TEXT("ForumPadFn")
#define		VAR_USECLIP		TEXT("UseClipboard")
#define		VAR_SEPPOS		TEXT("SeparatorPos")

/*
 * レジストリからの情報取得
 */
BOOL
MainApp::GetReg()
{
	HKEY	hk ;
	LONG	lret ;
	LPTSTR	name ;
	LPBYTE	lpData ;
	DWORD	dwType, cbData ;
	TCHAR	subkey[ MAX_PATH ] ;

	_tcscpy( subkey, REG_BASEKEY ) ;
	_tcscat( subkey, szTitleName ) ;
	/* レジストリキーをオープンする */
	lret = RegOpenKeyEx( HKEY_CURRENT_USER, subkey, 0, KEY_QUERY_VALUE, &hk ) ;
	if ( lret != ERROR_SUCCESS ) {
		return FALSE ;
	}
	/* エディタープログラム名 */
	name = VAR_EDITOR ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szEditor ;
	cbData = sizeof g_szEditor ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* ディレクトリ名 */
	name = VAR_BASEDIR ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szBaseDir ;
	cbData = sizeof g_szBaseDir ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* TabSize */
	name = VAR_TABSIZE ;
	dwType = REG_DWORD ;
	lpData = (LPBYTE) &g_dwTabSize ;
	cbData = sizeof g_dwTabSize ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* HMargin */
	name = VAR_HMARGIN ;
	dwType = REG_DWORD ;
	lpData = (LPBYTE) &g_dwHMargin ;
	cbData = sizeof g_dwHMargin ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* 引用記号 */
	name = VAR_QUOTE ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szQuote ;
	cbData = sizeof g_szQuote ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* PAD格納ディレクトリ */
	name = VAR_PADDIR ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szPadDir ;
	cbData = sizeof g_szPadDir ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* 返信用PADテンプレート */
	name = VAR_PADREPL ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szPadRepl ;
	cbData = sizeof g_szPadRepl ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* 新規用PADテンプレート */
	name = VAR_PADNEW ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szPadNew ;
	cbData = sizeof g_szPadNew ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* メール用PADテンプレート */
	name = VAR_PADMAIL ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szPadMail ;
	cbData = sizeof g_szPadMail ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* UseClipboard */
	name = VAR_USECLIP ;
	dwType = REG_DWORD ;
	lpData = (LPBYTE) &g_bUseClipboard ;
	cbData = sizeof g_bUseClipboard ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* SeparatorPos */
	name = VAR_SEPPOS ;
	dwType = REG_DWORD ;
	lpData = (LPBYTE) &g_dwSeparatorPos ;
	cbData = sizeof g_dwSeparatorPos ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* MAIL-PAD用ファイル名 */
	name = VAR_MAILPADFN ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szMailPadFn ;
	cbData = sizeof g_szMailPadFn ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* FORUM-PAD用ファイル名 */
	name = VAR_FORUMPADFN ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szForumPadFn ;
	cbData = sizeof g_szForumPadFn ;
	lret = RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) ;
	/* レジストリをクローズする */
	RegCloseKey( hk ) ;
	return TRUE ;
}

/*
 * レジストリへの情報設定
 */
BOOL
MainApp::SetReg() const
{
	HKEY	hk ;
	LONG	lret ;
	LPTSTR	name ;
	LPBYTE	lpData ;
	TCHAR	subkey[ MAX_PATH ] ;
	DWORD	ret, dwType, cbData ;

	_tcscpy( subkey, REG_BASEKEY ) ;
	_tcscat( subkey, szTitleName ) ;
	/* レジストリキーを作成する */
	lret = RegCreateKeyEx( HKEY_CURRENT_USER, subkey, 0, TEXT(""), 0,
#ifdef	_WIN32_WCE
						   0,
#else	/* _WIN32_WCE */
						   KEY_ALL_ACCESS,
#endif	/* _WIN32_WCE */
						   NULL, &hk, &ret ) ;
	if ( lret != ERROR_SUCCESS ) {
		return FALSE ;
	}
	/* エディタープログラム名 */
	name = VAR_EDITOR ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szEditor ;
	cbData = (_tcslen(g_szEditor) + 1) * sizeof (*g_szEditor) ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* ディレクトリ名 */
	name = VAR_BASEDIR ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szBaseDir ;
	cbData = (_tcslen(g_szBaseDir) + 1) * sizeof (*g_szBaseDir) ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* TabSize */
	name = VAR_TABSIZE ;
	dwType = REG_DWORD ;
	lpData = (LPBYTE) &g_dwTabSize ;
	cbData = sizeof g_dwTabSize ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* HMargin */
	name = VAR_HMARGIN ;
	dwType = REG_DWORD ;
	lpData = (LPBYTE) &g_dwHMargin ;
	cbData = sizeof g_dwHMargin ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* 引用記号 */
	name = VAR_QUOTE ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szQuote ;
	cbData = (_tcslen(g_szQuote) + 1) * sizeof (*g_szQuote) ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* PAD格納ディレクトリ */
	name = VAR_PADDIR ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szPadDir ;
	cbData = (_tcslen(g_szPadDir) + 1) * sizeof (*g_szPadDir) ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* 返信用PADテンプレート */
	name = VAR_PADREPL ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szPadRepl ;
	cbData = (_tcslen(g_szPadRepl) + 1) * sizeof (*g_szPadRepl) ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* 新規用PADテンプレート */
	name = VAR_PADNEW ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szPadNew ;
	cbData = (_tcslen(g_szPadNew) + 1) * sizeof (*g_szPadNew) ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* メール用PADテンプレート */
	name = VAR_PADMAIL ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szPadMail ;
	cbData = (_tcslen(g_szPadMail) + 1) * sizeof (*g_szPadMail) ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* UseClipboard */
	name = VAR_USECLIP ;
	dwType = REG_DWORD ;
	lpData = (LPBYTE) &g_bUseClipboard ;
	cbData = sizeof g_bUseClipboard ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* SeparatorPos */
	name = VAR_SEPPOS ;
	dwType = REG_DWORD ;
	lpData = (LPBYTE) &g_dwSeparatorPos ;
	cbData = sizeof g_dwSeparatorPos ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* MAIL-PAD用ファイル名 */
	name = VAR_MAILPADFN ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szMailPadFn ;
	cbData = (_tcslen(g_szMailPadFn) + 1) * sizeof (*g_szMailPadFn) ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* FORUM-PAD用ファイル名 */
	name = VAR_FORUMPADFN ;
	dwType = REG_SZ ;
	lpData = (LPBYTE) g_szForumPadFn ;
	cbData = (_tcslen(g_szForumPadFn) + 1) * sizeof (*g_szForumPadFn) ;
	lret = RegSetValueEx( hk, name, 0, dwType, lpData, cbData ) ;
	/* レジストリをクローズする */
	RegCloseKey( hk ) ;
	return TRUE ;
}

/*
 * レジストリ情報削除
 */
void
MainApp::DeleteReg() const
{
	TCHAR	subkey[ MAX_PATH ] ;

	_tcscpy( subkey, REG_BASEKEY ) ;
	_tcscat( subkey, szTitleName ) ;
	RegDeleteKey( HKEY_CURRENT_USER, subkey ) ;
}

/*-------------------------------------------------------------------------*
 * MainWindow
 *-------------------------------------------------------------------------*/
DWORD	MainWindow::m_dwMaxFileCol = 40 ;

MainWindow::MainWindow( MainApp *pApp )
{
	m_pApp = pApp ;
	m_hIcon = 0 ;
	_tcscpy( m_szCurDir, TEXT("\\") ) ;
	m_dwLogPos = 0 ;
	m_dwLogSize = 0 ;
	m_szFileBuf = 0 ;
	m_szForumID = NULL ;
	m_dwRoomNo = 0 ;
	m_szRoomName = NULL ;
	m_bMouseDown = FALSE ;
	m_dwListIndex = 0 ;
}

MainWindow::~MainWindow()
{
	FreeFileBuf() ;
	if ( m_hIcon ) {
		::DeleteObject( m_hIcon ) ;
	}
}

void
MainWindow::FreeFileBuf()
{
	if ( m_szFileBuf ) {
		LocalFree( m_szFileBuf ) ;
	}
	m_szFileBuf = 0 ;
}

void
MainWindow::WMCreate( HWND hWnd )
{
	RECT		rect ;
	DWORD		height = 2, tw, th ;
	DWORD		x1, x2, x3, x4, y1, y2, y3, y4 ;
	DWORD		w1, w2, w3, w4, h1, h2, h3, h4 ;
	HINSTANCE	hInst = m_pApp->get_inst() ;

	m_hwnd = hWnd ;
	/* 表示領域を求める */
	GetClientRect( m_hwnd, &rect ) ;
	tw = rect.right ;
	th = rect.bottom ;
	m_bNarrow = rect.right <= 400 ;
	/* アイコンを作成しタスクバーに登録する */
	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 ) ;
	}
	/* コマンドバーを追加する */
	height += CreateCommandBar() ;
	m_dwTopPos = height ;
	/* コントロールの配置を計算する */
	if ( m_bNarrow ) {
		if ( !g_dwSeparatorPos ) {
			g_dwSeparatorPos = (th - height - 4) / 2 + height ;
		}
		w1 = w2 = tw - 2 ;
		x1 = x2 = 0 ;
		y1 = height ;
		h1 = g_dwSeparatorPos - height ;
		h2 = (th - height - 4) - h1 ;
		y2 = y1 + h1 + 2 ;
		x4 = x1 ;
		y4 = y1 + h1 ;
		w4 = w1 ;
		h4 = 2 ;
	} else {
		if ( !g_dwSeparatorPos ) {
			g_dwSeparatorPos = 240 ;
		}
		w1 = g_dwSeparatorPos ;
		w2 = tw - 4 - w1 ;
		x1 = 0, x2 = x1 + w1 + 2 ;
		y1 = y2 = height ;
		h1 = h2 = th - height ;
		x4 = x1 + w1 ;
		y4 = y1 ;
		w4 = 2 ;
		h4 = h1 ;
	}
	x3 = 0, y3 = height ;
	w3 = tw - 2, h3 = th - height ;

	m_hwndFile = CreateWindow( CTRL_BIGLIST,
						TEXT(""),
						WS_CHILD|WS_VISIBLE|WS_BORDER|WS_TABSTOP|WS_VSCROLL,
						x1, y1, w1, h1,
						hWnd,
						(HMENU) IDC_FILE,
						hInst,
						0 ) ;

	m_hwndContent = CreateWindow( CTRL_MEMVIEW,
						TEXT(""),
						WS_CHILD|WS_VISIBLE|WS_BORDER|WS_TABSTOP|WS_VSCROLL,
						x2, y2, w2, h2,
						hWnd,
						(HMENU) IDC_CONTENT,
						hInst,
						0 ) ;

	m_hwndDetail = CreateWindow( CTRL_MEMVIEW,
						TEXT(""),
						WS_CHILD|WS_BORDER|WS_TABSTOP|WS_VSCROLL,
						x3, y3, w3, h3,
						hWnd,
						(HMENU) IDC_VIEW,
						hInst,
						0 ) ;

	m_hwndSeparator = CreateWindow( TEXT("STATIC"),
						TEXT(""),
						WS_CHILD|WS_BORDER,
						x4, y4, w4, h4,
						hWnd,
						(HMENU) IDC_SEPARATOR,
						hInst,
						0 ) ;

	/* TAB,HMARGINを設定する */
	SendMessage( m_hwndDetail, MVM_SETTAB, (WPARAM) g_dwTabSize, (LPARAM) FALSE ) ;
	SendMessage( m_hwndDetail, MVM_SETHMARGIN, (WPARAM) g_dwHMargin, (LPARAM) TRUE ) ;
	SendMessage( m_hwndDetail, MVM_SETKEYMAP, 0, 
				 (LPARAM) (m_bNarrow ? g_NarrowKeyMapInfo : g_WideKeyMapInfo) ) ;

	/* 初期ディレクトリ内容を表示する */
	GetFilenames( g_szBaseDir ) ;
	m_dwMode = MODE_FILE ;

	/* フォントをセットする */
	SendMessage( m_hwndFile, BLM_SETFONT, (WPARAM) 1, 0 ) ;
	/* 一覧領域に表示できる文字数を求める */
	m_dwMaxFileCol = SendMessage( m_hwndFile, BLM_GETMAXCOL, 0, 0 ) ;
	/* ダブルクリックでEnterするように設定する */
	SendMessage( m_hwndFile, BLM_SETDBLCLK, (WPARAM) TRUE, 0 ) ;
	/* 一覧用のプロシージャを設定する */
	SendMessage( m_hwndFile, BLM_SETPROC, 0, (LPARAM) file_proc ) ;

	/* フォントをセットする */
	SendMessage( m_hwndContent, MVM_SETFONT, (WPARAM) 1, (LPARAM) TRUE ) ;
	/* TAB,HMARGINを設定する */
	SendMessage( m_hwndContent, MVM_SETTAB, (WPARAM) g_dwTabSize, (LPARAM) TRUE ) ;
	SendMessage( m_hwndContent, MVM_SETHMARGIN, (WPARAM) g_dwHMargin, (LPARAM) TRUE ) ;
	SendMessage( m_hwndContent, MVM_SETKEYMAP, 0, 
				 (LPARAM) (m_bNarrow ? g_NarrowKeyMapInfo : g_WideKeyMapInfo) ) ;

	/* 初期フォーカスを設定する */
	SetFocus( m_hwndFile ) ;
}

void
MainWindow::WMDestroy()
{
	PostQuitMessage( 0 ) ;
}

LRESULT
MainWindow::WMCommand( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	LPCTSTR		ptr ;
	DWORD		index ;
	WORD		idCtrl = LOWORD(wParam) ;
	WORD		notifyCode = HIWORD(wParam) ;

	switch ( idCtrl ) {
	case IDC_FILE:
		switch ( notifyCode ) {
		case BLN_ENTER:
			index = SendMessage( m_hwndFile, BLM_GETCURSEL, 0, 0 ) ;
			switch ( m_dwMode ) {
			case MODE_FILE:
				/* ログリストを表示する */
				if ( g_bIsDir[ index ] ) {
					_tcscpy( g_szBaseDir, g_szFilePath ) ;
					SendMessage( m_hwnd, WM_COMMAND, IDM_FILE, 0 ) ;
				} else {
					SendMessage( m_hwnd, WM_COMMAND, IDM_LOG, 0 ) ;
				}
				break ;
			case MODE_LOG:
				/* ログ内容を表示する */
				OpenLogView() ;
				break ;
			}
			break ;
		case BLN_ESC:
			switch ( m_dwMode ) {
			case MODE_FILE:
				/* 一つ上のフォルダに移動する */
				SendMessage( m_hwnd, WM_COMMAND, IDM_UPDIR, 0 ) ;
				break ;
			case MODE_LOG:
				/* ファイルモードに移る */
				SendMessage( m_hwnd, WM_COMMAND, IDM_FILE, 0 ) ;
				break ;
			}
			break ;
		case BLN_CHANGE:
			index = SendMessage( m_hwndFile, BLM_GETCURSEL, 0, 0 ) ;
			m_dwListIndex = index ;
			switch ( m_dwMode ) {
			case MODE_FILE:
				rel2abs( g_szFilePath, g_szBaseDir, g_szFilename[ index ] ) ;
				break ;
			case MODE_LOG:
				index = g_bRefMode ? g_dwRefList[ index ] : g_dwNormList[ index ] ;
				ptr = GetLogFile( index, &m_dwLogPos, &m_dwLogSize ) ;
				if ( ptr ) {
					rel2abs( g_szFilePath, g_szBaseDir, ptr ) ;
				} else {
					*g_szFilePath = 0 ;
					GetForumInfo( index, &m_szForumID, &m_dwRoomNo, &m_szRoomName ) ;
				}
				break ;
			}
			PostMessage( hWnd, WM_USER_VIEW, 0, 0 ) ;
			break ;
		case BLN_CHAR:
			OneKeyMessage( (TCHAR) lParam ) ;
			break ;
		case BLN_KEYDOWN:
			switch ( LOWORD( lParam ) ) {
			case VK_DELETE:
				switch ( m_dwMode ) {
				case MODE_FILE:
					SendMessage( hWnd, WM_COMMAND, IDM_DELETE, 0 ) ;
					break ;
				}
				break ;
			}
			break ;
		}
		break ;
	case IDC_CONTENT:
	case IDC_VIEW:
		switch ( notifyCode ) {
		case MVN_ENTER:
			if ( idCtrl == IDC_CONTENT ) {
				/* 内容表示モードに移る */
				SendMessage( m_hwnd, WM_COMMAND, MAKEWPARAM( IDC_FILE, BLN_ENTER ), (LPARAM) hWnd ) ;
			}
			break ;
		case MVN_ESC:
			if ( idCtrl == IDC_CONTENT ) {
				/* ログ選択モードに移る */
				::SetFocus( m_hwndFile ) ;
			} else {
				/* ファイル内容表示から戻る */
				CloseLogView() ;
			}
			break ;
		case MVN_CHAR:
			OneKeyMessage( (TCHAR) lParam ) ;
			break ;
		}
		break ;
	case IDM_FILE:
		/* ファイル表示モードに移る */
		if ( IsWindowVisible( m_hwndDetail ) ) {
			CloseLogView() ;
		}
		GetFilenames( g_szBaseDir ) ;
		SendMessage( m_hwndFile, BLM_SETPROC, 0, (LPARAM) file_proc ) ;
		m_dwMode = MODE_FILE ;
		SetFocus( m_hwndFile ) ;
		break ;
	case IDM_LOG:
	case IDM_LOGALL:
		/* ログ表示モードに移る */
		if ( IsWindowVisible( m_hwndDetail ) ) {
			CloseLogView() ;
		}
		UpdateSelected( idCtrl == IDM_LOGALL ) ;
		if ( !GetLogs() ) {
			break ;
		}
		SendMessage( m_hwndFile, BLM_SETPROC, 0, (LPARAM) title_proc ) ;
		m_dwMode = MODE_LOG ;
		SetFocus( m_bNarrow ? m_hwndContent : m_hwndFile ) ;
		break ;
	case IDM_REFER:
		/* コメント順モードと標準モードをトグルする */
		if ( m_dwMode != MODE_LOG ) {
			break ;
		}
		if ( IsWindowVisible( m_hwndDetail ) ) {
			CloseLogView() ;
		}
		g_bRefMode = !g_bRefMode ;
		SendMessage( m_hwndFile, BLM_SETPROC, 0, (LPARAM) title_proc ) ;
		break ;
	case IDM_VIEWNEXT:
		/* 改ページした後に次メッセージを表示 */
		if ( m_dwMode != MODE_LOG ) {
			break ;
		}
		if ( IsWindowVisible( m_hwndDetail ) ) {
			if ( SendMessage( m_hwndDetail, MVM_PAGEDOWN, 0, 0 ) ) {
				break ;
			}
		} else {
			if ( SendMessage( m_hwndContent, MVM_PAGEDOWN, 0, 0 ) ) {
				break ;
			}
		}
		//
	case IDM_NEXTMSG:
		/* 次のメッセージを表示 */
		SendMessage( m_hwndFile, BLM_SETCURSEL, (WPARAM) m_dwListIndex + 1, 0 ) ;
		break ;
	case IDM_VIEWPREV:
		/* 改ページした後に前メッセージを表示 */
		if ( m_dwMode != MODE_LOG ) {
			break ;
		}
		if ( IsWindowVisible( m_hwndDetail ) ) {
			if ( SendMessage( m_hwndDetail, MVM_PAGEUP, 0, 0 ) ) {
				break ;
			}
		} else {
			if ( SendMessage( m_hwndContent, MVM_PAGEUP, 0, 0 ) ) {
				break ;
			}
		}
		//
	case IDM_PREVMSG:
		/* 前のメッセージを表示 */
		if ( m_dwListIndex ) {
			SendMessage( m_hwndFile, BLM_SETCURSEL, (WPARAM) m_dwListIndex - 1, 0 ) ;
		}
		break ;
	case IDM_COPY:
		/* 表示内容をクリップボードにコピーする */
		if ( !IsWindowVisible( m_hwndDetail ) ) {
			MessageBeep( 0xFFFFFFFF ) ;
			break ;
		}
		SendMessage( m_hwndDetail, WM_COPY, 0, 0 ) ;
		break ;
	case IDM_REPLYMSG:
		/* メッセージに対する返答を作成する */
		SetCursor( LoadCursor( NULL, IDC_WAIT ) ) ;
		MakeMessage( MESSAGE_REPLY ) ;
		SetCursor( NULL ) ;
		break ;
	case IDM_NEWMSG:
		/* 新しいメッセージを作成する */
		SetCursor( LoadCursor( NULL, IDC_WAIT ) ) ;
		MakeMessage( MESSAGE_POST ) ;
		SetCursor( NULL ) ;
		break ;
	case IDM_MAIL:
		/* 新しいメールを作成する */
		SetCursor( LoadCursor( NULL, IDC_WAIT ) ) ;
		MakeMessage( MESSAGE_MAIL ) ;
		SetCursor( NULL ) ;
		break ;
	case IDM_UPDIR:
		/* フォルダビューで一つ上のフォルダに移動する */
		if ( m_dwMode != MODE_FILE ) {
			break ;
		}
		rel2abs( g_szFilePath, g_szBaseDir, TEXT("..") ) ;
		_tcscpy( g_szBaseDir, g_szFilePath ) ;
		SendMessage( m_hwnd, WM_COMMAND, IDM_FILE, 0 ) ;
		break ;
	case IDM_DELETE:
		/* ファイルを削除する */
		if ( m_dwMode != MODE_FILE ) {
			break ;
		}
		index = SendMessage( m_hwndFile, BLM_GETCURSEL, 0, 0 ) ;
		if ( g_bIsDir[ index ] ) {
			/* ディレクトリは削除できない */
			MessageBeep( 0xFFFFFFFF ) ;
			break ;
		}
		wsprintf( MessageBuf, TEXT("Delete this file?\r\n[%s]"), g_szFilePath ) ;
		if ( MessageBox( hWnd, MessageBuf, TEXT("Delete"), MB_ICONQUESTION|MB_YESNO ) != IDYES ) {
			break ;
		}
		DeleteFile( g_szFilePath ) ;
		break ;
	case IDM_SETUP:
		if ( !SetupDialogExec( m_pApp->get_inst(), hWnd, m_bNarrow, &index ) ) {
			break ;
		}
		if ( index & SETUP_RET_CHANGE ) {
			SendMessage( m_hwndDetail, MVM_SETTAB, (WPARAM) g_dwTabSize, (LPARAM) FALSE ) ;
			SendMessage( m_hwndDetail, MVM_SETHMARGIN, (WPARAM) g_dwHMargin, (LPARAM) TRUE ) ;
		}
		break ;
	case IDM_SAVE:
		SaveAs() ;
		break ;
	case IDM_FIND_CONTINUE:
	case IDM_FIND:
		/* 文字列を検索する */
		if ( m_dwMode != MODE_LOG ) {
			break ;
		}
		if ( idCtrl != IDM_FIND_CONTINUE || !*g_szFindStr ) {
			if ( !FindDialogExec( m_pApp->get_inst(), m_hwnd ) ) {
				return FALSE ;
			}
		}
		FindString() ;
		break ;
	case IDM_EXIT:
		if ( IsWindowVisible( m_hwndDetail ) ) {
			CloseLogView() ;
		}
		SendMessage( hWnd, WM_CLOSE, 0, 0 ) ;
		break ;
	}
	return 0 ;
}

BOOL
MainWindow::WMClose()
{
	if ( IsWindowVisible( m_hwndDetail ) ) {
		CloseLogView() ;
		return TRUE ;
	}
	if ( g_bDeleteReg ) {
		m_pApp->DeleteReg() ;
	} else {
		m_pApp->SetReg() ;
	}
	return FALSE ;
}

void
MainWindow::WMSetFocus()
{
	if ( IsWindowVisible( m_hwndDetail ) ) {
		SetFocus( m_hwndDetail ) ;
	} else {
		SetFocus( m_hwndFile ) ;
	}
}

LRESULT
MainWindow::WMWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL *bDefault )
{
	MSG		msg1 ;
	DWORD	index ;

	*bDefault = FALSE ;
	switch ( msg ) {
	case WM_USER_VIEW:
		if ( PeekMessage( &msg1, hWnd, WM_USER_VIEW, WM_USER_VIEW, PM_NOREMOVE ) ) {
			break ;
		}
		*g_szContent = 0 ;
		index = SendMessage( m_hwndFile, BLM_GETCURSEL, 0, 0 ) ;
		switch ( m_dwMode ) {
		case MODE_FILE:
			if ( !*g_szFilePath ) {
				break ;
			}
			if ( g_bIsDir[ index ] ) {
				GetFolderContent( g_szFilePath, 20 ) ;
			} else {
				GetFileContent( g_szFilePath, 0, 0 ) ;
			}
			if ( !PeekMessage( &msg1, hWnd, WM_USER_VIEW, WM_USER_VIEW, PM_NOREMOVE ) ) {
				/* 内容表示用のプロシージャを設定する */
				SendMessage( m_hwndContent, MVM_SETBUFFER, 0, (LPARAM) g_szContent ) ;
			}
			break ;
		case MODE_LOG:
			if ( !GetLogContent() ) {
				break ;
			}
			if ( !PeekMessage( &msg1, hWnd, WM_USER_VIEW, WM_USER_VIEW, PM_NOREMOVE ) ) {
				/* 内容表示用のプロシージャを設定する */
				SendMessage( m_hwndContent, MVM_SETBUFFER, 0, (LPARAM) m_szFileBuf ) ;
				if ( IsWindowVisible( m_hwndDetail ) ) {
					SendMessage( m_hwndDetail, MVM_SETBUFFER, 0, (LPARAM) m_szFileBuf ) ;
				}
			}
			break ;
		}
		break ;
	case WM_INITMENUPOPUP:
		WMInitMenuPopup( (HMENU) wParam, (UINT) LOWORD(lParam), (BOOL) HIWORD(lParam) ) ;
		break ;
	case WM_HELP:
		DialogBox( m_pApp->get_inst(), MAKEINTRESOURCE(IDD_DLG_ABOUT), hWnd, AboutDlgFunc ) ;
		if ( g_bDeleteReg ) {
			SendMessage( hWnd, WM_COMMAND, IDM_EXIT, 0 ) ;
		}
		break ;
	case WM_LBUTTONDOWN:
		WMMouseDown( wParam, lParam ) ;
		break ;
	case WM_LBUTTONUP:
		WMMouseUp( wParam, lParam ) ;
		break ;
	case WM_MOUSEMOVE:
		WMMouseMove( wParam, lParam ) ;
		break ;
	case WM_CTLCOLORSTATIC:
		if ( (HWND) lParam == m_hwndSeparator ) {
			return (LRESULT) GetStockObject( BLACK_BRUSH ) ;
		}
		break ;
	default:
		*bDefault = TRUE ;
		break ;
	}
	return 0 ;
}

void
MainWindow::WMInitMenuPopup( HMENU hmenuPopup, UINT uPos, BOOL fSystemMenu )
{
	UINT			uEnable ;
	MENUITEMINFO	mii ;

	memset( &mii, 0, sizeof mii ) ;
	switch ( uPos ) {
	case 0:
		uEnable = MF_BYCOMMAND ;
		uEnable |= m_dwMode == MODE_LOG ? 0 : MF_GRAYED ;
		EnableMenuItem( hmenuPopup, IDM_FILE, uEnable ) ;
		EnableMenuItem( hmenuPopup, IDM_REFER, uEnable ) ;
		uEnable = MF_BYCOMMAND ;
		uEnable |= m_dwMode == MODE_LOG ? MF_GRAYED : 0 ;
		EnableMenuItem( hmenuPopup, IDM_LOG, uEnable ) ;
		EnableMenuItem( hmenuPopup, IDM_LOGALL, uEnable ) ;
		EnableMenuItem( hmenuPopup, IDM_DELETE, uEnable ) ;
		uEnable = MF_BYCOMMAND ;
		uEnable |= g_bRefMode ? MF_CHECKED : MF_UNCHECKED ;
		CheckMenuItem( hmenuPopup, IDM_REFER, uEnable ) ;
		break ;
	case 1:
		uEnable = MF_BYCOMMAND ;
		uEnable |= IsWindowVisible( m_hwndDetail ) ? 0 : MF_GRAYED ;
		EnableMenuItem( hmenuPopup, IDM_COPY, uEnable ) ;
		uEnable = MF_BYCOMMAND ;
		uEnable |= m_dwMode == MODE_LOG ? 0 : MF_GRAYED ;
		EnableMenuItem( hmenuPopup, IDM_FIND, uEnable ) ;
		EnableMenuItem( hmenuPopup, IDM_REPLYMSG, uEnable ) ;
		EnableMenuItem( hmenuPopup, IDM_NEWMSG, uEnable ) ;
		EnableMenuItem( hmenuPopup, IDM_MAIL, uEnable ) ;
		EnableMenuItem( hmenuPopup, IDM_PREVMSG, uEnable ) ;
		EnableMenuItem( hmenuPopup, IDM_VIEWNEXT, uEnable ) ;
		EnableMenuItem( hmenuPopup, IDM_NEXTMSG, uEnable ) ;
		break ;
	}
}

void
MainWindow::WMMouseDown( WPARAM wParam, LPARAM lParam )
{
	RECT	rect ;
	POINT	point ;
	WORD	xPos = LOWORD( lParam ) ;
	WORD	yPos = HIWORD( lParam ) ;

	GetWindowRect( m_hwndFile, &m_rectFile ) ;
	ScreenToClientRect( m_hwnd, &m_rectFile ) ;
	GetWindowRect( m_hwndContent, &m_rectContent ) ;
	ScreenToClientRect( m_hwnd, &m_rectContent ) ;
	if ( m_bNarrow ) {
		rect.left = m_rectFile.left ;
		rect.top = m_rectFile.bottom ;
		rect.right = m_rectContent.right ;
		rect.bottom = m_rectContent.top ;
	} else {
		rect.left = m_rectFile.right ;
		rect.top = m_rectFile.top ;
		rect.right = m_rectContent.left ;
		rect.bottom = m_rectContent.bottom ;
	}
	point.x = xPos ;
	point.y = yPos ;
	if ( PtInRect( &rect, point ) ) {
		m_bMouseDown = TRUE ;
		SetCapture( m_hwnd ) ;
		if ( m_bNarrow ) {
			g_dwSeparatorPos = yPos ;
		} else {
			g_dwSeparatorPos = xPos ;
		}
		DrawSeparator() ;
		ShowWindow( m_hwndSeparator, SW_SHOWNOACTIVATE ) ;
	}
}

void
MainWindow::WMMouseMove( WPARAM wParam, LPARAM lParam )
{
	WORD	xPos = LOWORD( lParam ) ;
	WORD	yPos = HIWORD( lParam ) ;

	if ( m_bMouseDown ) {
		if ( m_bNarrow ) {
			g_dwSeparatorPos = yPos ;
		} else {
			g_dwSeparatorPos = xPos ;
		}
		DrawSeparator() ;
	}
}

void
MainWindow::WMMouseUp( WPARAM wParam, LPARAM lParam )
{
	RECT	rect ;

	if ( m_bMouseDown ) {
		m_bMouseDown = FALSE ;
		ShowWindow( m_hwndSeparator, SW_HIDE ) ;
		GetWindowRect( m_hwndFile, &rect ) ;
		ScreenToClientRect( m_hwnd, &rect ) ;
		if ( m_bNarrow ) {
			MoveWindow( m_hwndFile,
						rect.left, rect.top,
						rect.right - rect.left, g_dwSeparatorPos - rect.top,
						TRUE ) ;
		} else {
			MoveWindow( m_hwndFile,
						rect.left, rect.top,
						g_dwSeparatorPos - rect.left, rect.bottom - rect.top,
						TRUE ) ;
			/* 一覧領域に表示できる文字数を求める */
			m_dwMaxFileCol = SendMessage( m_hwndFile, BLM_GETMAXCOL, 0, 0 ) ;
		}
		GetWindowRect( m_hwndContent, &rect ) ;
		ScreenToClientRect( m_hwnd, &rect ) ;
		if ( m_bNarrow ) {
			MoveWindow( m_hwndContent,
						rect.left, g_dwSeparatorPos + 2,
						rect.right - rect.left, rect.bottom - (g_dwSeparatorPos + 2),
						TRUE ) ;
		} else {
			MoveWindow( m_hwndContent,
						g_dwSeparatorPos + 2, rect.top,
						rect.right - (g_dwSeparatorPos + 2), rect.bottom - rect.top,
						TRUE ) ;
		}
	}
	ReleaseCapture() ;
}

void
MainWindow::DrawSeparator() const
{
	RECT	rect ;

	if ( m_bNarrow ) {
		rect.left = m_rectFile.left ;
		rect.top = g_dwSeparatorPos ;
		rect.right = m_rectContent.right ;
		rect.bottom = g_dwSeparatorPos + 1 ;
	} else {
		rect.left = g_dwSeparatorPos ;
		rect.top = m_rectFile.top ;
		rect.right = g_dwSeparatorPos + 1 ;
		rect.bottom = m_rectContent.bottom ;
	}
	SetWindowPos( m_hwndSeparator, (HWND) 0,
				  rect.left, rect.top,
				  rect.right - rect.left, rect.bottom - rect.top,
				  0 ) ;
}

BOOL
MainWindow::GetLogContent()
{
	DWORD	nRead ;
	HANDLE	hfile ;

	FreeFileBuf() ;
	if ( !*g_szFilePath ) {
		m_szFileBuf = (LPBYTE) LocalAlloc( LPTR, 256 ) ;
		if ( !m_szFileBuf ) {
			return FALSE ;
		}
		if ( m_dwRoomNo ) {
			Sprintf( (LPSTR) m_szFileBuf, "%sフォーラム\r\n %d番会議室\r\n %s",
					 m_szForumID, m_dwRoomNo, m_szRoomName ) ;
		} else {
			Sprintf( (LPSTR) m_szFileBuf, "%s", m_szRoomName ) ;
		}
	} else {
		m_szFileBuf = (LPBYTE) LocalAlloc( LPTR, m_dwLogSize + 1 ) ;
		if ( !m_szFileBuf ) {
			return FALSE ;
		}
		hfile = CreateFile( g_szFilePath,
					GENERIC_READ,
					FILE_SHARE_READ,
					NULL,
					OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL,
					NULL ) ;
		if ( hfile == INVALID_HANDLE_VALUE ) {
			FreeFileBuf() ;
			return FALSE ;
		}
		memset( m_szFileBuf, 0, m_dwLogSize ) ;
		if ( m_dwLogPos ) {
			SetFilePointer( hfile, m_dwLogPos, NULL, FILE_BEGIN ) ;
		}
		ReadFile( hfile, m_szFileBuf, m_dwLogSize, &nRead, NULL ) ;
		m_szFileBuf[ m_dwLogSize ] = 0 ;
		CloseHandle( hfile ) ;
	}
	return TRUE ;
}

void
MainWindow::OneKeyMessage( TCHAR chCharCode ) const
{
	switch ( chCharCode ) {
	case ' ':
		SendMessage( m_hwnd, WM_COMMAND, IDM_VIEWNEXT, 0 ) ;
		break ;
	case 'N':
	case 'n':
		SendMessage( m_hwnd, WM_COMMAND, IDM_NEXTMSG, 0 ) ;
		break ;
	case 'P':
	case 'p':
		SendMessage( m_hwnd, WM_COMMAND, IDM_PREVMSG, 0 ) ;
		break ;
	case 'R':
	case 'r':
	case 'A':
	case 'a':
		SendMessage( m_hwnd, WM_COMMAND, IDM_REPLYMSG, 0 ) ;
		break ;
	case 'E':
	case 'e':
		SendMessage( m_hwnd, WM_COMMAND, IDM_NEWMSG, 0 ) ;
		break ;
	case 'M':
	case 'm':
		SendMessage( m_hwnd, WM_COMMAND, IDM_MAIL, 0 ) ;
		break ;
	case '\b':
		if ( m_dwMode == MODE_FILE ) {
			SendMessage( m_hwnd, WM_COMMAND, IDM_UPDIR, 0 ) ;
		} else {
			SendMessage( m_hwnd, WM_COMMAND, IDM_VIEWPREV, 0 ) ;
		}
		break ;
	case 'O':
	case 'o':
		SendMessage( m_hwnd, WM_COMMAND, IDM_LOGALL, 0 ) ;
		break ;
	}
}

void
MainWindow::UpdateSelected( BOOL bAll ) const
{
	DWORD	i ;

	for ( i = 0 ; i < MAX_FN ; i ++ ) {
		g_bIsSelected[ i ] = FALSE ;
	}
	if ( bAll ) {
		for ( i = 0 ; i < g_dwNumFilename ; i ++ ) {
			g_bIsSelected[ i ] = TRUE ;
		}
	} else {
		i = SendMessage( m_hwndFile, BLM_GETCURSEL, 0, 0 ) ;
		g_bIsSelected[ i ] = TRUE ;
	}
}

void
MainWindow::OpenLogView()
{
	SendMessage( m_hwndDetail, MVM_SETBUFFER, 0, (LPARAM) m_szFileBuf ) ;
	ShowWindow( m_hwndDetail, SW_SHOW ) ;
	ShowWindow( m_hwndFile, SW_HIDE ) ;
	ShowWindow( m_hwndContent, SW_HIDE ) ;
	SetFocus( m_hwndDetail ) ;
}

void
MainWindow::CloseLogView()
{
	DWORD	dwIndex ;

	ShowWindow( m_hwndFile, SW_SHOW ) ;
	ShowWindow( m_hwndContent, SW_SHOW ) ;
	ShowWindow( m_hwndDetail, SW_HIDE ) ;
	SetFocus( m_bNarrow ? m_hwndContent : m_hwndFile ) ;
	dwIndex = SendMessage( m_hwndFile, BLM_GETCURSEL, 0, 0 ) ;
	if ( m_dwListIndex != dwIndex ) {
		SendMessage( m_hwndFile, BLM_SETCURSEL, (WPARAM) m_dwListIndex, 0 ) ;
	}
}

BOOL
MainWindow::MakeMessage( MESSAGEMODE dwMessageMode )
{
	HANDLE	hfile ;
	LPSTR	szReply ;
	TCHAR	fn[ MAX_PATH ] ;
	LPCTSTR	szPadFn = NULL ;
	DWORD	index, count, nRead, nWrite ;

	if ( m_dwMode != MODE_LOG ) {
		return FALSE ;
	} else if ( !m_szFileBuf ) {
		/* メッセージバッファに何もない場合 */
		return FALSE ;
	}
	/* 選択中の発言のインデックスを求める */
	index = g_bRefMode ? g_dwRefList[ m_dwListIndex ] : g_dwNormList[ m_dwListIndex ] ;
	/* メールに対する返信や新規発言かどうか調べる */
	if ( dwMessageMode == MESSAGE_REPLY || dwMessageMode == MESSAGE_POST ) {
		if ( IsMailForum( index ) ) {
			dwMessageMode = MESSAGE_MAIL ;
		}
	}
	/* モードに応じてPADテンプレートを選択する */
	if ( dwMessageMode == MESSAGE_REPLY ) {
		szPadFn = g_szPadRepl ;
	} else if ( dwMessageMode == MESSAGE_POST ) {
		szPadFn = g_szPadNew ;
	} else if ( dwMessageMode == MESSAGE_MAIL ) {
		szPadFn = g_szPadMail ;
	} else {
		return FALSE ;
	}
	/* (もしあれば)返信用のPADテンプレートを読み込む */
	hfile = CreateFile( szPadFn,
				GENERIC_READ,
				FILE_SHARE_READ,
				NULL,
				OPEN_EXISTING,
				FILE_ATTRIBUTE_NORMAL,
				NULL ) ;
	if ( hfile != INVALID_HANDLE_VALUE ) {
		if ( dwMessageMode == MESSAGE_REPLY ) {
			ReadFile( hfile, g_szReplyBase, sizeof g_szReplyBase, &nRead, NULL ) ;
			g_szReplyBase[ sizeof g_szReplyBase - 1 ] = 0 ;
		} else if ( dwMessageMode == MESSAGE_POST ) {
			ReadFile( hfile, g_szNewBase, sizeof g_szNewBase, &nRead, NULL ) ;
			g_szNewBase[ sizeof g_szNewBase - 1 ] = 0 ;
		} else if ( dwMessageMode == MESSAGE_MAIL ) {
			ReadFile( hfile, g_szMailBase, sizeof g_szMailBase, &nRead, NULL ) ;
			g_szMailBase[ sizeof g_szMailBase - 1 ] = 0 ;
		}
		CloseHandle( hfile ) ;
	}
	/* モードに応じてメッセージを作成する */
	if ( dwMessageMode == MESSAGE_REPLY ) {
		count = MakeReplyMessage( NULL, index, m_szFileBuf ) ;
	} else if ( dwMessageMode == MESSAGE_POST ) {
		count = MakeNewMessage( NULL, index, m_szFileBuf ) ;
	} else if ( dwMessageMode == MESSAGE_MAIL ) {
		count = MakeMailMessage( NULL, index, m_szFileBuf ) ;
	} else {
		count = 0 ;
	}
	if ( !count ) {
		/* 返信用メッセージがない場合 */
		return FALSE ;
	}
	if ( !MakeForumFn_EmTerm( fn, index, FALSE ) ) {
		/* PADファイル名を作成できなかった場合 */
		MessageBeep( 0xFFFFFFFF ) ;
		return FALSE ;
	}
	szReply = (LPSTR) LocalAlloc( LPTR, count ) ;
	if ( !szReply ) {
		/* 返信用メッセージを確保できなかった場合 */
		return FALSE ;
	}
	if ( dwMessageMode == MESSAGE_REPLY ) {
		MakeReplyMessage( (LPBYTE) szReply, index, m_szFileBuf ) ;
	} else if ( dwMessageMode == MESSAGE_POST ) {
		MakeNewMessage( (LPBYTE) szReply, index, m_szFileBuf ) ;
	} else if ( dwMessageMode == MESSAGE_MAIL ) {
		MakeMailMessage( (LPBYTE) szReply, index, m_szFileBuf ) ;
	}
	if ( g_bUseClipboard && (GetFileAttributes( fn ) == 0xFFFFFFFF) ) {
		/* クリップボード経由でのＰＡＤ作成を行う場合 */
		SendClipboard( szReply ) ;
	} else {
		hfile = CreateFile( fn,
					GENERIC_WRITE,
					FILE_SHARE_READ|FILE_SHARE_WRITE,
					NULL,
					OPEN_ALWAYS,
					FILE_ATTRIBUTE_NORMAL,
					NULL ) ;
		if ( hfile == INVALID_HANDLE_VALUE ) {
			LocalFree( szReply ) ;
			return FALSE ;
		}
		SetFilePointer( hfile, 0, NULL, FILE_END ) ;
		WriteFile( hfile, szReply, strlen( szReply ), &nWrite, NULL ) ;
		CloseHandle( hfile ) ;
	}
	LocalFree( szReply ) ;
	ExecProgram( fn ) ;
	return TRUE ;
}

BOOL
MainWindow::SaveAs()
{
	OPENFILENAME	ofn ;
	HANDLE			hFile ;
	DWORD			nWrite ;
	TCHAR			buf1[ MAX_PATH ] ;

	if ( m_dwMode != MODE_LOG ) {
		return FALSE ;
	} else if ( !m_szFileBuf || !m_dwLogSize ) {
		/* メッセージバッファに何もない場合 */
		return FALSE ;
	}
	memset( &ofn, 0, sizeof ofn ) ;
	_tcscpy( buf1, TEXT("*.txt") ) ;
	ofn.lStructSize = sizeof ofn ;
    ofn.hwndOwner = m_hwnd ;
    ofn.hInstance = m_pApp->get_inst() ;
    ofn.lpstrFilter = TEXT("Text Files (*.txt)\0*.txt\0\0") ;
    ofn.lpstrCustomFilter = NULL ;
    ofn.nMaxCustFilter = 0 ;
    ofn.nFilterIndex = 1 ;
    ofn.lpstrFile = buf1 ;
    ofn.nMaxFile = MAX_PATH ;
    ofn.lpstrFileTitle = NULL ;
    ofn.nMaxFileTitle = 0 ;
    ofn.lpstrInitialDir = NULL ;
    ofn.lpstrTitle = NULL ;
    ofn.Flags = 0 ;
    ofn.nFileOffset = 0 ;
    ofn.nFileExtension = 0 ;
    ofn.lpstrDefExt = TEXT("TXT") ;
    ofn.lCustData = 0 ;
    ofn.lpfnHook = NULL ;
    ofn.lpTemplateName = NULL ;
	if ( !GetSaveFileName( &ofn ) ) {
		return FALSE ;
	}
	hFile = CreateFile( buf1,
				GENERIC_WRITE,
				FILE_SHARE_READ,
				NULL,
				OPEN_ALWAYS,
				FILE_ATTRIBUTE_NORMAL,
				NULL ) ;
	if ( hFile == INVALID_HANDLE_VALUE ) {
		MessageBox( m_hwnd, TEXT("Can't open file"), TEXT("Save As ..."), MB_OK|MB_ICONASTERISK ) ;
		return FALSE ;
	}
	SetFilePointer( hFile, 0, NULL, FILE_END ) ;
	WriteFile( hFile, m_szFileBuf, m_dwLogSize, &nWrite, NULL ) ;
	CloseHandle( hFile ) ;
	return TRUE ;
}

/*
 * 既に指定された検索条件にしたがって文字列を探す
 */
BOOL
MainWindow::FindString()
{
	LPCTSTR	ptr ;
	BOOL	bRet ;
	DWORD	dwTop, dwIndex, dwMsgIdx ;

	dwIndex = m_dwListIndex ;
	SetCursor( LoadCursor( NULL, IDC_WAIT ) ) ;
	if ( IsWindowVisible( m_hwndDetail ) && m_szFileBuf ) {
		/* 詳細モードの場合はその中で検索する */
		dwTop = SendMessage( m_hwndDetail, MVM_GETTOPPOS, 1, 0 ) ;
		bRet = FindStringForwardMem( m_szFileBuf, m_dwLogSize + 1, dwTop + 1, g_szFindStr, g_bIgnoreCase, &dwTop ) ;
		if ( bRet ) {
			SendMessage( m_hwndDetail, MVM_SETTOPPOS, (WPARAM) dwTop, 0 ) ;
			SetCursor( NULL ) ;
			return TRUE ;
		}
		/* 見つからなかった場合は次の発言から検索 */
		dwIndex ++ ;
	}
	bRet = FindStringForwardLog( dwIndex, &dwIndex ) ;
	if ( !bRet ) {
		SetCursor( NULL ) ;
		MessageBox( m_hwnd, TEXT("String not found"), TEXT("Find"), MB_ICONINFORMATION|MB_OK ) ;
		return FALSE ;
	}
	m_dwListIndex = dwIndex ;
	dwMsgIdx = g_bRefMode ? g_dwRefList[ dwIndex ] : g_dwNormList[ dwIndex ] ;
	ptr = GetLogFile( dwMsgIdx, &m_dwLogPos, &m_dwLogSize ) ;
	if ( ptr ) {
		rel2abs( g_szFilePath, g_szBaseDir, ptr ) ;
		GetLogContent() ;
		OpenLogView() ;
		bRet = FindStringForwardMem( m_szFileBuf, m_dwLogSize + 1, 0, g_szFindStr, g_bIgnoreCase, &dwTop ) ;
		if ( bRet ) {
			SendMessage( m_hwndDetail, MVM_SETTOPPOS, (WPARAM) dwTop, 0 ) ;
		}
		SetCursor( NULL ) ;
		return TRUE ;
	}
	SetCursor( NULL ) ;
	return FALSE ;
}

/*
 * ログ内の文字列を検索する
 */
BOOL
MainWindow::FindStringForwardLog( DWORD dwStartIndex, LPDWORD pFoundIndex )
{
	BOOL	bRet ;
	LPCTSTR	szPath ;
	LPBYTE	szBody ;
	DWORD	i, dwPos, dwSize, dwMsgIdx ;


	/* ログファイルを検索していく */
	for ( i = dwStartIndex ; i < g_dwNumRefList ; i ++ ) {
		/* ログのインデックスを得る */
		dwMsgIdx = g_bRefMode ? g_dwRefList[ i ] : g_dwNormList[ i ] ;
		/* ログファイル名、位置、サイズを求める */
		szPath = GetLogFile( dwMsgIdx, &dwPos, &dwSize ) ;
		if ( !szPath || !dwSize ) {
			continue ;
		}
		szBody = (LPBYTE) LocalAlloc( LPTR, dwSize ) ;
		if ( !szBody ) {
			continue ;
		}
		bRet = FALSE ;
		/* ログファイルをオープンする */
		if ( Fopen( szPath, TEXT("rb") ) ) {
			/* 該当するログを読み込む */
			Fseek( dwPos, 0 ) ;
			dwSize = Fread( (char *) szBody, dwSize ) ;
			/* ログの中で文字列を検索する */
			bRet = FindStringForwardMem( szBody, dwSize, 0, g_szFindStr, g_bIgnoreCase, NULL ) ;
			Fclose() ;
		}
		LocalFree( szBody ) ;
		/* ログが見つかった場合 */
		if ( bRet ) {
			if ( pFoundIndex ) {
				*pFoundIndex = i ;
			}
			return TRUE ;
		}
	}
	return FALSE ;
}

int
MainWindow::file_proc( int index, const BYTE **ptr, int *len )
{
	LPTSTR			dst ;
	DWORD			len1, count ;
	TCHAR			unicode[ MAX_PATH ], buf[ MAX_PATH ] ;
	static	BYTE	sjis[ MAX_PATH ] ;

	if ( index < 0 ) {
		return (int) g_dwNumFilename ;
	} else if ( index >= (int) g_dwNumFilename ) {
		return -1 ;
	}
	if ( g_bIsDir[ index ] ) {
		wsprintf( unicode, TEXT("[%s]"), g_szFilename[ index ] ) ;
		_tcscpy( buf, TEXT("<DIR>") ) ;
	} else {
		_tcscpy( unicode, g_szFilename[ index ] ) ;
		wsprintf( buf, TEXT("%d"), g_dwFilesize[ index ] ) ;
	}
	len1 = CalcStrCols( unicode ) + CalcStrCols( buf ) ;
	if ( m_dwMaxFileCol > len1 ) {
		dst = unicode ;
		dst += _tcslen( unicode ) ;
		count = m_dwMaxFileCol - len1 ;
		do {
			*dst++ = TEXT(' ') ;
		} while ( -- count ) ;
		_tcscpy( dst, buf ) ;
		dst += _tcslen( dst ) ;
		*dst = 0 ;
	}
	/* Unicode→SJIS変換を行う */
	unicode2sjis( unicode, sjis, sizeof sjis ) ;

	*ptr = sjis ;
	*len = strlen( (LPSTR) *ptr ) ;
	return 0 ;
}

int
MainWindow::title_proc( int index, const BYTE **ptr, int *len )
{
	DWORD			dwLogIdx ;
	static	BYTE	sjis[ MAX_PATH ] ;
	int				num = g_bRefMode ? g_dwNumRefList : g_dwNumNormList ;

	if ( index < 0 ) {
		return (int) num ;
	} else if ( index >= (int) num ) {
		return -1 ;
	}
	dwLogIdx = g_bRefMode ? g_dwRefList[ index ] : g_dwNormList[ index ] ;
	*ptr = (LPBYTE) GetLogTitle( dwLogIdx, g_bRefMode, m_dwMaxFileCol ) ;
	if ( !ptr ) {
		strcpy( (LPSTR) sjis, "{内部エラー}" ) ;
		*ptr = sjis ;
	}
	*len = strlen( (LPSTR) *ptr ) ;
	return 0 ;
}

BOOL
MainWindow::Create()
{
	HWND	hWnd = CreateWindowEx( 0,
						GetClassName(),
						szTitleName,
						WS_VISIBLE,
#ifdef	_WIN32_WCE
						0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
#else	/* _WIN32_WCE */
						0, 0, 640, 240,
#endif	/* _WIN32_WCE */
						NULL,
						NULL,
						m_pApp->get_inst(),
						this ) ;
	if ( hWnd == 0 ) {
		return FALSE ;
	}
    ShowWindow( hWnd, SW_SHOW ) ;
    UpdateWindow( hWnd ) ;
    return TRUE ;
}

DWORD
MainWindow::CreateCommandBar()
{
	HINSTANCE	hInst = m_pApp->get_inst() ;

#ifdef	_WIN32_WCE
	TBBUTTON	g_tbWideButton[] = {
		{ 0,            0, TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0, -1},
		{ 3,     IDM_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
		{ 0,            0, TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0, -1},
		{ 0,  IDM_PREVMSG, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
		{ 1, IDM_VIEWNEXT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
		{ 2,  IDM_NEXTMSG, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
		{ 0,            0, TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0, -1},
		{ 4,   IDM_NEWMSG, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
		{ 5, IDM_REPLYMSG, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
		{ 6,     IDM_MAIL, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
		{ 0,            0, TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0, -1},
		{ 8,     IDM_FIND, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	} ;
	TBBUTTON	g_tbNarrowButton[] = {
		{ 0,            0, TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0, -1},
		{ 0,  IDM_PREVMSG, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
		{ 2,  IDM_NEXTMSG, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
		{ 0,            0, TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0, -1},
		{ 5, IDM_REPLYMSG, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	} ;

	m_hwndCB = CommandBar_Create( hInst, m_hwnd, 0 ) ;
	CommandBar_InsertMenubar( m_hwndCB, hInst, IDR_MAIN_MENU, 0 ) ;
	CommandBar_AddBitmap( m_hwndCB, hInst, IDR_TOOLBAR1, 16, 0, 0 ) ;
	if ( m_bNarrow ) {
		CommandBar_AddButtons( m_hwndCB, sizeof(g_tbNarrowButton) / sizeof(*g_tbNarrowButton), g_tbNarrowButton ) ;
	} else {
		CommandBar_AddButtons( m_hwndCB, sizeof(g_tbWideButton) / sizeof(*g_tbWideButton), g_tbWideButton ) ;
	}
	CommandBar_AddAdornments( m_hwndCB, CMDBAR_HELP, 0 ) ;
	return CommandBar_Height( m_hwndCB ) ;
#else	/* _WIN32_WCE */
	return 0 ;
#endif	/* _WIN32_WCE */
}

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 ) ;
#ifdef	_WIN32_WCE
	wc.lpszMenuName  = 0 ;
#else	/* _WIN32_WCE */
	wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MAIN_MENU) ;
#endif	/* _WIN32_WCE */
	wc.lpszClassName = 	GetClassName() ;
	return ::RegisterClass( &wc ) ;
}
