/*-----------------------------------------------------------------------------
[名称]	CommandInput.cpp
[概要]	文字入力コマンドクラスの実装
[備考]	なし
[履歴]	2003-03-13	NC		コメント付加(moralog)
-----------------------------------------------------------------------------*/


//-----------------------------------------------------------------------------
// インクルード
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "Common.h"
#include "Shitarabian.h"
#include "ShitarabianDoc.h"
#include "CommandInput.h"
#include "CommandDelete.h"
#include "CommandCaret.h"
#include "ShitarabianPlugInManager.h"
#include "ExeCommon.h"

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


/*-----------------------------------------------------------------------------
[名称]	コンストラクタ
[機能]	インスタンスの生成。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
CCommandInput::CCommandInput():
	m_strInput(),			// 入力された文字列 [-] (-)
	m_idxStartRow( 0 ),		// 入力された開始位置 [行] (-)
	m_idxStartColumn( 0 ),	// 入力された開始位置 [列] (-)
	m_idxEndRow( 0 ),		// 入力された終了位置 [行] (-)
	m_idxEndColumn( 0 )		// 入力された終了位置 [列] (-)
{

}


/*-----------------------------------------------------------------------------
[名称]	デストラクタ
[機能]	インスタンスの破棄。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
CCommandInput::~CCommandInput()
{

}


/*-----------------------------------------------------------------------------
[名称]	複製
[機能]	新しいインスタンスを生成して複製する。
[戻値]	ICommand*	複製されたインスタンスへのポインタ [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
ICommand*	CCommandInput::Duplicate()
{
	ICommand*	pcmdNew;

	pcmdNew = new CCommandInput;
	pcmdNew->Copy( *this );

	return( pcmdNew );
}


/*-----------------------------------------------------------------------------
[名称]	属性コピー
[機能]	属性をコピーする。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void		CCommandInput::Copy(
	ICommand& cmdSrc		// I  :コピー元オブジェクト [-] (-) :-
)
{
	CCommandInput*	pInput;
	pInput = dynamic_cast<CCommandInput*>(&cmdSrc);

	if ( pInput != NULL )
	{
		m_strInput = pInput->m_strInput;			// 入力された文字列 [-] (-)
		m_idxStartRow = pInput->m_idxStartRow;		// 入力された開始位置 [行] (-)
		m_idxStartColumn = pInput->m_idxStartColumn;// 入力された開始位置 [列] (-)
		m_idxEndRow = pInput->m_idxEndRow;			// 入力された終了位置 [行] (-)
		m_idxEndColumn = pInput->m_idxEndColumn;	// 入力された終了位置 [列] (-)
	}
	else
	{
		// 異なる型のコピーをしようとした
		ASSERT( FALSE );
	}
}


/*-----------------------------------------------------------------------------
[名称]	実行
[機能]	文字入力コマンドを実行する。
[戻値]	BOOL	処理結果 [-] (TURE:成功、FALSE:失敗)
[備考]	SetAttribute()されていること。
		１文字入力から複数行入力まで対応。
-----------------------------------------------------------------------------*/
BOOL		CCommandInput::Execute(
	CShitarabianDoc* pDoc		// I  :操作対象ドキュメント [-] (-) :-
)
{
	// 文字列を改行で切って文字列リストを作成、
	// リストをドキュメントにInsertする。

	// 改行で区切ってリスト化する
	CStringList	lstAddz;
	CString		strDelimiter( pDoc->ReturnChar() );
	long	nLine;
	nLine = ::StringToList(
		m_strInput,
		&lstAddz,
		strDelimiter
	);

	// 入力データがない場合は処理しない
	if( nLine == 0)
	{
//		ASSERT( FALSE );
		return( TRUE );
	}

	// Insert処理
	{
		CString*		pstrLine;
		pstrLine = pDoc->GetLine( m_idxStartRow );

		// 挿入後キャレットの位置の計算
		CString&	strTail = lstAddz.GetTail();
		long iNewCaretPosition = ::ByteColumnToCaretColumn( strTail, strTail.GetLength() );

		if ( pstrLine != NULL )
		{
		// 現在行の半ばへ挿入する処理
			long		idxByte = ::CaretColumnToByteColumn( *pstrLine, m_idxStartColumn );

			// 現在行を分割
			CString		strLeft = pstrLine->Left( idxByte );
			CString		strRight = pstrLine->Right( pstrLine->GetLength() - idxByte );

			// 改行までを現在行にマージ
			CString&	strHead = lstAddz.GetHead();
			strHead.Insert( 0, strLeft );

			// 最後の行に現在行後半をマージ
			iNewCaretPosition = ::ByteColumnToCaretColumn( strTail, strTail.GetLength() );
			strTail += strRight;

		}

		// 行の更新
		{
			// 現在行をデリート
			pDoc->DeleteLine( m_idxStartRow );
			// リストへ追加
			pDoc->InsertLinez( m_idxStartRow, lstAddz );

			// 更新通知
			CShitarabianPlugInManager::GetInstance()->OnEdit(
				pDoc
			);
		}

		// キャレット位置の設定
		{
			m_idxEndRow = m_idxStartRow + nLine -1;
			m_idxEndColumn = iNewCaretPosition;
			CCommandCaret	cmdCaret;
			cmdCaret.SetAttribute( 0x00, m_idxEndRow, m_idxEndColumn );
			cmdCaret.Execute( pDoc );
		}

		// 再描画情報更新
		if ( nLine == 1 )
		{
		// 行数変更なし
			pDoc->SetUpdateStartRow( m_idxStartRow );
			pDoc->SetUpdateEndRow(m_idxStartRow );
		}
		else
		{
		// 行数変更あり
			pDoc->SetUpdateStartRow( m_idxStartRow );
			pDoc->SetUpdateEndRow( AllRow );
		}
		return( TRUE );
	}

	return( FALSE );
}


/*-----------------------------------------------------------------------------
[名称]	取り消し
[機能]	文字入力コマンドを取り消す。
[戻値]	BOOL	処理結果 [-] (TURE:成功、FALSE:失敗)
[備考]	Execute()されていること。
-----------------------------------------------------------------------------*/
BOOL		CCommandInput::UnExecute(
	CShitarabianDoc* pDoc		// I  :操作対象ドキュメント [-] (-) :-
)
{
	// Deleteコマンドを利用して削除する
	CCommandDelete	cmdDelete;
	cmdDelete.SetAttribute(
		m_idxStartRow,
		m_idxStartColumn,
		m_idxEndRow,
		m_idxEndColumn
	);
	cmdDelete.Execute( pDoc );

	return( TRUE );
}


/*-----------------------------------------------------------------------------
[名称]	属性設定
[機能]	インスタンスの属性を設定する。
[戻値]	なし
[備考]	Execute()前に必ず行っておくこと。
-----------------------------------------------------------------------------*/
void		CCommandInput::SetAttribute(
	CString		strInput,		// I  :入力された文字列 [-] (-) :-
	long		idxRow,			// I  :入力された位置 [行] (-) :-
	long		idxColumn		// I  :入力された位置 [列] (-) :-
)
{
	m_strInput = strInput;			// 入力された文字列 [-] (-)
	m_idxStartRow = idxRow;			// 入力された位置 [行] (-)
	m_idxStartColumn = idxColumn;	// 入力された位置 [列] (-)

	// 以下はUnExecute用情報。Execute時に有効な値に設定される
	m_idxEndRow = idxRow;			// 入力された位置 [行] (-)
	m_idxEndColumn = idxColumn;		// 入力された位置 [列] (-)
}


