/*-----------------------------------------------------------------------------
[名称]	ShitarabianDoc.cpp
[概要]	ドキュメントクラスの実装
[備考]	なし
[履歴]	2003-03-11	NC		コメント付加	(moralog)
		2003-10-24	b031031 (3199)修正		(dincom)
		2003-11-08	b031130	(3146)読み込み時、オプションを反映(moralog)
		2003-12-06	b031130 (3146)タグジャンプ機能起動時AccessViolation修正(moralog)
		2003-12-20	b031220 (3146)(moralog)
		2004-01-30	b031228 (3367)Grep検索(dincom)
		2004-05-10	b031228 (3751)文書名がショートファイルネームで表示される(moralog)
-----------------------------------------------------------------------------*/


//-----------------------------------------------------------------------------
// インクルード
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "Shitarabian.h"
#include "MainFrm.h"
#include "ShitarabianDoc.h"
#include "CommandDelete.h"
#include "CommandCaret.h"
#include "CommandManager.h"
#include "Selection.h"
#include "BoxSelection.h"
#include "ROISelection.h"
#include "FloatingSelection.h"
#include "ShitarabianView.h"
#include "Common.h"
#include "ShitarabianPlugInManager.h"
#include "DocumentIF.h"
#include "EditDrawer.h"
#include "Unicoder.h"
#include "ExeCommon.h"
#include "SettingPath.h"
#include "EmphasisLine.h"
#include "BackUp.h"
#include "CommandInput.h"
#include "CommandMultiEdit.h"
#include "Padding.h"
#include "EmphasisDefine.h"
#include "GeneralSetting.h"

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

IMPLEMENT_DYNCREATE(CShitarabianDoc, CDocument)

BEGIN_MESSAGE_MAP(CShitarabianDoc, CDocument)
	//{{AFX_MSG_MAP(CShitarabianDoc)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/*-----------------------------------------------------------------------------
[名称]	コンストラクタ
[機能]	インスタンスの生成。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
CShitarabianDoc::CShitarabianDoc()
:	m_lststrEditz()
,	m_idxCaretRow( 0 )
,	m_idxCaretColumn( 0 )
,	m_bOverwrite( FALSE )
,	m_eMode( OperationNormal )
,	m_paIndex( NULL )
,	m_bModified( FALSE )
,	m_idxUpdateStartRow( -1 )
,	m_idxUpdateEndRow( -1 )
,	m_nMark( 0 )
,	m_pviewMain( NULL )
,	m_bNeedBackUp( FALSE )
{
	GetSelection()->Attach( this );
	GetBoxSelection()->Attach( this );
	GetFloatingSelection()->Attach( this );

	m_Interface.Attach( ::AfxGetInstanceHandle() );

	::SetDocument( this );
}


/*-----------------------------------------------------------------------------
[名称]	デストラクタ
[機能]	インスタンスの破棄。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
CShitarabianDoc::~CShitarabianDoc()
{
	if ( m_paIndex != NULL )
	{
		delete m_paIndex;
		m_paIndex = NULL;
	}
}


/*-----------------------------------------------------------------------------
[名称]	「新規」ハンドラ
[機能]	新規ドキュメントの初期化。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CShitarabianDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// テキストの初期化
	m_lststrEditz.RemoveAll();
	CEmphasisLine NewLine;
	NewLine.SetString("");
	m_lststrEditz.AddTail( NewLine );
	m_bModified = TRUE;

	// キャレット位置の初期化
	CCommandCaret	cmdCaret;
	cmdCaret.SetAttribute( 0x00, 0, 0 );
	cmdCaret.Execute( this );

	// Undo履歴の破棄
	CCommandManager::GetInstance()->RemoveAll();

	// 選択状態の初期化
	GetSelection()->SetSelectedNutral();

	// タイトルの設定
	SetTitle( "" );

	// ビューの初期化
	SetMainView( NULL );
	POSITION pos = GetFirstViewPosition();
	if ( pos != NULL )
	{
		SetMainView( (CShitarabianView*)GetNextView(pos) );
		GetMainView()->ResetHScroll();
		GetMainView()->ScrollToCaret();
	} 

	// 更新情報初期化
	SetModifiedFlag( FALSE );
	m_bNeedBackUp = FALSE;

	// 更新通知
	CShitarabianPlugInManager::GetInstance()->OnEdit(
		this
	);
	return TRUE;
}


/*-----------------------------------------------------------------------------
[名称]	保存
[機能]	ドキュメントの書き出し。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianDoc::Write(CArchive& ar)
{
	POSITION	pos;
	pos = m_lststrEditz.GetHeadPosition();
	while( pos != NULL )
	{
		CString&	strLine = *((m_lststrEditz.GetNext( pos )).GetString());
		ar.WriteString( strLine  );

		// 次の行があるなら改行する
		if( pos != NULL )
		{
			ar << (char)0x0D;
			ar << (char)0x0A;
		}
	}
}

/*-----------------------------------------------------------------------------
[名称]	シリアライゼーション
[機能]	ドキュメントの読み込み／書き出し。
[戻値]	なし
[備考]	CDocument::Serialize()のヘルプを参照。
-----------------------------------------------------------------------------*/
void CShitarabianDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// 書き出し
		Write( ar );

		// 更新状態の初期化
		// DeModify() 
		for ( int idxLine=0 ; idxLine<GetLineCount() ; idxLine++ )
		{
			POSITION	pos;
			pos = GetPosition( idxLine );
			if( pos != NULL )
			{
				m_lststrEditz.GetAt( pos ).SetModify( FALSE );
			}
		}
		SetAllUpdate();
		ReDraw();
	}
	else
	{
	// 読み込み

		// 編集データの破棄
		m_lststrEditz.RemoveAll();

		// 拡張子に対応した設定を読み込む
		int	idxSeparater = ar.GetFile()->GetFileName().ReverseFind( '.' );
		if ( idxSeparater > -1 )
		{
// ▼ (3751) BGN 2004.05.10 (moralog) 拡張子取得関数化
			CString strExt = ::ExtFromPathName( ar.GetFile()->GetFileName() );
// ▽ original BGN
//			CString strExt = ar.GetFile()->GetFileName().Mid(
//					idxSeparater+1
//				);
// △ original END
// ▲ (3751) END
			CSettingPath::GetInstance()->PrepareExtFolder( strExt );

			// Drawerにフォント変更通知
			CEditDrawer::GetInstance()->RecalcFontSize();

			// 表示色情報構築
			ReflectEmphasis();
		}

		while( 1 )
		{
			CString	strLine;
			BOOL bExists = ar.ReadString( strLine );

			if ( bExists )
			{
				CEmphasisLine	NewLine;
				NewLine.SetString( strLine );
				NewLine.SetModify( FALSE );
				m_lststrEditz.AddTail( NewLine );
			}
			else
			{
				// もし最後のデータが改行であれば、最後行を追加する
				char*	pstrCRLF = ReturnChar();
				DWORD	dwCRLFLength = strlen( pstrCRLF );

// please! この辺catchすべき
				CFile*	pFile = ar.GetFile();
				if ( pFile->GetLength() >= dwCRLFLength )
				{
					// 最後の改行にシークし
					pFile->Seek( -(int)dwCRLFLength, CFile::end );

					// 読み込んでみる
					char*	pLastChar = new char [ dwCRLFLength ];
					pFile->Read( pLastChar, dwCRLFLength );

					// 本当に改行であれば、最後の行を追加する
					if ( 0 == memcmp( pLastChar, pstrCRLF, dwCRLFLength ) )
					{
						CEmphasisLine	NewLine;
						NewLine.SetString( "" );
						NewLine.SetModify( FALSE );
						m_lststrEditz.AddTail( NewLine );
					}

					delete [] pLastChar;
				}
				break;
			}
		}

		m_bModified = TRUE;

		// 表示色解析
		// 速度を優先するため、複数行表示色の解析のみを行い、
		// まじめな解析は表示時にする。
		AnalizeEmphasisLinez(
			0,
			GetLineCount()-1
		);

		// バックアップ作成
		SetPathName( ar.GetFile()->GetFilePath() );
		CBackUp::GetInstance()->DocumentSave( this );
	}
}


