// ★コメント未記入

/*-----------------------------------------------------------------------------
[名称]	MainFrmAccel.cpp
[概要]	コマンドハンドラの実装
[備考]	CMainFrame のコマンドハンドル関数のみを抜き出してある。
[履歴]	2003-02-27	NC		コメント付加(moralog)
		2003-11-18	b031130 (3180)Shift+Insert/Shift+Deleteに対応	(dincom)
		2003-12-20	b031228 (3146)タグジャンプキー割り当て(moralog)
		2004-01-30  b031228 (3367)Grep検索(dincom)
		2004-05-10	b031228 (3751)文書名がショートファイルネームで表示される(moralog)
-----------------------------------------------------------------------------*/


//-----------------------------------------------------------------------------
// インクルード
//-----------------------------------------------------------------------------
#include "stdafx.h"
#define	APSTUDIO_INVOKED	// リソースIDの設定をちょっと覗き見たい
#include "resource.h"
#include "Shitarabian.h"
#include "MainFrm.h"
#include "Selection.h"
#include "EditDrawer.h"
#include "GeneralSetting.h"
#include "ShitarabianView.h"
#include "CommandManager.h"
#include "CommandInput.h"
#include "CommandCaret.h"
#include "CommandDelete.h"
#include "Common.h"
#include "ShitarabianDoc.h"
#include "TokenReader.h"
#include "Padding.h"
#include "CommandMultiEdit.h"
#include "Unicoder.h"
#include "ExeCommon.h"
#include "ClipHistoryDlg.h"
#include "ClipHistory.h"
#include "LinkDefine.h"
#include <process.h>

extern CShitarabianApp theApp;


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


typedef struct
{
	int		idMenu;
	UCHAR	unKey;
	BOOL	bShift;
	BOOL	bCtrl;
	BOOL	bAlt;
	BOOL	bWithNormal;
	BOOL	bWithBoxSelect;
	BOOL	bWithFloating;
	BOOL	bWithROI;
} TAccelDefine;


static const TAccelDefine	f_aAccel[] =
{
//	idMenu					unKey			bShift	bCtrl	bAlt		Normal	Box		Float	ROI
	{ IDM_EDIT_ALLSELECT,	'A',			FALSE,	TRUE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},

	{ IDM_EDIT_FIND,		'F',			FALSE,	TRUE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},
	{ IDM_EDIT_FINDPREV,	VK_F3,			TRUE,	FALSE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},
	{ IDM_EDIT_FINDNEXT,	VK_F3,			FALSE,	FALSE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},
	{ IDM_EDIT_FINDMAGICROD,VK_F3,			FALSE,	TRUE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},
	{ IDM_EDIT_REPLACE,		'H',			FALSE,	TRUE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},

	{ IDM_EDIT_MARK,		VK_F2,			FALSE,	TRUE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},
	{ IDM_EDIT_PREVMARK,	VK_F2,			TRUE,	FALSE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},
	{ IDM_EDIT_NEXTMARK,	VK_F2,			FALSE,	FALSE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},

	{ ID_EDIT_COPY,			'C',			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	TRUE,	FALSE	},
	{ ID_EDIT_CUT,			'X',			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	TRUE,	FALSE	},
	{ ID_EDIT_PASTE,		'V',			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	TRUE,	FALSE	},
	{ ID_EDIT_CLIPHISTORY,	'B',			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	TRUE,	FALSE	},

	{ ID_EDIT_UNDO,			'Z',			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	FALSE,	FALSE	},
	{ ID_EDIT_REDO,			'Y',			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	FALSE,	FALSE	},

	{ IDM_VIEW_ZOOMIN,		VK_ADD,			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	TRUE,	TRUE	},
	{ IDM_VIEW_ZOOMOUT,		VK_SUBTRACT,	FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	TRUE,	TRUE	},

	{ IDM_EDIT_CHARPALETTE,	' ',			FALSE,	TRUE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},

	{ ID_FILE_OPEN,			'O',			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	TRUE,	TRUE	},
	{ ID_FILE_NEW,			'N',			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	TRUE,	TRUE	},
//	{ ID_FILE_PRINT,		'P',			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	TRUE,	TRUE	},
//	{ ID_FILE_SAVE,			'S',			FALSE,	TRUE,	FALSE,		TRUE,	TRUE,	TRUE,	TRUE	},

	{ ID_NEXT_PANE,			VK_F6,			FALSE,	FALSE,	FALSE,		TRUE,	TRUE,	TRUE,	TRUE	},
	{ ID_PREV_PANE,			VK_F6,			TRUE,	FALSE,	FALSE,		TRUE,	TRUE,	TRUE,	TRUE	},

	{ IDM_EDIT_SHIFTLEFT,	VK_LEFT,		TRUE,	TRUE,	TRUE,		TRUE,	FALSE,	FALSE,	FALSE	},
	{ IDM_EDIT_SHIFTRIGHT,	VK_RIGHT,		TRUE,	TRUE,	TRUE,		TRUE,	FALSE,	FALSE,	FALSE	},

	{ IDM_FIND_NEXTMODIFY,	'T',			FALSE,	TRUE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},
	{ IDM_FIND_PREVMODIFY,	'T',			TRUE,	TRUE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},

	// ▼ (3180) BGN 2003.11.18 (dincom)
	{ ID_EDIT_CUT,			VK_DELETE,		TRUE,	FALSE,	FALSE,		TRUE,	TRUE,	TRUE,	FALSE	},
	{ ID_EDIT_PASTE,		VK_INSERT,		TRUE,	FALSE,	FALSE,		TRUE,	TRUE,	TRUE,	FALSE	},
	// ▲ (3180) END

// ▼ (3146) BGN 2003.12.20 (moralog) タグジャンプのキー割り当て追加
	{ IDM_EDIT_TAGJUMP,		VK_F10,			FALSE,	FALSE,	FALSE,		TRUE,	FALSE,	FALSE,	FALSE	},
// ▲ (3146) END

	//	idMenu					unKey			bShift	bCtrl	bAlt		Normal	Box		Float	ROI
};


