// ★コメント未記入
// Line.cpp: CLine クラスのインプリメンテーション
//
//		2004-05-27 (3344)	共通設定のユニコード文字で追加のボタンを押すと強制終了(moralog)
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "shitarabian.h"
#include "EmphasisLine.h"
#include "EmphasisDefine.h"
#include "FinderVBScript.h"
#include "EditDrawer.h"
#include "Unicoder.h"
#include "GeneralSetting.h"
#include "Selection.h"
#include "ExeCommon.h"
#include "MainFrm.h"

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


BOOL	CEmphasisLine::m_bEmphasisAnalizeEnable = TRUE;


//////////////////////////////////////////////////////////////////////
// 構築/消滅
//////////////////////////////////////////////////////////////////////

CEmphasisLine::CEmphasisLine()
:	m_strLine()					// 行文字列
,	m_bMark( FALSE )			// マーク有無
,	m_bModify( FALSE )			// 更新有無
,	m_bInitialized( FALSE )		// 情報取得済みフラグ
,	m_lAllWidth( 0 )
,	m_nColumn( 0 )
,	m_listCharz()				// 強調表示文字情報リスト
,	m_idxPrevRelationEmphasis( EMPHASIS_TEXT )		// 和えの行から連結する強調表示
,	m_idxNextContinueEmphasis( EMPHASIS_TEXT )		// 次の行へ連結する強調表示
,	m_bMultiLineEmphasisAnalized( FALSE )
{

}

CEmphasisLine::~CEmphasisLine()
{

}

void CEmphasisLine::SetString( const char* pstrSrc )
{
	m_strLine = pstrSrc;
	m_bModify = TRUE;
	ResetDetailEmphasis();
}


// 表示設定すべての初期化
void CEmphasisLine::ResetWholeEmphasis()
{
	m_bMultiLineEmphasisAnalized = FALSE;
	m_idxPrevRelationEmphasis = EMPHASIS_TEXT;
	m_idxNextContinueEmphasis = EMPHASIS_TEXT;

	ResetDetailEmphasis();
}

// 表示設定詳細（複数行表示色繰越設定以外）の初期化
void CEmphasisLine::ResetDetailEmphasis()
{
	m_bInitialized = FALSE;
	m_lAllWidth = 0;
	m_nColumn = 0;
	m_listCharz.RemoveAll();
}



// 戻り値 処理したか。
BOOL CEmphasisLine::Analize()
{
	if ( m_bInitialized )
	{
		return( FALSE );
	}

	HDC	hdc = ::GetDC( NULL );
	CDC*	pDC = CDC::FromHandle( hdc );

	// 複数行強調表示の解析
	AnalizeStringMultiLineEmphasis(
		pDC,
		CGeneralSetting::GetInstance()->GetEmphasisDefine()
	);

	BOOL	bProcess = Analize(
		pDC,
		CGeneralSetting::GetInstance()->GetEmphasisDefine()
	);

	::ReleaseDC( NULL, hdc );

	return( bProcess );
}



// 戻り値 処理したか。

