/*-----------------------------------------------------------------------------
[名称]	ShitarabianViewBoxSelection.cpp
[概要]	Viewクラス（BOX選択時）の実装
[備考]	なし
[履歴]	2003-02-25	NC		コメント付加(moralog)
-----------------------------------------------------------------------------*/


//-----------------------------------------------------------------------------
// インクルード
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "Common.h"
#include "Shitarabian.h"
#include "ShitarabianDoc.h"
#include "ShitarabianView.h"
#include "imm.h"
#include "EditDrawer.h"
#include "CommandManager.h"
#include "CommandInput.h"
#include "CommandCaret.h"
#include "CommandDelete.h"
#include "GeneralSetting.h"
#include <process.h>
#include "Selection.h"
#include "BoxSelection.h"
#include "FloatingSelection.h"
#include "CommandMultiEdit.h"
#include "Padding.h"
#include "TokenReader.h"
#include "ExeCommon.h"


//-----------------------------------------------------------------------------
// ファイル内関数
//-----------------------------------------------------------------------------

/*-----------------------------------------------------------------------------
[名称]	描画オブジェクト取得
[機能]	描画オブジェクト取得処理。
[戻値]	CEditDrawer*	描画オブジェクト [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
static CEditDrawer*	GetDrawer()
{
	return( CEditDrawer::GetInstance() );
}


//-----------------------------------------------------------------------------
// クラスメンバ関数
//-----------------------------------------------------------------------------

/*-----------------------------------------------------------------------------
[名称]	イベントハンドラ
[機能]	主にマウスイベント処理。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CShitarabianView::PreTranslateBoxSelectMode(
	MSG*	pMsg,				// I  :メッセージ [-] (-)
	BOOL	bShift,				// I  :シフト状態 [-] (TRUE:押下、FALSE:なし)
	BOOL	bCtrl,				// I  :Ctrl状態 [-] (TRUE:押下、FALSE:なし)
	BOOL	bAlt				// I  :Alt状態 [-] (TRUE:押下、FALSE:なし)
) 
{
	// warning C4100:警告の無視
	bAlt; bShift; 

	CEditDrawer*	pDrawer = GetDrawer();
	CShitarabianDoc* pDoc = GetDocument();
	CSelection*			pSelection = pDoc->GetSelection();

	BOOL	bBreak = FALSE;
	BOOL	bRedraw = FALSE;
	BOOL	bSelectedModify = FALSE;

	int idxOldSelectedStartRow = pSelection->GetSelectedStartRow();
	int idxOldSelectedEndRow = pSelection->GetSelectedEndRow();

	switch( pMsg->message )
	{
	case WM_LBUTTONUP:
		m_bDrag = FALSE;
		m_bVisibleCaret = TRUE;
		ReleaseCapture();
		break;

	case WM_MOUSEMOVE:
		// 入力操作時に消えていたマウスカーソルはマウス移動で現れる
		m_bInputMode = FALSE;
		DrawStatusBar();

		if ( !(GetAsyncKeyState( VK_LBUTTON ) &0x8000) )
		{
			m_bDrag = FALSE;
		}
		if ( m_bDrag )
		{
			// ピクセル座標を得る
			POINTS	pt = MAKEPOINTS( pMsg->lParam );
			CPoint posCursor( pt.x, pt.y );
			posCursor = ScrollBoxToPixel( posCursor );
			
			pDoc->GetBoxSelection()->SetSelectedEndPixel( posCursor );
			posCursor.y = max( posCursor.y, 0 );

			bSelectedModify = TRUE;
			bRedraw = TRUE;

			// オートスクロール
			{
				// ScrollToCaret() でカタをつけるためにキャレットを移動させる
				// 該当行計算
				int idxRow = pDrawer->PixelToCaretRow( posCursor.y, pDoc );
				idxRow = min( idxRow, pDoc->GetLineCount()-1 );

				CString*	pstrCurrentLine = pDoc->GetLine( idxRow );
				if ( pstrCurrentLine != NULL )
				{
					int	idxColumn = 0;
					CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxRow );
					if ( pEmphasisLine != NULL )
					{
						idxColumn = pEmphasisLine->PixelToCaretColumn( posCursor.x );
					}

					// キャレットの移動
					CCommandCaret	cmdCaret;
					cmdCaret.SetAttribute( 0x00, idxRow, idxColumn );
					cmdCaret.Execute( pDoc );

					ScrollToCaret();
				}
			}
		}
		bBreak = TRUE;
		break;

	case WM_LBUTTONDOWN:
		{
			// ピクセル座標を得る
			POINTS	pt = MAKEPOINTS( pMsg->lParam );
			CPoint posCursor( pt.x, pt.y );
			posCursor = ScrollBoxToPixel( posCursor );

			CDC*		pDC = NULL;
			pDC = GetDC();
			if ( pDC == NULL )
			{
				break;
			}

			// クリックされた行、カラム位置を計算
			int idxRow = pDoc->GetCaretRow();
			int idxColumn = pDoc->GetCaretColumn();
			idxRow = pDrawer->PixelToCaretRow( posCursor.y, pDoc );
			CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxRow );
			if ( pEmphasisLine != NULL )
			{
				idxColumn = pEmphasisLine->PixelToCaretColumn( posCursor.x, TRUE );
			}
			else
			{
				// 該当行がない
				break;
			}

			// コントロールキーを押しながらであればちくちく選択
			if ( bCtrl )
			{
				pDoc->GetBoxSelection()->SetLineInfo(
					idxRow,
					idxColumn
				);

				bSelectedModify = TRUE;
				bRedraw = TRUE;
				bBreak = TRUE;
				break;
			}

			// ドラッグの開始
			m_bDrag = TRUE;
			SetCapture( );

			// ドラッグ中はカーソル非表示
			DestroyCaret();
			m_bVisibleCaret = FALSE;

			if ( pSelection->IsSelected( idxRow, idxColumn ) )
			{
				// フローティングモードに移行
				BoxSelectToFloating();

				CFloatingSelection*	pSelection;
				pSelection = pDoc->GetFloatingSelection();
				CPoint	ptFloat = pSelection->GetPosition();

				m_iFloatOffsetX = ptFloat.x - posCursor.x;
				m_iFloatOffsetY = ptFloat.y - posCursor.y;
			}
			else
			{
				SetCapture( );
				// キャレットの移動
				{
					int idxRow = pDoc->GetCaretRow();
					idxRow = pDrawer->PixelToCaretRow( posCursor.y, pDoc );

					CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxRow );
					if ( pEmphasisLine != NULL )
					{
						int		idxColumn = 0;
						idxColumn = pEmphasisLine->PixelToCaretColumn(
							posCursor.x
						);

						CCommandCaret	cmdCaret;
						cmdCaret.SetAttribute( 0x00, idxRow, idxColumn );
						cmdCaret.Execute( pDoc );
					}

					ReleaseDC( pDC );
				}

				if ( GetAsyncKeyState( VK_SHIFT ) &0x8000 )
				{
					// Shift押しながらなら選択範囲を変更
					pDoc->GetBoxSelection()->SetSelectedEndPixel(
							posCursor
					);
				}
				else
				{
					pDoc->GetBoxSelection()->SetSelectedStartPixel(
							posCursor
					);

					// 選択状態の解除
					pDoc->GetBoxSelection()->SetSelectedNutral();
				}
			}
		}
		bSelectedModify = TRUE;
		bRedraw = TRUE;
		bBreak = TRUE;
		break;

	default:
		break;
	}

	if ( bSelectedModify )
	{
		pDoc->SetUpdateStartRow( min( idxOldSelectedStartRow, pSelection->GetSelectedStartRow() ) );
		pDoc->SetUpdateEndRow( max( idxOldSelectedEndRow, pSelection->GetSelectedEndRow() ) );
	}

	if ( bRedraw )
	{
		pDoc->ReDraw();

	}

	if( bBreak )
	{
		return( TRUE );
	}
	else
	{
		return( FALSE );
	}
}


/*-----------------------------------------------------------------------------
[名称]	フローティング貼り付けモード移行
[機能]	選択中文字列を引きずってフローティング貼り付けモードへ移行する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianView::BoxSelectToFloating()
{
	CShitarabianDoc*	pDoc = GetDocument();
	CBoxSelection*		pSelection = pDoc->GetBoxSelection();
	CEditDrawer*		pDrawer = CEditDrawer::GetInstance();

	// BOX選択範囲からの上下空白行の除去
	{
		CArray<TSelectColumn, TSelectColumn&>* patColumnz = pSelection->GetSelectedLinez();

		long	lStartRow = pDrawer->PixelToCaretRow( pSelection->GetSelectedStartY(), pDoc); 
		long	lEndRow =  pDrawer->PixelToCaretRow( pSelection->GetSelectedEndY(), pDoc); 

		// （空白文字のみの行も除去）
		CWhitespaceDefine*	pWhitespace = CGeneralSetting::GetInstance()->GetWhitespace();
		CArray<TWhiteSpace, TWhiteSpace&>*	paCharz = pWhitespace->GetCharz();
		long	lRowHeight = pDrawer->CaretRowToPixel( 1 );
		long	idxRow;
		for( idxRow=lEndRow ; idxRow>=lStartRow ; idxRow-- )
		{
			// 下のほうの空白行を除去
			if ( idxRow < pDoc->GetLineCount() )
			{
				long		idxBlackSpace;
				CPadding	Padding;
				idxBlackSpace = Padding.NextBlackSpaceColumn(
					*(pDoc->GetLine( idxRow )),
					patColumnz->GetAt(idxRow-lStartRow).idxStart,
					*(paCharz)
				);
				if ( idxBlackSpace >= 0 )
				if ( idxBlackSpace <= patColumnz->GetAt(idxRow-lStartRow).idxEnd )
				{
					break;
				}
			}
			patColumnz->RemoveAt( idxRow-lStartRow );
			lEndRow--;
			pSelection->SetSelectedEndY(
				pSelection->GetSelectedEndY() - lRowHeight
			);
		}
		for( idxRow=lStartRow ; idxRow<=lEndRow ; idxRow++ )
		{
			// 上のほうの空白行を除去
			if ( idxRow < pDoc->GetLineCount() )
			{
				long		idxBlackSpace;
				CPadding	Padding;
				idxBlackSpace = Padding.NextBlackSpaceColumn(
					*(pDoc->GetLine( idxRow )),
					patColumnz->GetAt(idxRow-lStartRow).idxStart,
					*(paCharz)
				);
				if ( idxBlackSpace >= 0 )
				if ( idxBlackSpace <= patColumnz->GetAt(idxRow-lStartRow).idxEnd )
				{
					break;
				}
			}
			patColumnz->RemoveAt( idxRow-lStartRow );
			lStartRow ++;
			pSelection->SetSelectedStartY(
				pSelection->GetSelectedStartY() + lRowHeight
			);
		}

		if ( patColumnz->GetSize() < 1 )
		{
			// BOX選択範囲に文字がなければフローティングに移行しない
			pSelection->SetSelectedNutral();
			return;
		}

		// BOX選択の選択範囲を更新
		pSelection->SetSelectedStart( lStartRow, patColumnz->GetAt(0).idxStart );
		pSelection->SetSelectedEnd( lEndRow, patColumnz->GetAt(lEndRow-lStartRow).idxEnd );
	}

	// 空白カラム除去
	pSelection->TrimSelection();

	// 掴む位置のズレを取得
	CStringArray	astrLinez;
	long			lLeftGap;
	pSelection->GetSelectedLinezWithPadding(
		&astrLinez,
		&lLeftGap
	);

	// フローティング選択文字を設定
	CString		strLinez;
	strLinez = pSelection->GetSelectedText();
	ToFloating(
		strLinez,
		pSelection->GetSelectedStartX() +lLeftGap,
		pSelection->GetSelectedStartY()
	);
	TRACE("%s\n",strLinez.Left(255));

	pDoc->SetAllUpdate();
}



/*-----------------------------------------------------------------------------
[名称]	フローティング貼り付けモード移行
[機能]	フローティング貼り付けモードへ移行する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianView::ToFloating(
	CString		strLinez,		// I  :フロート文字列 [-] (-) :-
	int			iPixelX,		// I  :フロート左肩 [プレーンpixel] (-) :-
	int			iPixelY			// I  :フロート左肩 [プレーンpixel] (-) :-
)
{
	CShitarabianDoc*	pDoc = GetDocument();

	// 入力操作時に消えていたマウスカーソル表示
	m_bInputMode = FALSE;

	CFloatingSelection*	pFloating;
	pFloating = pDoc->GetFloatingSelection();

	// フローティング選択文字を設定
	CString strDelimiter( pDoc->ReturnChar() );
	CStringArray	astrLinez;
	::StringToArray(
		strLinez,
		&astrLinez,
		strDelimiter
	);
	pFloating->SetLinez( astrLinez );

	pFloating->SetPosition(
		CPoint(
			iPixelX,
			iPixelY
		)
	);
	// フローティングモードに移行
	pDoc->SetOperationMode( OperationFloating );
	pFloating->DoReflect();
}


/*-----------------------------------------------------------------------------
[名称]	キー押下ハンドラ
[機能]	押下されたキーに応じた処理。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CShitarabianView::PreTranslateKeyDownBoxSelectMode(
	UCHAR	unKey,				// I  :キー [仮想キーコード] (-)
	BOOL	bShift,				// I  :シフト状態 [-] (TRUE:押下、FALSE:なし)
	BOOL	bCtrl,				// I  :Ctrl状態 [-] (TRUE:押下、FALSE:なし)
	BOOL	bAlt				// I  :Alt状態 [-] (TRUE:押下、FALSE:なし)
)
{
	CShitarabianDoc*	pDoc = GetDocument();
	CSelection*			pSelection = pDoc->GetSelection();

	BOOL	bBreak = FALSE;
	BOOL	bSelectedModify = FALSE;

	int idxOldSelectedStartRow = pSelection->GetSelectedStartRow();
	int idxOldSelectedEndRow = pSelection->GetSelectedEndRow();

	int	nRow = pDoc->GetLineCount();

	switch( unKey )
	{
	case VK_ESCAPE:
		// 選択状態の解除
		pSelection->SetSelectedNutral();
		bSelectedModify = TRUE;
		OnEditModeselect();
		bBreak = TRUE;
		break;

	case VK_F4:
		pSelection->SetSelectedNutral();
		bSelectedModify = TRUE;
		OnEditModeselect();
		bBreak = TRUE;
		break;

	case VK_TAB:
		if ( pDoc->GetSelection()->IsSelected() )
		{
			// タブ文字生成
			CString		strTabString;
			int			nTabChar;
			if ( CGeneralSetting::GetInstance()->GetTabConvert() )
			{
				strTabString = CGeneralSetting::GetInstance()->GetTabString();
			}
			else
			{
				strTabString = (char)(unKey);
			}
			nTabChar = ::StringToColumn( strTabString );

			// マルチインデントの実行
			int		idxStartRow = pSelection->GetSelectedStartRow();
			CArray<TSelectColumn, TSelectColumn&>*	pLinez;
			pLinez = pSelection->GetSelectedLinez();
			{
				CCommandMultiEdit	cmdEdit;
				for( int idxLine=0 ; idxLine<pLinez->GetSize() ; idxLine++ )
				{
					int	idxColumn = pLinez->GetAt(idxLine).idxStart;
					int idxRow = idxStartRow+idxLine;

					int idxStartColumn = pLinez->GetAt(idxLine).idxStart;
					int idxEndColumn = pLinez->GetAt(idxLine).idxEnd;

					CString* pstrLine = pDoc->GetLine( idxRow );
					if( pstrLine != NULL )
					{
						if ( bShift )
						{
						// マルチ逆インデント

							// 空白文字？
							BOOL	bWhiteSpace = FALSE;
							{
								CArray< TToken, TToken& >	aTokenz;
								CTokenReader::StringToCharTypez(
									*pstrLine,
									&aTokenz
								);

								// 単語特定
								int		idxToken = CTokenReader::TokenIndex(
									aTokenz,
									idxColumn-1
								);
								if ( idxToken != InvalidTokenIndex )
								{
									bWhiteSpace = ( aTokenz[idxToken].eCharType == CharTypeWhitespace );
								}
							}

							// 空白文字の削除
							if( bWhiteSpace )
							{
								// 入力コマンドの登録
								CCommandDelete	cmdDelete;
								cmdDelete.SetAttribute(
									idxRow, idxColumn-1,
									idxRow, idxColumn
								);
								cmdEdit.Add( cmdDelete );

								pDoc->GetBoxSelection()->SetLineInfo(
									idxRow,
									idxColumn-1,
									idxEndColumn-1
								);
							}
						}
						else
						{
						// マルチインデント
							if ( !pstrLine->IsEmpty() )
							{
								// 入力コマンドの登録
								CCommandInput	cmdInput;
								cmdInput.SetAttribute( strTabString, idxRow, idxColumn );
								cmdEdit.Add( cmdInput );
							}

							pDoc->GetBoxSelection()->SetLineInfo(
								idxRow,
								idxStartColumn+nTabChar,
								idxEndColumn+nTabChar
							);
						}
					}
				// please! Addしてから設定したほうがよさげ
				}
				cmdEdit.Execute( pDoc );

				// コマンドマネージャに登録
				CCommandManager*	pCmd = CCommandManager::GetInstance();
				pCmd->Add( cmdEdit );
				// please! Addしてから設定したほうがよさげ
			}
		}
		bBreak = TRUE;
		break;

	case VK_UP:
	case VK_DOWN:
	case VK_LEFT:
	case VK_RIGHT:
		// フローティングモードに移行
		if ( pDoc->GetSelection()->IsSelected() )
		{
			BoxSelectToFloating();
			PreTranslateKeyDownFloatingMode(
					unKey,				// I  :キー [仮想キーコード] (-)
					bShift,				// I  :シフト状態 [-] (TRUE:押下、FALSE:なし)
					bCtrl,				// I  :Ctrl状態 [-] (TRUE:押下、FALSE:なし)
					bAlt
			);
			bBreak = TRUE;
		}
		break;

	case VK_BACK:
		// 選択状態の解除
		// モードの取り消し
		// Box選択範囲の切り取り削除
		{
			CCommandMultiEdit	cmdEdit;

			// 行単位にDeleteをかける
			CBoxSelection* pSelection = dynamic_cast<CBoxSelection*>(pDoc->GetSelection());
			if ( pSelection == NULL )
			{
				break;
			}
			int		idxStartRow = pSelection->GetSelectedStartRow();
			CArray<TSelectColumn, TSelectColumn&>*	pLinez;
			pLinez = pSelection->GetSelectedLinez();

			for( int idxLine=0 ; idxLine<pLinez->GetSize() ; idxLine++ )
			{
				CCommandDelete	cmdDelete;
				cmdDelete.SetAttribute(
					idxStartRow+idxLine,
					pLinez->GetAt(idxLine).idxStart,
					idxStartRow+idxLine,
					pLinez->GetAt(idxLine).idxEnd
				);
				cmdEdit.Add( cmdDelete );
			}

			// please! Addしてから設定したほうがよさげ
			cmdEdit.Execute( pDoc );

			// コマンドマネージャに登録
			CCommandManager*	pCmd = CCommandManager::GetInstance();
			pCmd->Add( cmdEdit );
			// please! Addしてから設定したほうがよさげ


			// 選択状態の解除
			pSelection->SetSelectedNutral();
		}
		bBreak = TRUE;
		break;

	case VK_DELETE:
		// 選択状態の解除
		// Box選択範囲のクリア
		pDoc->GetBoxSelection()->BoxClear();
		bBreak = TRUE;
		break;

	default:
		bBreak = PreTranslateKeyDownNormalMode( unKey, bShift, bCtrl, bAlt );
		return( bBreak );
		break;
	}

	if ( bSelectedModify )
	{
		pDoc->SetUpdateStartRow( min( idxOldSelectedStartRow, pSelection->GetSelectedStartRow() ) );
		pDoc->SetUpdateEndRow( max( idxOldSelectedEndRow, pSelection->GetSelectedEndRow() ) );
	}

	if ( nRow != pDoc->GetLineCount() )
	{
		ResetHScroll();
	}

	if( bBreak )
	{
		// スクロールできそうであればスクロールバーを制御
		ScrollToCaret();

		// 再描画
		pDoc->ReDraw();

		// ここでDrawCaret()すると描画が全くされない。
		// キャレットの描画はDrawPage()内でする。

		GetDocument()->SetMainView( this );
		return( TRUE );
	}
	return( FALSE );
}


/*-----------------------------------------------------------------------------
[名称]	文字入力ハンドラ
[機能]	入力された文字に応じた処理。
[戻値]	なし
[備考]	VK_ESCAPE:	選択の解除、通常編集への移行
		VK_F4:		選択の解除、通常編集への移行
		VK_TAB:		マルチインデント
-----------------------------------------------------------------------------*/
BOOL CShitarabianView::PreTranslateCharBoxSelectMode(
	CString	strChar,			// I  :入力文字列　[-] (-)
	BOOL	bShift,				// I  :シフト状態 [-] (TRUE:押下、FALSE:なし)
	BOOL	bCtrl,				// I  :Ctrl状態 [-] (TRUE:押下、FALSE:なし)
	BOOL	bAlt				// I  :Alt状態 [-] (TRUE:押下、FALSE:なし)
)
{
	CShitarabianDoc*	pDoc = GetDocument();
	CSelection*			pSelection = pDoc->GetSelection();

	BOOL	bBreak = FALSE;
	BOOL	bSelectedModify = FALSE;

	int idxOldSelectedStartRow = pSelection->GetSelectedStartRow();
	int idxOldSelectedEndRow = pSelection->GetSelectedEndRow();

	int	nRow = pDoc->GetLineCount();

	if( strChar == (CString)VK_ESCAPE )
	{
		// 選択状態の解除
		pSelection->SetSelectedNutral();
		bSelectedModify = TRUE;
		OnEditModeselect();
		bBreak = TRUE;
	}
	else if( strChar == (CString)VK_F4 )
	{
		pSelection->SetSelectedNutral();
		bSelectedModify = TRUE;
		OnEditModeselect();
		bBreak = TRUE;
	}
	else if( strChar == (CString)VK_TAB )
	{
		if ( pDoc->GetSelection()->IsSelected() )
		{
			// タブ文字生成
			CString		strTabString;
			int			nTabChar;
			if ( CGeneralSetting::GetInstance()->GetTabConvert() )
			{
				strTabString = CGeneralSetting::GetInstance()->GetTabString();
			}
			else
			{
				strTabString = strChar;
			}
			nTabChar = ::StringToColumn( strTabString );

			// マルチインデントの実行
			int		idxStartRow = pSelection->GetSelectedStartRow();
			CArray<TSelectColumn, TSelectColumn&>*	pLinez;
			pLinez = pSelection->GetSelectedLinez();
			{
				CCommandMultiEdit	cmdEdit;
				for( int idxLine=0 ; idxLine<pLinez->GetSize() ; idxLine++ )
				{
					int	idxColumn = pLinez->GetAt(idxLine).idxStart;
					int idxRow = idxStartRow+idxLine;

					int idxStartColumn = pLinez->GetAt(idxLine).idxStart;
					int idxEndColumn = pLinez->GetAt(idxLine).idxEnd;

					CString* pstrLine = pDoc->GetLine( idxRow );
					if( pstrLine != NULL )
					{
						if ( bShift )
						{
						// マルチ逆インデント

							// 空白文字？
							BOOL	bWhiteSpace = FALSE;
							{
								CArray< TToken, TToken& >	aTokenz;
								CTokenReader::StringToCharTypez(
									*pstrLine,
									&aTokenz
								);

								// 単語特定
								int		idxToken = CTokenReader::TokenIndex(
									aTokenz,
									idxColumn-1
								);
								if ( idxToken != InvalidTokenIndex )
								{
									bWhiteSpace = ( aTokenz[idxToken].eCharType == CharTypeWhitespace );
								}
							}

							// 空白文字の削除
							if( bWhiteSpace )
							{
								// 入力コマンドの登録
								CCommandDelete	cmdDelete;
								cmdDelete.SetAttribute(
									idxRow, idxColumn-1,
									idxRow, idxColumn
								);
								cmdEdit.Add( cmdDelete );

								pDoc->GetBoxSelection()->SetLineInfo(
									idxRow,
									idxColumn-1,
									idxEndColumn-1
								);
							}
						}
						else
						{
						// マルチインデント
							if ( !pstrLine->IsEmpty() )
							{
								// 入力コマンドの登録
								CCommandInput	cmdInput;
								cmdInput.SetAttribute( strTabString, idxRow, idxColumn );
								cmdEdit.Add( cmdInput );
							}

							pDoc->GetBoxSelection()->SetLineInfo(
								idxRow,
								idxStartColumn+nTabChar,
								idxEndColumn+nTabChar
							);
						}
					}
				// please! Addしてから設定したほうがよさげ
				}
				cmdEdit.Execute( pDoc );

				// コマンドマネージャに登録
				CCommandManager*	pCmd = CCommandManager::GetInstance();
				pCmd->Add( cmdEdit );
				// please! Addしてから設定したほうがよさげ
			}
		}
		bBreak = TRUE;
	}
	else
	{
		bBreak = PreTranslateCharNormalMode( strChar, bShift, bCtrl, bAlt );
		return( bBreak );
	}

	if ( bSelectedModify )
	{
		pDoc->SetUpdateStartRow( min( idxOldSelectedStartRow, pSelection->GetSelectedStartRow() ) );
		pDoc->SetUpdateEndRow( max( idxOldSelectedEndRow, pSelection->GetSelectedEndRow() ) );
	}

	if ( nRow != pDoc->GetLineCount() )
	{
		ResetHScroll();
	}

	if( bBreak )
	{
		// スクロールできそうであればスクロールバーを制御
		ScrollToCaret();

		// 再描画
		pDoc->ReDraw();

		// ここでDrawCaret()すると描画が全くされない。
		// キャレットの描画はDrawPage()内でする。

		GetDocument()->SetMainView( this );
		return( TRUE );
	}
	return( FALSE );
}