BOOL CMainFrame::AccelKeyDown(
	UCHAR*	punKey,
	BOOL*	pbShift,
	BOOL*	pbCtrl,
	BOOL*	pbAlt
)
{
	CShitarabianDoc* pDoc = GetDocument();

	int	idxCommand;
	for ( idxCommand=0 ; idxCommand<sizeof(f_aAccel)/sizeof(TAccelDefine) ; idxCommand++ )
	{
		if ( f_aAccel[idxCommand].unKey == *punKey )
		if ( (f_aAccel[idxCommand].bShift?1:0) == (*pbShift?1:0) )
		if ( (f_aAccel[idxCommand].bCtrl?1:0) == (*pbCtrl?1:0) )
		if ( (f_aAccel[idxCommand].bAlt?1:0) == (*pbAlt?1:0) )
		{
			TRACE("%d\n",*pbCtrl?1:0);
			TRACE("%d\n",f_aAccel[idxCommand].bCtrl?1:0);

			switch( pDoc->GetOperationMode() )
			{
			case OperationROI:
				if ( !f_aAccel[idxCommand].bWithROI )
				{
					continue;
				}
				break;
			case OperationBoxSelect:
				if ( !f_aAccel[idxCommand].bWithBoxSelect )
				{
					continue;
				}
				break;
			case OperationFloating:
				if ( !f_aAccel[idxCommand].bWithFloating )
				{
					continue;
				}
				break;
			case OperationNormal:
				if ( !f_aAccel[idxCommand].bWithNormal )
				{
					continue;
				}
				break;
			default:
				break;
			}

			switch( f_aAccel[idxCommand].idMenu )
			{
			case IDM_EDIT_ALLSELECT:
				OnEditAllselect();
				break;

			case IDM_EDIT_FIND:
				OnEditFind();
				break;
			case IDM_EDIT_FINDNEXT:
				OnEditFindnext();
				break;
			case IDM_EDIT_FINDPREV:
				OnEditFindprev();
				break;
			case IDM_EDIT_FINDMAGICROD:
				OnEditFindmagicrod();
				break;
			case IDM_EDIT_REPLACE:
				OnEditReplace();
				break;

			case IDM_EDIT_MARK:
				OnEditMark();
				break;
			case IDM_EDIT_PREVMARK:
				OnEditPrevmark();
				break;
			case IDM_EDIT_NEXTMARK:
				OnEditNextmark();
				break;


			case ID_EDIT_COPY:
				OnEditCopy();
				break;
			case ID_EDIT_CUT:
				OnEditCut();
				break;
			case ID_EDIT_PASTE:
				OnEditPaste();
				break;
			case ID_EDIT_CLIPHISTORY:
				OnEditClipHistory();
				break;

			case ID_EDIT_UNDO:
				OnEditUndo();
				break;
			case ID_EDIT_REDO:
				OnEditRedo();
				break;

			case IDM_VIEW_ZOOMIN:
				OnViewZoomin();
				break;
			case IDM_VIEW_ZOOMOUT:
				OnViewZoomout();
				break;

			case IDM_EDIT_CHARPALETTE:
				OnEditCharpalette();
				break;


			case ID_NEXT_PANE:
				OnNextPane();
				break;
			case ID_PREV_PANE:
				OnPrevPane();
				break;


			case ID_FILE_OPEN:
				theApp.FileOpen();
				break;

			case ID_FILE_NEW:
				{
					theApp.FileNew();
					CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
					pDoc->SetAllUpdate();
					pDoc->ReDraw();
				}
				break;

			case ID_FILE_PRINT:
				{
					theApp.PostThreadMessage( ID_FILE_PRINT,0,0 );
//					pDoc->GetMainView()->PostMessage( ID_FILE_PRINT );
				}
				break;
			case ID_FILE_SAVE:
{
	MSG	msg;
	msg.message = ID_FILE_SAVE;
	msg.wParam = 0;
	msg.lParam = 0;
//				theApp.PostThreadMessage( ID_FILE_SAVE,0,0 );
//				pDoc->GetMainView()->PostMessage( ID_FILE_SAVE );
	theApp.PreTranslateMessage( &msg );
}
				break;

			case IDM_EDIT_SHIFTLEFT:
				OnEditShiftleft();
				break;
			case IDM_EDIT_SHIFTRIGHT:
				OnEditShiftright();
				break;

			case IDM_FIND_NEXTMODIFY:
				OnFindNextmodify();
				break;

			case IDM_FIND_PREVMODIFY:
				OnFindPrevmodify();
				break;

// ▼ (3146) BGN 2003.12.20 (moralog) タグジャンプのキー割り当て追加
			case IDM_EDIT_TAGJUMP:
				OnEditTagjump();
				break;
// ▲ (3146) END

			default:
				continue;
				break;
			}
			return( TRUE );
			break;
		}
	}
	return( FALSE );
}


// ★
void CMainFrame::OnEditCopy() 
{
	CShitarabianDoc* pDoc = GetDocument();
	CString		strCopy = pDoc->GetSelection()->GetSelectedText();
// ▼ (3204) BGN 2004.05.12 (moralog) ExeCommon.cppから移動。汎用関数化。
	::EditCopyStringWithHistory( strCopy );
// ▽ original BGN
//	::EditCopyString( strCopy );
// △ original END
// ▲ (3204) END
}


void CMainFrame::OnEditCut() 
{
	// クリップボードへコピーして
	OnEditCopy();

	// 選択文字列のデリート
	CShitarabianDoc* pDoc = GetDocument();
	pDoc->SelectedDelete();

	// 選択状態の解除
	pDoc->GetSelection()->SetSelectedNutral();

	// 表示更新
	pDoc->ReDraw();
}