/*-----------------------------------------------------------------------------
[名称]	表示色解析
[機能]	表示色解析を行って表示できる状態にする。
[戻値]	BOOL	処理結果 [-] (TRUE:成功、FALSE:失敗)
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CEmphasisLine::Analize(
	CDC*				pDstDC,				// I: 出力先DC [-] (-) :-
	CEmphasisDefine*	pEmphasisDefine		// I: 表示色設定 [-] (-) :-
)
{
	// 表示色解析がすんでいなければ解析する
	if ( !m_bInitialized )
	{
		AnalizeString(
			pDstDC,
			pEmphasisDefine
		);
	}
	return( TRUE );
}


BOOL CEmphasisLine::Copy( CEmphasisLine& Src )
{
	m_strLine	= Src.m_strLine;		// 行文字列
	m_bMark		= Src.m_bMark;		// マーク有無
	m_bModify	= Src.m_bModify;		// 更新有無


	m_idxPrevRelationEmphasis = Src.m_idxPrevRelationEmphasis;	// 強調表示種類
	m_idxNextContinueEmphasis = Src.m_idxNextContinueEmphasis;	// 強調表示種類

	m_bInitialized	= Src.m_bInitialized;				// 情報取得済みフラグ

	m_listCharz.RemoveAll();
	m_listCharz.AddTail( &Src.m_listCharz );			// 強調表示文字情報リスト

	return( TRUE );
}


void	CEmphasisLine::SetEmphasisPrevRelation(
	short idxPrevRelationEmphasis
)
{
	m_idxPrevRelationEmphasis = idxPrevRelationEmphasis;
	m_idxNextContinueEmphasis = idxPrevRelationEmphasis;
	ResetDetailEmphasis();
}






// 文字列の文字位置→ピクセル
long CEmphasisLine::CaretColumnToPixel(
	long			idxTargetChar
)
{
	// 表示情報が構築されていなければする
	Analize();

	long		idxChar = 0;
	long		lSizeX = 0;
	POSITION	pos = m_listCharz.GetHeadPosition();
	while( pos != NULL )
	{
		if( idxChar >= idxTargetChar )
		{
			break;
		}
		TEmphasisChar&	tChar = m_listCharz.GetNext( pos );
		lSizeX += tChar.iWidth;
		idxChar += tChar.nColumn;
	}

	return( lSizeX );
}

long CEmphasisLine::CaretColumnToPixelZoomed(
	long			idxTargetChar
)
{
	int	lSizeX = CaretColumnToPixel( idxTargetChar );
	CEditDrawer*	pDrawer = CEditDrawer::GetInstance();
	return( pDrawer->PixelToZoomedPixel( lSizeX ) );
}

// ピクセル→文字列の文字位置
long CEmphasisLine::PixelToCaretColumnZoomed(
	long			iX,
	BOOL			bAbsolute	// 文字上のＸ前半後半を判定に加味しない　[-] (TRUE:しない、FALSE:する) :FALSE
)
{
	CEditDrawer*	pDrawer = CEditDrawer::GetInstance();
	long	iColumn = PixelToCaretColumn(
		pDrawer->ZoomedPixelToPixel( iX ) ,
		bAbsolute
	);
	return( iColumn );
}

long CEmphasisLine::CaretColumnToWindowPixelZoomed(
	long	idxChar
)
{
	int	lSizeX = CaretColumnToPixelZoomed( idxChar );

	long	lLeftMargin;
	lLeftMargin = CGeneralSetting::GetInstance()->GetLeftMargin();

	return( lSizeX + lLeftMargin );
}

// ピクセル→文字列の文字位置
long CEmphasisLine::PixelToCaretColumn(
	long	iX,
	BOOL	bAbsolute	// 文字上のＸ前半後半を判定に加味しない　[-] (TRUE:しない、FALSE:する) :FALSE
)
{
	// 表示情報が構築されていなければする
	Analize();

	long	idxCaretColumn = 0;
	POSITION	pos = m_listCharz.GetHeadPosition();
	while( pos != NULL )
	{
		TEmphasisChar&	tChar = m_listCharz.GetNext( pos );

		// 終了検査
		if ( iX <= tChar.iWidth )
		{
			// 文字の前半なら文字の前、文字の後半なら文字の後ろを採用する。
			if ( !bAbsolute )
			if ( iX > ((double)tChar.iWidth/2) )
			{
				idxCaretColumn += tChar.nColumn;
			}
			break;
		}
		iX -= tChar.iWidth;
		idxCaretColumn += tChar.nColumn;
	}
	return( idxCaretColumn );
}



long CEmphasisLine::GetColumnCount()
{
	// 表示情報が構築されていなければする
	Analize();
	return( m_nColumn );
}






// ★
/*-----------------------------------------------------------------------------
[名称]	繰越表示文字終端検索
[機能]	繰越表示設定の終端を検索する。
[戻値]	int		終端文字終了位置 [カラム] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
int	CEmphasisLine::SerchEmphasisTerminator(
//	const char*			pstrSrc,			// 行文字列 [-] (-)
	CEmphasisDefine*	pEmphasisDefine,	// 表示色設定 [-] (-)
	short				iContinueEmphasis	// 繰越表示色 [インデクス] (-)
){
	// 強調表示設定取得
	CArray<CEmphasisItem, CEmphasisItem&>&	aEmphasisz = pEmphasisDefine->GetItemz();

	CString		strTerminator( aEmphasisz[ iContinueEmphasis ].GetTerminator() );
	if ( !strTerminator.IsEmpty() )
	{
		TMatch	Match;
		CFinder*	pFinder = ::GetFinder( aEmphasisz[ iContinueEmphasis ].GetFindCondition()->bRegExp );
		BOOL bFound = pFinder->QuickMatch(
			(LPCTSTR)m_strLine,
			strTerminator,
			&Match,
			aEmphasisz[ iContinueEmphasis ].GetFindCondition()->bCaseCare,
			aEmphasisz[ iContinueEmphasis ].GetFindCondition()->bToken
		);

		int		iRelatedColumn;
		if ( bFound )
		{
			iRelatedColumn = Match.idxStartColumn + Match.nColumn;
		}
		else
		{
			iRelatedColumn = -1;
		}
		return( iRelatedColumn );
	}

	
/*
	// 強調表示設定取得
	CArray<CEmphasisItem, CEmphasisItem&>&	aEmphasisz = pEmphasisDefine->GetItemz();

	CString		strTerminator( aEmphasisz[ iContinueEmphasis ].GetTerminator() );
	if ( !strTerminator.IsEmpty() )
	{
		CArray< TMatch, TMatch& > aMatchz;
		CFinderVBScript		Finder;
//		CString	strSrc( pstrSrc );
		Finder.GetMatchz(
			m_strLine,
			strTerminator,
			&aMatchz,
			TRUE,
			FALSE
		);

		int		iRelatedColumn;
		if ( aMatchz.GetSize() > 0 )
		{
			iRelatedColumn = aMatchz[0].idxStartColumn + aMatchz[0].nColumn;
		}
		else
		{
			iRelatedColumn = -1;
		}
		return( iRelatedColumn );
	}
*/
	return( 0 );
}


