// ★コメント未記入
/*-----------------------------------------------------------------------------
[名称]	ShitarabianView.cpp
[概要]	CShitarabianView の実装
[備考]	なし
[履歴]	2003-11-08	b031031 (3199) データ読み込み前に表示更新しようとすると、存在しない行を見に行って落ちる
		2003-11-08	b031031 (3184) 行表示を１からに変更
		2003-12-20	b031228 (3177)DCのマッピング廃止に伴う修正(moralog)
		2003-12-28  b040111 (3632)キャレット位置の強調(moralog)
		2004-02-09	b031228 (3367)Grep検索(dincom)
		2004-05-10	b031228 (3204)へぼぺとの連携(moralog)
-----------------------------------------------------------------------------*/
#include "stdafx.h"
#include "Common.h"
#include "Shitarabian.h"
#include "MainFrm.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 "ToolBarManager.h"
#include "ShitarabianPlugInManager.h"
#include "Selection.h"
#include "ROISelection.h"
#include "ExeCommon.h"

#include "EmphasisLine.h"


extern CShitarabianApp	theApp;
extern CStatusBar*		m_pSystemStatusBar; 



// ■IMEのCompositionウィンドウの設定方法
// http://mambo.kuhp.kyoto-u.ac.jp/~miyoshi/mked/index.html

// ■キャレットの表示・非表示
// pDoc->SetAllUpdate();で再描画を行うとき、キャレットの再作成を行う。
// キャレット非表示時にもHideCaretをいれまくるので、キャレットの表示開始に必要。

static CEditDrawer*	GetDrawer()
{
	return( CEditDrawer::GetInstance() );
}


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

/////////////////////////////////////////////////////////////////////////////
// CShitarabianView

IMPLEMENT_DYNCREATE(CShitarabianView, CView)

BEGIN_MESSAGE_MAP(CShitarabianView, CView)
	//{{AFX_MSG_MAP(CShitarabianView)
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()
	ON_WM_ERASEBKGND()
	ON_WM_SETCURSOR()
	ON_WM_DROPFILES()
	ON_WM_VSCROLL()
	ON_WM_HSCROLL()
	ON_WM_MOUSEWHEEL()
	ON_COMMAND(IDM_EDIT_MODESELECT, OnEditModeselect)
	ON_WM_RBUTTONDOWN()
	ON_WM_SIZE()
	ON_COMMAND(IDM_EDIT_FLOAT_CANCEL, OnEditFloatCancel)
	ON_COMMAND(IDM_EDIT_FLOAT_COPY, OnEditFloatCopy)
	ON_COMMAND(IDM_EDIT_FLOAT_MOVE, OnEditFloatMove)
	//}}AFX_MSG_MAP
	// 標準印刷コマンド
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CShitarabianView クラスの構築/消滅

CShitarabianView::CShitarabianView():
	m_bVisibleCaret( FALSE ),
	m_bDrag( FALSE ),
	m_bInputMode( FALSE ),
	m_idxUpdateStartRow( AllRow ),
	m_idxUpdateEndRow( AllRow ),
	m_iFloatOffsetX( 0 ),
	m_iFloatOffsetY( 0 ),
	m_lMaxXPixel( 0 ),
	m_nRow( 0 ),
	m_iPrevVisibleRowStart( -1 ),
	m_iPrevVisibleRowCount( -1 )
{
	// 水平スクロールバーの初期化
	ResetHScroll();
}

CShitarabianView::~CShitarabianView()
{
}


/////////////////////////////////////////////////////////////////////////////
// CShitarabianView クラスの描画

void CShitarabianView::OnDraw(CDC* pDC)
{
	CShitarabianDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	// 必要な部分の描画領域を再設定する
	{
		CRect		rcUpdateReq;
		if ( pDC->GetClipBox( &rcUpdateReq ) != NULLREGION )
		{
// ▼ (3177) BGN 2003.12.20 (moralog) DCのマッピング廃止に伴う修正
			CRect	rcClient;
			GetClientRect( &rcClient );
			CPoint	ptScrollBox = GetDeviceScrollPosition();
			rcUpdateReq.top += ptScrollBox.y;
			rcUpdateReq.bottom += ptScrollBox.y;
			rcUpdateReq.left = ptScrollBox.x;
			rcUpdateReq.right = ptScrollBox.x + rcClient.Width();
// ▲ (3177) END

			CEditDrawer*	pDrawer = CEditDrawer::GetInstance();
			pDoc->SetUpdateStartRow( pDrawer->WindowPixelToCaretRowZoomed( rcUpdateReq.top, pDoc ) );
			pDoc->SetUpdateEndRow( pDrawer->WindowPixelToCaretRowZoomed( rcUpdateReq.bottom, pDoc )+1 );

			DrawPage(
				pDC,
				&rcUpdateReq
			);
		}
		else
		{
			DrawPage( pDC );
		}
	}
}

void CShitarabianView::OnInitialUpdate()
{
	CView::OnInitialUpdate();

	// ドキュメントとオブジェクトの関連を設定
	CCommandManager*	pCmd = CCommandManager::GetInstance();
	pCmd->Attach( GetDocument() );

	// Dropを許可する
	DragAcceptFiles( TRUE );
}

/////////////////////////////////////////////////////////////////////////////
// CShitarabianView クラスの印刷



void CShitarabianView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
}

void CShitarabianView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
}

/////////////////////////////////////////////////////////////////////////////
// CShitarabianView クラスの診断

#ifdef _DEBUG
void CShitarabianView::AssertValid() const
{
	CView::AssertValid();
}