// ★
void CMainFrame::OnEditPaste() 
{
	// クリップボードから文字列取得
	CString	strInsert = EditPasteString();

	// 選択範囲の削除
	CShitarabianDoc* pDoc = GetDocument();
	pDoc->SelectedDelete();

	// 貼り付け処理（文字列のインサート）
	switch ( pDoc->GetOperationMode() )
	{
	case OperationNormal:
		{
			// コマンドの登録
			CCommandInput	cmdInput;
			cmdInput.SetAttribute(
				strInsert,
				pDoc->GetCaretRow(),
				pDoc->GetCaretColumn()
			);
			cmdInput.Execute( pDoc );

			CCommandManager*	pCmd = CCommandManager::GetInstance();
			pCmd->Add( cmdInput );

			// 選択状態の解除
			pDoc->GetSelection()->SetSelectedNutral();
		}
		break;
	case OperationFloating:
	case OperationBoxSelect:
		// フローティングモードへ移行
		{
			CShitarabianView*	pView = pDoc->GetMainView();
			CPoint	ptScrollBox = pView->GetDeviceScrollPosition();

			CPoint	ptFloat( ptScrollBox );
			ptFloat.x /= CEditDrawer::GetInstance()->GetZoom();
			ptFloat.y /= CEditDrawer::GetInstance()->GetZoom();
			pView->ToFloating(
				strInsert,
				ptFloat.x,
				ptFloat.y
			);
		}
		break;
	default:
		break;
	}

	// 再描画
	pDoc->GetMainView()->ScrollToCaret();
	pDoc->ReDraw();	
}



void CMainFrame::OnEditQuotepaste() 
{
	// クリップボードから文字列取得
	CString	strInsert = EditPasteString();

	// 選択範囲の削除
	CShitarabianDoc* pDoc = GetDocument();
	pDoc->SelectedDelete();

	// 引用符の挿入
	CString		strQuote( CGeneralSetting::GetInstance()->GetQuote() );
	CString		strCRLFQuote( pDoc->ReturnChar()+strQuote );
	strInsert.Replace(
		pDoc->ReturnChar(),
		strCRLFQuote
	);
	strInsert.Insert( 0, strQuote );

	// 貼り付け処理（文字列のインサート）
	{
		// コマンドの登録
		CCommandInput	cmdInput;
		cmdInput.SetAttribute(
			strInsert,
			pDoc->GetCaretRow(),
			pDoc->GetCaretColumn()
		);
		cmdInput.Execute( pDoc );

		CCommandManager*	pCmd = CCommandManager::GetInstance();
		pCmd->Add( cmdInput );

		// 選択状態の解除
		pDoc->GetSelection()->SetSelectedNutral();
	}

	// 再描画
	pDoc->GetMainView()->ScrollToCaret();
	pDoc->ReDraw();
}


void CMainFrame::OnEditClipHistory()
{
	CClipHistoryDlg		dlg;
	dlg.Attach( CClipHistory::GetInstance() );

	if ( dlg.DoModal() == IDOK )
	{
		OnEditPaste();
	}
}



void CMainFrame::OnEditAllselect() 
{
	CShitarabianDoc*	pDoc = GetDocument();
	switch( pDoc->GetOperationMode() )
	{
	case OperationNormal:
		{
			// 先頭行セット
			pDoc->GetSelection()->SetSelectedStart(0,0);

			// 最後尾行セット
			int		idxLastLine = pDoc->GetLineCount()-1;
			CString*	pstrLastLine = pDoc->GetLine( idxLastLine );
			pDoc->GetSelection()->SetSelectedEnd( idxLastLine, ::StringToColumn( (LPCTSTR)*pstrLastLine ) );

			// 再描画
			pDoc->SetAllUpdate();
			pDoc->ReDraw();	
		}
		break;

	default:
		break;
	}	
}




void CMainFrame::OnViewZoomin() 
{
	CEditDrawer*	pDraw = CEditDrawer::GetInstance();
	int		iZoom = pDraw->GetZoom();
	pDraw->SetZoom( iZoom+1 );

	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();

	RecalcScrollBar();

// 判った。設定してもまだドキュメントが小さいからだ。
	// スクロールボックス移動
	CPoint		ptScroll = pDoc->GetMainView()->GetDeviceScrollPosition();
	ptScroll.x = ptScroll.x*(iZoom+1)/iZoom;
	ptScroll.y = ptScroll.y*(iZoom+1)/iZoom;

// please! すべてのVIewに適用しないといけないと思うが
	pDoc->GetMainView()->SetDeviceScrollPosition( ptScroll );
//	pDoc->GetMainView()->ResetHScroll();

	// 表示更新
	pDoc->SetAllUpdate();
	pDoc->ReDraw();
}

void CMainFrame::OnViewZoomout() 
{
	CEditDrawer*	pDraw = CEditDrawer::GetInstance();
	int		iZoom = pDraw->GetZoom();
	pDraw->SetZoom( iZoom-1 );

	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();

	// スクロールボックス移動
	CPoint		ptScroll = pDoc->GetMainView()->GetDeviceScrollPosition();
	ptScroll.x = ptScroll.x*(iZoom-1)/(iZoom);
	ptScroll.y = ptScroll.y*(iZoom-1)/(iZoom);

	// please! すべてのViewに適用しないといけないと思うが
	RecalcScrollBar();
	pDoc->GetMainView()->SetDeviceScrollPosition( ptScroll );
	pDoc->GetMainView()->ResetHScroll();

	// 表示更新
	pDoc->SetAllUpdate();
	pDoc->ReDraw();
}


void CMainFrame::OnEditUndo() 
{
	// 選択状態の解除
	// 表示更新範囲設定
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument( );
	CSelection*			pSelection = pDoc->GetSelection();
	pDoc->SetUpdateStartRow( pSelection->GetSelectedStartRow() );
	pDoc->SetUpdateEndRow( pSelection->GetSelectedEndRow() );
	pSelection->SetSelectedNutral();

	// Undo
	CCommandManager*	pCmd = CCommandManager::GetInstance();
	pCmd->UnDo();

	// 表示更新
	pDoc->GetMainView()->ScrollToCaret();
	pDoc->ReDraw();
}


