/*-----------------------------------------------------------------------------
[名称]	MainFrm.cpp
[概要]	へぼぺ本体の実装
[備考]	自動生成ファイルなので、変更を加えた箇所のみコメントを付加する。
[履歴]	2003-03-14	NC		新規作成(moralog)
-----------------------------------------------------------------------------*/


//-----------------------------------------------------------------------------
// インクルード
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "hebope.h"
#include "MainFrm.h"
#include "AAHanger.h"
#include "HebopeDoc.h"
#include "AAListView.h"
#include "../Common/Common.h"
#include "ExeCommon.h"
#include "CategoryTreeView.h"
#include "SettingDlg.h"
#include "EditAADlg.h"
#include "../Common/ShitarabianPostCommand.h"

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

// ソート用 long比較関数
int IndexSort(const void * pA, const void * pB) 
{
	if ( *((long*)pA) < *((long*)pB) )
	{
		return( -1 );
	}
	else
	if ( *((long*)pA) == *((long*)pB) )
	{
		return( 0 );
	}
	else
	{
		return( 1 );
	}

}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
	//{{AFX_MSG_MAP(CMainFrame)
	ON_WM_CREATE()
	ON_COMMAND(IDM_VIEW_FONT, OnViewFont)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
	ON_WM_CLOSE()
	ON_COMMAND(IDM_EDIT_MARGE, OnEditMarge)
	ON_COMMAND(IDM_EDIT_ARRANGE, OnEditArrange)
	ON_COMMAND(IDM_EDIT_APPEND, OnEditAppend)
	ON_COMMAND(IDM_TREE_CATEGORIZE, OnTreeCategorize)
	ON_UPDATE_COMMAND_UI(IDM_TREE_ADDNODE, OnUpdateTreeAddnode)
	ON_UPDATE_COMMAND_UI(IDM_TREE_CATEGORIZE, OnUpdateTreeCategorize)
	ON_UPDATE_COMMAND_UI(IDM_TREE_DELETENODE, OnUpdateTreeDeletenode)
	ON_UPDATE_COMMAND_UI(IDM_LIST_ADDAA, OnUpdateListAddaa)
	ON_UPDATE_COMMAND_UI(IDM_LIST_DELETEINDEX, OnUpdateListDeleteindex)
	ON_UPDATE_COMMAND_UI(IDM_LIST_EDITAA, OnUpdateListEditaa)
	ON_UPDATE_COMMAND_UI(IDM_SHITARABIAN_PASTE, OnUpdateShitarabianPaste)
	ON_COMMAND(IDM_SHITARABIAN_PASTE, OnShitarabianPaste)
	ON_UPDATE_COMMAND_UI(IDM_EDIT_MARGE, OnUpdateEditMarge)
	ON_UPDATE_COMMAND_UI(IDM_EDIT_ARRANGE, OnUpdateEditArrange)
	ON_UPDATE_COMMAND_UI(IDM_EDIT_APPEND, OnUpdateEditAppend)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
	ON_WM_SHOWWINDOW()
	ON_COMMAND(IDM_HELP_MANUAL, OnHelpManual)
	ON_COMMAND(IDM_HELP_WEB, OnHelpWeb)
	//}}AFX_MSG_MAP
	ON_UPDATE_COMMAND_UI_RANGE(AFX_ID_VIEW_MINIMUM, AFX_ID_VIEW_MAXIMUM, OnUpdateViewStyles)
	ON_COMMAND_RANGE(AFX_ID_VIEW_MINIMUM, AFX_ID_VIEW_MAXIMUM, OnViewStyle)
END_MESSAGE_MAP()

static UINT indicators[] =
{
	ID_SEPARATOR,           // ステータス ライン インジケータ
	ID_INDICATOR_KANA,
	ID_INDICATOR_CAPS,
	ID_INDICATOR_NUM,
	ID_INDICATOR_SCRL,
};

/////////////////////////////////////////////////////////////////////////////
// CMainFrame クラスの構築/消滅