void CShitarabianView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CShitarabianDoc* CShitarabianView::GetDocument() // 非デバッグ バージョンはインラインです。
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CShitarabianDoc)));
	return (CShitarabianDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CShitarabianView クラスのメッセージ ハンドラ


void CShitarabianView::DrawCaret(
	CDC*	pDC
) 
{
	CShitarabianDoc* pDoc = GetDocument();
	if ( !m_bVisibleCaret )
	{
		return;	
	}

	switch( pDoc->GetOperationMode() )
	{
	case OperationNormal:
		break;
	default:
		return;
		break;
	}

	CEditDrawer*	pDrawer = GetDrawer();

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

	// キャレットの配置
	POINT	ptCaret;
	{
		CShitarabianDoc* pDoc = GetDocument();
		long	idxRow = 0;
		long	idxColumn = 0;
		// ドキュメントからキャレット情報を取得
		{
			if( pDoc != NULL )
			{
				idxRow = pDoc->GetCaretRow();
				idxColumn = pDoc->GetCaretColumn();
			}
		}
		// キャレット情報からキャレットのピクセル座標を計算
		{
			CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxRow );
			if ( pEmphasisLine != NULL )
			{
				ptCaret.x = pEmphasisLine->CaretColumnToPixelZoomed( idxColumn );
				ptCaret.y = pDrawer->CaretRowToPixelZoomed( idxRow );
			}
			else
			{
				ptCaret.x = lLeftMargin;
				ptCaret.y = lTopMargin;
			}
		}

		// スクロールボックス内の座標に変換
		ptCaret = PixelToScrollBox( CPoint(ptCaret.x, ptCaret.y) );
		if ( ptCaret.x < lLeftMargin )
		{
			ptCaret.x = -2*pDrawer->GetZoom();
		}
		if ( ptCaret.y < lTopMargin )
		{
			ptCaret.x = -2*pDrawer->GetZoom();
		}

		SetCaretPos( ptCaret );


		if ( !pDoc->IsOverwriteMode() )
		{
			ShowCaret();
		}

	}


	// IMEの配置
	{
		HIMC hIMC = ImmGetContext( m_hWnd );

		// 配置
		COMPOSITIONFORM cf;
		cf.dwStyle = CFS_POINT;
		cf.ptCurrentPos = ptCaret;
		ImmSetCompositionWindow(hIMC, &cf);

		// フォントサイズの設定
		LOGFONT*	pLogFont = CGeneralSetting::GetInstance()->GetLogFont()->GetLogFont( pDC );
		pLogFont->lfHeight *= pDrawer->GetZoom();
		ImmSetCompositionFont( hIMC, pLogFont );
		pLogFont->lfHeight /= pDrawer->GetZoom();

		ImmReleaseContext( m_hWnd, hIMC );
	}
}


CPoint CShitarabianView::PixelToScrollBox(
	CPoint	ptPixel
)
{
	CPoint	ptClientTopLeft;
	ptClientTopLeft = GetDeviceScrollPosition();

	int		iLeftMargin = CGeneralSetting::GetInstance()->GetLeftMargin();
	int		iTopMargin = CGeneralSetting::GetInstance()->GetTopMargin();
	ptPixel.x -= ptClientTopLeft.x - iLeftMargin;
	ptPixel.y -= ptClientTopLeft.y - iTopMargin;
	return( ptPixel );
}


CPoint CShitarabianView::ScrollBoxToPixel(
	CPoint	ptPixel
)
{
	CPoint	ptClientTopLeft;
	ptClientTopLeft = GetDeviceScrollPosition();

	int		iLeftMargin = CGeneralSetting::GetInstance()->GetLeftMargin();
	int		iTopMargin = CGeneralSetting::GetInstance()->GetTopMargin();
	ptPixel.x += ptClientTopLeft.x - iLeftMargin;
	ptPixel.y += ptClientTopLeft.y - iTopMargin;

	CEditDrawer*	pDrawer = GetDrawer();
	ptPixel.x = ptPixel.x / pDrawer->GetZoom();
	ptPixel.y = ptPixel.y / pDrawer->GetZoom();
	return( ptPixel );
}



	
// キャレットが見えるようにスクロール
BOOL	CShitarabianView::ScrollToCaret()
{
	CShitarabianDoc* pDoc = GetDocument();
	int idxRow = pDoc->GetCaretRow();
	int idxColumn = pDoc->GetCaretColumn();
		CEditDrawer*	pDrawer = CEditDrawer::GetInstance();

	BOOL	bVScroll = FALSE;
	BOOL	bHScroll = FALSE;
	HDC		hdc = ::GetDC( NULL );
	CDC		DC;
	DC.Attach( hdc );
	{
		// キャレットのPixel座標を計算
		CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxRow );
		if ( pEmphasisLine != NULL )
		{
			// 終了座標のキャレット位置取得
			long	lPixelX = pEmphasisLine->CaretColumnToWindowPixelZoomed( idxColumn );
			long	lPixelY = pDrawer->CaretRowToWindowPixelZoomed( idxRow );

			// スクロールボックスに収まるか？
			CPoint	ptClientTopLeft;
			ptClientTopLeft = GetDeviceScrollPosition();
			POINT	ptScrollBoxTopLeft;
			ptScrollBoxTopLeft.x = ptClientTopLeft.x;
			ptScrollBoxTopLeft.y = ptClientTopLeft.y;

			int		iColumnWidth = pDrawer->GetBlankWidth() * pDrawer->GetZoom();
// ▼ (3632) BGN 2003.12.28 (moralog) 下端に行ピッチを反映
			int		iRowHeight = pDrawer->CaretRowToPixelZoomed(1);
// ▽ original BGN
//			int		iRowHeight = pDrawer->GetBlankHeight() * pDrawer->GetZoom();
// △ original END
// ▲ (3632) END
			int		iLeftMargin = CGeneralSetting::GetInstance()->GetLeftMargin();
			int		iTopMargin = CGeneralSetting::GetInstance()->GetTopMargin();

			CRect	rcClient;
			GetClientRect( &rcClient );
			if ( lPixelX < ptClientTopLeft.x+iLeftMargin )
			{
				ptScrollBoxTopLeft.x = lPixelX-iLeftMargin;
				bHScroll = TRUE;
			}
			if ( lPixelX+iColumnWidth > ptClientTopLeft.x+rcClient.Width() )
			{
				ptScrollBoxTopLeft.x = lPixelX+iColumnWidth - rcClient.Width();
				bHScroll = TRUE;
			}
			if ( lPixelY < ptClientTopLeft.y+iTopMargin )
			{
				ptScrollBoxTopLeft.y = lPixelY-iTopMargin;
				bVScroll = TRUE;
			}
			if ( lPixelY+iRowHeight > ptClientTopLeft.y+rcClient.Height() )
			{
				ptScrollBoxTopLeft.y = lPixelY+ iRowHeight - rcClient.Height();
				bVScroll = TRUE;
			}

			// 収まらなければスクロールさせる
			if ( bVScroll )
			{
				// ドキュメント大きさが変化している場合を考慮して
				// スクロールボックス領域をとりあえずキャレット位置の大きさ以上にする
				m_lMaxXPixel = max( m_lMaxXPixel, lPixelX-iLeftMargin );
				RecalcScrollBar();

				// スクロールボックス内の画像をずらす＆必要な領域を再描画
				ManualVScroll( ptScrollBoxTopLeft.y );
			}
			if ( bHScroll )
			{
				// ドキュメント大きさが変化している場合を考慮して
				// スクロールボックス領域をとりあえずキャレット位置の大きさ以上にする
				m_lMaxXPixel = max( m_lMaxXPixel, lPixelX-iLeftMargin );
				RecalcScrollBar();

				// スクロールボックス内の画像をずらす＆必要な領域を再描画
				ManualHScroll( ptScrollBoxTopLeft.x );
			}
		}
	}
	DC.Detach();
	::ReleaseDC( NULL, hdc );

	return( bVScroll || bHScroll );
}