void CMainFrame::OnEditRedo() 
{
	// 選択状態の解除
	// 表示更新範囲設定
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument( );
	CSelection*			pSelection = pDoc->GetSelection();
	pDoc->SetUpdateStartRow( pSelection->GetSelectedStartRow() );
	pDoc->SetUpdateEndRow( pSelection->GetSelectedEndRow() );
	pSelection->SetSelectedNutral();

	// Redo
	CCommandManager*	pCmd = CCommandManager::GetInstance();
	pCmd->ReDo();

	// 表示更新
	pDoc->GetMainView()->ScrollToCaret();
	pDoc->ReDraw();
}


void CMainFrame::OnEditMark() 
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	int		iCurrentRow = pDoc->GetCaretRow();

	pDoc->Mark( iCurrentRow );

	pDoc->SetUpdateStartRow( iCurrentRow );
	pDoc->SetUpdateEndRow( iCurrentRow );
	pDoc->ReDraw();
}

void CMainFrame::OnEditNextmark() 
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
//	int		iCurrentRow = pDoc->GetCaretRow();

	pDoc->NextMark();

	pDoc->SetAllUpdate();
	pDoc->GetMainView()->ScrollToCaret();
	pDoc->ReDraw();
}

void CMainFrame::OnEditPrevmark() 
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
//	int		iCurrentRow = pDoc->GetCaretRow();

	pDoc->PrevMark();

	pDoc->SetAllUpdate();
	pDoc->GetMainView()->ScrollToCaret();
	pDoc->ReDraw();
}




void CMainFrame::OnEditFind() 
{
	// ▼ (3367) BGN 2004.1.30 (dincom) 
	m_dlgGrep.ShowWindow( SW_HIDE );
	// ▲ (3367) END

	m_dlgReplacer.ShowWindow( SW_HIDE );
	m_dlgFinder.ShowWindow( SW_SHOW );
	return;
}

void CMainFrame::OnEditFindnext() 
{
	CString		strSubString;
	m_wndSubStringCombo.GetWindowText( strSubString );
	AddSubString( strSubString, &m_wndSubStringCombo );

	m_dlgFinder.FindNext(  );
}

void CMainFrame::OnEditFindprev() 
{
	CString		strSubString;
	m_wndSubStringCombo.GetWindowText( strSubString );
	AddSubString( strSubString, &m_wndSubStringCombo );

	m_dlgFinder.FindPrev(  );
}

void CMainFrame::OnEditFindmagicrod() 
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	pDoc->GetMainView()->FindMagicRod();
}


void CMainFrame::OnEditReplace() 
{
	// ▼ (3367) BGN 2004.1.30 (dincom) 
	m_dlgGrep.ShowWindow( SW_HIDE );
	// ▲ (3367) END

	m_dlgFinder.ShowWindow( SW_HIDE );
	m_dlgReplacer.ShowWindow( SW_SHOW );
	return;
}

void CMainFrame::OnEditCharpalette() 
{
// ▼ (ワーニング回避) BGN 2003.12.29 (moralog) warning C4189
// ▽ original BGN
//	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
// △ original END
// ▲ (ワーニング回避) END

	CCharPaletteDlg*	pDlg = CGeneralSetting::GetInstance()->GetCharPaletteManager()->GetCharPaletteDlg();
	pDlg->ShowWindow( SW_SHOW );
	pDlg->SetFocus();
}



void CMainFrame::OnNextPane()
{
	CSplitterWnd*	pSplitter = ((CMainFrame*)::AfxGetMainWnd())->GetSplitter();

	int	iRow;
	int	iColumn;
	pSplitter->GetActivePane(
		&iRow,
		&iColumn
	);

	iColumn++;
	if ( iColumn >= pSplitter->GetColumnCount() )
	{
		iColumn = 0;
		iRow++;
		if ( iRow >= pSplitter->GetRowCount() )
		{
			iRow = 0;
		}

	}
	pSplitter->SetActivePane( iRow, iColumn, NULL );

	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	pDoc->SetAllUpdate();
	pDoc->ReDraw();
}


void CMainFrame::OnPrevPane()
{
	CSplitterWnd*	pSplitter = ((CMainFrame*)::AfxGetMainWnd())->GetSplitter();

	int	iRow;
	int	iColumn;
	pSplitter->GetActivePane(
		&iRow,
		&iColumn
	);

	iColumn--;
	if ( iColumn < 0 )
	{
		iColumn = pSplitter->GetColumnCount() - 1;
		iRow--;
		if ( iRow < 0 )
		{
			iRow = pSplitter->GetRowCount() -1;
		}

	}
	pSplitter->SetActivePane( iRow, iColumn, NULL );

	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	pDoc->SetAllUpdate();
	pDoc->ReDraw();
}


void CMainFrame::OnEditShiftleft() 
{
	EditShift( FALSE );
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	pDoc->ReDraw();
}

void CMainFrame::OnEditShiftright() 
{
	EditShift( TRUE );
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	pDoc->ReDraw();
}


