File Annotation

Not logged in
dcdd144598 2011-02-23        kinaba: #include "stdafx.h"
dcdd144598 2011-02-23        kinaba: #include "ip_view.h"
dcdd144598 2011-02-23        kinaba: using namespace editwing;
dcdd144598 2011-02-23        kinaba: using namespace editwing::view;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //=========================================================================
dcdd144598 2011-02-23        kinaba: //---- ip_wrap.cpp   折り返し
dcdd144598 2011-02-23        kinaba: //
dcdd144598 2011-02-23        kinaba: //		Documentで文字列データが更新されるのを受けて
dcdd144598 2011-02-23        kinaba: //		Viewでは折り返し位置情報を更新する。その処理がココ。
dcdd144598 2011-02-23        kinaba: //
dcdd144598 2011-02-23        kinaba: //---- ip_text.cpp   文字列操作・他
dcdd144598 2011-02-23        kinaba: //---- ip_parse.cpp  キーワード解析
dcdd144598 2011-02-23        kinaba: //---- ip_scroll.cpp スクロール
dcdd144598 2011-02-23        kinaba: //---- ip_draw.cpp   描画・他
dcdd144598 2011-02-23        kinaba: //---- ip_cursor.cpp カーソルコントロール
dcdd144598 2011-02-23        kinaba: //=========================================================================
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: // 初期化
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: ViewImpl::ViewImpl( View& vw, DocImpl& dc )
dcdd144598 2011-02-23        kinaba: 	: doc_   ( dc )
dcdd144598 2011-02-23        kinaba: 	, cvs_   ( vw )
dcdd144598 2011-02-23        kinaba: 	, cur_   ( vw.hwnd(), *this, dc )
dcdd144598 2011-02-23        kinaba: 	, hwnd_  ( vw.hwnd() )
dcdd144598 2011-02-23        kinaba: 	, vlNum_ ( 0 )
dcdd144598 2011-02-23        kinaba: 	, textCx_( 0 )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 適当に折り返し情報初期化
dcdd144598 2011-02-23        kinaba: 	InsertMulti( 0, doc_.tln()-1 );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 適当にスクロール情報初期化
dcdd144598 2011-02-23        kinaba: 	udScr_.cbSize = rlScr_.cbSize = sizeof(udScr_);
dcdd144598 2011-02-23        kinaba: 	udScr_.fMask  = rlScr_.fMask  = SIF_PAGE | SIF_POS | SIF_RANGE;
dcdd144598 2011-02-23        kinaba: 	udScr_.nMin   = rlScr_.nMin   = 0;
dcdd144598 2011-02-23        kinaba: 	udScr_.nPos   = rlScr_.nPos   = 0;
dcdd144598 2011-02-23        kinaba: 	udScr_.fMask |= SIF_DISABLENOSCROLL;
dcdd144598 2011-02-23        kinaba: 	udScr_tl_     = udScr_vrl_    = 0;
dcdd144598 2011-02-23        kinaba: 	ReSetScrollInfo();
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: // 状態変更への対応
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void ViewImpl::DoResize( bool wrapWidthChanged )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 折り返し位置再計算
dcdd144598 2011-02-23        kinaba: 	if( wrapWidthChanged )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		ReWrapAll();
dcdd144598 2011-02-23        kinaba: 		UpdateTextCx();
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// スクロール情報変更
dcdd144598 2011-02-23        kinaba: 	ReSetScrollInfo();
dcdd144598 2011-02-23        kinaba: 	if( wrapWidthChanged )
dcdd144598 2011-02-23        kinaba: 		ForceScrollTo( udScr_tl_ );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 再描画
dcdd144598 2011-02-23        kinaba: 	ReDraw( ALL );
dcdd144598 2011-02-23        kinaba: 	cur_.ResetPos();
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void ViewImpl::DoConfigChange()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 折り返し位置再計算
dcdd144598 2011-02-23        kinaba: 	ReWrapAll();
dcdd144598 2011-02-23        kinaba: 	UpdateTextCx();
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// スクロール情報変更
dcdd144598 2011-02-23        kinaba: 	ReSetScrollInfo();
dcdd144598 2011-02-23        kinaba: 	ForceScrollTo( udScr_tl_ );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 再描画
dcdd144598 2011-02-23        kinaba: 	ReDraw( ALL );
dcdd144598 2011-02-23        kinaba: 	cur_.ResetPos();
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void ViewImpl::on_text_update
dcdd144598 2011-02-23        kinaba: 	( const DPos& s, const DPos& e, const DPos& e2, bool bAft, bool mCur )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// まず、折り返し位置再計算
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 置換範囲の先頭行を調整
dcdd144598 2011-02-23        kinaba: 	int r3 = 0, r2 = 1, r1 = ReWrapSingle( s );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 残りを調整
dcdd144598 2011-02-23        kinaba: 	if( s.tl != e.tl )
dcdd144598 2011-02-23        kinaba: 		r2 = DeleteMulti( s.tl+1,  e.tl );
dcdd144598 2011-02-23        kinaba: 	if( s.tl != e2.tl )
dcdd144598 2011-02-23        kinaba: 		r3 = InsertMulti( s.tl+1, e2.tl );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// この変更で横幅が…
dcdd144598 2011-02-23        kinaba: 	// if( "長くなったなてはいない" AND "短くなっちゃった可能性あり" )
dcdd144598 2011-02-23        kinaba: 	//     横幅再計算();
dcdd144598 2011-02-23        kinaba: 	if( !(r1==2 || r3==1) && (r1==0 || r2==0) )
dcdd144598 2011-02-23        kinaba: 		UpdateTextCx();
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// スクロールバー修正
dcdd144598 2011-02-23        kinaba: 	ReDrawType t = TextUpdate_ScrollBar( s, e, e2 );
dcdd144598 2011-02-23        kinaba: 	bool doResize = false;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 行数に変化があって、行番号表示域の幅を変えなきゃならん時
dcdd144598 2011-02-23        kinaba: 	if( e.tl!=e2.tl && cvs_.on_tln_change( doc_.tln() ) )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		doResize = true;
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else if( bAft && t!=ALL )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		t = AFTER;
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// カーソル移動
dcdd144598 2011-02-23        kinaba: 	cur_.on_text_update( s, e, e2, mCur );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 再描画
dcdd144598 2011-02-23        kinaba: 	if( doResize )
dcdd144598 2011-02-23        kinaba: 		DoResize( true );
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		if( e.tl != e2.tl ) // 行番号領域再描画の必要があるとき
dcdd144598 2011-02-23        kinaba: 			ReDraw( LNAREA, 0 );
dcdd144598 2011-02-23        kinaba: 		ReDraw( t, &s );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: // 折り返し位置計算補助ルーチン
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void ViewImpl::UpdateTextCx()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	if( cvs_.wrapType() == NOWRAP )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		// 折り返しなしなら、数えてみないと横幅はわからない
dcdd144598 2011-02-23        kinaba: 		ulong cx=0;
dcdd144598 2011-02-23        kinaba: 		for( ulong i=0, ie=doc_.tln(); i<ie; ++i )
dcdd144598 2011-02-23        kinaba: 			if( cx < wrap_[i].width() )
dcdd144598 2011-02-23        kinaba: 				cx = wrap_[i].width();
dcdd144598 2011-02-23        kinaba: 		textCx_ = cx;
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		// 折り返しありなら、横幅:=折り返し幅とする
dcdd144598 2011-02-23        kinaba: 		textCx_ = cvs_.wrapWidth();
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: ulong ViewImpl::CalcLineWidth( const unicode* txt, ulong len ) const
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 行を折り返さずに書いたときの横幅を計算する
dcdd144598 2011-02-23        kinaba: 	// ほとんどの行が折り返し無しで表示されるテキストの場合、
dcdd144598 2011-02-23        kinaba: 	// この値を計算しておくことで、処理の高速化が可能。
dcdd144598 2011-02-23        kinaba: 	const Painter& p = cvs_.getPainter();
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	ulong w=0;
dcdd144598 2011-02-23        kinaba: 	for( ulong i=0; i<len; ++i )
dcdd144598 2011-02-23        kinaba: 		if( txt[i] == L'\t' )
dcdd144598 2011-02-23        kinaba: 			w = p.nextTab(w);
dcdd144598 2011-02-23        kinaba: 		else
dcdd144598 2011-02-23        kinaba: 			w += p.W( &txt[i] );
dcdd144598 2011-02-23        kinaba: 	return w;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void ViewImpl::CalcEveryLineWidth()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 全ての行に対してCalcLineWidthを実行
dcdd144598 2011-02-23        kinaba: 	// …するだけ。
dcdd144598 2011-02-23        kinaba: 	for( ulong i=0, ie=doc_.tln(); i<ie; ++i )
dcdd144598 2011-02-23        kinaba: 		wrap_[i].width() = CalcLineWidth( doc_.tl(i), doc_.len(i) );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void ViewImpl::ModifyWrapInfo(
dcdd144598 2011-02-23        kinaba: 		const unicode* txt, ulong len, WLine& wl, ulong stt )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 設定幅での折り返しを実行する。
dcdd144598 2011-02-23        kinaba: 	// 行の途中からの変更の場合、sttが開始addressを指している
dcdd144598 2011-02-23        kinaba: 	const Painter& p = cvs_.getPainter();
dcdd144598 2011-02-23        kinaba: 	const ulong   ww = cvs_.wrapWidth();
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	while( stt < len )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		ulong i, w;
dcdd144598 2011-02-23        kinaba: 		for( w=0,i=stt; i<len; ++i )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			if( txt[i] == L'\t' )
dcdd144598 2011-02-23        kinaba: 				w = p.nextTab(w);
dcdd144598 2011-02-23        kinaba: 			else
dcdd144598 2011-02-23        kinaba: 				w += p.W( &txt[i] );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 			if( w>ww )
dcdd144598 2011-02-23        kinaba: 				break; // 幅が設定値を超えた所でおしまい
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 		wl.Add( stt = (i==stt?i+1:i) );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: int ViewImpl::GetLastWidth( ulong tl ) const
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	if( rln(tl)==1 )
dcdd144598 2011-02-23        kinaba: 		return wrap_[tl][0];
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	ulong beg = rlend(tl,rln(tl)-2);
dcdd144598 2011-02-23        kinaba: 	return CalcLineWidth( doc_.tl(tl)+beg, doc_.len(tl)-beg );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void ViewImpl::ReWrapAll()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 折り返し幅に変更があった場合に、全ての行の
dcdd144598 2011-02-23        kinaba: 	// 折り返し位置情報を変更する。
dcdd144598 2011-02-23        kinaba: 	const ulong ww = cvs_.wrapWidth();
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	ulong vln=0;
dcdd144598 2011-02-23        kinaba: 	for( ulong i=0, ie=doc_.tln(); i<ie; ++i )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		WLine& wl = wrap_[i];
dcdd144598 2011-02-23        kinaba: 		wl.ForceSize(1);
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		if( wl.width() < ww )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			// 設定した折り返し幅より短い場合は一行で済む。
dcdd144598 2011-02-23        kinaba: 			wl.Add( doc_.len(i) );
dcdd144598 2011-02-23        kinaba: 			++vln;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 		else
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			// 複数行になる場合
dcdd144598 2011-02-23        kinaba: 			ModifyWrapInfo( doc_.tl(i), doc_.len(i), wl, 0 );
dcdd144598 2011-02-23        kinaba: 			vln += wl.rln();
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	vlNum_ = vln;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: // 折り返し位置計算メインルーチン
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: int ViewImpl::ReWrapSingle( const DPos& s )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 指定した一行のみ折り返しを修正。
dcdd144598 2011-02-23        kinaba: 	//
dcdd144598 2011-02-23        kinaba: 	// 返値は
dcdd144598 2011-02-23        kinaba: 	//   2: "折り返しあり" or "この行が横に一番長くなった"
dcdd144598 2011-02-23        kinaba: 	//   1: "この行以外のどこかが最長"
dcdd144598 2011-02-23        kinaba: 	//   0: "さっきまでこの行は最長だったが短くなっちゃった"
dcdd144598 2011-02-23        kinaba: 	// で、上位ルーチンにm_TextCx修正の必要性を伝える。
dcdd144598 2011-02-23        kinaba: 	//
dcdd144598 2011-02-23        kinaba: 	// 昔は再描画範囲の計算のために、表示行数の変化を返していたが、
dcdd144598 2011-02-23        kinaba: 	// これは上位ルーチン側で vln() を比較すれば済むし、
dcdd144598 2011-02-23        kinaba: 	// むしろその方が効率的であるため廃止した。
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 旧情報保存
dcdd144598 2011-02-23        kinaba: 	WLine& wl            = wrap_[s.tl];
dcdd144598 2011-02-23        kinaba: 	const ulong oldVRNum = wl.rln();
dcdd144598 2011-02-23        kinaba: 	const ulong oldWidth = wl.width();
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 横幅更新
dcdd144598 2011-02-23        kinaba: 	wl.width() = CalcLineWidth( doc_.tl(s.tl), doc_.len(s.tl) );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	if( wl.width() < cvs_.wrapWidth() )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		// 設定した折り返し幅より短い場合は一行で済む。
dcdd144598 2011-02-23        kinaba: 		wl[1] = doc_.len(s.tl);
dcdd144598 2011-02-23        kinaba: 		wl.ForceSize( 2 );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		// 複数行になる場合
dcdd144598 2011-02-23        kinaba: 		ulong vr=1, stt=0;
dcdd144598 2011-02-23        kinaba: 		while( wl[vr] < s.ad ) // while( vr行目は変更箇所より手前 )
dcdd144598 2011-02-23        kinaba: 			stt = wl[ vr++ ];  // stt = 次の行の行頭のアドレス
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		// 変更箇所以降のみ修正
dcdd144598 2011-02-23        kinaba: 		wl.ForceSize( vr );
dcdd144598 2011-02-23        kinaba: 		ModifyWrapInfo( doc_.tl(s.tl), doc_.len(s.tl), wl, stt );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 表示行の総数を修正
dcdd144598 2011-02-23        kinaba: 	vlNum_ += ( wl.rln() - oldVRNum );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 折り返しなしだと総横幅の更新が必要
dcdd144598 2011-02-23        kinaba: 	if( cvs_.wrapType() == NOWRAP )
dcdd144598 2011-02-23        kinaba: 		if( textCx_ <= wl.width() )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			textCx_ = wl.width();
dcdd144598 2011-02-23        kinaba: 			return 2;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 		else if( textCx_ == oldWidth )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			return 0;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 		else
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			return 1;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 	return 2;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: int ViewImpl::InsertMulti( ulong ti_s, ulong ti_e )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 指定した分だけ新しく行情報を追加。
dcdd144598 2011-02-23        kinaba: 	// &折り返し情報もきちんと計算
dcdd144598 2011-02-23        kinaba: 	//
dcdd144598 2011-02-23        kinaba: 	// 返値は
dcdd144598 2011-02-23        kinaba: 	//   1: "折り返しあり" or "この行が横に一番長くなった"
dcdd144598 2011-02-23        kinaba: 	//   0: "この行以外のどこかが最長"
dcdd144598 2011-02-23        kinaba: 	// 詳しくは ReWrapSingle() を見よ。
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	ulong dy=0, cx=0;
dcdd144598 2011-02-23        kinaba: 	for( ulong i=ti_s; i<=ti_e; ++i )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		WLine* pwl = new WLine;
dcdd144598 2011-02-23        kinaba: 		pwl->Add( CalcLineWidth( doc_.tl(i), doc_.len(i) ) );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		if( pwl->width() < cvs_.wrapWidth() )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			// 設定した折り返し幅より短い場合は一行で済む。
dcdd144598 2011-02-23        kinaba: 			pwl->Add( doc_.len(i) );
dcdd144598 2011-02-23        kinaba: 			dy++;
dcdd144598 2011-02-23        kinaba: 			if( cx < pwl->width() )
dcdd144598 2011-02-23        kinaba: 				cx = pwl->width();
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 		else
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			// 複数行になる場合
dcdd144598 2011-02-23        kinaba: 			ModifyWrapInfo( doc_.tl(i), doc_.len(i), *pwl, 0 );
dcdd144598 2011-02-23        kinaba: 			dy += pwl->rln();
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		wrap_.InsertAt( i, pwl );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 表示行の総数を修正
dcdd144598 2011-02-23        kinaba: 	vlNum_ += dy;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 折り返しなしだと総横幅の更新が必要
dcdd144598 2011-02-23        kinaba: 	if( cvs_.wrapType() == NOWRAP )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		if( textCx_ <= cx )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			textCx_ = cx;
dcdd144598 2011-02-23        kinaba: 			return 1;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 		return 0;
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	return 1;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: int ViewImpl::DeleteMulti( ulong ti_s, ulong ti_e )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 指定した範囲の行情報を削除
dcdd144598 2011-02-23        kinaba: 	//
dcdd144598 2011-02-23        kinaba: 	// 返値は
dcdd144598 2011-02-23        kinaba: 	//   1: "折り返しあり" or "この行以外のどこかが最長"
dcdd144598 2011-02-23        kinaba: 	//   0: "さっきまでこの行は最長だったが短くなっちゃった"
dcdd144598 2011-02-23        kinaba: 	// 詳しくは ReWrapSingle() を見よ。
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	bool  widthChanged = false;
dcdd144598 2011-02-23        kinaba: 	ulong dy = 0;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 情報収集しながら削除
dcdd144598 2011-02-23        kinaba: 	for( ulong cx=textCx_, i=ti_s; i<=ti_e; ++i )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		WLine& wl = wrap_[i];
dcdd144598 2011-02-23        kinaba: 		dy += wl.rln();
dcdd144598 2011-02-23        kinaba: 		if( cx == wl.width() )
dcdd144598 2011-02-23        kinaba: 			widthChanged = true;
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	wrap_.RemoveAt( ti_s, (ti_e-ti_s+1) );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 表示行の総数を修正
dcdd144598 2011-02-23        kinaba: 	vlNum_ -= dy;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 折り返しなしだと総横幅の更新が必要
dcdd144598 2011-02-23        kinaba: 	return ( cvs_.wrapType()==NOWRAP && widthChanged ) ? 0 : 1;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: // 座標値変換
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void ViewImpl::ConvDPosToVPos( DPos dp, VPos* vp, const VPos* base ) const
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 補正
dcdd144598 2011-02-23        kinaba: 	dp.tl = Min( dp.tl, doc_.tln()-1 );
dcdd144598 2011-02-23        kinaba: 	dp.ad = Min( dp.ad, doc_.len(dp.tl) );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 変換の基準点が指定されていなければ、原点を基準とする
dcdd144598 2011-02-23        kinaba: 	VPos topPos(false); // 0クリア
dcdd144598 2011-02-23        kinaba: 	if( base == NULL )
dcdd144598 2011-02-23        kinaba: 		base = &topPos;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// とりあえずbase行頭の値を入れておく
dcdd144598 2011-02-23        kinaba: 	ulong vl = base->vl - base->rl;
dcdd144598 2011-02-23        kinaba: 	ulong rl = 0;
dcdd144598 2011-02-23        kinaba: 	int vx;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 同じ行内だった場合
dcdd144598 2011-02-23        kinaba: 	//if( dp.tl == base->tl )
dcdd144598 2011-02-23        kinaba: 	//{
dcdd144598 2011-02-23        kinaba: 	//	例えば [→] を押したときなど、右隣の文字の横幅を
dcdd144598 2011-02-23        kinaba: 	//	足すだけで次の位置は算出できる。これを使って普通の
dcdd144598 2011-02-23        kinaba: 	//	カーソル移動はずっと高速化できるはずであるが、
dcdd144598 2011-02-23        kinaba: 	//	とりあえず面倒くさいので、今のところ略。
dcdd144598 2011-02-23        kinaba: 	//}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 違う行だった場合
dcdd144598 2011-02-23        kinaba: 	//else
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		// vlを合わせる
dcdd144598 2011-02-23        kinaba: 		ulong tl = base->tl;
dcdd144598 2011-02-23        kinaba: 		if( tl > dp.tl )      // 目的地が基準より上にある場合
dcdd144598 2011-02-23        kinaba: 			do
dcdd144598 2011-02-23        kinaba: 				vl -= rln(--tl);
dcdd144598 2011-02-23        kinaba: 			while( tl > dp.tl );
dcdd144598 2011-02-23        kinaba: 		else if( tl < dp.tl ) // 目的地が基準より下にある場合
dcdd144598 2011-02-23        kinaba: 			do
dcdd144598 2011-02-23        kinaba: 				vl += rln(tl++);
dcdd144598 2011-02-23        kinaba: 			while( tl < dp.tl );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		// rlを合わせる
dcdd144598 2011-02-23        kinaba: 		ulong stt=0;
dcdd144598 2011-02-23        kinaba: 		while( wrap_[tl][rl+1] < dp.ad )
dcdd144598 2011-02-23        kinaba: 			stt = wrap_[tl][++rl];
dcdd144598 2011-02-23        kinaba: 		vl += rl;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		// x座標計算
dcdd144598 2011-02-23        kinaba: 		vx = CalcLineWidth( doc_.tl(tl)+stt, dp.ad-stt );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	vp->tl = dp.tl;
dcdd144598 2011-02-23        kinaba: 	vp->ad = dp.ad;
dcdd144598 2011-02-23        kinaba: 	vp->vl = vl;
dcdd144598 2011-02-23        kinaba: 	vp->rl = rl;
dcdd144598 2011-02-23        kinaba: 	vp->rx = vp->vx = vx;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void ViewImpl::GetVPos( int x, int y, VPos* vp, bool linemode ) const
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: // x座標補正
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	x = x - lna() + rlScr_.nPos;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: // まず行番号計算
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	int tl = udScr_tl_;
dcdd144598 2011-02-23        kinaba: 	int vl = udScr_.nPos - udScr_vrl_;
dcdd144598 2011-02-23        kinaba: 	int rl = y / fnt().H() + udScr_vrl_;
dcdd144598 2011-02-23        kinaba: 	if( rl >= 0 ) // View上端より下の場合、下方向を調べる
dcdd144598 2011-02-23        kinaba: 		while( tl < (int)doc_.tln() && (int)rln(tl) <= rl )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			vl += rln(tl);
dcdd144598 2011-02-23        kinaba: 			rl -= rln(tl);
dcdd144598 2011-02-23        kinaba: 			++tl;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 	else           // View上端より上の場合、上方向を調べる
dcdd144598 2011-02-23        kinaba: 		while( 0<=tl && rl<0 )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			vl -= rln(tl);
dcdd144598 2011-02-23        kinaba: 			rl += rln(tl);
dcdd144598 2011-02-23        kinaba: 			--tl;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	if( tl == (int)doc_.tln() ) // EOFより下に行ってしまう場合の補正
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		--tl, vl-=rln(tl), rl=rln(tl)-1;
dcdd144598 2011-02-23        kinaba: 		if( linemode )
dcdd144598 2011-02-23        kinaba: 			x = 0x4fffffff;
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else if( tl == -1 ) // ファイル頭より上に行ってしまう場合の補正
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		tl = vl = rl = 0;
dcdd144598 2011-02-23        kinaba: 		if( linemode )
dcdd144598 2011-02-23        kinaba: 			x = 0;
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		if( linemode ) // 行選択モードの場合
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			if( tl == (int)doc_.tln()-1 )
dcdd144598 2011-02-23        kinaba: 				rl=rln(tl)-1, x=0x4fffffff;
dcdd144598 2011-02-23        kinaba: 			else
dcdd144598 2011-02-23        kinaba: 				vl+=rln(tl), rl=0, ++tl, x=0;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	vp->tl = tl;
dcdd144598 2011-02-23        kinaba: 	vp->vl = vl + rl;
dcdd144598 2011-02-23        kinaba: 	vp->rl = rl;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: // 次に、横位置を計算
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	if( rl < static_cast<int>(wrap_[tl].rln()) )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		const unicode* str = doc_.tl(tl);
dcdd144598 2011-02-23        kinaba: 		const ulong adend = rlend(tl,rl);
dcdd144598 2011-02-23        kinaba: 		ulong ad = (rl==0 ? 0 : rlend(tl,rl-1));
dcdd144598 2011-02-23        kinaba: 		int   vx = (rl==0 ? 0 : fnt().W(&str[ad++]));
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		while( ad<adend )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			int nvx = (str[ad]==L'\t'
dcdd144598 2011-02-23        kinaba: 				? fnt().nextTab(vx)
dcdd144598 2011-02-23        kinaba: 				:  vx + fnt().W(&str[ad])
dcdd144598 2011-02-23        kinaba: 			);
dcdd144598 2011-02-23        kinaba: 			if( x+2 < nvx )
dcdd144598 2011-02-23        kinaba: 				break;
dcdd144598 2011-02-23        kinaba: 			vx = nvx;
dcdd144598 2011-02-23        kinaba: 			++ad;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		vp->ad          = ad;
dcdd144598 2011-02-23        kinaba: 		vp->rx = vp->vx = vx;
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		vp->ad = vp->rx = vp->vx = 0;
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: }