CPoint	CShitarabianView::GetDeviceScrollPosition()
{
	CPoint	pt;
	SCROLLINFO	tInfo;

	if ( GetScrollInfo( SB_VERT, &tInfo ) )
	{
		pt.y = tInfo.nPos;
	}
	if ( GetScrollInfo( SB_HORZ, &tInfo ) )
	{
		pt.x = tInfo.nPos;
	}

	return( pt );
}

void	CShitarabianView::SetDeviceScrollPosition( CPoint pt )
{
	SCROLLINFO	tInfo;

	GetScrollInfo( SB_VERT, &tInfo );
	tInfo.nPos = min( pt.y, tInfo.nMax );
	SetScrollInfo( SB_VERT, &tInfo );

	GetScrollInfo( SB_HORZ, &tInfo );
	tInfo.nPos = min( pt.x, tInfo.nMax );
	SetScrollInfo( SB_HORZ, &tInfo );
}

void CShitarabianView::SetScrollSizes(
	CSize	sizeDocument,
	CSize	sizePage,
	CSize	sizeLine
)
{
	// warning C4100:警告の無視
	sizeLine;

	SCROLLINFO	tInfo;

	// 縦
	GetScrollInfo(
		SB_VERT,
		&tInfo
	);
	tInfo.fMask = SIF_DISABLENOSCROLL | SIF_ALL; 
	tInfo.nMin = 0; 
	tInfo.nMax = sizeDocument.cy; 
	tInfo.nPage = sizePage.cy;
	SetScrollInfo(
		SB_VERT,
		&tInfo,
		TRUE
	);

	// 横
	GetScrollInfo(
		SB_HORZ,
		&tInfo
	);
	tInfo.fMask = SIF_DISABLENOSCROLL | SIF_ALL; 
	tInfo.nMin = 0; 
	tInfo.nMax = sizeDocument.cx; 
	tInfo.nPage = sizePage.cx;
	SetScrollInfo(
		SB_HORZ,
		&tInfo,
		TRUE
	);
}

// 可視の開始行
int CShitarabianView::VisibleRowStart()
{
	CPoint	ptScrollBox = GetDeviceScrollPosition();

	CEditDrawer*		pDrawer = GetDrawer();
	int	lRowHeight = pDrawer->CaretRowToPixelZoomed( 1 );

	return( ptScrollBox.y / lRowHeight );
}

// 可視の行数
int CShitarabianView::VisibleRowCount()
{
	CRect	rcClient;
	GetClientRect( &rcClient );

	CEditDrawer*		pDrawer = GetDrawer();
	int	lRowHeight = pDrawer->CaretRowToPixelZoomed( 1 );

	return( (rcClient.Height()-CGeneralSetting::GetInstance()->GetTopMargin()) / lRowHeight );
}




