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: }