// ★
/*-----------------------------------------------------------------------------
[名称]	複数行強調表示のみ表示色解析（文字列）
[機能]	簡易表示色解析。
		高速化のため複数行強調表示色のみ解析を行う。行の表示色繰越を設定する。
[戻値]	BOOL	処理結果 [-] (TRUE:成功、FALSE:失敗)
[備考]	文字列追加処理から
		AnalizeStringMultiLineEmphasis() を経由して呼ばれる。
-----------------------------------------------------------------------------*/
BOOL CEmphasisLine::AnalizeStringMultiLineEmphasis(
	CDC*				pDstDC,				// I: 出力先DC [-] (-) :-
	CEmphasisDefine*	pEmphasisDefine		// I: 表示色設定 [-] (-) :-
)
{
// ▼ (ワーニング回避) BGN 2003.12.29 (moralog) warning C4100
	// warning C4100 回避
	pDstDC;
// ▲ (ワーニング回避) END

	if ( !m_bEmphasisAnalizeEnable )
	{
		return( TRUE );
	}

	// 複数行強調表示の始端を検索する
	BOOL	bFound = FALSE;
	{

		// 正規表現ものについて検索する
		{
			// 強調表示設定から複数行強調表示の検索対象を得る
			CString&	strPattern = pEmphasisDefine->GetMultiLineEmphasisStarterRegExp();
			if( !strPattern.IsEmpty() )
			{
				// 始端を検索する
				CArray< TMatch, TMatch& > aMatchz;
				CFinder*	pFinder = ::GetFinder( TRUE );
				if( pFinder != NULL )
				{
					int		nMatch = pFinder->GetMatchz(
						m_strLine,
						strPattern,
						&aMatchz,
						TRUE, //aEmphasisz[ idxEmphasis ].GetFindCondition()->bCaseCare,	// bCaseCare
						FALSE //aEmphasisz[ idxEmphasis ].GetFindCondition()->bToken		// bToken
					);
					// １つでもマッチすれば発見として終了
					if ( nMatch > 0 )
					{
						// 始端が存在することはわかったが
						// その始端は他の強調表示に打ち消されている場合があるので
						// まじめに解析する必要がある
						//    // /*   ←たとえばこういう場合は/*は無効。
						bFound = TRUE;
					}
				}
			}
		}

		// 正規表現でないものについて検索する
		if( !bFound )
		if ( pEmphasisDefine->IsMultiLineEmphasisStarterNormalExist() )
		{
			// 強調表示設定取得
			CArray<CEmphasisItem, CEmphasisItem&>&	aEmphasisz = pEmphasisDefine->GetItemz();

			// 強調表示設定から複数行強調表示のもののみ検索する
			int		idxEmphasis;
			for( idxEmphasis=EMPHASIS_NEEDCOLORINGITEM ; idxEmphasis<aEmphasisz.GetSize() ; idxEmphasis++ )
			if ( !aEmphasisz[ idxEmphasis ].GetFindCondition()->bRegExp )
			if( aEmphasisz[ idxEmphasis ].GetEnable() )					// 定義が有効
			if( !aEmphasisz[ idxEmphasis ].GetTerminator().IsEmpty() )	// 終端がある == 複数行強調表示
			{
				CString	strPattern( aEmphasisz[ idxEmphasis ].GetPattern() );
				if( !strPattern.IsEmpty() )
				{
					// 始端を検索する
					CArray< TMatch, TMatch& > aMatchz;
					CFinder*	pFinder = ::GetFinder( FALSE );
					int		nMatch = pFinder->GetMatchz(
						m_strLine,
						strPattern,
						&aMatchz,
						aEmphasisz[ idxEmphasis ].GetFindCondition()->bCaseCare,	// bCaseCare
						aEmphasisz[ idxEmphasis ].GetFindCondition()->bToken		// bToken
					);
					// １つでもマッチすれば発見として終了
					if ( nMatch > 0 )
					{
						// 始端が存在することはわかったが
						// その始端は他の強調表示に打ち消されている場合があるので
						// まじめに解析する必要がある
						//    // /*   ←たとえばこういう場合は/*は無効。
						bFound = TRUE;
					}
				}
			}
		}
	}

	// 行中に複数行強調表示の始端が存在するならまじめに解析する
	if( bFound )
	{
		HDC	hdc = ::GetDC( NULL );
		CDC*	pDC = CDC::FromHandle( hdc );

		Analize(
			pDC,
			CGeneralSetting::GetInstance()->GetEmphasisDefine()
		);

		::ReleaseDC( NULL, hdc );
	}
	else
	{
		// 複数行強調表示の始端が存在しなかったので
		// 開始色と同じ色で終了するかも
		SetEmphasisNextContinue( GetEmphasisPrevRelation() );
	}

	return( TRUE );
}















// ==========================================================
// 03.02.24