// スクロールボックス内の画像をずらす＆必要な領域を再描画
// 縦移動のときしかここへはこない
void CShitarabianView::UpdateScrollBox(
	CPoint		ptOldBox,
	CPoint		ptNewBox,
	CRect		rcClient
) 
{
	CEditDrawer*	pDrawer = GetDrawer();
	CShitarabianDoc* pDoc = GetDocument();

	if ( ptNewBox.y < 0 )
	{
		ptNewBox.y = 0;
	}
	if ( ptNewBox.y > GetScrollLimit(SB_VERT) )
	{
		ptNewBox.y = GetScrollLimit(SB_VERT);
	}

	// 更新領域計算
	int		iTop;
	int		iBottom;

	// 上へ移動した場合
	if ( ptNewBox.y <  ptOldBox.y )
	{
		// 上は新しく表示領域になる部分
		iTop = ptNewBox.y;
		// 下は今まで表示していたうえはし
		iBottom = ptOldBox.y;
// MARK R00004(2002.09.16) スクロールがおそい
		iBottom = min( iBottom, ptNewBox.y + rcClient.Height() );
// MARK R00004 end


		if ( m_idxUpdateStartRow == InitialRow )
		{
			m_idxUpdateStartRow = ( pDrawer->PixelToCaretRowZoomed(iTop, pDoc) );
		}
		else
		{
			m_idxUpdateStartRow = min( m_idxUpdateStartRow, pDrawer->PixelToCaretRowZoomed(iTop, pDoc) );
		}

		if ( m_idxUpdateStartRow == AllRow )
		{
			m_idxUpdateEndRow = pDrawer->PixelToCaretRowZoomed(iBottom, pDoc);
		}
		else
		{
			m_idxUpdateEndRow = max( m_idxUpdateEndRow, pDrawer->PixelToCaretRowZoomed(iBottom, pDoc) );
		}
	}
	else if ( ptNewBox.y >  ptOldBox.y )
	{
		// 上は今まで表示していた下はし
		iTop = ptOldBox.y + rcClient.Height();
// MARK R00004(2002.09.16) スクロールがおそい
		iTop = max( iTop, ptNewBox.y );
// MARK R00004 end

		// 下は新しく表示領域になる下はし
		iBottom = ptNewBox.y + rcClient.Height();

		if ( m_idxUpdateStartRow == InitialRow )
		{
			m_idxUpdateStartRow = ( pDrawer->WindowPixelToCaretRowZoomed(iTop, pDoc) );
		}
		else
		{
			m_idxUpdateStartRow = min( m_idxUpdateStartRow, pDrawer->WindowPixelToCaretRowZoomed(iTop, pDoc) );
		}
		m_idxUpdateEndRow = ( AllRow );
	}

	// イメージのスクロール
	{
		//　縦移動の場合はBitBltで省力化できる
		long	lLeftMargin;
		long	lTopMargin;
		lLeftMargin = CGeneralSetting::GetInstance()->GetLeftMargin();
		lTopMargin = CGeneralSetting::GetInstance()->GetTopMargin();
		CRect	rcClip(
			0,//lLeftMargin,
			lTopMargin,
			rcClient.Width(),
			rcClient.Height()
		);
		ScrollWindow(
			ptOldBox.x - ptNewBox.x,	// 水平方向にスクロールする量
			ptOldBox.y - ptNewBox.y,	// 垂直方向にスクロールする量
			NULL,						// スクロールするクライアント領域の部分
			&rcClip						// スクロールするクリッピング四角形
		);
	}
}








void CShitarabianView::DrawPage(
	CDC*	pDC,
	CRect*	prcRequest
)
{
	CEditDrawer*	pDrawer = GetDrawer();
	CShitarabianDoc* pDoc = GetDocument();

	long	lMaxScrollWidth = m_lMaxXPixel;
	long	iStartRow = m_idxUpdateStartRow;
	long	iEndRow = m_idxUpdateEndRow;

	// 表示領域取得
	CRect	rcClient;		// ウィンドウのクライアント
	CPoint	ptScrollBox;	// スクロールボックスの位置
	GetClientRect( &rcClient );
	ptScrollBox = GetDeviceScrollPosition();

	// 更新領域取得
	CRect	rcUpdate;		// 更新領域 [スクロールボックス座標] (-)
	if ( prcRequest != NULL )
	{
		rcUpdate = *prcRequest;
// ▼ (3177) BGN 2003.12.20 (moralog) DCのマッピング廃止に伴う修正
		rcUpdate.right = rcUpdate.left + rcClient.Width();
// ▽ oridinal BGN
//		rcUpdate.left -= CGeneralSetting::GetInstance()->GetLeftMargin();
//		rcUpdate.right -= CGeneralSetting::GetInstance()->GetLeftMargin();
// △ oridinal END
// ▲ (3177) END
		rcUpdate.top -= CGeneralSetting::GetInstance()->GetTopMargin();
		rcUpdate.bottom -= CGeneralSetting::GetInstance()->GetTopMargin();
	}
	else
	{
		// 更新矩形計算
		CRect		rcUpdateReq;
//		if ( pDC->GetClipBox( &rcUpdate ) == NULLREGION )
		{
			pDC->GetClipBox( &rcUpdateReq );
			rcUpdate.left = ptScrollBox.x;
			rcUpdate.right = rcUpdate.left + rcClient.Width();

			// 仮想座標上で使用する最大矩形を計算
			rcUpdate.top = 0;
			rcUpdate.bottom = 0;

			if ( iStartRow == AllRow )
			{
				rcUpdate.top = ptScrollBox.y;
			}
			else
			{
				if ( iStartRow != InitialRow )
				{
					rcUpdate.top = pDrawer->CaretRowToPixelZoomed( iStartRow );
					rcUpdate.top = max( ptScrollBox.y, rcUpdate.top );
				}
				if ( iEndRow != InitialRow )
				{
					rcUpdate.bottom = pDrawer->CaretRowToPixelZoomed( iEndRow );
					rcUpdate.bottom = min( rcUpdate.bottom, rcUpdate.top+rcClient.Height() );
				}
			}

			if( iEndRow == AllRow )
			{
				rcUpdate.bottom = ptScrollBox.y+rcClient.Height();
			}
		}
	}
	pDrawer->SetUpdateRect( rcUpdate );


	// 描画情報を構築する
	{
		int		iStartLine = pDrawer->PixelToCaretRowZoomed( rcUpdate.top, pDoc );
		int		iEndLine = pDrawer->PixelToCaretRowZoomed( rcUpdate.bottom, pDoc );

		TRACE( "CShitarabianView::DrawPage 再構築試行-> %d - %d\n", iStartLine, iEndLine );

		int		idxLine;
		for( idxLine=iStartLine ; idxLine<=iEndLine ; idxLine++ )
		{
			CEmphasisLine*	pLine = pDoc->GetEmphasisLine( idxLine );
			if ( pLine != NULL )
			{
				pLine->Analize();
			}
//			pDoc->AnalizeMultiLineEmphasis(
//				CGeneralSetting::GetInstance()->GetEmphasisDefine(),
//				idxLine
//			);
		}

		// 描画領域拡張
//		rcUpdate.bottom = max(
//			rcUpdate.bottom,
//			pDrawer->CaretRowToPixelZoomed( m_idxUpdateEndRow+1 )
//		);
	}

	// 画面全書き換えのタイミングでキャレットを作り直す。
	switch( pDoc->GetOperationMode() )
	{
	case OperationNormal:
		if ( m_bVisibleCaret )
		if ( !pDoc->IsOverwriteMode() )
		if ( iStartRow == 0 )
		if ( iEndRow == AllRow )
		{
			DestroyCaret();
			CreateSolidCaret(
				2*pDrawer->GetZoom(),
				pDrawer->GetBlankHeight() * pDrawer->GetZoom()
			);
			ShowCaret();
		}
		break;
	default:
		break;
	}

	// テキストの表示
	{
		HideCaret();

		CRgn	rgn;
		rgn.CreateRectRgn(
			0,
			CGeneralSetting::GetInstance()->GetTopMargin(),
			rcClient.right,
			rcClient.bottom
		);
		pDC->SelectClipRgn(
			&rgn,
			RGN_AND
		);

		// 表示行の計算
		int		iStartLine = pDrawer->PixelToCaretRowZoomed( rcUpdate.top, pDoc );
		int		iEndLine = pDrawer->PixelToCaretRowZoomed( rcUpdate.bottom, pDoc );

		int		idxLine;
		for( idxLine=iEndLine ; idxLine>=iStartLine ; idxLine-- )
		{
			// 行を描画
			long	lXPixel;
			lXPixel = pDrawer->DrawZoomedLine(
				pDoc,
				pDC,
				idxLine,
				ptScrollBox.x,
// ▼ (3177) BGN 2003.12.20 (moralog) DCのマッピング廃止に伴う修正
				pDrawer->CaretRowToPixelZoomed( idxLine ) - ptScrollBox.y
// ▽ oridinal BGN
//				pDrawer->CaretRowToPixelZoomed( idxLine )
// △ oridinal END
// ▲ (3177) END
			);

			lXPixel += pDrawer->GetEOFWidth()*pDrawer->GetZoom();
			if ( lXPixel > m_lMaxXPixel*pDrawer->GetZoom() )
			{
				m_lMaxXPixel = lXPixel/pDrawer->GetZoom();
			}
		}

		SetPrevVisibleRow(
			VisibleRowStart(),
			VisibleRowCount()
		);

		pDC->SelectClipRgn( NULL );
		rgn.DeleteObject();

		pDrawer->DrawRuler(
				pDC,
// ▼ (3632) BGN 2003.12.28 (moralog) キャレット位置の表示追加
				pDoc,
// ▲ (3632) END
// ▼ (3177) BGN 2003.12.20 (moralog) DCのマッピング廃止に伴う修正
				ptScrollBox.x,
// ▽ oridinal BGN
//				rcUpdate.left,
// △ oridinal END
// ▲ (3177) END
				ptScrollBox.y
		);

		// キャレットの表示
		if ( !pDoc->IsOverwriteMode() )
		{
			DrawCaret( pDC );
		}
	}

	// 表示内容の幅が変化していればスクロールバーを設定しなおす
	// 行数が変化していたときにも RecalcScrollBar() する必要がある。
	BOOL	bRecalcScrollBar = FALSE;
	if	( m_nRow != pDoc->GetLineCount() )
	{
		m_nRow = pDoc->GetLineCount();
		bRecalcScrollBar = TRUE;
	}
	if	( lMaxScrollWidth != m_lMaxXPixel )
	{
		bRecalcScrollBar = TRUE;
	}
	if ( bRecalcScrollBar )
	{
		RecalcScrollBar();
	}

	DrawStatusBar();


/*
	CEmphasysLine	Line;
	CEmphasisDefine*	pEmphasisDefine;
	pEmphasisDefine = CGeneralSetting::GetInstance()->GetEmphasisDefine();
	Line.SetString(
		*pDoc->GetLine( 0 )
	);
	Line.Draw(
		pDC,
		0,
		100,
		pEmphasisDefine,
		TRUE,
		TRUE,
		0,
		INT_MAX,
		FALSE
	);
*/

	// 描画必要領域の初期化
	m_idxUpdateStartRow = InitialRow;
	m_idxUpdateEndRow = InitialRow;

	// 更新領域未設定で呼ばれてしまう場合を検出するために
	// 使用後は初期化してみる。
// ▼ (ワーニング回避) BGN 2003.12.29 (moralog) warning C4239
	CRect	rcInit(0,0,0,0);
	pDrawer->SetUpdateRect( rcInit );
// ▽ original BGN
//	pDrawer->SetUpdateRect( CRect(0,0,0,0) );
// △ original END
// ▲ (ワーニング回避) END
}