CMainFrame::CMainFrame()
	: 	m_bAlive( FALSE )
	,	m_uiMinMember( 3 )
	,	m_uiNearPattern( 2 )
	,	m_hwndParent( NULL )
{
	// メッセージ送信するウィンドウを取得
	CString		strParentHWND = ::GetCommandtailOption( ::GetString(IDS_SHITARABIAN) );
	if ( !strParentHWND.IsEmpty() )
	{
		HWND	hwnd = (HWND)(atol( strParentHWND ));
		if ( ::IsWindow( hwnd ) )
		{
			m_hwndParent = hwnd;
		}
	}

//	long	idxOption;
//	for( idxOption=0 ; idxOption<__argc ; idxOption++ )
//	{
//		::AfxMessageBox( __argv[idxOption] );
//	}
}

CMainFrame::~CMainFrame()
{
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
		| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
		!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
	{
		TRACE0("Failed to create toolbar\n");
		return -1;      // 作成に失敗
	}

	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		  sizeof(indicators)/sizeof(UINT)))
	{
		TRACE0("Failed to create status bar\n");
		return -1;      // 作成に失敗
	}

	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
	EnableDocking(CBRS_ALIGN_ANY);
	DockControlBar(&m_wndToolBar);

	// グローバルから参照できるようにする
	::SetMainFrame( this );

	m_bAlive = TRUE;

	return 0;
}