void CMainFrame::EditShift(
	BOOL	bRight
)
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();

	// キャレット位置のカラムと行を取得
	int		iCaretRow = pDoc->GetCaretRow();
	int		iCaretColumn = pDoc->GetCaretColumn();

	// キャレット行の取得
	CString*		pstr = pDoc->GetLine( iCaretRow );

	// トークンに分解
	CArray< TToken, TToken& >	aTokenz;
	CTokenReader::StringToCharTypez(
		*pstr,
		&aTokenz
	);

	// 処理対象のトークンを探す
	int		idxToken;
	{
		// キャレットのあるトークン
		idxToken = CTokenReader::TokenIndex(
			aTokenz,
			iCaretColumn
		);
		if ( idxToken != InvalidTokenIndex )
		{
			// キャレットが空白位置との境界にいれば空白位置とみなす
			if ( aTokenz[idxToken].eCharType != CharTypeWhitespace )
			if ( aTokenz[idxToken].idxStartColumn == iCaretColumn )
			if ( idxToken > 0 )
			if ( aTokenz[idxToken-1].eCharType == CharTypeWhitespace )
			{
				idxToken--;
			}
		}
	}

	if ( idxToken != InvalidTokenIndex )
	// キャレットが空白位置にいる場合
	if ( aTokenz[idxToken].eCharType == CharTypeWhitespace )
	{
		CDC*	pDC = GetDC();
		// 二つのトークンの間の空白の大きさを取得
		int		iOldWidth;
		{
			int iStartByte = ::CaretColumnToByteColumn( *pstr, aTokenz[idxToken].idxStartColumn );
			int iEndByte = ::CaretColumnToByteColumn( *pstr, aTokenz[idxToken].idxStartColumn + aTokenz[idxToken].nColumn );
			CString		strSubString = pstr->Mid( 
				iStartByte,
				iEndByte - iStartByte
			);
			CEditDrawer*	pDraw = CEditDrawer::GetInstance();
			iOldWidth = pDraw->StringToPixelX(
				strSubString,
				pDC
			);
		}

		// 空白の大きさにプラス１してみてパディング。
		CString		strPad;
		int		iOffset;
		for ( iOffset=1 ; iOffset<100 ; iOffset++ )	// 無限ループ対策。適当
		{
			CPadding	Padding;
			long	iGap;
			if ( bRight )
			{
				iGap = Padding.Padding(
					pDC,
					iOldWidth+iOffset,
					strPad,
					*( CGeneralSetting::GetInstance()->GetWhitespace()->GetCharz() ),
					TRUE
				);
			}
			else
			{
				if ( iOldWidth-iOffset <= 0 )
				{
					strPad.Empty();
					break;
				}
				iGap = Padding.Padding(
					pDC,
					iOldWidth-iOffset,
					strPad,
					*( CGeneralSetting::GetInstance()->GetWhitespace()->GetCharz() ),
					TRUE
				);
			}

			if ( iGap == 0 )
			{
				// HIT!
				break;
			}
			strPad.Empty();
		}
		ReleaseDC( pDC );

		// コマンドの登録
		CCommandManager*	pCmd = CCommandManager::GetInstance();
		CCommandMultiEdit	cmdEdit;
		{
			CCommandDelete	cmdDelete;
			cmdDelete.SetAttribute(
				iCaretRow,
				aTokenz[idxToken].idxStartColumn,
				iCaretRow,
				aTokenz[idxToken].idxStartColumn + aTokenz[idxToken].nColumn
			);
			cmdEdit.Add( cmdDelete );

			// コマンドの登録
			CCommandInput	cmdInput;
			cmdInput.SetAttribute( strPad, iCaretRow, aTokenz[idxToken].idxStartColumn );
			cmdEdit.Add( cmdInput );
		}
		cmdEdit.Execute( pDoc );
		pCmd->Add( cmdEdit );
	}
	else
	if ( bRight )
	{
		// パディングできる大きさを得たら
		CDC*	pDC = GetDC();

		// 空白の大きさにプラス１してみてパディング。
		CString		strPad;
		int		iOffset;
		for ( iOffset=1 ; iOffset<100 ; iOffset++ )	// 無限ループ対策。適当
		{
			CPadding	Padding;
			long	iGap = Padding.Padding(
				pDC,
				iOffset,
				strPad,
				*( CGeneralSetting::GetInstance()->GetWhitespace()->GetCharz() ),
				TRUE
			);
			if ( iGap == 0 )
			{
				// HIT!
				break;
			}
			strPad.Empty();
		}
		ReleaseDC( pDC );

		// 間に突っ込んで終了
		CCommandInput	cmdInput;
		cmdInput.SetAttribute( strPad, iCaretRow, iCaretColumn );
		cmdInput.Execute( pDoc );
		CCommandManager*	pCmd = CCommandManager::GetInstance();
		pCmd->Add( cmdInput );
	}	
}


void CMainFrame::OnFindNextmodify() 
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	pDoc->NextModify();
	pDoc->SetAllUpdate();
	pDoc->GetMainView()->ScrollToCaret();
	pDoc->ReDraw();
}

void CMainFrame::OnFindPrevmodify() 
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	pDoc->PrevModify();
	pDoc->SetAllUpdate();
	pDoc->GetMainView()->ScrollToCaret();
	pDoc->ReDraw();
}