void CShitarabianView::DrawStatusBar()
{
	CShitarabianDoc* pDoc = GetDocument();

	// 操作モードによってステータスバー表示を切り替える
	CSelection* pSelection = pDoc->GetSelection();
	switch( pDoc->GetOperationMode() )
	{
	case OperationNormal:
		if ( pSelection->IsSelected() )
		{
			// 選択中であれば選択情報を表示
			int idxStartRow = pSelection->GetSelectedStartRow();
			int idxEndRow = pSelection->GetSelectedEndRow();

			CString	str = pSelection->GetSelectedText();
			int	nRow = abs( idxStartRow - idxEndRow ) +1;
			int	nByte = str.GetLength();
			CString	strMes;
// ▼ (3184) BGN 2003.11.08 (moralog) カラム数表示追加
// ▽ original BGN 
//			strMes.Format( "選択中 %d行（ %dByte = %0.2fKB ）", nRow, nByte, (double)nByte/1024 );
//			m_pSystemStatusBar->SetWindowText( strMes );
// △ original END
			// カラム数計算
			int nColumn( 0 );
			{
				// 最初の行について追加
				if ( idxStartRow != idxEndRow )
				{
					CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxStartRow );
					if ( pEmphasisLine != NULL)
					{
						nColumn += pEmphasisLine->GetColumnCount() - pSelection->GetSelectedStartColumn();
					}
				}

				// １行丸ごと選択中の行について追加
				int	idxRow;
				for( idxRow=idxStartRow+1 ; idxRow<idxEndRow ; idxRow++ )
				{
					CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxRow );
					if ( pEmphasisLine != NULL)
					{
						nColumn += pEmphasisLine->GetColumnCount();
					}
				}

				// 最後の行について追加
				if ( idxStartRow != idxEndRow )
				{
					CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxEndRow );
					if ( pEmphasisLine != NULL)
					{
						nColumn += pSelection->GetSelectedEndColumn();
					}
				}

				// １行の場合について追加
				if ( idxStartRow == idxEndRow )
				{
					CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( idxStartRow );
					if ( pEmphasisLine != NULL)
					{
						nColumn += pSelection->GetSelectedEndColumn() - pSelection->GetSelectedStartColumn();
					}
				}
			}
			strMes.Format( _T("選択中 %d 行　%d カラム （ %dByte = %0.2fKB ）"), nRow, nColumn, nByte, (double)nByte/1024 );