/*-----------------------------------------------------------------------------
[名称]	描画
[機能]	文字列の強調表示あり描画処理。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CEmphasisLine::Draw(
	CDC*				pDstDC,
	long				lStartX,			// I  :DC上の開始位置 [-] (-) :-
	long				lStartY,			// I  :DC上の開始位置 [-] (-) :-
	int					iLeftX,				// I  :DC上の描画必要開始座標 [-] (-) :-
	int					iWidthX,			// I  :DC上の描画必要幅 [-] (-) :-
	BOOL				bCareEmphasis,		// I  :強調表示有無 [-] (TRUE:有、FALSE:無) :-
	CEmphasisDefine*	pEmphasisDefine,	// I  :強調表示定義 [-] (-) :-
	BOOL				bCareSelection,		// I  :選択表示有無 [-] (TRUE:有、FALSE:無) :-
	CShitarabianDoc*	pDoc,				// I  :ﾄﾞｷｭﾒﾝﾄ [-] (-) :-
	int					iRow				// I  :行 [-] (-) :-
)
{
// ▼ (ワーニング回避) BGN 2003.12.29 (moralog) warning C4100
	// warning C4100 回避
	iLeftX;
// ▲ (ワーニング回避) END

	// コーディングエラーチェック
	{
		// 更新領域未設定で呼ばれてしまう場合を検出してみる
		// 更新領域を SetUpdateRect() で正しく設定する必要がある。
		ASSERT( iWidthX != 0 );
	}

	// warning C4100:警告の無視
	bCareEmphasis;

	// 表示色解析がすんでいなければ解析する
	Analize(
		pDstDC,
		pEmphasisDefine
	);

	COLORREF	colBackNatural = ::GetBackColor( EMPHASIS_TEXT );
	COLORREF	colForeSelect = ::GetForeColor( EMPHASIS_SELECTED );
	COLORREF	colBackSelect = ::GetBackColor( EMPHASIS_SELECTED );

	long		lX;
	int			idxColumn;
	BOOL		bContinue;
	POSITION	pos;

	CEditDrawer*	pDrawer = CEditDrawer::GetInstance();
	TEmphasisChar	tEOFChar = { TypeEOF, 0x00, 0x00, EMPHASIS_EOF, (USHORT)pDrawer->GetEOFWidth(), 0,0,FALSE };
	TEmphasisChar	tEOLChar = { TypeEOL, 0x00, 0x00, EMPHASIS_CRLF, (USHORT)pDrawer->GetBlankWidth(), 0,0,FALSE };

	// 背景塗りつぶし
	lX = lStartX;
	idxColumn = 0;
	pos = m_listCharz.GetHeadPosition();
	bContinue = TRUE;
	while( bContinue )
	{
		bContinue = ( pos != NULL );

		TEmphasisChar*	pChar;
		if ( pos != NULL )
		{
			pChar = &(m_listCharz.GetNext( pos ));
		}
		else
		{
			if ( iRow == pDoc->GetLineCount()-1 )
			{
				if ( !CGeneralSetting::GetInstance()->GetEmphasisDefine()->GetItemz()[EMPHASIS_EOF].GetEnable() )
				{
					break;
				}
				pChar = &tEOFChar;
			}
			else
			{
				if ( !CGeneralSetting::GetInstance()->GetEmphasisDefine()->GetItemz()[EMPHASIS_CRLF].GetEnable() )
				{
					break;
				}
				pChar = &tEOLChar;
			}
		}
		TEmphasisChar&	tChar = *pChar;

		// 描画要求範囲であれば描画する
		if ( lX+tChar.iWidth >= 0 )
		{
			BOOL	bSelection = FALSE;
			if ( bCareSelection )
			if ( pDoc != NULL )
			{
				bSelection = pDoc->GetSelection()->IsSelected( iRow, idxColumn );
			}

			if ( bSelection )
			{
				pDstDC->FillSolidRect(
					lX,
					lStartY,
					tChar.iWidth,
					pDrawer->GetBlankHeight(),
					colBackSelect
				);
			}
			else
			{
				// 標準の背景色は壁紙表示のためヌキ色とする。
				// 標準の背景色でないときだけ塗りつぶす。
				COLORREF	colBack = pEmphasisDefine->GetItemz()[ tChar.idxEmphasis ].GetBackColor();
				if ( colBackNatural != colBack )
				{
					pDstDC->FillSolidRect(
						lX,
						lStartY,
						tChar.iWidth,
						pDrawer->GetBlankHeight(),
						colBack
					);
				}
			}
		}
		lX += tChar.iWidth;
		idxColumn += tChar.nColumn;

		// 描画要求範囲を描画し終えたら抜ける
		if ( lX > iWidthX )
		{
			break;
		}
	}

	// 文字描画
	long	idxByte = 0;
	lX = lStartX;
	idxColumn = 0;
	pos = m_listCharz.GetHeadPosition();

	pDstDC->SetBkMode( TRANSPARENT );
	pDrawer->ReflectFont( pDstDC );
	BOOL	bUnderLineEmphasis = FALSE;

	bContinue = TRUE;
	while( bContinue )
	{
		bContinue = ( pos != NULL );

		TEmphasisChar*	pChar;
		if ( pos != NULL )
		{
			pChar = &(m_listCharz.GetNext( pos ));
		}
		else
		{
			if ( iRow == pDoc->GetLineCount()-1 )
			{
				if ( !CGeneralSetting::GetInstance()->GetEmphasisDefine()->GetItemz()[EMPHASIS_EOF].GetEnable() )
				{
					break;
				}
				pChar = &tEOFChar;
			}
			else
			{
				if ( !CGeneralSetting::GetInstance()->GetEmphasisDefine()->GetItemz()[EMPHASIS_CRLF].GetEnable() )
				{
					break;
				}
				pChar = &tEOLChar;
			}
		}
		TEmphasisChar&	tChar = *pChar;

		// フォント設定が異なるのであればフォントを設定しなおす
		BOOL bUnderLine = pEmphasisDefine->GetItemz()[tChar.idxEmphasis].GetUnderLine();
		if ( bUnderLine != bUnderLineEmphasis )
		{
			// フォント設定解除
			pDrawer->RestoreFont( pDstDC );

			// UnderLineを設定してフォント設定
			CGeneralSetting::GetInstance()->GetLogFont()->m_bUnderLine = bUnderLine;
			pDrawer->ReflectFont( pDstDC );

			// UnderLine状態を記録
			bUnderLineEmphasis = bUnderLine;
		}

		// 描画要求範囲であれば描画する
		if ( lX+tChar.iWidth >= 0 )
		{
			// 選択状態？
			BOOL	bSelection = FALSE;
			if ( bCareSelection )
			if ( pDoc != NULL )
			{
				bSelection = pDoc->GetSelection()->IsSelected( iRow, idxColumn );
			}
			// 色選択
			if ( bSelection )
			{
				pDstDC->SetTextColor( colForeSelect );
			}
			else
			{
				COLORREF	colFore = pEmphasisDefine->GetItemz()[ tChar.idxEmphasis ].GetForeColor();
				pDstDC->SetTextColor( colFore );
			}

			pDrawer->SetDstX( lX );
			pDrawer->SetDstY( lStartY );

			switch( tChar.eType )
			{
			case TypeShiftJis:
				{
					int		iPrintedChar;
					pDrawer->DrawSJisCharactor(
						((LPCTSTR)m_strLine) + idxByte,
						pDstDC,
						&iPrintedChar,
						tChar.iWidth,
						tChar.bBox
					);
				}
				break;
			case TypeUnicode:
				{
					if ( tChar.bBox )
					{
						int		iPrintedChar;
						pDrawer->DrawSJisCharactor(
							((LPCTSTR)m_strLine) + idxByte,
							pDstDC,
							&iPrintedChar,
							tChar.iWidth,
							TRUE
						);
					}
					else
					{
						CUnicoder*	pUnicoder = CUnicoder::GetInstance();
						CRect	rcDst( pDrawer->GetDstX(), pDrawer->GetDstY(), pDrawer->GetDstX(), pDrawer->GetDstY() );
						pUnicoder->DrawCharCode(
// ▼ (3344) BGN 2004.05.20 (moralog) Unicodeレンダリング方法変更
							pDstDC->m_hDC,
// ▽ original BGN
//							pDstDC,
// △ original END
// ▲ (3344) END
							rcDst,
							(wchar_t)(tChar.aiCode[1]*256 + tChar.aiCode[0])
						);
					}
				}
				break;
			case TypeEOL:
				pDrawer->DrawEOL( pDstDC, FALSE, bSelection );
				break;
			case TypeEOF:
				pDrawer->DrawEOL( pDstDC, TRUE, bSelection );
				break;
			default:
				break;
			}
		}

		idxByte += tChar.nByte;
		lX += tChar.iWidth;
		idxColumn += tChar.nColumn;

		// 描画要求範囲を描画し終えたら抜ける
		if ( lX > iWidthX )
		{
			break;
		}
	}

	// UnderLine設定を解除、FONT設定を解除
	CGeneralSetting::GetInstance()->GetLogFont()->m_bUnderLine = FALSE;
	pDrawer->RestoreFont( pDstDC );
}





/*-----------------------------------------------------------------------------
[名称]	表示色解析（文字列）
[機能]	表示色解析を行って表示できる状態にする。
[戻値]	int		文字列幅 [Pixel] (-)
[備考]	なし
-----------------------------------------------------------------------------*/
long CEmphasisLine::AnalizeString(
	CDC*				pDstDC,				// I: 出力先DC [-] (-) :-
	CEmphasisDefine*	pEmphasisDefine		// I: 表示色設定 [-] (-) :-
)
{
	const char*			pstrSrc = m_strLine;

	m_bInitialized = FALSE;
	m_lAllWidth = 0;
	m_nColumn = 0;
	m_listCharz.RemoveAll();

	// 強調表示設定取得
	CArray<CEmphasisItem, CEmphasisItem&>&	aEmphasisz = pEmphasisDefine->GetItemz();

	int	idxByte = 0;
	int	idxColumn = 0;
	int	X = 0;

	int		iRelatedColumn = 0;		// 前の行から連続している強調表示のカラム数

	// 前行からの表示色設定を反映
	{
		// 次の行への強調表示設定継続を初期化
		SetEmphasisNextContinue( EMPHASIS_TEXT );

		// 行の開始色が終端ありの表示色であれば終端を探す
		CString		strTerminator( aEmphasisz[ m_idxPrevRelationEmphasis ].GetTerminator() );
		if ( !strTerminator.IsEmpty() )
		{
			// 終端の検索
			int	idxTerminator = SerchEmphasisTerminator(
				pEmphasisDefine,			// 表示色設定 [-] (-)
				m_idxPrevRelationEmphasis	// 繰越表示色 [インデクス] (-)
			);
			if ( idxTerminator >= 0 )
			{
				// 終端までは開始色で埋まる
				iRelatedColumn = idxTerminator;
			}
			else
			{
				// 行全体が開始色で埋まる
				iRelatedColumn = INT_MAX;

				// 次の行へ連結する
				SetEmphasisNextContinue( GetEmphasisPrevRelation() );
			}
		}
	}

	// 強調表示HIT情報を作成
	CList< TEmphasisHit, TEmphasisHit& >	listHitz;
	AnalizeString(
		pEmphasisDefine,
		&listHitz,
		iRelatedColumn
	);

	// DCにNULLが渡された場合、表示色解析だけを行い、
	// 文字幅等は不定のまま終了とする。
	// ここまでで複数行強調表示の次の行への繰越は設定されている。
	// please! DCはスクリーン固定としてやっちゃうのもいいかも
	if( pDstDC == NULL )
	{
		return( 0 );
	}

	CEditDrawer*	pDrawer = CEditDrawer::GetInstance();
	pDrawer->ReflectFont( pDstDC );
	while( *(pstrSrc+idxByte) != 0x00 )
	{
		int		iPrintedByte = 0;
		int		iPrintedColumn = 0;
		CSize	sizeExtent;
		sizeExtent = pDrawer->ExtentCharactor(
			pstrSrc + idxByte,
			pDstDC,
			&iPrintedByte,
			&iPrintedColumn,
			X
		);
		// 文字情報を保存
		{
			// 文字情報の作成
			TEmphasisChar EmphasisChar;
			EmphasisChar.iWidth = (WORD)sizeExtent.cx;	// 表示幅
			EmphasisChar.nByte = (char)iPrintedByte;			// バイト数
			EmphasisChar.nColumn = (char)iPrintedColumn;		// カラム数
			if ( iPrintedColumn == 1 )
			{
				// シングルカラム文字JISコード
				EmphasisChar.eType = TypeShiftJis;
				EmphasisChar.aiCode[0] = pstrSrc[idxByte +0];
				EmphasisChar.aiCode[1] = pstrSrc[idxByte +1];
			}
			else
			{
				// マルチカラム文字（ユニコード）
				CUnicoder*	pUnicoder = CUnicoder::GetInstance();
				wchar_t		wcharUnicode;
				pUnicoder->IsUnicode(
					pstrSrc +idxByte,
					&wcharUnicode
				);
				EmphasisChar.eType = TypeUnicode;
				EmphasisChar.aiCode[0] = (char)(((WORD)wcharUnicode)%0x100);
				EmphasisChar.aiCode[1] = (char)(((WORD)wcharUnicode)/0x100);
			}

			// 基本色設定
			EmphasisChar.idxEmphasis = EMPHASIS_TEXT;			// 強調表示種類
			if ( idxColumn < iRelatedColumn )
			{
				// 前の行から継続している強調表示
				EmphasisChar.idxEmphasis = GetEmphasisPrevRelation();
			}

			// 強調表示検査
			{
				// listHitz に該当するカラムがあるかを検査する
				// あれば強調表示
				POSITION pos = listHitz.GetHeadPosition();
				while( pos != NULL )
				{
					TEmphasisHit& Hit = listHitz.GetNext( pos );
					if( Hit.iStartColumn <= idxColumn )
					{
						if( Hit.nColumn == INT_MAX ) // nColumnがINT_MAXであることもある
						{
							EmphasisChar.idxEmphasis = Hit.idxEmphasisType;
							break;
						}

// ▼ (3344) BGN 2004.05.27 (moralog) ＨＴＭＬ文字符号内に検索文字列があったときに表示色が出ない不具合
// ▽ original BGN
//						if( Hit.iStartColumn+Hit.nColumn >= idxColumn+iPrintedColumn )
// △ original END

						if( ( Hit.iStartColumn+Hit.nColumn >= idxColumn+iPrintedColumn ) ||
							( Hit.iStartColumn == idxColumn ) )
// ▲ (3344) END
						{
							EmphasisChar.idxEmphasis = Hit.idxEmphasisType;
							break;
						}
					}
				}
			}

			EmphasisChar.bBox = FALSE;
			{
				EmphasisChar.bBox = CGeneralSetting::GetInstance()->GetBoxCharDefine()->IsBox(
					( pstrSrc+idxByte )
				);
			}

			m_listCharz.AddTail( EmphasisChar );
		}

		idxByte += iPrintedByte;
		idxColumn += iPrintedColumn;
		X += sizeExtent.cx;
	}

	pDrawer->RestoreFont( pDstDC );

	m_strLine = pstrSrc;
	m_lAllWidth = X;
	m_nColumn = idxColumn;

	m_bInitialized = TRUE;

	return( X );
}