void CMainFrame::Alignment(
	long	idxRow,
	EAlign	eAlign
)
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	CString*	pstrLine = pDoc->GetLine( idxRow );

	// 現在行の長さを得る
	long		lLineWidth = 0;
	CString		strSolidLine;
	if ( pstrLine != NULL )
	{
		// トークンに分割し、空白でない部分を取得する
		CArray< TToken, TToken& >	aTokenz;
		CTokenReader::StringToCharTypez(
			*pstrLine,
			&aTokenz
		);

		// 空白でない文字列を得る
		int		idxSolidStartByteColumn = 0;
		for( int idxToken=0 ; idxToken<aTokenz.GetSize() ; idxToken++ )
		{
			if ( aTokenz[idxToken].eCharType != CharTypeWhitespace )
			{
				idxSolidStartByteColumn =
					::CaretColumnToByteColumn(
						*pstrLine,
						aTokenz[idxToken].idxStartColumn
					);
				break;
			}
		}
		int		idxSolidEndByteColumn = 0;
		for( idxToken=aTokenz.GetSize()-1 ; idxToken>=0 ; idxToken-- )
		{
			if ( aTokenz[idxToken].eCharType != CharTypeWhitespace )
			{
				idxSolidEndByteColumn =
					::CaretColumnToByteColumn(
						*pstrLine,
						aTokenz[idxToken].idxStartColumn+aTokenz[idxToken].nColumn
					);
				break;
			}
		}
		strSolidLine = pstrLine->Mid(
			idxSolidStartByteColumn,
			idxSolidEndByteColumn - idxSolidStartByteColumn
		);

		// 長さを取得する
		CDC*	pDC = GetDC();
		lLineWidth = CEditDrawer::GetInstance()->StringToPixelX(
			strSolidLine,
			pDC
		);
		ReleaseDC( pDC );
	}

	// パディングすべき長さを得る
	long	lClientWidth = CGeneralSetting::GetInstance()->GetPrintDefine()->m_lPrintPixelWidth;
	long	lPaddingWidth;
	switch( eAlign )
	{
	case AlignLeft:
	default:
		lPaddingWidth = 0;
		break;

	case AlignCenter:
		lPaddingWidth = (lClientWidth - lLineWidth)/2;
		break;

	case AlignRight:
		lPaddingWidth = lClientWidth - lLineWidth;
		break;
	}

	// パディング文字列を得る
	CString	strPadding;
	{
		CPadding	Padding;
		CDC*	pDC = GetDC();
		Padding.Padding(
			pDC,
			lPaddingWidth,
			strPadding,
			*( CGeneralSetting::GetInstance()->GetWhitespace()->GetCharz() )
		);
		ReleaseDC( pDC );
	}

	// 行の差し替え
	CCommandMultiEdit	cmdEdit;
	{
		CCommandDelete	cmdDelete;
		cmdDelete.SetAttribute(
			idxRow, 0,
			idxRow, ::StringToColumn( *pstrLine )
		);
		cmdEdit.Add( cmdDelete );

		if( !strSolidLine.IsEmpty() )
		{
			CCommandInput	cmdInput;
			cmdInput.SetAttribute(
				strPadding + strSolidLine,
				idxRow,
				0
			);
			cmdEdit.Add( cmdInput );
		}
	}
	cmdEdit.Execute( pDoc );
	CCommandManager*	pCmd = CCommandManager::GetInstance();
	pCmd->Add( cmdEdit );
}

void CMainFrame::Alignment(
	EAlign	eAlign
)
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument( );
	CSelection*			pSelection = pDoc->GetSelection();
	if( pSelection->IsSelected() )
	{
		for( int idxRow=pSelection->GetSelectedStartRow();
					idxRow<=pSelection->GetSelectedEndRow();
					idxRow++ )
		{
			Alignment( idxRow, eAlign );
		}

		// 選択状態変更
		int		idxStart = pSelection->GetSelectedStartRow();
		int		idxEnd = pSelection->GetSelectedEndRow();
		pSelection->SetSelectedStart(
			idxStart,
			0
		);
		pSelection->SetSelectedEnd(
			idxEnd,
			::StringToColumn(
				*( pDoc->GetLine( idxEnd ) )
			)
		);
	}
	else
	{
		Alignment(
			pDoc->GetCaretRow(),
			eAlign
		);
	}
}

void CMainFrame::OnEditLeft() 
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	CSelection*			pSelection = pDoc->GetSelection();
	if( pSelection->IsSelected() && CGeneralSetting::GetInstance()->GetBlockAlignment() )
	{
		BlockAlignment(
			AlignLeft
		);
	}
	else
	{
		Alignment(
			AlignLeft
		);
	}
	pDoc->ReDraw();
}

void CMainFrame::OnEditMid() 
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	CSelection*			pSelection = pDoc->GetSelection();
	if( pSelection->IsSelected() && CGeneralSetting::GetInstance()->GetBlockAlignment() )
	{
		BlockAlignment(
			AlignCenter
		);
	}
	else
	{
		Alignment(
			AlignCenter
		);
	}
	pDoc->ReDraw();	
}

void CMainFrame::OnEditRight() 
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument();
	CSelection*			pSelection = pDoc->GetSelection();
	if( pSelection->IsSelected() && CGeneralSetting::GetInstance()->GetBlockAlignment() )
	{
		BlockAlignment(
			AlignRight
		);
	}
	else
	{
		Alignment(
			AlignRight
		);
	}
	pDoc->ReDraw();
}