// ▲ (3184) END
			m_pSystemStatusBar->SetWindowText( strMes );
		}
		else
		{
			// 選択中でなければキャレット情報を表示
			CString	strMes;
// ▼ (3199) BGN 2003.11.08 (moralog) データ読み込み前に表示更新しようとすると、存在しない行を見に行って落ちる
// ▼ (3184) BGN 2003.11.08 (moralog) 行表示を１からに変更
// ▽ original BGN 
//			strMes.Format( "%d/%d 行　%d/%d カラム",
//				pDoc->GetCaretRow(),
//				pDoc->GetLineCount(),
//				pDoc->GetCaretColumn(),
//				pDoc->GetEmphasisLine( pDoc->GetCaretRow() )->GetColumnCount()
//			);
// △ original END
			CEmphasisLine*	pEmphasisLine = pDoc->GetEmphasisLine( pDoc->GetCaretRow() );
			if ( pEmphasisLine != NULL)
			{
				strMes.Format( _T("%d/%d 行　%d/%d カラム"),
					pDoc->GetCaretRow()+1,
					pDoc->GetLineCount(),
					pDoc->GetCaretColumn(),
					pEmphasisLine->GetColumnCount()
				);
			}
// ▲ (3184) END
// ▲ (3199) END

			m_pSystemStatusBar->SetWindowText( strMes );
		}
		break;

	case OperationBoxSelect:
		m_pSystemStatusBar->SetWindowText( "BOX選択" );
		break;

	case OperationFloating:
		m_pSystemStatusBar->SetWindowText( "フローティング貼り付け" );
		break;

	case OperationROI:
		{
			CRect	rcROI = pDoc->GetROISelection()->GetROI();
			rcROI.NormalizeRect();
			CString	strMes;
			strMes.Format( "ROI:( %d, %d )-( %d, %d ) width=%d, height=%d",
				rcROI.left,rcROI.top,
				rcROI.right, rcROI.bottom,
				rcROI.Width(), rcROI.Height()
			);
			m_pSystemStatusBar->SetWindowText( strMes );
		}
		break;

	default:
		break;
	}

    // 上書きモード
	{
		CString		strOverWriteMode;
		if ( pDoc->IsOverwriteMode() )
		{
			strOverWriteMode.LoadString( IDS_MODE_OVERWRITE );
		}
		else
		{
			strOverWriteMode.LoadString( IDS_MODE_INSERT );
		}
		if ( m_pSystemStatusBar != NULL )
		{
			m_pSystemStatusBar->SetPaneText( m_pSystemStatusBar->CommandToIndex( IDS_STATUS_OVERWRITE ), strOverWriteMode );
		}
	}

	// 選択モード
	{
		CString		strOperationMode;
		switch( pDoc->GetOperationMode() )
		{
		case OperationBoxSelect:
			strOperationMode.LoadString( IDS_MODE_BOXSELECT );
			break;

		case OperationFloating:
			strOperationMode.LoadString( IDS_MODE_FLOATING );
			break;

		case OperationNormal:
			strOperationMode.LoadString( IDS_MODE_NORMAL );
			break;

		case OperationROI:
			strOperationMode.LoadString( IDS_MODE_ROI );
			break;

		default:
			strOperationMode.Empty();
			break;
		}
		if ( m_pSystemStatusBar != NULL )
		{
			m_pSystemStatusBar->SetPaneText( m_pSystemStatusBar->CommandToIndex( IDS_STATUS_OPERATION ), strOperationMode );
		}
	}
}

void CShitarabianView::RecalcScrollBar() 
{
	CEditDrawer*	pDrawer = GetDrawer();
	CShitarabianDoc* pDoc = GetDocument();

	int	lCharWidth = pDrawer->GetBlankWidth();
	int	iLineHeight = pDrawer->CaretRowToPixelZoomed( 1 );

	CRect	rcClient;		// ウィンドウのクライアント
	GetClientRect( &rcClient );

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

	// ページの大きさ
	CSize	sizePage(
		rcClient.Width(),
		rcClient.Height()
	);

	// ドキュメント全体の大きさ
	CSize	sizeDocument(
		lLeftMargin+ m_lMaxXPixel*pDrawer->GetZoom(),
		pDoc->GetLineCount() * iLineHeight + rcClient.Height()
	);

	// 矢印を押したときの移動量
	CSize	sizeLine(
		lCharWidth,
		iLineHeight
	);

	SetScrollSizes(
		sizeDocument,
		sizePage,
		sizeLine
	);
}


void CShitarabianView::ManualHScroll( long lPos ) 
{
	CSplitterWnd*	pSplitter = ((CMainFrame*)::AfxGetMainWnd())->GetSplitter();

	// ▼ (3146) BGN 2003.11.21 (dincom) ペインの存在チェック
	if ( pSplitter->GetColumnCount() * pSplitter->GetRowCount() > 0 )
	// ▲ (3146) END
	{
		int	iRow;
		int	iColumn;

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

		CPoint	ptOld;
		ptOld = GetDeviceScrollPosition();
		CPoint	ptNew = ptOld;
		ptNew.x = lPos;
 		SetDeviceScrollPosition( ptNew );

		pSplitter->DoScrollBy( this, ptOld.x-ptNew.x );
		for ( int idxRow=0 ; idxRow<pSplitter->GetRowCount() ; idxRow++ )
		{
			CWnd*	pWnd = pSplitter->GetPane( idxRow, iColumn );
			((CShitarabianView*)pWnd)->HScrollCore(
				SB_THUMBPOSITION,
				lPos,
				GetScrollBarCtrl( SB_HORZ ),
				ptOld
			);
		}
	}
}