/*-----------------------------------------------------------------------------
[名称]	クライアント領域作成
[機能]	ペインの作成。
[戻値]	なし
[備考]	m_wndHorizontalSplitter で左右を分割し左をリストとする。
		さらに右を m_wndVirticalSplitter で上下に分割し、
		上をリスト（レポート）、下をエディットとする。
-----------------------------------------------------------------------------*/
BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT /*lpcs*/,
	CCreateContext* pContext)
{
	// 分割ウィンドウを作成します
	if (!m_wndHorizontalSplitter.CreateStatic(this, 1, 2))
		return FALSE;

	// 分割ウィンドウの作成
	// http://www2s.biglobe.ne.jp/~m_harada/cpptips/splitter.html
	{
		BOOL	bSuccess = TRUE;
		bSuccess &= m_wndHorizontalSplitter.CreateView(0, 0, RUNTIME_CLASS(CCategoryTreeView), CSize(200, 100), pContext);
		bSuccess &= m_wndVirticalSplitter.CreateStatic(&m_wndHorizontalSplitter, 2, 1, WS_CHILD | WS_VISIBLE, m_wndHorizontalSplitter.IdFromRowCol(0, 1));
		bSuccess &= m_wndVirticalSplitter.CreateView(0, 0, RUNTIME_CLASS(CAAListView), CSize(100, 200), pContext);
		bSuccess &= m_wndVirticalSplitter.CreateView(1, 0, RUNTIME_CLASS(CEditView), CSize(100, 100), pContext);
		if ( !bSuccess )
		{
			m_wndVirticalSplitter.DestroyWindow();
			m_wndHorizontalSplitter.DestroyWindow();
			return FALSE;
		}

		DWORD	dwLong;

		// ツリービューの概観を変更
		dwLong = ::GetWindowLong( (HWND)GetTreeView()->GetTreeCtrl(), GWL_STYLE );
		::SetWindowLong( (HWND)GetTreeView()->GetTreeCtrl(), GWL_STYLE, dwLong | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_EDITLABELS );

		// リストビューの概観を変更
		CListCtrl*	pList = &(GetListView()->GetListCtrl());
		dwLong = ::GetWindowLong( (HWND)*pList, GWL_STYLE );
		::SetWindowLong( (HWND)*pList, GWL_STYLE, dwLong | LVS_REPORT | LVS_SHOWSELALWAYS );
		pList->InsertColumn( 0, "名称", LVCFMT_LEFT, 300 );
		GetListView()->ColorSortColumn( TRUE );
		GetListView()->EnableSortIcon( TRUE );

		// エディットビューの概観を変更
		dwLong = ::GetWindowLong( (HWND)GetEditView()->GetEditCtrl(), GWL_STYLE );
		::SetWindowLong( (HWND)GetEditView()->GetEditCtrl(), GWL_STYLE, dwLong | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN );
		// フォントの設定
		{
			HDC	hdc = ::GetDC( NULL );
			CDC* pDC = CDC::FromHandle( hdc );
			GetEditView()->SetFont( m_Font.GetFont( pDC ) );
			::ReleaseDC( NULL, hdc );
		}
	}
	return TRUE;
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame クラスの診断

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	CFrameWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainFrame メッセージ ハンドラ

void CMainFrame::OnUpdateViewStyles(CCmdUI* pCmdUI)
{
/*
	if (pView == NULL)
		pCmdUI->Enable(FALSE);
	else
	{
		DWORD dwStyle = pView->GetStyle() & LVS_TYPEMASK;

		if (pCmdUI->m_nID == ID_VIEW_LINEUP)
		{
			if (dwStyle == LVS_ICON || dwStyle == LVS_SMALLICON)
				pCmdUI->Enable();
			else
				pCmdUI->Enable(FALSE);
		}
		else
		{
			pCmdUI->Enable();
			BOOL bChecked = FALSE;

			switch (pCmdUI->m_nID)
			{
			case ID_VIEW_DETAILS:
				bChecked = (dwStyle == LVS_REPORT);
				break;

			case ID_VIEW_SMALLICON:
				bChecked = (dwStyle == LVS_SMALLICON);
				break;

			case ID_VIEW_LARGEICON:
				bChecked = (dwStyle == LVS_ICON);
				break;

			case ID_VIEW_LIST:
				bChecked = (dwStyle == LVS_LIST);
				break;

			default:
				bChecked = FALSE;
				break;
			}

			pCmdUI->SetRadio(bChecked ? 1 : 0);
		}
	}
*/
}


void CMainFrame::OnViewStyle(UINT nCommandID)
{
/*
	if (pView != NULL)
	{
		DWORD dwStyle = -1;

		switch (nCommandID)
		{
		case ID_VIEW_LINEUP:
			{
				CListCtrl& refListCtrl = pView->GetListCtrl();
				refListCtrl.Arrange(LVA_SNAPTOGRID);
			}
			break;

		case ID_VIEW_DETAILS:
			dwStyle = LVS_REPORT;
			break;

		case ID_VIEW_SMALLICON:
			dwStyle = LVS_SMALLICON;
			break;

		case ID_VIEW_LARGEICON:
			dwStyle = LVS_ICON;
			break;

		case ID_VIEW_LIST:
			dwStyle = LVS_LIST;
			break;
		}

		if (dwStyle != -1)
			pView->ModifyStyle(LVS_TYPEMASK, dwStyle);
	}
*/
}



/*-----------------------------------------------------------------------------
[名称]	ツリービュー取得
[機能]	左のペインのビューを取得する。
[戻値]	CCategoryTreeView*	ツリービュー [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
CCategoryTreeView* CMainFrame::GetTreeView()
{
	CWnd* pWnd = m_wndHorizontalSplitter.GetPane(0, 0);
	CCategoryTreeView* pView = DYNAMIC_DOWNCAST(CCategoryTreeView, pWnd);
	return pView;
}


/*-----------------------------------------------------------------------------
[名称]	リストビュー取得
[機能]	右上のペインのビューを取得する。
[戻値]	CAAListView*	リストビュー [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
CAAListView* CMainFrame::GetListView()
{
	CWnd* pWnd = m_wndVirticalSplitter.GetPane(0, 0);
	CAAListView* pView = DYNAMIC_DOWNCAST(CAAListView, pWnd);
	return pView;
}

/*-----------------------------------------------------------------------------
[名称]	エディットビュー取得
[機能]	右下のペインのビューを取得する。
[戻値]	CEditView*	エディットビュー [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
CEditView* CMainFrame::GetEditView()
{
	CWnd* pWnd = m_wndVirticalSplitter.GetPane(1, 0);
	CEditView* pView = DYNAMIC_DOWNCAST(CEditView, pWnd);
	return pView;
}


/*-----------------------------------------------------------------------------
[名称]	リストペイン表示更新
[機能]	ドキュメント内容をビューに反映する
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CMainFrame::ReflectListView()
{
	if ( m_bAlive )
	{
		CAAHanger*		pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();
		CAAListView*	pListView = GetListView();

		// ツリービューで選択されているノードを得る
		CCategoryNode*	pCategoryNode = NULL;
		{
			HTREEITEM Node = GetTreeView()->GetTreeCtrl().GetSelectedItem();
			if ( Node != NULL )
			{
				pCategoryNode = (CCategoryNode*)(GetTreeView()->GetTreeCtrl().GetItemData( Node ));
			}
		}

		if ( pCategoryNode != NULL )
		{
			pListView->ReflectView(
				pCategoryNode
			);
		}
	}
}

/*-----------------------------------------------------------------------------
[名称]	エディットペイン表示更新
[機能]	ドキュメント内容をビューに反映する
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CMainFrame::ReflectEditView()
{
	if ( m_bAlive )
	{
		CAAHanger*		pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();
		CAAListView*	pListView = GetListView();
		CEditView*		pEditView = GetEditView();

		// リストに選択されているAAの情報を得る（番号）
		long	idxAA = -1;
		{
			CListCtrl* pList = &(pListView->GetListCtrl());
			long	idxLine = 0;
			{
				POSITION pos = pList->GetFirstSelectedItemPosition();
				if (pos != NULL)
				{
					idxLine = pList->GetNextSelectedItem( pos );

					// AAデータを取得
					long	idxItem = (long)(pListView->GetListCtrl().GetItemData( idxLine ));
					idxAA = pListView->Node()->GetIndex( idxItem );

					// AAを得る
					CString		strText = pAAHanger->GetAA( idxAA );

					// エディットビューに描画
					pEditView->GetEditCtrl().SetWindowText( strText );
				}
			}
		}
	}
}

/*-----------------------------------------------------------------------------
[名称]	表示更新
[機能]	ドキュメント内容をビューに反映する
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CMainFrame::ReflectView()
{
	if ( m_bAlive )
	{
		CCategoryTreeView*	pTreeView = GetTreeView();
		CAAListView*	pAAListView = GetListView();

		// ツリーに追加してみるテスト
		pTreeView->ReflectView();

		// リストを初期化
		pAAListView->GetListCtrl().DeleteAllItems();
	}
}


/*-----------------------------------------------------------------------------
[名称]	エディットビューフォント変更
[機能]	フォントの変更ダイアログを表示し、エディットビューに設定を反映する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CMainFrame::OnViewFont() 
{
	HDC	hdc = ::GetDC( NULL );
	CDC* pDC = CDC::FromHandle( hdc );
	CFontDialog		dlg( m_Font.GetLogFont( pDC ) );

	if ( dlg.DoModal() == IDOK )
	{
		// 属性を設定しなおす
		m_Font.m_iPointSize = (dlg.GetSize())/10;
		m_Font.m_strFontName = dlg.GetFaceName();
		m_Font.m_bBold = dlg.IsBold();
		m_Font.m_bItalic = dlg.IsItalic();
		m_Font.m_bUnderLine = dlg.IsUnderline();
		m_Font.m_bStrikeOut = dlg.IsStrikeOut();

		LOGFONT		tLogFont;
		dlg.GetCurrentFont( &tLogFont );
		m_Font.m_nCharSet = tLogFont.lfCharSet;

		// フォントの反映
		GetEditView()->SetFont( m_Font.GetFont( pDC ) );
	}

	::ReleaseDC( NULL, hdc );
}


/*-----------------------------------------------------------------------------
[名称]	上書きセーブＵＩハンドラ
[機能]	ＵＩの制御。
[戻値]	なし
[備考]	ギコペデータを開いたときは上書きセーブできない。
-----------------------------------------------------------------------------*/
void CMainFrame::OnUpdateFileSave(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable( !((CHebopeDoc*)GetActiveDocument())->IsGikopeFile() );
}


/*-----------------------------------------------------------------------------
[名称]	ウィンドウ閉じるハンドラ
[機能]	死に向かう。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CMainFrame::OnClose() 
{
	m_bAlive = FALSE;
	if ( ((CHebopeDoc*)GetActiveDocument())->IsModified() )
	if ( ((CHebopeDoc*)GetActiveDocument())->IsGikopeFile() )
	{
		int iDecide = ::AfxMessageBox(
			"へぼぺインデクスを保存しますか？",
			MB_YESNOCANCEL
		);
		switch( iDecide )
		{
		case IDYES:
			// ファイルを指定して保存
			SendMessage( WM_COMMAND, ID_FILE_SAVE_AS );
			GetActiveDocument()->SetModifiedFlag( FALSE );
			break;

		case IDNO:
			GetActiveDocument()->SetModifiedFlag( FALSE );
			break;

		default:
			// 閉じない
			return;
			break;
		}
	}
	CFrameWnd::OnClose();
}


/*-----------------------------------------------------------------------------
[名称]	Viewの初期化
[機能]	
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CMainFrame::InitView() 
{
	GetEditView()->SetWindowText( _T("") );
	GetListView()->GetListCtrl().DeleteAllItems();
	GetTreeView()->GetTreeCtrl().DeleteAllItems();
}


/*-----------------------------------------------------------------------------
[名称]	AAの追加
[機能]	ぎこぺデータにAAを追加し、インデクス情報を作成する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
long CMainFrame::AAAppend(
	const CString&	strName,
	const CString&	strAA
)
{
	CAAHanger*		pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();
	CString			strGikopeFilePath = pAAHanger->GetFilePathName();

	// 存在確認
	CFileStatus	FileStatus;
	if ( CFile::GetStatus( strGikopeFilePath, FileStatus ) == FALSE )
	{
		::AfxMessageBox( _T("ぎこぺファイルを新規作成します。") );

		CFileDialog		dlg( FALSE );
		if ( dlg.DoModal() == IDOK )
		{
			strGikopeFilePath = dlg.GetPathName();
			pAAHanger->SetFilePathName( strGikopeFilePath );

			CStdioFile	file;
			file.Open(
				strGikopeFilePath,
				CFile::modeWrite | CFile::modeCreate
			);

		}
		else
		{
			return( -1 );
		}
	}

	// ギコペデータファイルにアペンドする
	long	posLine(0);
	try
	{
		// ファイルを開いて末尾へシーク
		CStdioFile	file;
		file.Open(
			strGikopeFilePath,
			CFile::modeWrite
		);
		file.SeekToEnd();

		// 改行を挿入
		CString	str( _T("\n") );
		file.Write( str, strlen(str) );
		posLine = file.GetPosition();

		// ギコペデータを１つ追加
		str.Format(
			_T("%s%s%c\n"),
			f_strStart,
			strName,
			f_charBracket
		);
		file.Write( str, strlen(str) );

		str.Format(
			_T("%s\n%s"),
			strAA,
			f_strEnd
		);
		str.Replace( f_strCRLF, _T("\n") );
		file.Write( str, strlen(str) );
	}
	catch( CFileException* e )
	{
		// うわ〜
		e->Delete();
		return( -1 );
	}

	// インデクスを追加する
	{
		// シーク情報を追加
		long	idxAA = pAAHanger->AddAA(
			strName,
			posLine
		);

		// ドキュメントに変更あり！
		::NotifyModified();

		return( idxAA );
	}
}


// インデクスされていないギコペデータを列挙する
void CMainFrame::OnEditMarge() 
{
	// プログレスダイアログの表示

	// スレッドの起動

	// スレッド終了を待つ
//}

// インデクスされていないギコペデータを列挙するスレッド
//{
	// 列挙要素格納用新規フォルダを作成
	CCategoryNode*	pRootNode = NULL;
	CCategoryNode*	pNewNode = NULL;
	{
		// ルートのノードを得る
		{
			HTREEITEM Node = GetTreeView()->GetTreeCtrl().GetSelectedItem();
			pRootNode = ((CHebopeDoc*)GetActiveDocument())->GetCategoryTree()->Node();
		}

		// 新規ノードの追加
		if( pRootNode != NULL )
		{
			// 内部データにノード追加
			pNewNode = pRootNode->AddNode( (CString)"(未インデクスアイテム)", FALSE );
		}
	}

	// 使用しているインデクスを列挙する
	CList<long, long>	listlIndexz;
	pRootNode->GetIndexz( &listlIndexz );

	long	nFound( 0 );

	long	nIndex = listlIndexz.GetCount();
	long*	plIndex = new long[ nIndex ];
	{
		// インデクスをソート
		{
			long		idxIndex = 0;
			POSITION	pos = listlIndexz.GetHeadPosition();
			while( pos != NULL )
			{
				plIndex[ idxIndex++ ] = listlIndexz.GetAt( pos );
				listlIndexz.GetNext(pos);
			}
		}
		listlIndexz.RemoveAll();
		qsort(
			plIndex,
			nIndex,
			sizeof( long ),
			IndexSort
		);

		// 存在しないインデクスであればノードへ追加
		CAAHanger*		pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();
		long	idxAA( 0 );
		// 列挙された要素と比較しつつ追加
		for( long idxExistItem=0 ; idxExistItem<nIndex ; idxExistItem++ )
		{
			for ( ; idxAA<plIndex[idxExistItem] ; idxAA++ )
			{
				// 存在しないインデクスであれば
				// ノードへ追加
				pNewNode->AddIndex(
					idxAA
				);
				nFound++;
			}
			idxAA++;
		}
		// 列挙された存在済みの要素以後のもの（存在しない要素）を追加
		for ( ; idxAA<pAAHanger->GetCount() ; idxAA++ )
		{
			// 存在しないインデクスなので
			// ノードへ追加
			pNewNode->AddIndex(
				idxAA
			);
			nFound++;
		}

	}
	delete [] plIndex;

	// 表示更新
	GetTreeView()->ReflectView();

	// 「n 個のぎこぺデータを列挙しました」
	CString		str;
	str.Format( _T("%d 個のぎこぺデータを列挙しました。"), nFound );
	::AfxMessageBox( str );

	// ドキュメントに変更あり！
	::NotifyModified();
}



// インデクスされていないギコペデータを削除して新ファイルにする
void CMainFrame::OnEditArrange() 
{
	// プログレスダイアログの表示

	// スレッドの起動

	// スレッド終了を待つ
//}


// インデクスされていないギコペデータを削除して新ファイルにするスレッド
//{
	CAAHanger*	pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();

	// ルートのノードを得る
	CCategoryNode*	pRootNode = NULL;
	HTREEITEM Node = GetTreeView()->GetTreeCtrl().GetSelectedItem();
	pRootNode = ((CHebopeDoc*)GetActiveDocument())->GetCategoryTree()->Node();

	// 使用しているインデクスを列挙する
	CList<long, long>	listlIndexz;
	pRootNode->GetIndexz( &listlIndexz );
	long	nIndex = listlIndexz.GetCount();
	long*	plIndex = new long[ nIndex ];
	{
		// インデクスをソート
		{
			long		idxIndex = 0;
			POSITION	pos = listlIndexz.GetHeadPosition();
			while( pos != NULL )
			{
				plIndex[ idxIndex++ ] = listlIndexz.GetAt( pos );
				listlIndexz.GetNext(pos);
			}
		}
		qsort(
			plIndex,
			nIndex,
			sizeof( long ),
			IndexSort
		);

		// ギコペファイルを開く
		CFileDialog	dlg( FALSE );
		if ( dlg.DoModal() == IDOK )
		{
			CStdioFile	fileSrc( pAAHanger->GetFilePathName(), CFile::modeRead );
			CStdioFile	fileDst( dlg.GetFileName(), CFile::modeWrite|CFile::modeCreate );

			// データを見つける
			long	idxNewIndex( 0 );
			for( long idxExists=0 ; idxExists<nIndex ; idxExists++ )
			{
				long posFile = pAAHanger->GetIndex( plIndex[idxExists] );
				fileSrc.Seek( posFile, CFile::begin );
				// 新ファイルに保存する
				while( 1 )
				{
					CString		strLine;
					BOOL		bExists = fileSrc.ReadString( strLine );
					if ( strLine == f_strEnd )
					{
						bExists = FALSE;
					}
					if ( !bExists )
					{
						break;
					}

					strLine += "\n";
					fileDst.WriteString( strLine );
				}
				fileDst.WriteString( f_strEnd + "\n" );

				// 旧新インデクスの対応を記録
				listlIndexz.AddHead( plIndex[idxExists] );

				idxNewIndex++;
			}
			fileSrc.Close();
			fileDst.Close();

			// ツリーの再構築（若い番号から順に書き換え）
			pRootNode->Renumbering( listlIndexz );

			// Hanger再構築
			CStdioFile	file( dlg.GetFileName(), CFile::modeRead );
			CArchive	ar( &file, CArchive::load );
			pAAHanger->Load( ar );

			// リストの再描画
			CAAListView*	pListView = GetListView();
			pListView->ReflectView( pListView->Node() );

			// ドキュメントに変更あり！
			::NotifyModified();
		}
	}
	delete [] plIndex;

}

// ぎこぺデータの連結
void CMainFrame::OnEditAppend() 
{
	// ファイルを指定する
	CFileDialog	dlg( TRUE );
	if ( dlg.DoModal() == IDOK )
	{
		CAAHanger*		pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();

		// ギコペファイルを連結する
		{
			// 追加するデータを読み込む
			CFile	fileSlave( dlg.GetFileName(), CFile::modeRead );
			fileSlave.Seek( 0, CFile::end );
			long	sizeSlave = fileSlave.GetPosition();
			fileSlave.Seek( 0, CFile::begin );
			char* pSlave = new char[sizeSlave];
			fileSlave.Read( pSlave, sizeSlave );
			fileSlave.Close();

			// 書き出す
			// ドキュメントとして開いているギコペデータを開く
			CFile	fileMaster( pAAHanger->GetFilePathName(), CFile::modeWrite );
			fileMaster.Seek( 0, CFile::end );
			fileMaster.Write( f_strCRLF, strlen(f_strCRLF) );
			fileMaster.Write( pSlave, sizeSlave );
			fileMaster.Close();
			delete [] pSlave;
		}

		// Hangerを更新する
		{
			CFile	file( pAAHanger->GetFilePathName(), CFile::modeRead );
			CArchive	ar( &file, CArchive::load );
			pAAHanger->Load( ar );
		}

		// 未使用のインデクスを列挙する
		OnEditMarge();
	}
}

void CMainFrame::OnTreeCategorize() 
{
	// ツリービューで選択されているノードを得る
	CCategoryNode*	pCategoryNode = NULL;
	HTREEITEM ParentNode = GetTreeView()->GetTreeCtrl().GetSelectedItem();
	if ( ParentNode != NULL )
	{
		pCategoryNode = (CCategoryNode*)(GetTreeView()->GetTreeCtrl().GetItemData( ParentNode ));
	}

	// 自動カテゴライズ発動
	if( pCategoryNode != NULL )
	{
		// 設定ダイアログの表示
		CSettingDlg	dlg;
		dlg.m_uiMinMember = GetMinMember();
		dlg.m_uiNearPattern = GetNearPattern();
		if ( dlg.DoModal() == IDOK )
		{
			// 設定の保存
			SetMinMember( dlg.m_uiMinMember );
			SetNearPattern( dlg.m_uiNearPattern );

			// 自動カテゴライズ
			CAAHanger*		pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();
			((CHebopeDoc*)GetActiveDocument())->GetCategoryTree()->Categorize(
				*pAAHanger,
				pCategoryNode
			);

			// 表示更新
			GetTreeView()->ReflectView();
			GetListView()->ReflectView( pCategoryNode );

			// ドキュメントに変更あり！
			::NotifyModified();
		}
	}
}

void CMainFrame::OnUpdateTreeAddnode(CCmdUI* pCmdUI) 
{
	// ツリーの選択要素が無ければ無効にする
	CCategoryNode*	pCategoryNode = NULL;
	HTREEITEM ParentNode = GetTreeView()->GetTreeCtrl().GetSelectedItem();
	pCmdUI->Enable( ParentNode != NULL );
}

void CMainFrame::OnUpdateTreeCategorize(CCmdUI* pCmdUI) 
{
	// ツリーの選択要素が無ければ無効にする
	CCategoryNode*	pCategoryNode = NULL;
	HTREEITEM ParentNode = GetTreeView()->GetTreeCtrl().GetSelectedItem();
	pCmdUI->Enable( ParentNode != NULL );
}

void CMainFrame::OnUpdateTreeDeletenode(CCmdUI* pCmdUI) 
{
	// ツリーの選択要素が無ければ無効にする
	CCategoryNode*	pCategoryNode = NULL;
	HTREEITEM ParentNode = GetTreeView()->GetTreeCtrl().GetSelectedItem();
	pCmdUI->Enable( ParentNode != NULL );
}

void CMainFrame::OnUpdateListAddaa(CCmdUI* pCmdUI) 
{
	// 対象ノードが無ければ無効にする
	pCmdUI->Enable( GetListView()->Node() != NULL );
}

void CMainFrame::OnUpdateListDeleteindex(CCmdUI* pCmdUI) 
{
	// リストの選択要素が無ければ無効にする
	POSITION pos = GetListView()->GetListCtrl().GetFirstSelectedItemPosition();
	pCmdUI->Enable( pos != NULL );
}

void CMainFrame::OnUpdateListEditaa(CCmdUI* pCmdUI) 
{
	// リストの選択要素が無ければ無効にする
	POSITION pos = GetListView()->GetListCtrl().GetFirstSelectedItemPosition();
	pCmdUI->Enable( pos != NULL );
}

void CMainFrame::OnUpdateShitarabianPaste(CCmdUI* pCmdUI) 
{
	BOOL	bEnable( TRUE );

	// リストの選択要素が無ければ無効にする
	POSITION pos = GetListView()->GetListCtrl().GetFirstSelectedItemPosition();
	bEnable &= ( pos != NULL );

	// 親がいなければ無効にする
	bEnable &= ( m_hwndParent != NULL );

	pCmdUI->Enable( bEnable );
}

void CMainFrame::OnShitarabianPaste() 
{
	if ( m_hwndParent != NULL )
	{
		// AAを得る
		CString		strAA;
		{
			CEditView*		pEditView = GetEditView();
			pEditView->GetEditCtrl().GetWindowText( strAA );
		}

		// クリップボードへ送る
		::EditCopyString( strAA );

		COPYDATASTRUCT cds;
		cds.dwData = COMMAND_MESSAGE_INSERT;
		cds.cbData = strAA.GetLength() + 1;
		cds.lpData = (PVOID)((LPCTSTR)strAA);

		CShitarabianPostCommand*	pSender = CShitarabianPostCommand::GetInstance();
		pSender->Send(
			m_hwndParent,
			m_hWnd,
			COMMAND_MESSAGE_PASTE,
			NULL,
			0
		);
	}
}


void CMainFrame::OnUpdateEditMarge(CCmdUI* pCmdUI) 
{
	CAAHanger*		pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();
	pCmdUI->Enable( !pAAHanger->GetFilePathName().IsEmpty() );
}

void CMainFrame::OnUpdateEditArrange(CCmdUI* pCmdUI) 
{
	CAAHanger*		pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();
	pCmdUI->Enable( !pAAHanger->GetFilePathName().IsEmpty() );
}

void CMainFrame::OnUpdateEditAppend(CCmdUI* pCmdUI) 
{
	CAAHanger*		pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();
	pCmdUI->Enable( !pAAHanger->GetFilePathName().IsEmpty() );
}

void CMainFrame::OnUpdateFileSaveAs(CCmdUI* pCmdUI) 
{
	CAAHanger*		pAAHanger = ((CHebopeDoc*)GetActiveDocument())->GetAAHanger();
	pCmdUI->Enable( !pAAHanger->GetFilePathName().IsEmpty() );
}

void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus) 
{
	CFrameWnd::OnShowWindow(bShow, nStatus);

	// ビューの内容更新
	ReflectView();
}

void CMainFrame::OnHelpManual() 
{
	CString	strURL;
	strURL.LoadString( IDS_MANUALURL );

	CString	strPathName = __argv[0];
	int	idxLastSlash = strPathName.ReverseFind( '\\' );
	CString	strPath = strPathName.Left( idxLastSlash );

	strPathName.Format( "%s\\%s", strPath, strURL );
	ShellExecute( HWND_DESKTOP, NULL, strPathName, NULL, NULL, SW_SHOWNORMAL);
}

void CMainFrame::OnHelpWeb() 
{
	CString	strURL;
	strURL.LoadString( IDS_WEBURL );
	ShellExecute( HWND_DESKTOP, NULL, strURL, NULL, NULL, SW_SHOWNORMAL);
}