/*-----------------------------------------------------------------------------
[名称]	強調表示HIT情報作成
[機能]	カラム単位の強調表示HIT情報を構築する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
long CEmphasisLine::AnalizeString(
	CEmphasisDefine*						pEmphasisDefine,	// I  :強調表示定義 [-] (-) :-
	CList< TEmphasisHit, TEmphasisHit& >*	plstEmphasisHitz,	//   O:強調表示HIT情報 [-] (-) :-
	long									iRelatedColumn		// I  :複数行強調表示繰越影響カラム [-] (-) :-
																//     （ここまでが前の行の表示色をひきずっている） :-
)
{
	plstEmphasisHitz->RemoveAll();

	// 強調表示設定取得
	CArray<CEmphasisItem, CEmphasisItem&>&	aEmphasisz = pEmphasisDefine->GetItemz();

	// 強調表示HIT情報を作成
	{
		// 強調表示にHITするすべての情報を収集
		CList< TEmphasisHit, TEmphasisHit& >	listHitAllz;

		// 全パターンの検索
		{
			CArray<CEmphasisItem, CEmphasisItem&>&	EmphasisItem = pEmphasisDefine->GetItemz();

			int		idxEmphasis;
			for( idxEmphasis=EMPHASIS_NEEDCOLORINGITEM ; idxEmphasis<EmphasisItem.GetSize() ; idxEmphasis++ )
			if( EmphasisItem[ idxEmphasis ].GetEnable() )
			{
				CString	strPattern( EmphasisItem[ idxEmphasis ].GetPattern() );
				if( !strPattern.IsEmpty() )
				{
					CArray< TMatch, TMatch& > aMatchz;

					CFinder*	pFinder = ::GetFinder( EmphasisItem[ idxEmphasis ].GetFindCondition()->bRegExp );
					pFinder->GetMatchz(
						m_strLine,
						strPattern,
						&aMatchz,
						EmphasisItem[ idxEmphasis ].GetFindCondition()->bCaseCare,	// bCaseCare
						EmphasisItem[ idxEmphasis ].GetFindCondition()->bToken		// bToken
					);

					int		idxMatch;
					for( idxMatch=0 ; idxMatch<aMatchz.GetSize() ; idxMatch++ )
					{
						// 普通の強調表示は複数行表示色の繰越部分より後ろ、
						// EMPHASIS_FOUND は繰越にかかわらずすべて収集する
						BOOL	bHit =  ( iRelatedColumn <= aMatchz[idxMatch].idxStartColumn );
						bHit |= ( idxEmphasis == EMPHASIS_FOUND );
						if ( bHit )
						{
							TEmphasisHit	tHit;
							tHit.iStartColumn = aMatchz[idxMatch].idxStartColumn;
							tHit.nColumn = aMatchz[idxMatch].nColumn;
							tHit.idxEmphasisType = (USHORT)idxEmphasis;
							tHit.bTerminated = TRUE;

							listHitAllz.AddTail( tHit );
						}
					}
				}
			}
		}

		// HITした情報を見つつ小さいものからソート
		// 重複するカラムは優先度の低い順に捨てる
		// 他の強調表示の後半に含まれるものは捨てる
		long		iExecedColumn = -1;
		while( TRUE )
		{
			long				iMinColumn = INT_MAX;
			TEmphasisHit*	pHit = NULL;
			POSITION		pos = listHitAllz.GetHeadPosition();
			while( pos != NULL )
			{
				TEmphasisHit& Item = listHitAllz.GetNext( pos );

				// Found は特別処理（強調表示解析後、上に載せるかんじ）
				if ( Item.idxEmphasisType != EMPHASIS_FOUND )
				{
					// 検索済みカラムを無視
					if ( Item.iStartColumn <= iExecedColumn )
					{
						continue;
					}

					// カラムが小さい？
					if ( Item.iStartColumn < iMinColumn )
					{
						pHit = &Item;
						iMinColumn = pHit->iStartColumn;
					}
					// カラムが同じで優先度が高い？
					if ( Item.iStartColumn == iMinColumn )
					{
						if ( pHit != NULL )
						if ( Item.idxEmphasisType >= pHit->idxEmphasisType )
						{
							continue;
						}
						pHit = &Item;
					}
				}
			}

			if ( pHit != NULL )
			{
				// 終端指定があれば探す
				CString strTerminator( aEmphasisz[ pHit->idxEmphasisType ].GetTerminator() );
				if( !strTerminator.IsEmpty() )
				{
					int	idxSerchByte = ::CaretColumnToByteColumn(
							(LPCTSTR)m_strLine,
							pHit->iStartColumn+pHit->nColumn
					);

					TMatch	Match;
					CFinder*	pFinder = ::GetFinder( aEmphasisz[ pHit->idxEmphasisType ].GetFindCondition()->bRegExp );
					BOOL bFound = pFinder->QuickMatch(
						(LPCTSTR)m_strLine + idxSerchByte,
						strTerminator,
						&Match,
						aEmphasisz[ pHit->idxEmphasisType ].GetFindCondition()->bCaseCare,
						aEmphasisz[ pHit->idxEmphasisType ].GetFindCondition()->bToken
					);

					int		iRelatedColumn;
					if ( bFound )
					{
						iRelatedColumn = pHit->iStartColumn+pHit->nColumn + Match.idxStartColumn + Match.nColumn;

						// 終端を見つけた
						// pHitの内容を改変する
						pHit->nColumn +=
							Match.idxStartColumn + Match.nColumn;
						pHit->bTerminated = TRUE;
					}
					else
					{
						iRelatedColumn = -1;

						// 見つからない場合は行末までHITとみなす
						pHit->bTerminated = FALSE;
						pHit->nColumn = INT_MAX;

						// 次の行へ連結する
						SetEmphasisNextContinue( pHit->idxEmphasisType );

					}
/*
					CArray< TMatch, TMatch& > aMatchz;
					CFinderVBScript		Finder;
					Finder.GetMatchz(
						m_strLine,
						strTerminator,
						&aMatchz,
						TRUE,
						FALSE
					);

					int		idxMatch;
					for( idxMatch=0 ; idxMatch<aMatchz.GetSize() ; idxMatch++ )
					{
						if ( pHit->iStartColumn+pHit->nColumn <= aMatchz[idxMatch].idxStartColumn )
						{
							// 終端を見つけた
							// pHitの内容を改変する
							pHit->nColumn =
								aMatchz[idxMatch].idxStartColumn - pHit->iStartColumn +
								aMatchz[idxMatch].nColumn
							;
							pHit->bTerminated = TRUE;
							break;
						}
					}
					if( idxMatch == aMatchz.GetSize() )
					{
						// 見つからない場合は行末までHITとみなす
						pHit->bTerminated = FALSE;
						pHit->nColumn = INT_MAX;

						// 次の行へ連結する
						SetEmphasisNextContinue( pHit->idxEmphasisType );
					}
*/
				}
				plstEmphasisHitz->AddTail( *pHit );
				if ( pHit->nColumn == INT_MAX )
				{
					iExecedColumn = INT_MAX;
				}
				else
				{
					iExecedColumn = pHit->iStartColumn + pHit->nColumn -1;
				}
			}
			else
			{
				break;
			}
		}

		// Found は特別処理（強調表示解析後、上に載せるかんじ）
		POSITION		pos = listHitAllz.GetHeadPosition();
		while( pos != NULL )
		{
			TEmphasisHit& FoundItem = listHitAllz.GetNext( pos );
			if ( FoundItem.idxEmphasisType == EMPHASIS_FOUND )
			{
				// 該当するカラム情報を探し、書き換える
				POSITION		posHitz = plstEmphasisHitz->GetHeadPosition();
//				if( posHitz == NULL )
//				{
//					// 検索文字列登録
//					plstEmphasisHitz->AddTail( FoundItem );
//					continue;
//				}

				BOOL	bInserted = FALSE;
				while( posHitz != NULL )
				{
					POSITION	posPrev = posHitz;
					TEmphasisHit& HitzItem = plstEmphasisHitz->GetNext( posHitz );
					if ( HitzItem.idxEmphasisType != EMPHASIS_FOUND )
					{
						// 検索文字列が無限表示色内部にある場合
						if ( HitzItem.nColumn == INT_MAX )
						{
							if ( HitzItem.iStartColumn <= FoundItem.iStartColumn )
							{
								// 検索文字列登録
								plstEmphasisHitz->InsertAfter( posHitz, FoundItem );
								bInserted = TRUE;

								// 表示色後半を登録
								TEmphasisHit tmp = HitzItem;
								tmp.nColumn = INT_MAX;
								tmp.iStartColumn = FoundItem.iStartColumn + FoundItem.nColumn;
								plstEmphasisHitz->InsertAfter( posHitz, tmp );

								// 表示色前半の長さを切り詰める
								//HitzItem.nColumn = FoundItem.iStartColumn;
								HitzItem.nColumn = FoundItem.iStartColumn;
							}
							break;
						}

						// 表示色全体が検索文字列とかぶっていた場合
						if ( HitzItem.iStartColumn >= FoundItem.iStartColumn )
						if ( HitzItem.iStartColumn + HitzItem.nColumn <= FoundItem.iStartColumn + FoundItem.nColumn )
						{
							// 表示色を削除する
							plstEmphasisHitz->RemoveAt( posPrev );
							continue;
						}

						// 検索文字列が表示色内部にある場合
						if ( HitzItem.iStartColumn <= FoundItem.iStartColumn )
						if ( HitzItem.iStartColumn + HitzItem.nColumn >= FoundItem.iStartColumn + FoundItem.nColumn )
						{
							// 表示色後半を登録
							TEmphasisHit tmp = HitzItem;
							tmp.nColumn = (tmp.iStartColumn+tmp.nColumn)-(FoundItem.iStartColumn+FoundItem.nColumn);
							tmp.iStartColumn = FoundItem.iStartColumn + FoundItem.nColumn;
							if ( tmp.nColumn > 0 )
							{
								plstEmphasisHitz->InsertBefore( posHitz, tmp );
							}

							// 検索文字列登録
							plstEmphasisHitz->InsertBefore( posHitz, FoundItem );
							bInserted = TRUE;

							// 表示色前半の長さを切り詰める
							HitzItem.nColumn = FoundItem.iStartColumn - HitzItem.iStartColumn;
							break;
						}

						// 表示色後半が検索文字列とかぶっていた場合
						if ( HitzItem.iStartColumn <= FoundItem.iStartColumn )
						if ( HitzItem.iStartColumn + HitzItem.nColumn > FoundItem.iStartColumn )
						{
							// 表示色の長さを切り詰める
							HitzItem.nColumn = FoundItem.iStartColumn - HitzItem.iStartColumn;
							continue;
						}

						// 表示色前半が検索文字列とかぶっていた場合
						if ( HitzItem.iStartColumn >= FoundItem.iStartColumn )
						if ( HitzItem.iStartColumn + HitzItem.nColumn <= FoundItem.iStartColumn + FoundItem.nColumn )
						{
							// 表示色開始位置をずらす
							HitzItem.nColumn = (HitzItem.iStartColumn+HitzItem.nColumn)-(FoundItem.iStartColumn+FoundItem.nColumn);
							HitzItem.iStartColumn = FoundItem.iStartColumn + FoundItem.nColumn;
							break;
						}

						// 表示色が検索文字列より後ろの場合
						if ( HitzItem.iStartColumn < FoundItem.iStartColumn + FoundItem.nColumn )
						{
// ▼ (3344) BGN 2004.05.27 (moralog) ＨＴＭＬ文字符号内に検索文字列があったときに表示色が出ない不具合
							continue;
// ▽ original BGN
//							// 検索文字列表示の挿入
//							plstEmphasisHitz->InsertBefore( posHitz, FoundItem );
//							bInserted = TRUE;
//							break;
// △ original END
// ▲ (3344) END
						}
					}
				}

				if ( !bInserted )
				{
					// 検索文字列登録
					plstEmphasisHitz->AddTail( FoundItem );
				}
			}
		}
	}

//	// 該当するカラム情報を探し、書き換える
//	POSITION		pos = plstEmphasisHitz->GetHeadPosition();
//	while( pos != NULL )
//	{
//		TEmphasisHit	Item;
//		Item = plstEmphasisHitz->GetNext( pos );
//		TRACE( "%d(%d) = %d\n", Item.iStartColumn, Item.nColumn, Item.idxEmphasisType );
//	}
//	TRACE( "\n" );

	return( plstEmphasisHitz->GetCount() );
}




// 描画幅取得
long	CEmphasisLine::GetWidth()
{
	Analize();
	return( m_lAllWidth );
};