void CShitarabianView::ManualVScroll( long lPos ) 
{
	CSplitterWnd*	pSplitter = ((CMainFrame*)::AfxGetMainWnd())->GetSplitter();

	// ▼ (3146) BGN 2003.11.21 (dincom) ペインの存在チェック
	if ( pSplitter->GetColumnCount() * pSplitter->GetRowCount() > 0 )
	// ▲ (3146) END
	{
		int	iRow;
		int	iColumn;
		pSplitter->GetActivePane(
			&iRow,
			&iColumn
		);

		CPoint	ptOld;
		ptOld = GetDeviceScrollPosition();
		CPoint	ptNew = ptOld;
		ptNew.y = lPos;
 		SetDeviceScrollPosition( ptNew );

		for ( int idxColumn=0 ; idxColumn<pSplitter->GetColumnCount() ; idxColumn++ )
		{
			CWnd*	pWnd = pSplitter->GetPane( iRow, idxColumn );
			((CShitarabianView*)pWnd)->VScrollCore(
				SB_THUMBPOSITION,
				lPos,
				GetScrollBarCtrl( SB_VERT ),
				ptOld
			);
		}
	}
}


void CShitarabianView::VScrollCore(
	UINT		nSBCode,
	UINT		nPos,
	CScrollBar*	pScrollBar,
	CPoint		ptOldScroll
)
{
	// warning C4100:警告の無視
	pScrollBar; nPos; 

	CEditDrawer*		pDrawer = GetDrawer();
	int	lRowHeight = pDrawer->GetBlankHeight() + CGeneralSetting::GetInstance()->GetRowGap();
	lRowHeight *= pDrawer->GetZoom();

	CRect		rcClient;
	GetClientRect( &rcClient );

	CPoint		ptMyPaneOldScroll = GetDeviceScrollPosition();
	ptOldScroll.x = ptMyPaneOldScroll.x;

	BOOL	bNeedReDraw = FALSE;
	// SetFocusと描画がかち合うのはまずいのでとりあえず
	// サムをクリックしてSetFocus()したときには処理しない。please!こんなんでいいのか？
	if ( m_idxUpdateStartRow == InitialRow )
	if ( m_idxUpdateEndRow == InitialRow )
	{
		bNeedReDraw = TRUE;
	}

	CPoint		ptScroll = ptOldScroll;
	int			iPos = ptScroll.y;

	switch( nSBCode )
	{
	case SB_TOP:		
		break;
	case SB_BOTTOM:			// Scroll to bottom.
		break;
	case SB_ENDSCROLL:		// End scroll.
		return;
		break;
	case SB_LINEDOWN:		// Scroll one line down.
		switch( CGeneralSetting::GetInstance()->GetVScrollUnit() )
		{
		case Scroll1Pixel:
			iPos += 1;
			break;
		case Scroll1Row:
			iPos += lRowHeight;
			break;
		case Scroll2Row:
			iPos += lRowHeight*2;
			break;
		default:
			break;
		}
		break;
	case SB_LINEUP:			// Scroll one line up.
		switch( CGeneralSetting::GetInstance()->GetVScrollUnit() )
		{
		case Scroll1Pixel:
			iPos -= 1;
			break;
		case Scroll1Row:
			iPos -= lRowHeight;
			break;
		case Scroll2Row:
			iPos -= lRowHeight*2;
			break;
		default:
			break;
		}
		break;
	case SB_PAGEDOWN:		// Scroll one page down.
		iPos += rcClient.Height();
		break;
	case SB_PAGEUP:			// Scroll one page up.
		iPos -= rcClient.Height();
		break;
	case SB_THUMBPOSITION:	// Scroll to the absolute position. The current position is provided in nPos.
	case SB_THUMBTRACK:		// Drag scroll box to specified position. The current position is provided in nPos.
		{
			SCROLLINFO	tInfo;
			GetScrollInfo( SB_VERT, &tInfo );
			iPos = tInfo.nTrackPos;
		}
		break;
	default:
		break;
	}

	ptScroll.y = iPos;

	// スクロールボックス内の画像をずらす＆必要な領域を再描画
	UpdateScrollBox(
		ptOldScroll,
		ptScroll,
		rcClient
	);
 	SetDeviceScrollPosition( ptScroll );

// ▼ (ワーニング回避) BGN 2003.12.29 (moralog) warning C4189
/*
// ▽ original BGN
	// 再描画
	CShitarabianDoc* pDoc = GetDocument();
	if ( bNeedReDraw )
	{
//		pDoc->ReDraw( this );
	}
// △ original END
*/
// ▲ (ワーニング回避) END
}