//-----------------------------------------------------------------------------
// 診断
//-----------------------------------------------------------------------------
#ifdef _DEBUG
void CShitarabianDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CShitarabianDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG


/*-----------------------------------------------------------------------------
[名称]	行位置取得
[機能]	指定行のインデクスデータを得る。
[戻値]	POSITION	行位置 [m_lststrEditz内] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
POSITION	CShitarabianDoc::GetPosition(
	long idxRow				// I  :行　[-] (-) :-
)
{
	if ( m_bModified )
	{
		// 必要であれば行インデクスを構築する
		PrepareIndex();
		m_bModified = FALSE;
	}

	if ( idxRow >= 0 )
	if ( m_paIndex != NULL )
	if ( idxRow < m_lststrEditz.GetCount() )
	{
		return( m_paIndex[ idxRow ] );
	}

	return( NULL );
}


/*-----------------------------------------------------------------------------
[名称]	行文字列取得
[機能]	指定行の文字列を得る。
[戻値]	CString*	行文字列 [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
CString*	CShitarabianDoc::GetLine(
	long idxRow				// I  :行　[-] (-) :-
)
{
	POSITION	pos = NULL;
	pos = GetPosition( idxRow );

	if( pos != NULL )
	{
		CString*	pstrLine = m_lststrEditz.GetAt( pos ).GetString();
		return( pstrLine );
	}

	return( NULL );
}


/*-----------------------------------------------------------------------------
[名称]	色付き行取得
[機能]	指定行の情報を得る。
[戻値]	CEmphasisLine*	色付き行 [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
CEmphasisLine*	CShitarabianDoc::GetEmphasisLine(
	long idxRow
)
{
	POSITION	pos = NULL;
	pos = GetPosition( idxRow );

	if( pos != NULL )
	{
		CEmphasisLine&	Line = m_lststrEditz.GetAt( pos );
		return( &Line );
	}

	return( NULL );
}


/*-----------------------------------------------------------------------------
[名称]	行削除
[機能]	指定行を削除する
[戻値]	BOOL	処理結果 [-] (TRUE:成功、FALSE:失敗)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL	CShitarabianDoc::DeleteLine(
	long idxRow				// I  :行 [-] (-) :-
)
{
	POSITION	pos;
	pos = GetPosition( idxRow );
	if( pos != NULL )
	{
		m_lststrEditz.RemoveAt( pos );
		m_bModified = TRUE;
		SetModifiedFlag( TRUE );
		m_bNeedBackUp = TRUE;
		return( TRUE );
	}

	return( FALSE );
}


/*-----------------------------------------------------------------------------
[名称]	範囲行削除
[機能]	指定範囲行を削除する。
[戻値]	BOOL	処理結果 [-] (TRUE:成功、FALSE:失敗)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL	CShitarabianDoc::DeleteLinez(
	long	idxStartRow,		// I  :開始行 [-] (-) :-
	long	nRow				// I  :行数 [-] (-) :-
)
{
	// 行の削除
	{
		POSITION	pos;
		pos = GetPosition( idxStartRow );
		while( pos!=NULL && nRow>0 )
		{
			POSITION	posNext = pos;
			m_lststrEditz.GetNext( posNext );

			m_lststrEditz.RemoveAt( pos );
			m_bModified = TRUE;

			pos = posNext;
			nRow--;
		}
	}

	// 複数行表示色の構築
	// 前の行の繰越を取得、削除後行の先頭と合致しなければ表示色解析初期化
	CEmphasisLine*	pPrevLine = GetEmphasisLine( idxStartRow );
	CEmphasisLine*	pNextLine = GetEmphasisLine( idxStartRow+1 );
	short	idxContinueEmphasis = EMPHASIS_TEXT;
	if ( pPrevLine != NULL )
	{
		idxContinueEmphasis = pPrevLine->GetEmphasisNextContinue();
	}
	if ( pNextLine != NULL )
	{
		if ( idxContinueEmphasis != pNextLine->GetEmphasisPrevRelation() )
		{
			// 表示色解析初期化
			pNextLine->SetEmphasisPrevRelation( idxContinueEmphasis );
			pNextLine->SetMultiLineEmphasisAnalized( FALSE );
			pNextLine->ResetDetailEmphasis();
		}
	}

	SetModifiedFlag( TRUE );
	m_bNeedBackUp = TRUE;
	return( TRUE );
}


/*-----------------------------------------------------------------------------
[名称]	行群挿入
[機能]	行群を挿入する。
[戻値]	BOOL	処理結果 [-] (TRUE:成功、FALSE:失敗)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL	CShitarabianDoc::InsertLinez(
	long idxRow,
	CStringList& lstAddz
)
{
	POSITION	posDst;
	posDst = GetPosition( idxRow );

	POSITION	posSrc;
	posSrc = lstAddz.GetHeadPosition();

	if( posDst == NULL )
	{
		// 文書の末尾に追加
		while( posSrc != NULL )
		{
			InsertLine(
				NULL,
				lstAddz.GetNext( posSrc )
			);
		}
	}
	else
	{
		// 文書の途中に挿入
		while( posSrc != NULL )
		{
			InsertLine(
				posDst,
				lstAddz.GetNext( posSrc )
			);
		}
	}

	// 更新情報設定
	m_bModified = TRUE;
	SetModifiedFlag( TRUE );
	m_bNeedBackUp = TRUE;

	// 表示色解析
	for( int idxLine=0 ; idxLine<lstAddz.GetCount() ; idxLine++ )
	{
		AnalizeMultiLineEmphasis(
			CGeneralSetting::GetInstance()->GetEmphasisDefine(),
			idxRow + idxLine
		);
	}

	return( TRUE );
}


/*-----------------------------------------------------------------------------
[名称]	行挿入
[機能]	行を挿入する。
[戻値]	BOOL	処理結果 [-] (TRUE:成功、FALSE:失敗)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL	CShitarabianDoc::InsertLine(
	POSITION	pos,			// I  :行位置 [-] (-) :-
	CString&	strAdd			// I  :挿入行文字列 [-] (-) :-
)
{
	// 色付き行作成
	CEmphasisLine	Line;
	{
		Line.SetString( strAdd );

		// 表示色解析
		{
			// １行前のリレーション情報を反映
			POSITION	posPrev;
			if( pos == NULL )
			{
				posPrev = m_lststrEditz.GetTailPosition();
			}
			else
			{
				posPrev = pos;
				m_lststrEditz.GetPrev( posPrev );
			}
			if ( posPrev != NULL )
			{
				CEmphasisLine& EmphasisLine = m_lststrEditz.GetAt( posPrev );
				Line.SetEmphasisPrevRelation( EmphasisLine.GetEmphasisNextContinue() );
			}
		}
	}

	// 文書に挿入
	if( pos != NULL )
	{
		m_lststrEditz.InsertBefore( pos, Line );
	}
	else
	{
		m_lststrEditz.AddTail( Line );
	}

	return( TRUE );
}


/*-----------------------------------------------------------------------------
[名称]	選択範囲削除
[機能]	選択範囲を削除する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void	CShitarabianDoc::SelectedDelete()
{
	CSelection*	pSelection = GetSelection();

	if ( pSelection->IsSelected() )
	{
		switch ( GetOperationMode() )
		{
		case OperationBoxSelect:
			GetBoxSelection()->BoxClear();
			break;

		case OperationFloating:
			break;

		case OperationNormal:
		default:
			{
				// Undo履歴の登録
				CCommandDelete	cmdDelete;

				// 選択範囲削除
				cmdDelete.SetAttribute(
					pSelection->GetSelectedStartRow(),
					pSelection->GetSelectedStartColumn(),
					pSelection->GetSelectedEndRow(),
					pSelection->GetSelectedEndColumn()
				);
				cmdDelete.Execute( this );

				CCommandManager*	pCmd = CCommandManager::GetInstance();
				pCmd->Add( cmdDelete );
			}
			break;
		}

		pSelection->SetSelectedNutral();
	}
}


/*-----------------------------------------------------------------------------
[名称]	選択情報取得
[機能]	操作モードに応じた選択情報を取得する。
[戻値]	CSelection*		選択情報 [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
CSelection*		CShitarabianDoc::GetSelection()
{

	switch ( GetOperationMode() )
	{
	case OperationROI:
		return( GetROISelection() );
		break;

	case OperationBoxSelect:
		return( GetBoxSelection() );
		break;

	case OperationFloating:
		return( GetFloatingSelection() );
		break;

	case OperationNormal:
	default:
		return( GetNormalSelection() );
		break;
	}
}


/*-----------------------------------------------------------------------------
[名称]	通常選択情報取得
[機能]	通常選択情報を取得する。
[戻値]	CSelection*		選択情報 [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
CSelection*		CShitarabianDoc::GetNormalSelection()
{
	static CSelection	sNormalSelection;
	return( &sNormalSelection );
}


/*-----------------------------------------------------------------------------
[名称]	ROI選択情報取得
[機能]	ROI選択情報を取得する。
[戻値]	CROISelection*		選択情報 [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
CROISelection*	CShitarabianDoc::GetROISelection()
{
	static CROISelection	sROISelection;

	return( &sROISelection );
}


/*-----------------------------------------------------------------------------
[名称]	Box選択情報取得
[機能]	Box選択情報を取得する。
[戻値]	CBoxSelection*		選択情報 [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
CBoxSelection*	CShitarabianDoc::GetBoxSelection()
{
	static CBoxSelection	sBoxSelection;

	return( &sBoxSelection );
}


/*-----------------------------------------------------------------------------
[名称]	フローティング情報取得
[機能]	フローティング情報を取得する。
[戻値]	CFloatingSelection*		フローティング情報 [-] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
CFloatingSelection*	CShitarabianDoc::GetFloatingSelection()
{
	static CFloatingSelection	sFloatingSelection;

	return( &sFloatingSelection );
}


/*-----------------------------------------------------------------------------
[名称]	「開く」ハンドラ
[機能]	CDocument::OnOpenDocument()のヘルプを参照。
[戻値]	BOOL	処理結果 [-] (TRUE:成功、FALSE:失敗)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CShitarabianDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
	// ファイルの存在確認
	{
		CFileStatus		tStatus;
		BOOL	bExists;
		bExists = CFile::GetStatus(
			lpszPathName,
			tStatus
		);
		if (!bExists) 
		{
			// 存在しなければ警告して読み込まない
			CString	strMsg;
			strMsg = CString("ファイル\n") + lpszPathName + "\nが存在しません。";
			AfxMessageBox( strMsg );
			return( FALSE );
		}
	}

	// あらかじめ行リストを初期化する
	m_lststrEditz.RemoveAll();

	// ▼ (3199) BGN 2003.10.24 (dincom) 共有ファイルを強引に開く
	// ▽ oridinal BGN
	// シリアライズによる読み込み
	//if (!CDocument::OnOpenDocument(lpszPathName))
	//{
		// 読み込みに失敗したら、しょうがないので文書をクリアする
	//	m_lststrEditz.RemoveAll();
	//}
	// △ oridinal END
	if (!OnOpenDocumentCore(lpszPathName))
	{
		// 読み込みに失敗したら、しょうがないので文書をクリアする
		m_lststrEditz.RemoveAll();
	}
	// ▲ (3199) END

	// １行も存在しないのであれば１行作ってやる
	if ( m_lststrEditz.GetCount() == 0 )
	{
		CEmphasisLine	NewLine;
		NewLine.SetString( "" );
		m_lststrEditz.AddTail( NewLine );
	}
	// 更新されたぃょほほほぉ〜ん
	m_bModified = TRUE;

	// 選択状態の初期化
	GetSelection()->SetSelectedNutral();

	// マーキングは解除されている
	m_nMark = 0;

	// キャレット位置の初期化
	CCommandCaret	cmdCaret;
// ▼ (3146) BGN 2003.12.06 (moralog) CMainFrame::OnShowWindow)へ移動
// ▽ oridinal BGN
// ▼ (3146) BGN 2003.11.08 (moralog) 読み込み時、オプションを反映
// ▽ oridinal BGN
	cmdCaret.SetAttribute( 0x00, 0, 0 );
// △ oridinal END
/*
	long	idxRow( 0 );
	long	idxColumn( 0 );
	// ▽ oridinal BGN
	//idxRow = atol(::GetCommandtailOption( ::GetString( IDS_OPTION_ROW ) ));
	// △ oridinal END

	// ▼ (3146) BGN 2003.11.21 (dincom) 最大行を超えない処置
	static BOOL sbFirstOpen = TRUE;

	if ( sbFirstOpen )
	{
		sbFirstOpen = FALSE;

		idxRow = atol(::GetCommandtailOption( ::GetString( IDS_OPTION_ROW ) )) -1;
		if( idxRow > GetLineCount() )
		{
			idxRow = GetLineCount() - 1;
		}
		else if( idxRow < 0 )
		{
			idxRow = 0;
		}
		// ▲ (3146) END
		idxColumn = atol(::GetCommandtailOption( ::GetString( IDS_OPTION_COLUMN ) ));
	}
	cmdCaret.SetAttribute( 0x00, idxRow, idxColumn );
// ▲ (3146) END
*/
// △ oridinal END
// ▲ (3146) END
	cmdCaret.Execute( this );

	// コマンドリストの破棄
	CCommandManager::GetInstance()->RemoveAll();

	SetMainView( NULL );
	POSITION pos = GetFirstViewPosition();
	if ( pos != NULL )
	{
		SetMainView( (CShitarabianView*)GetNextView(pos) );
		GetMainView()->SetPrevVisibleRow(
			0,
			0
		);
		GetMainView()->ResetHScroll();
		GetMainView()->ScrollToCaret();
	}

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

	return TRUE;
}