void CMainFrame::BlockAlignment(
	long	idxRow,
	EAlign	eAlign,
	long	lSrcBlockLeft,
	long	lSrcBlockRight
)
{
	CDC*	pDC = GetDC();

	CShitarabianDoc*	pDoc = ::GetDocument();
//	CEditDrawer*		pDrawer = CEditDrawer::GetInstance();
	CString*			pstrLine = pDoc->GetLine( idxRow );

	// 現在行の長さを得る
	int		idxSolidStartPixel = 0;
	int		idxSolidEndPixel = 0;
	long		lLineWidth = 0;
	CString		strSolidLine;
	if ( pstrLine != NULL )
	{
		// トークンに分割し、空白でない部分を取得する
		CArray< TToken, TToken& >	aTokenz;
		CTokenReader::StringToCharTypez(
			*pstrLine,
			&aTokenz
		);

		// 空白でない文字列を得る
		int		idxSolidStartByteColumn = 0;
		int		idxSolidEndByteColumn = 0;
		int		idxSolidStartCaretColumn = 0;
		int		idxSolidEndCaretColumn = 0;
		{
			for( int idxToken=0 ; idxToken<aTokenz.GetSize() ; idxToken++ )
			{
				if ( aTokenz[idxToken].eCharType != CharTypeWhitespace )
				{
					idxSolidStartCaretColumn  = aTokenz[idxToken].idxStartColumn;
					idxSolidStartByteColumn = ::CaretColumnToByteColumn(
						*pstrLine,
						idxSolidStartCaretColumn
					);

					CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxRow );
					if ( pEmphasisLine != NULL )
					{
						idxSolidStartPixel = pEmphasisLine->CaretColumnToPixel( idxSolidStartCaretColumn );
					}
					break;
				}
			}
			for( idxToken=aTokenz.GetSize()-1 ; idxToken>=0 ; idxToken-- )
			{
				if ( aTokenz[idxToken].eCharType != CharTypeWhitespace )
				{
					idxSolidEndCaretColumn = aTokenz[idxToken].idxStartColumn+aTokenz[idxToken].nColumn;
					idxSolidEndByteColumn = ::CaretColumnToByteColumn(
						*pstrLine,
						idxSolidEndCaretColumn
					);


					idxSolidEndPixel = 0;
					CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxRow );
					if ( pEmphasisLine != NULL )
					{
						idxSolidEndPixel = pEmphasisLine->CaretColumnToPixel( idxSolidEndCaretColumn );
					}
					break;
				}
			}
		}
		strSolidLine = pstrLine->Mid(
			idxSolidStartByteColumn,
			idxSolidEndByteColumn - idxSolidStartByteColumn
		);

		// 長さを取得する
		lLineWidth = CEditDrawer::GetInstance()->StringToPixelX(
			strSolidLine,
			pDC
		);
	}

	// パディングすべき長さを得る
	long	lClientWidth = CGeneralSetting::GetInstance()->GetPrintDefine()->m_lPrintPixelWidth;
	long	lPaddingWidth;
	switch( eAlign )
	{
	case AlignLeft:
	default:
		lPaddingWidth = idxSolidStartPixel - lSrcBlockLeft;;
		break;

	case AlignCenter:
		lPaddingWidth = (lClientWidth - (lSrcBlockRight - lSrcBlockLeft))/2
						 + idxSolidStartPixel - lSrcBlockLeft;
		break;

	case AlignRight:
		lPaddingWidth = (lClientWidth - (lSrcBlockRight - lSrcBlockLeft))
						 + idxSolidStartPixel - lSrcBlockLeft;
		break;
	}

	// パディング文字列を得る
	CString	strPadding;
	{
		CPadding	Padding;
		Padding.Padding(
			pDC,
			lPaddingWidth,
			strPadding,
			*( CGeneralSetting::GetInstance()->GetWhitespace()->GetCharz() )
		);
	}

	// 行の差し替え
	CCommandMultiEdit	cmdEdit;
	{
		CCommandDelete	cmdDelete;
		cmdDelete.SetAttribute(
			idxRow, 0,
			idxRow, ::StringToColumn( *pstrLine )
		);
		cmdEdit.Add( cmdDelete );

		if( !strSolidLine.IsEmpty() )
		{
			CCommandInput	cmdInput;
			cmdInput.SetAttribute(
				strPadding + strSolidLine,
				idxRow,
				0
			);
			cmdEdit.Add( cmdInput );
		}
	}
	cmdEdit.Execute( pDoc );
	CCommandManager*	pCmd = CCommandManager::GetInstance();
	pCmd->Add( cmdEdit );


	ReleaseDC( pDC );
}

void CMainFrame::BlockAlignment(
	EAlign		eAlign
)
{
	CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument( );
	CSelection*			pSelection = pDoc->GetSelection();
//	CEditDrawer*		pDrawer = CEditDrawer::GetInstance();

	if( pSelection->IsSelected() )
	{
		int idxRow;
		// ブロックの長さを得る
		long	lBlockLeft = INT_MAX;
		long	lBlockRight = 0;
		for( idxRow=pSelection->GetSelectedStartRow();
			idxRow<=pSelection->GetSelectedEndRow();
			idxRow++ )
		{
			CString*			pstrLine = pDoc->GetLine( idxRow );

			// 現在行の長さを得る
			if ( pstrLine != NULL )
			if ( !pstrLine->IsEmpty() )
			{
				// トークンに分割し、空白でない部分を取得する
				CArray< TToken, TToken& >	aTokenz;
				CTokenReader::StringToCharTypez(
					*pstrLine,
					&aTokenz
				);

				// 空白でない文字列を得る
				int		idxSolidStartCaretColumn = 0;
				int		idxSolidEndCaretColumn = 0;
				int		idxSolidStartPixel = 0;
				int		idxSolidEndPixel = 0;
				{
					CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxRow );
					for( int idxToken=0 ; idxToken<aTokenz.GetSize() ; idxToken++ )
					{
						if ( aTokenz[idxToken].eCharType != CharTypeWhitespace )
						{
							idxSolidStartCaretColumn  = aTokenz[idxToken].idxStartColumn;
							if ( pEmphasisLine != NULL )
							{
								idxSolidStartPixel = pEmphasisLine->CaretColumnToPixel(
									idxSolidStartCaretColumn
								);
							}
							break;
						}
					}
					for( idxToken=aTokenz.GetSize()-1 ; idxToken>=0 ; idxToken-- )
					{
						if ( aTokenz[idxToken].eCharType != CharTypeWhitespace )
						{
							idxSolidEndCaretColumn = aTokenz[idxToken].idxStartColumn+aTokenz[idxToken].nColumn;
							if ( pEmphasisLine != NULL )
							{
								idxSolidEndPixel = pEmphasisLine->CaretColumnToPixel(
									idxSolidEndCaretColumn
								);
							}
							break;
						}
					}
				}
				lBlockLeft = min ( lBlockLeft, idxSolidStartPixel );
				lBlockRight = max ( lBlockRight, idxSolidEndPixel );
			}
		}

		// パディングしつつ行の差し替え
		for( idxRow=pSelection->GetSelectedStartRow();
					idxRow<=pSelection->GetSelectedEndRow();
					idxRow++ )
		{
			BlockAlignment(
				idxRow,
				eAlign,
				lBlockLeft,
				lBlockRight
			);
		}

		// 選択状態変更
		{
			int		idxStart = pSelection->GetSelectedStartRow();
			int		idxEnd = pSelection->GetSelectedEndRow();
			pSelection->SetSelectedStart(
				idxStart,
				0
			);
			pSelection->SetSelectedEnd(
				idxEnd,
				::StringToColumn(
					*( pDoc->GetLine( idxEnd ) )
				)
			);
		}
	}
}