void CShitarabianView::HScrollCore(
	UINT		nSBCode,
	UINT		nPos,
	CScrollBar*	pScrollBar,
	CPoint		ptOldScroll
)
{
	// warning C4100:警告の無視
	pScrollBar; nPos; 

	CEditDrawer*		pDrawer = GetDrawer();
	int	lCharWidth = pDrawer->GetBlankWidth();
	lCharWidth *= pDrawer->GetZoom();

	CPoint		ptMyPaneOldScroll = GetDeviceScrollPosition();
	ptOldScroll.y = ptMyPaneOldScroll.y;

	CRect		rcClient;
	GetClientRect( &rcClient );

//	BOOL	bNeedReDraw = TRUE;
	// SetFocusと描画がかち合うのはまずいのでとりあえず
	// サムをクリックしてSetFocus()したときには処理しない。please!こんなんでいいのか？
	if ( m_idxUpdateStartRow != InitialRow )
	if ( m_idxUpdateEndRow != InitialRow )
	{
//		bNeedReDraw = FALSE;
	}

	CPoint		ptScroll = ptOldScroll;
	int			iPos = ptScroll.x;

	switch( nSBCode )
	{
	case SB_TOP:		
		break;
	case SB_BOTTOM:			// Scroll to bottom.
		break;
	case SB_ENDSCROLL:		// End scroll.
		break;
	case SB_LINEDOWN:		// Scroll one line down.
		switch( CGeneralSetting::GetInstance()->GetHScrollUnit() )
		{
		case Scroll1Pixel:
			iPos += 1;
			break;
		case Scroll1Char:
			iPos += lCharWidth;
			break;
		case Scroll2Char:
			iPos += lCharWidth*2;
			break;
		default:
			break;
		}
		break;
	case SB_LINEUP:			// Scroll one line up.
		switch( CGeneralSetting::GetInstance()->GetHScrollUnit() )
		{
		case Scroll1Pixel:
			iPos -= 1;
			break;
		case Scroll1Char:
			iPos -= lCharWidth;
			break;
		case Scroll2Char:
			iPos -= lCharWidth*2;
			break;
		default:
			break;
		}
		break;
	case SB_PAGEDOWN:		// Scroll one page down.
		iPos += rcClient.Width();
		break;
	case SB_PAGEUP:			// Scroll one page up.
		iPos -= rcClient.Width();
		break;
	case SB_THUMBPOSITION:	// Scroll to the absolute position. The current position is provided in nPos.
	case SB_THUMBTRACK:		// Drag scroll box to specified position. The current position is provided in nPos.
		{
			SCROLLINFO	tInfo;
			GetScrollInfo( SB_HORZ, &tInfo );
			iPos = tInfo.nTrackPos;
		}
		break;
	default:
		break;
	}

	ptScroll.x = iPos;

	// スクロールボックス内の画像をずらす＆必要な領域を再描画
/*
	UpdateScrollBox(
		ptOldScroll,
		ptScroll,
		rcClient
	);
*/
	SetDeviceScrollPosition( ptScroll );

	// 再描画
	CShitarabianDoc* pDoc = GetDocument();
//	if ( bNeedReDraw )
	{
		// 横スクロールのときは強制的にすべてを描画
		pDoc->SetAllUpdate();
		pDoc->ReDraw( this );
	}
}


void CShitarabianView::DrawToROI(
	CDC*		pDstDC,
	int			iDstLeft,
	int			iDstTop,
	CRect		rcSrc
) 
{
	CEditDrawer*		pDrawer = CEditDrawer::GetInstance();
	CShitarabianDoc*	pDoc = GetDocument();

	// ページ内行数
	int		iLineHeight = pDrawer->CaretRowToPixel( 1 );

	// 印刷する総行数
	int		iStartLine = rcSrc.top / iLineHeight;
	int		iEndLine = rcSrc.bottom / iLineHeight;

	// メモリＤＣ作成
	CBitmap*	pOldBitmap;
	CDC			MemDC;
	CDC*		pSrcDC = GetDC();
	{
		MemDC.CreateCompatibleDC ( pSrcDC );
		CBitmap		MemBitmap;
		MemBitmap.CreateCompatibleBitmap(
			pSrcDC,
			rcSrc.Width(),
			rcSrc.Height()
		);
		pOldBitmap = MemDC.SelectObject( &MemBitmap );

		COLORREF	colBack = ::GetBackColor( EMPHASIS_TEXT );
		MemDC.FillSolidRect(
			0,0,
			rcSrc.Width(),
			rcSrc.Height(),
			colBack
		);
		MemDC.SetMapMode( MM_TEXT );
	}

	// テキストの表示
	pDrawer->SetUpdateRect( rcSrc );
	int		idxLine;
	for( idxLine=iStartLine ; idxLine<=iEndLine ; idxLine++ )
	{
		int		iRow = idxLine - iStartLine;

		// 行を描画
		{
			CString*			pstr = pDoc->GetLine( idxLine );
			if ( pstr != NULL )
			{
				long boom = iRow * iLineHeight;
				boom -= ( rcSrc.top - iStartLine*iLineHeight );
				CPoint	pt;
				pt.x = -rcSrc.left;
				pt.y = boom;
				pDrawer->SetDstX( pt.x );
				pDrawer->SetDstY( pt.y );

				long	lXPixel;

				lXPixel = pDrawer->DrawPlaneLine(
						pDoc,
						&MemDC,
						idxLine,
//						rcSrc.Width(),
						FALSE
				);
			}
		}
	}
// ▼ (ワーニング回避) BGN 2003.12.29 (moralog) warning C4239
	CRect	rcInit(0,0,0,0);
	pDrawer->SetUpdateRect( rcInit );
// ▽ original BGN
//	pDrawer->SetUpdateRect( CRect(0,0,0,0) );
// △ original END
// ▲ (ワーニング回避) END

	pDstDC->BitBlt(
		iDstLeft,
		iDstTop,
		rcSrc.Width(),
		rcSrc.Height(),
		&MemDC,
		0,
		0,
		SRCCOPY
	);

	MemDC.SelectObject( pOldBitmap );

	ReleaseDC( pSrcDC );
}

// ▼ (3367) BGN 2004.02.09 (dincom)
/*-----------------------------------------------------------------------------
[名称]	プログレスバー表示状態取得
[機能]	プログレスバーの表示状態を取得する
[戻値]	BOOL 
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CShitarabianView::IsProgress()
{
	CMainFrame* pMainFrm = (CMainFrame*)::AfxGetMainWnd();

	if( (pMainFrm->GetProgressDlg())->IsWindowVisible() )
	{
		return TRUE;
	}
	if( (pMainFrm->GetGrepProgressDlg())->IsWindowVisible() )
	{
		return TRUE;
	}

	return FALSE;
}
// ▲ (3367) END

// ▼ (3204) BGN 2004.05.10 (moralog) ランチャツールバー追加
/*-----------------------------------------------------------------------------
[名称]	いきなり選択
[機能]	未選択状態のとき、キャッレト下のトークンを選択する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CShitarabianView::SelectMagicRod()
{
	CShitarabianDoc* pDoc = GetDocument();
	CSelection*	pSelection = pDoc->GetSelection();
	if ( !pSelection->IsSelected() )
	{
		SelectToken();
	}
}
// ▲ (3204) END