// ▼ (3199) BGN 2003.11.08 (dincom) 新規追加
/*-----------------------------------------------------------------------------
[名称]	ドキュメントオープン
[機能]	CDocument::OnOpenDocument()のヘルプを参照。
[戻値]	BOOL	処理結果 [-] (TRUE:成功、FALSE:失敗)
[備考]	(3199) 2003-10-24	 関数付加(dincom)
		基底クラスのOnOpenDocumentカスタマイズのため新規追加。
-----------------------------------------------------------------------------*/
BOOL CShitarabianDoc::OnOpenDocumentCore(LPCTSTR lpszPathName)
{
	if (IsModified())
		TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n");

	CFileException fe;
	CFile* pFile = GetFile(lpszPathName,
		CFile::modeRead|CFile::shareDenyWrite, &fe);

	if (pFile == NULL)
	{
		//共有違反でも強引に開く
		if( ::AfxMessageBox( _T("他のアプリケーションで上書きが禁止されています。\n開きますか？") , MB_OKCANCEL ) == IDOK )
		{
			pFile = GetFile( lpszPathName, CFile::modeRead|CFile::shareDenyNone , &fe);
		}
		else
		{
			return FALSE;
		}
	}

	DeleteContents();
	SetModifiedFlag();  // dirty during de-serialize

	CArchive loadArchive(pFile, CArchive::load | CArchive::bNoFlushOnDelete);
	loadArchive.m_pDocument = this;
	loadArchive.m_bForceFlat = FALSE;
	TRY
	{
		CWaitCursor wait;
		if (pFile->GetLength() != 0)
			Serialize(loadArchive);     // load me
		loadArchive.Close();
		ReleaseFile(pFile, FALSE);
	}
	CATCH_ALL(e)
	{
		ReleaseFile(pFile, TRUE);
		DeleteContents();   // remove failed contents

		TRY
		{
			ReportSaveLoadException(lpszPathName, e,
				FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
		}
		END_TRY
		DELETE_EXCEPTION(e);
		return FALSE;
	}
	END_CATCH_ALL

	SetModifiedFlag(FALSE);     // start off with unmodified

	return TRUE;
}
// ▲ (3199) END

/*-----------------------------------------------------------------------------
[名称]	文書名設定
[機能]	ウィンドウタイトルに表示する文書名を設定する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianDoc::SetTitle(
	LPCTSTR lpszTitle		// I  :文書名称 [-] (-)
) 
{
	// warning C4100:警告の無視
	lpszTitle;

	// タイトル表示の設定
	CString		strTitle;
	CString		strFilePath = GetPathName();

// ▼ (3751) BGN 2004.05.10 (moralog) ショートファイルネームをロングファイルネームに変換
	// ショートファイルネームをロングファイルネームに変換
	strFilePath = ::GetLongFilePath( strFilePath );
// ▲ (3751) END

	if ( strFilePath.IsEmpty() )
	{
		strFilePath = _T( "（無題）" );
	}

// ▼ (3751) BGN 2004.05.20 (moralog) フォーカス有無による表示の変化
	// フォーカスが外れたときはファイル名のみ表示する
	if( ::GetMainFrame()->m_hWnd != ::GetForegroundWindow() )
	{
		CString	strName = ::FilenameFromPathName( strFilePath );
		CString	strExt = ::ExtFromPathName( strFilePath );
		if ( !strExt.IsEmpty() )
		{
			strTitle.Format( _T("%s.%s"), strName, strExt );
		}
		else
		{
			strTitle.Format( _T("%s"), strName );
		}
		CDocument::SetTitle( strTitle );
		return;
	}
// ▲ (3751) END

	if ( IsModified() )
	{
		strTitle.Format( _T("%s [更新]"), strFilePath );
	}
	else
	{
		strTitle.Format( _T("%s"), strFilePath );
	}

	CDocument::SetTitle( strTitle );
}


/*-----------------------------------------------------------------------------
[名称]	行インデクスの構築
[機能]	行インデクスの構築をする。
[戻値]	なし
[備考]	リストで保持する行データを、配列イメージでアクセスするために
		インデクス情報を構築する。（←行データへのポインタを配列で持つ）
-----------------------------------------------------------------------------*/
void CShitarabianDoc::PrepareIndex()
{
	if ( m_paIndex != NULL )
	{
		delete m_paIndex;
		m_paIndex = NULL;
	}

	// インデクス用の配列を確保
	long	nRow = m_lststrEditz.GetCount();
	m_paIndex = new POSITION[ nRow ];

	POSITION	pos;
	pos = m_lststrEditz.GetHeadPosition();
	long	idxRow;
	for( idxRow=0 ; idxRow<nRow ; idxRow++ )
	{
		m_paIndex[ idxRow ] = pos;
		m_lststrEditz.GetNext( pos );
	}
}


/*-----------------------------------------------------------------------------
[名称]	再描画
[機能]	再描画処理。
[戻値]	なし
[備考]	更新要求の出ている部分のみ描画する。
-----------------------------------------------------------------------------*/
void CShitarabianDoc::ReDraw(
	CShitarabianView*	pView		// I  :対象ビュー [-] (-) :NULL
)
{
	// タイトル表示の設定
	SetTitle( "" );

	if ( pView == NULL )
	{
		// 全ペイン表示
		CMainFrame*		pFrame = (CMainFrame*)::AfxGetMainWnd();
		if ( pFrame != NULL )
		{
			CSplitterWnd*	pSplitter = pFrame->GetSplitter();

			int	nRow = pSplitter->GetRowCount();
			int	nColumn = pSplitter->GetColumnCount();

			if ( pSplitter != NULL )
			for ( int idxRow=0 ; idxRow<nRow ; idxRow++ )
			for ( int idxColumn=0 ; idxColumn<nColumn ; idxColumn++ )
			{
				CShitarabianView*	pWnd = (CShitarabianView*)(pSplitter->GetPane( idxRow, idxColumn ));
				if ( pWnd != NULL )
				{
					CDC*	pDC = NULL;
					pDC = pWnd->GetDC();	
					pWnd->OnPrepareDC( pDC, NULL );
					pWnd->DrawPage( pDC );
					pWnd->ReleaseDC( pDC );
				}
			}
		}
	}
	else
	{
		CDC*	pDC = NULL;
		pDC = pView->GetDC();	
		pView->OnPrepareDC( pDC, NULL );
		pView->DrawPage( pDC );
		pView->ReleaseDC( pDC );
	}
	m_idxUpdateStartRow = InitialRow;
	m_idxUpdateEndRow = InitialRow;
}


/*-----------------------------------------------------------------------------
[名称]	表示更新開始行設定
[機能]	表示更新開始行の設定。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void	CShitarabianDoc::SetUpdateStartRow(
	long idxUpdateStartRow		// I  :表示更新開始行 [-] (-) :-
)
{
	switch( idxUpdateStartRow )
	{
	case InitialRow:
	case AllRow:
		m_idxUpdateStartRow = idxUpdateStartRow;
		break;

	default:
		if ( m_idxUpdateStartRow != InitialRow )
		{
			if ( idxUpdateStartRow < m_idxUpdateStartRow )
			{
				m_idxUpdateStartRow = idxUpdateStartRow;
			}
			else
			{
				switch( m_idxUpdateEndRow )
				{
				case InitialRow:
				case AllRow:
					break;

				default:
					if ( idxUpdateStartRow > m_idxUpdateEndRow )
					{
						m_idxUpdateEndRow = idxUpdateStartRow;
					}
				}
			}
		}
		else
		{
			m_idxUpdateStartRow = idxUpdateStartRow;
		}
		break;
	}

	POSITION pos = GetFirstViewPosition();
	while (pos != NULL)
	{
		CShitarabianView* pView = (CShitarabianView*)GetNextView(pos);
		pView->SetUpdateStartRow( m_idxUpdateStartRow );
	}
}


/*-----------------------------------------------------------------------------
[名称]	表示更新終了行設定
[機能]	表示更新終了行の設定。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void	CShitarabianDoc::SetUpdateEndRow(
	long idxUpdateEndRow		// I  :表示更新開始行 [-] (-) :-
)
{
	switch( idxUpdateEndRow )
	{
	case InitialRow:
	case AllRow:
		m_idxUpdateEndRow = idxUpdateEndRow;
		break;

	default:
		if ( m_idxUpdateEndRow == AllRow )
		{
			break;
		}

		if ( m_idxUpdateEndRow == InitialRow )
		{
			m_idxUpdateEndRow = idxUpdateEndRow;
			break;
		}

		m_idxUpdateEndRow = max( idxUpdateEndRow, m_idxUpdateEndRow );

		// スタートを改変する必要がある？
		{
			switch( m_idxUpdateStartRow )
			{
			case InitialRow:
			case AllRow:
				break;

			default:
				if ( idxUpdateEndRow < m_idxUpdateStartRow )
				{
					m_idxUpdateStartRow = idxUpdateEndRow;
				}
				break;
			}
		}
		break;
	}

	POSITION pos = GetFirstViewPosition();
	while (pos != NULL)
	{
		CShitarabianView* pView = (CShitarabianView*)GetNextView(pos);
		pView->SetUpdateEndRow( m_idxUpdateEndRow );
	}
}


/*-----------------------------------------------------------------------------
[名称]	更新状態取得
[機能]	更新されたかを得る。
[戻値]	BOOL	更新状態 [-] (TRUE:更新された、FALSE:未更新)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL	CShitarabianDoc::IsModify(
	long idxRow			// I  :行 [-] (-)
)
{
	POSITION	pos;
	pos = GetPosition( idxRow );
	if( pos != NULL )
	{
		return( m_lststrEditz.GetAt( pos ).IsModify() );
	}
	return( FALSE );
}


/*-----------------------------------------------------------------------------
[名称]	マーキングトグル
[機能]	行マークをトグルする。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianDoc::Mark(
	int		idxLine			// I  :行 [-] (-)			  
) 
{
	BOOL	bMarking = !IsMark( idxLine );
	SetMark( idxLine, bMarking );
	SetUpdateStartRow( idxLine );

	if ( bMarking )
	{
		m_nMark ++ ;
	}
	else
	{
		m_nMark -- ;
	}
}


/*-----------------------------------------------------------------------------
[名称]	「次のマーク行へ」
[機能]	次のマーク行へジャンプする。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianDoc::NextMark() 
{
	int		iCurrentRow = GetCaretRow();

	int idxLine;
	for( idxLine=iCurrentRow+1 ; idxLine<GetLineCount() ; idxLine++ )
	{
		if ( IsMark( idxLine ) )
		{
			SetCaretRow( idxLine );
			return;
		}
	}
	for(idxLine=0 ; idxLine<iCurrentRow ; idxLine++ )
	{
		if ( IsMark( idxLine ) )
		{
			SetCaretRow( idxLine );
			return;
		}
	}
}


/*-----------------------------------------------------------------------------
[名称]	「前のマーク行へ」
[機能]	前のマーク行へジャンプする。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianDoc::PrevMark() 
{
	int		iCurrentRow = GetCaretRow();

	int idxLine;
	for( idxLine=iCurrentRow-1 ; idxLine>=0 ; idxLine-- )
	{
		if ( IsMark( idxLine ) )
		{
			SetCaretRow( idxLine );
			return;
		}
	}
	for(idxLine=GetLineCount() ; idxLine>iCurrentRow ; idxLine-- )
	{
		if ( IsMark( idxLine ) )
		{
			SetCaretRow( idxLine );
			return;
		}
	}
}


/*-----------------------------------------------------------------------------
[名称]	「全マーク解除」
[機能]	全マーク行を解除する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianDoc::DeMark() 
{
	int idxLine;
	for( idxLine=0 ; idxLine<GetLineCount() ; idxLine++ )
	{
		SetMark( idxLine, FALSE );
	}

	m_nMark = 0;
}


/*-----------------------------------------------------------------------------
[名称]	マーク設定
[機能]	行のマーク状態を設定する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void	CShitarabianDoc::SetMark(
	long	idxRow,			// I  :行 [-] (-) :-
	BOOL	bMark			// I  :マーク状態 [-] (TRUE:マーク行、FALSE:通常行) :-
){
	POSITION	pos;
	pos = GetPosition( idxRow );
	if( pos != NULL )
	{
		m_lststrEditz.GetAt( pos ).SetMark( bMark );
	}
}

/*-----------------------------------------------------------------------------
[名称]	行マーク取得
[機能]	行のマーク状態を取得する。
[戻値]	BOOL	マーク状態 [-] (TRUE:マーク行、FALSE:通常行)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL	CShitarabianDoc::IsMark(
	long idxRow			// I  :行 [-] (-) :-
)
{
	POSITION	pos;
	pos = GetPosition( idxRow );
	if( pos != NULL )
	{
		return( m_lststrEditz.GetAt( pos ).IsMark() );
	}
	return( FALSE );
}


/*-----------------------------------------------------------------------------
[名称]	「次のマーク行へ」
[機能]	次のマーク行へジャンプする。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianDoc::NextModify() 
{
	int		iCurrentRow = GetCaretRow();

	int idxLine;
	for( idxLine=iCurrentRow+1 ; idxLine<GetLineCount() ; idxLine++ )
	{
		if ( IsModify( idxLine ) )
		{
			SetCaretRow( idxLine );
			return;
		}
	}
	for(idxLine=0 ; idxLine<iCurrentRow ; idxLine++ )
	{
		if ( IsModify( idxLine ) )
		{
			SetCaretRow( idxLine );
			return;
		}
	}
}


/*-----------------------------------------------------------------------------
[名称]	「前のマーク行へ」
[機能]	前のマーク行へジャンプする。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianDoc::PrevModify() 
{
	int		iCurrentRow = GetCaretRow();

	int idxLine;
	for( idxLine=iCurrentRow-1 ; idxLine>=0 ; idxLine-- )
	{
		if ( IsModify( idxLine ) )
		{
			SetCaretRow( idxLine );
			return;
		}
	}
	for(idxLine=GetLineCount() ; idxLine>iCurrentRow ; idxLine-- )
	{
		if ( IsModify( idxLine ) )
		{
			SetCaretRow( idxLine );
			return;
		}
	}
}


/*-----------------------------------------------------------------------------
[名称]	マルチカラム文字を考慮したキャレットカラム位置取得
[機能]	キャレットが置けるカラムを取得する。
[戻値]	long		カラム位置 [キャレットカラム] (-)
[備考]	マルチカラム文字をスキップして、見えるカラム位置を返す。
		idxCaretColumnがマルチカラム文字内であれば、
		マルチカラム文字の直後のカラムを返す。
-----------------------------------------------------------------------------*/
long CShitarabianDoc::MultiColumnSkip(
	long			idxCaretRow,		// I  :行 [-] (-) :-
	long			idxCaretColumn		// I  :カラム [-] (-) :-
)
{
	CUnicoder*	pUnicoder = CUnicoder::GetInstance();
	if ( pUnicoder->GetEnable() )
	{
		// マルチカラムをスキップする
		CEmphasisLine*	pEmphasisLine = GetEmphasisLine( idxCaretRow );
		if ( pEmphasisLine != NULL )
		{
			long	lPixelX = pEmphasisLine->CaretColumnToPixel( idxCaretColumn );
// please! ﾁｮｯﾄ効率が悪い？
			// 表示したときにX座標が変化するカラムを探す
			long	nColumn = pEmphasisLine->GetColumnCount();
			for( idxCaretColumn++ ; idxCaretColumn<=nColumn ; idxCaretColumn++ )
			{
				if ( lPixelX != pEmphasisLine->CaretColumnToPixel( idxCaretColumn ) )
				{
					return( idxCaretColumn-1 );
					break;
				}
			}
			return( nColumn );
		}
		// 指定行が取得できない
		ASSERT( FALSE );
		return( 0 );
	}
	// Unicode表示が有効でないときはマルチカラムが存在しないので何もしない
	return( idxCaretColumn );
}


/*-----------------------------------------------------------------------------
[名称]	表示色解析情報初期化
[機能]	表示色解析情報の初期化。
[戻値]	なし
[備考]	表示色設定が変更されたときに使用する。
-----------------------------------------------------------------------------*/
void CShitarabianDoc::ReflectEmphasis()
{
	// 複数行表示色情報の再構築
	CGeneralSetting::GetInstance()->GetEmphasisDefine()->MultiLineEmphasisStarterPrepare();

	// 行ごとの色情報の初期化
	POSITION	pos;
	pos = m_lststrEditz.GetHeadPosition();
	while( pos != NULL )
	{
		CEmphasisLine&	Line = m_lststrEditz.GetNext( pos );
		Line.ResetWholeEmphasis();
	}	
}


/*-----------------------------------------------------------------------------
[名称]	メインビュー取得
[機能]	メインビューを取得する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
CShitarabianView*	CShitarabianDoc::GetMainView()
{
	// スプリットウィンドウの操作によってViewが失われていた場合、
	// 新しく有効なViewを取得しなおす
	if ( m_pviewMain != NULL )
	if ( !::IsWindow( m_pviewMain->m_hWnd ) )
	{
		SetMainView( NULL );
		POSITION pos = GetFirstViewPosition();
		if ( pos != NULL )
		{
		  SetMainView( (CShitarabianView*)GetNextView(pos) );
		} 
	}
	return( m_pviewMain );
}


/*-----------------------------------------------------------------------------
[名称]	複数行強調表示限定解析
[機能]	複数行強調表示の解析を行い、以降の行に反映する。
[戻値]	BOOL	処理したか [-] (TRUE:した、FALSE:しない)
[備考]	行の追加・編集を行うときにコールすること。
-----------------------------------------------------------------------------*/
BOOL CShitarabianDoc::AnalizeMultiLineEmphasis(
	CEmphasisDefine*	pEmphasisDefine,	// I  :表示色設定情報 [-] (-) :-
	int					iRow				// I  :行 [-] (-) :-
)
{
	// 複数行表示解析を停止のときはスキップ
	if ( !CEmphasisLine::GetAnalizeMultiLineEmphasisEnable() )
	{
		return( TRUE );
	}

	// 行の存在確認
	CEmphasisLine* pLine =GetEmphasisLine( iRow );
	if ( pLine == NULL )
	{
		return( FALSE );
	}

	// 行がすでに解析されていればスキップ
	if ( pLine->GetMultiLineEmphasisAnalized() )
	{
		return( FALSE );
	}

	// この行まで複数行表示色解析が済んでいることが前提
	// 前の行にさかのぼって調べる
	if ( iRow > 0 )
	if ( !GetEmphasisLine( iRow-1 )->GetMultiLineEmphasisAnalized() )
	{
		// デバッグ時に異変を知るためだけのチェック。
		ASSERT( FALSE );
	}

	SetUpdateStartRow( iRow );

	// 複数行表示色解析がすんでいなければ解析する
	BOOL	bContinue = TRUE;
	while( bContinue )
	{
		if ( iRow >= GetLineCount() )
		{
			break;
		}

		// 行の簡易解析（複数行表示色のみ解析）
		if ( GetEmphasisLine( iRow )->GetEmphasisPrevRelation() != EMPHASIS_TEXT )
		{
			// 複数行表示を繰り越している場合は
			// どこで繰越が終わるのか、そして再開するのかわからないので
			// まじめに解析する。
			GetEmphasisLine( iRow )->Analize(
				NULL,
				pEmphasisDefine
			);
		}
		else
		{
			// 繰越でない（テキスト表示色で始まった場合）は
			// 複数行表示が開始するかだけを解析する
			GetEmphasisLine( iRow )->ResetWholeEmphasis();
			GetEmphasisLine( iRow )->AnalizeStringMultiLineEmphasis(
				NULL,
				pEmphasisDefine
			);
		}

		// 複数行表示判定完了
		GetEmphasisLine( iRow )->SetMultiLineEmphasisAnalized( TRUE );

		// 複数行強調表示設定を次の行以降に反映する
		short	iNextContinue = GetEmphasisLine( iRow )->GetEmphasisNextContinue();

		if ( !pEmphasisDefine->GetItemz()[ iNextContinue ].GetTerminator().IsEmpty() )
		{
			// 複数行強調表示が発生したので、以降の行に適用する
			int		idxRelationRow;
			for( idxRelationRow=iRow+1 ; idxRelationRow<GetLineCount() ; idxRelationRow++ )
			{
				// 繰越表示設定が
				// 「前の行からの強調表示繰越」に合致する行が見つかるまで探索を行う
				if( GetEmphasisLine( idxRelationRow )->GetEmphasisPrevRelation()
					== iNextContinue
				)
				{
					// 「前の行からの強調表示繰越」が
					// 求める繰越表示設定と同じなので改めて解析する必要がない
					bContinue = FALSE;
					break;
				}
				else
				{
					GetEmphasisLine( idxRelationRow )->SetEmphasisPrevRelation( iNextContinue );

					// 繰越表示設定の終端を検索
					int	idxTerminator = GetEmphasisLine( idxRelationRow )->SerchEmphasisTerminator(
						pEmphasisDefine,
						iNextContinue
					);

					if( idxTerminator > 0 )
					{
						// 終端が見つかったので繰越はこの行で終了。
						// しかし、この行に複数行表示色の開始がないか新たに複数行表示色解析をする必要がある。
						GetEmphasisLine( idxRelationRow )->SetMultiLineEmphasisAnalized( FALSE );
						break;
					}
					// 次の行を検索する必要アリ
					GetEmphasisLine( idxRelationRow )->SetEmphasisNextContinue( iNextContinue );
				}

				GetEmphasisLine( idxRelationRow )->ResetDetailEmphasis();
				GetEmphasisLine( idxRelationRow )->SetMultiLineEmphasisAnalized( TRUE );
			}
			iRow = idxRelationRow;
		}
		else
		{
			// 複数行強調表示が発生しなかったので、以降の行の繰越を解除する
			int		idxRelationRow;
			for( idxRelationRow=iRow+1 ; idxRelationRow<GetLineCount() ; idxRelationRow++ )
			{
				if( GetEmphasisLine( idxRelationRow )->GetEmphasisPrevRelation()
					== EMPHASIS_TEXT
				)
				{
					// もともと繰り越していない行を発見したので
					// 以降の行について処理する必要はない
					bContinue = FALSE;
					break;
				}
				else	
				{
					// 繰越を解除して、ふつーのテキスト表示色で開始する行とする
					GetEmphasisLine( idxRelationRow )->SetEmphasisPrevRelation( EMPHASIS_TEXT );
					// しかし、新たにこの行の複数行表示色解析をする必要がある。
					GetEmphasisLine( idxRelationRow )->ResetWholeEmphasis();
					GetEmphasisLine( idxRelationRow )->SetMultiLineEmphasisAnalized( TRUE );
					break;
				}
			}
			iRow = idxRelationRow;
		}
	}
	SetUpdateEndRow( iRow );

	return( TRUE );
}


/*-----------------------------------------------------------------------------
[名称]	表示色解析詳細情報の初期化
[機能]	表示色解析詳細情報を初期化する。
[戻値]	なし
[備考]	表示色設定情報の一部が変更されたときに表示色解析の再処理のために使用する。
		検索文字列が変更されたとき。
-----------------------------------------------------------------------------*/
void CShitarabianDoc::UpdateEmphasis()
{
	// 行ごとの色情報の初期化
	POSITION	pos;
	pos = m_lststrEditz.GetHeadPosition();
	while( pos != NULL )
	{
		CEmphasisLine&	Line = m_lststrEditz.GetNext( pos );
		Line.ResetDetailEmphasis();
	}	
}


/*-----------------------------------------------------------------------------
[名称]	表示色解析
[機能]	指定行の表示色解析を行う。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianDoc::AnalizeEmphasisLinez(
	const long	idxStart,		// I  :開始行 [-] (-) :-
	const long	idxEnd			// I  :終了行 [-] (-) :-
)
{
	CMainFrame*		pFrame = (CMainFrame*)::AfxGetMainWnd();
	CProgressDlg*	pProgress = pFrame->GetProgressDlg();
	
	// ▼ (3367) BGN 2004.02.03 (dincom) XPでファイル名指定起動後、終了時にAccessViolation修正
	if ( pProgress != NULL )
	{
		pProgress->Run();
		pProgress->Show();
	}
	// ▲ (3367) END

	int		idxLine;
	for( idxLine=idxStart ; idxLine<=idxEnd ; idxLine++ )
	{
		// まず、いまある複数行表示色情報を無効にする
		CEmphasisLine*	pLine = GetEmphasisLine( idxLine );
		if ( pLine != NULL )
		{
			pLine->SetMultiLineEmphasisAnalized( FALSE );
		}
	}

	// 繰越表示色の再構築
	for( idxLine=idxStart; idxLine<idxEnd ; idxLine++ )
	{
		pProgress->NotifyProgress( (idxLine*100)/(idxEnd-idxStart+1) );

		AnalizeMultiLineEmphasis(
			CGeneralSetting::GetInstance()->GetEmphasisDefine(),
			idxLine
		);
	}

	// ▼ (3367) BGN 2003.02.03 (dincom) XPでファイル名指定起動後、終了時にAccessViolation修正
	if ( pProgress != NULL )
	// ▲ (3367) END
	{	
		pProgress->Hide();
	}
}

/*-----------------------------------------------------------------------------
[名称]	表示色解析
[機能]	指定行の表示色解析を行う。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianDoc::AnalizeEmphasisLinez(
	const CDWordArray& adwLinez		// I  :行群 [-] (-) :-
)
{
	CMainFrame*		pFrame = (CMainFrame*)::AfxGetMainWnd();
	CProgressDlg*	pProgress = pFrame->GetProgressDlg();
	
	// ▼ (3367) BGN 2004.02.03 (dincom) XPでファイル名指定起動後、終了時にAccessViolation修正
	if ( pProgress != NULL )
	{
		pProgress->Run();
		pProgress->Show();
	}
	// ▲ (3367) END

	int		idxLine;
	for( idxLine=0 ; idxLine<adwLinez.GetSize() ; idxLine++ )
	{
		// まず、いまある複数行表示色情報を無効にする
		CEmphasisLine*	pLine = GetEmphasisLine( adwLinez[idxLine] );
		if ( pLine != NULL )
		{
			pLine->SetMultiLineEmphasisAnalized( FALSE );
		}
		else
		{
			TRACE( "%d\n",adwLinez[idxLine]);
			ASSERT( FALSE );
		}
	}

	// 繰越表示色の再構築
	for( idxLine=0 ; idxLine<adwLinez.GetSize() ; idxLine++ )
	{
		pProgress->NotifyProgress( (idxLine*100)/adwLinez.GetSize() );

		AnalizeMultiLineEmphasis(
			CGeneralSetting::GetInstance()->GetEmphasisDefine(),
			adwLinez[idxLine]
		);
	}

	// ▼ (3367) BGN 2004.02.03 (dincom) XPでファイル名指定起動後、終了時にAccessViolation修正
	if ( pProgress != NULL )
	// ▲ (3367) END
	{
		pProgress->Hide();
	}
}


/*-----------------------------------------------------------------------------
[名称]	行の拡張
[機能]	指定位置まで行を拡張する。
[戻値]	なし
[備考]	フリーカーソルモード用。
-----------------------------------------------------------------------------*/
void CShitarabianDoc::AppendRow(
	long		idxRow		// I  :行 [-] (-) :-
)
{
	// 行が存在しなければそこまで作る
	if ( idxRow >= GetLineCount() )
	{
		// 末尾に行を挿入
		int nRow = GetLineCount()-1;
		int nColumn = GetEmphasisLine(nRow)->GetColumnCount();

		CString		strAdd;
		long	idxLine;
		for( idxLine=0 ; idxLine<idxRow-nRow ; idxLine++ )
		{
			strAdd += ReturnChar();
		}

		// 行を追加
		CCommandInput		cmdInput;
		CCommandManager*	pCmd = CCommandManager::GetInstance();
		cmdInput.SetAttribute( strAdd, nRow, nColumn );
		cmdInput.Execute( this );
		pCmd->Add( cmdInput );
	}
}

/*-----------------------------------------------------------------------------
[名称]	カラムの拡張
[機能]	指定位置までカラムを拡張する。
[戻値]	なし
[備考]	フリーカーソルモード用。
-----------------------------------------------------------------------------*/
void CShitarabianDoc::AppendColumn(
	long		idxRow,			// I  :行 [-] (-) :-
	long		lXColummn		// I  :カラム位置 [pixel] (-) :-
)
{
	CDC*		pDC = NULL;
	pDC = GetMainView()->GetDC();
	if ( pDC != NULL )
	{
	// カラムが足りなければカラムを作る
		CString		strPad;
		CEmphasisLine*	pEmphasisLine = GetEmphasisLine( idxRow );
		if ( pEmphasisLine != NULL )
		{
			int		iBlankStartX;
			int		iBlankStartColumn;
			CEmphasisLine*	pEmphasisLine = GetEmphasisLine( idxRow );
			// 選択行の空白開始位置を探す
			{
				CWhitespaceDefine*	pWhitespace = CGeneralSetting::GetInstance()->GetWhitespace();
				CArray<TWhiteSpace, TWhiteSpace&>*	paCharz = pWhitespace->GetCharz();

				// 挿入座標のキャレット位置取得
				if ( pEmphasisLine != NULL )
				{
					// そこから左へ走査。前半パディング開始カラム捜索。
					CPadding	Padding;
					iBlankStartColumn = Padding.PrevWhiteSpaceColumn(
						*(::GetDocument()->GetLine( idxRow )),
						pEmphasisLine->GetColumnCount(),
						*paCharz
					);
					iBlankStartX = pEmphasisLine->CaretColumnToPixel(
						iBlankStartColumn
					);
				}
				else
				{
					// 存在しない行に対してはパディングできないにょ
					ASSERT( FALSE );
					return;
				}
			}

			long	lNewLength = max( 0, lXColummn );
			if ( iBlankStartX < lNewLength )
			{
				CPadding	Padding;
				long	iGap;
				iGap = Padding.Padding(
					pDC,
					lNewLength - iBlankStartX,
					strPad,
					*( CGeneralSetting::GetInstance()->GetWhitespace()->GetCharz() ),
					TRUE
				);

				// 行の更新
				{
					CCommandMultiEdit		cmdEdit;

					// 行の内容を削除
					if (pEmphasisLine->GetColumnCount() > 0 )
					{
						CCommandDelete	cmdDelete;
						cmdDelete.SetAttribute(
							idxRow,
							iBlankStartColumn,
							idxRow,
							pEmphasisLine->GetColumnCount()
						);
						cmdEdit.Add( cmdDelete );
					}

					// 選択位置に文字列挿入
					CCommandInput	cmdInput;
					cmdInput.SetAttribute(
						strPad,
						idxRow,
						GetEmphasisLine(idxRow)->GetColumnCount()
					);
					cmdEdit.Add( cmdInput );

					cmdEdit.Execute( this );
					CCommandManager*	pCmd = CCommandManager::GetInstance();
					pCmd->Add( cmdEdit );
				}
			}
		}
	}
	GetMainView()->ReleaseDC( pDC );
}