/*-----------------------------------------------------------------------------
[名称]	リンクハンドラ
[機能]	編集文中のリンクを開く。
[戻値]	なし
[備考]	右クリックのポップアップメニューからコールされる。
-----------------------------------------------------------------------------*/
void CMainFrame::OnLink() 
{
	// カレントフォルダ移動
	{
		// 今開いているドキュメントのフォルダをカレントフォルダとする
		CShitarabianDoc* pDoc = (CShitarabianDoc*)GetActiveDocument( );
		CString	strPathName = pDoc->GetPathName();
		if ( !strPathName.IsEmpty() )
		{
			int	idxLastSlash = strPathName.ReverseFind( '\\' );
			strPathName = strPathName.Left( idxLastSlash+1 );

			if ( !strPathName.IsEmpty() )
			{
				::SetCurrentDirectory( strPathName );
			}
		}
	}

	// リンク処理
	CLinkDefine*	pLinkDefine = CLinkDefine::GetInstance();
	TLinkTarget*	pLink = pLinkDefine->TargetLink();
	switch( pLink->eLinkType )
	{
	case LinkOpenAction:
		// shell open
		{
			::ShellExecute( HWND_DESKTOP, NULL, pLink->strTarget, NULL, NULL, SW_SHOWNORMAL);
			// please! 開けなかった場合のメッセージを出したいが
		}
		break;

	case LinkTxt:
		// したらびあんで開く
		{
// ▼ (3751) BGN 2004.05.10 (moralog) 関数化
			// 実行ファイル名を得る
			CString	strExeShortPath = ::GetShortFilePath( ::GetExePathName() );
/*
// ▽ original BGN
			const	iMaxLength( 1028 );	// パス格納バッファ長さ

			// 実行ファイル名を得る
			char	strExeShortPath[ iMaxLength ];
			{
				char	strExeLongPath[ iMaxLength ];
				::GetModuleFileName(
					NULL,
					strExeLongPath,
					iMaxLength
				);

				// ショートファイルのパスを得る
				::GetShortPathName( strExeLongPath, strExeShortPath, iMaxLength );
			}
// △ original END
*/
// ▲ (3751) END

			BOOL	bExist;
			CFileStatus	dummy;
			bExist = CFile::GetStatus( pLink->strTarget, dummy );
			if ( bExist )
			{
				// ドキュメントファイル名を得る
// ▼ (3751) BGN 2004.05.10 (moralog) 関数化
// ▽ original BGN
//				char	strDocumentShortPath[ iMaxLength ];
//				::GetShortPathName( pLink->strTarget, strDocumentShortPath, iMaxLength );
// △ original END
				CString	strDocumentShortPath = ::GetShortFilePath( pLink->strTarget );
// ▲ (3751) END

				// 別窓で開く
				_spawnl( _P_NOWAIT, strExeShortPath, strExeShortPath, strDocumentShortPath, NULL );
			}
			else
			{
				CString		strMes;
				strMes.Format( "ファイル\"%s\"が存在しません", pLink->strTarget );
				::AfxMessageBox( strMes );
			}
		}
		break;

	case LinkJump:
		// 行へジャンプ
		{
			// リンク先から数字部分を取り出す

			// 行頭に該当する数字のある行を検索してジャンプ
			CString		strSubString(  pLink->strTarget );
			AddSubString( strSubString, NULL );

			BOOL	bLoopOld = m_dlgFinder.m_bLoop;
			m_dlgFinder.m_bLoop = TRUE;
			m_dlgFinder.FindNext(  );
			m_dlgFinder.m_bLoop = bLoopOld;
		}
		break;

	default:
		
		break;
	}
}


/*-----------------------------------------------------------------------------
[名称]	文字列選択ハンドラ
[機能]	編集文中の文字列を選択する。
[戻値]	なし
[備考]	右クリックのポップアップメニューからコールされる。
-----------------------------------------------------------------------------*/
void CMainFrame::OnMagicSelect() 
{
	// 選択する。
	TLinkTarget*	pLink = CLinkDefine::GetInstance()->TargetLink();
	CShitarabianDoc* pDoc = GetDocument();
	CSelection*	pSelection = pDoc->GetNormalSelection();

	pSelection->SetSelectedStart(
		pLink->idxRow,
		pLink->idxColumn
	);

	pSelection->SetSelectedEnd(
		pLink->idxRow,
		pLink->idxColumn + pLink->nColumn
	);

	// 再描画
	pDoc->SetUpdateStartRow( pLink->idxRow );
	pDoc->SetUpdateEndRow( pLink->idxRow );
	pDoc->ReDraw();
}


/*-----------------------------------------------------------------------------
[名称]	文字列コピーハンドラ
[機能]	編集文中の文字列をコピーする。
[戻値]	なし
[備考]	右クリックのポップアップメニューからコールされる。
-----------------------------------------------------------------------------*/
void CMainFrame::OnMagicCopy() 
{
	TLinkTarget*	pLink = CLinkDefine::GetInstance()->TargetLink();
// ▼ (3204) BGN 2004.05.12 (moralog) ExeCommon.cppから移動。汎用関数化。
	::EditCopyStringWithHistory( pLink->strTarget );
// ▽ original BGN
//	::EditCopyString( pLink->strTarget );
// △ original END
// ▲ (3204) END
}

// ▼ (3367) BGN 2004.03.13 (moralog)
/*-----------------------------------------------------------------------------
[名称]	Grep開始ハンドラ
[機能]	Grepダイアログを表示する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CMainFrame::OnGrep() 
{
	m_dlgFinder.ShowWindow( SW_HIDE );
	m_dlgReplacer.ShowWindow( SW_HIDE );
	m_dlgGrep.ShowWindow( SW_SHOW );
}
// ▲ (3367) END
