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_scroll.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: //---- ip_text.cpp 文字列操作・他 dcdd144598 2011-02-23 kinaba: //---- ip_parse.cpp キーワード解析 dcdd144598 2011-02-23 kinaba: //---- ip_wrap.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: namespace dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: static int Log10( ulong n ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: const static ulong power_of_ten[] = dcdd144598 2011-02-23 kinaba: { 1, 10, 100, 1000, 10000, 100000, 1000000, dcdd144598 2011-02-23 kinaba: 10000000, 100000000, 1000000000 }; // 10^0 〜 10^9 dcdd144598 2011-02-23 kinaba: int c=3; dcdd144598 2011-02-23 kinaba: if( power_of_ten[9] <= n ) dcdd144598 2011-02-23 kinaba: c=10; dcdd144598 2011-02-23 kinaba: else dcdd144598 2011-02-23 kinaba: while( power_of_ten[c] <= n ) dcdd144598 2011-02-23 kinaba: c++; dcdd144598 2011-02-23 kinaba: return c; // 3<=c<=10 s.t. 10^(c-1) <= n < 10^c dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: bool Canvas::CalcLNAreaWidth() dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: const int prev = txtZone_.left; dcdd144598 2011-02-23 kinaba: if( showLN_ ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: txtZone_.left = (1 + figNum_) * font_->F(); dcdd144598 2011-02-23 kinaba: if( txtZone_.left+font_->W() >= txtZone_.right ) dcdd144598 2011-02-23 kinaba: txtZone_.left = 0; // 行番号ゾーンがデカすぎるときは表示しない dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: else dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: txtZone_.left = 0; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: return (prev != txtZone_.left); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void Canvas::CalcWrapWidth() dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: switch( wrapType_ ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: case NOWRAP: dcdd144598 2011-02-23 kinaba: wrapWidth_ = 0xffffffff; dcdd144598 2011-02-23 kinaba: break; dcdd144598 2011-02-23 kinaba: case RIGHTEDGE: dcdd144598 2011-02-23 kinaba: wrapWidth_ = txtZone_.right - txtZone_.left - 3; dcdd144598 2011-02-23 kinaba: break; //Caretの分-3補正 dcdd144598 2011-02-23 kinaba: default: dcdd144598 2011-02-23 kinaba: wrapWidth_ = wrapType_ * font_->W(); dcdd144598 2011-02-23 kinaba: break; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: Canvas::Canvas( const View& vw ) dcdd144598 2011-02-23 kinaba: : wrapType_ ( -1 ) dcdd144598 2011-02-23 kinaba: , showLN_ ( false ) dcdd144598 2011-02-23 kinaba: , wrapWidth_( 0xffffffff ) dcdd144598 2011-02-23 kinaba: , figNum_ ( 3 ) dcdd144598 2011-02-23 kinaba: , font_ ( new Painter( ::GetDC(vw.hwnd()), dcdd144598 2011-02-23 kinaba: VConfig(TEXT("FixedSys"),14) ) ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: vw.getClientRect( &txtZone_ ); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: bool Canvas::on_view_resize( int cx, int cy ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: txtZone_.right = cx; dcdd144598 2011-02-23 kinaba: txtZone_.bottom = cy; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: CalcLNAreaWidth(); dcdd144598 2011-02-23 kinaba: if( wrapType_ == RIGHTEDGE ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: CalcWrapWidth(); dcdd144598 2011-02-23 kinaba: return true; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: return false; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void Canvas::on_font_change( const VConfig& vc ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: HDC dc = font_->getDC(); dcdd144598 2011-02-23 kinaba: font_ = NULL; // 先にデストラクタを呼ばねばならない… dcdd144598 2011-02-23 kinaba: // ってうわー格好悪ぃーーー(T_T) dcdd144598 2011-02-23 kinaba: font_ = new Painter( dc, vc ); dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: CalcLNAreaWidth(); dcdd144598 2011-02-23 kinaba: CalcWrapWidth(); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void Canvas::on_config_change( int wrap, bool showln ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: showLN_ = showln; dcdd144598 2011-02-23 kinaba: wrapType_ = wrap; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: CalcLNAreaWidth(); dcdd144598 2011-02-23 kinaba: CalcWrapWidth(); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: bool Canvas::on_tln_change( ulong tln ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: figNum_ = Log10( tln ); // 桁数計算 dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: if( CalcLNAreaWidth() ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: if( wrapType_ == RIGHTEDGE ) dcdd144598 2011-02-23 kinaba: CalcWrapWidth(); dcdd144598 2011-02-23 kinaba: return true; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: return false; 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: // rl (横スクロール情報) dcdd144598 2011-02-23 kinaba: // max: view.txt.txtwidth() dcdd144598 2011-02-23 kinaba: // page: view.cx() dcdd144598 2011-02-23 kinaba: // pos: 0〜max-page dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // ud (縦スクロール情報) dcdd144598 2011-02-23 kinaba: // max: view.txt.vln() + page - 1 dcdd144598 2011-02-23 kinaba: // page: view.cy() / view.fnt.H() dcdd144598 2011-02-23 kinaba: // delta: 0〜view.fnt.H() dcdd144598 2011-02-23 kinaba: // pos: 0〜max-page (topの行番号) dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: bool ViewImpl::ReSetScrollInfo() dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: const int prevRlPos = rlScr_.nPos; dcdd144598 2011-02-23 kinaba: const ulong cx = cvs_.zone().right - cvs_.zone().left; dcdd144598 2011-02-23 kinaba: const ulong cy = cvs_.zone().bottom; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 横は変な値にならないよう補正するだけでよい dcdd144598 2011-02-23 kinaba: // rlScr_.nPage = cx + 1; dcdd144598 2011-02-23 kinaba: // rlScr_.nMax = Max( textCx_, cx ); dcdd144598 2011-02-23 kinaba: // rlScr_.nPos = Min<int>( rlScr_.nPos, rlScr_.nMax-rlScr_.nPage+1 ); dcdd144598 2011-02-23 kinaba: rlScr_.nPage = cx + 1; dcdd144598 2011-02-23 kinaba: rlScr_.nMax = Max( textCx_+3, cx ); dcdd144598 2011-02-23 kinaba: rlScr_.nPos = Min<int>( rlScr_.nPos, rlScr_.nMax-rlScr_.nPage+1 ); dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 縦はnPageとnMaxはとりあえず補正 dcdd144598 2011-02-23 kinaba: // nPosは場合によって直し方が異なるので別ルーチンにて dcdd144598 2011-02-23 kinaba: udScr_.nPage = cy / cvs_.getPainter().H() + 1; dcdd144598 2011-02-23 kinaba: udScr_.nMax = vln() + udScr_.nPage - 2; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 横スクロールが起きたらtrue dcdd144598 2011-02-23 kinaba: return (prevRlPos != rlScr_.nPos); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void ViewImpl::ForceScrollTo( ulong tl ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: udScr_.nPos = tl2vl(tl); dcdd144598 2011-02-23 kinaba: udScr_tl_ = tl; dcdd144598 2011-02-23 kinaba: udScr_vrl_ = 0; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: ulong ViewImpl::tl2vl( ulong tl ) const dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: if( vln() == doc_.tln() ) dcdd144598 2011-02-23 kinaba: return tl; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: ulong vl=0; dcdd144598 2011-02-23 kinaba: for( ulong i=0; i<tl; ++i ) dcdd144598 2011-02-23 kinaba: vl += rln(i); dcdd144598 2011-02-23 kinaba: return vl; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void ViewImpl::UpdateScrollBar() dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: ::SetScrollInfo( hwnd_, SB_HORZ, &rlScr_, TRUE ); dcdd144598 2011-02-23 kinaba: ::SetScrollInfo( hwnd_, SB_VERT, &udScr_, TRUE ); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: ReDrawType ViewImpl::TextUpdate_ScrollBar dcdd144598 2011-02-23 kinaba: ( const DPos& s, const DPos& e, const DPos& e2 ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: const ulong prevUdMax = udScr_.nMax; dcdd144598 2011-02-23 kinaba: const bool rlScrolled = ReSetScrollInfo(); dcdd144598 2011-02-23 kinaba: const long vl_dif = (udScr_.nMax - prevUdMax); dcdd144598 2011-02-23 kinaba: ReDrawType ans = dcdd144598 2011-02-23 kinaba: (vl_dif!=0 || s.tl!=e2.tl ? AFTER : LINE); dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: if( udScr_tl_ < s.tl ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // パターン1:現在の画面上端より下で更新された場合 dcdd144598 2011-02-23 kinaba: // スクロールしない dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: else if( udScr_tl_ == s.tl ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // パターン2:現在の画面上端と同じ行で更新された場合 dcdd144598 2011-02-23 kinaba: // 出来るだけ同じ位置を表示し続けようと試みる。 dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: if( static_cast<ulong>(udScr_.nPos) >= vln() ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // パターン2-1:しかしそこはすでにEOFよりも下だ! dcdd144598 2011-02-23 kinaba: // しゃーないので一番下の行を表示 dcdd144598 2011-02-23 kinaba: udScr_.nPos = vln()-1; dcdd144598 2011-02-23 kinaba: udScr_tl_ = doc_.tln()-1; dcdd144598 2011-02-23 kinaba: udScr_vrl_ = rln(udScr_tl_)-1; dcdd144598 2011-02-23 kinaba: ans = ALL; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: else dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // パターン2-2: dcdd144598 2011-02-23 kinaba: // スクロール無し dcdd144598 2011-02-23 kinaba: while( udScr_vrl_ >= rln(udScr_tl_) ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: udScr_vrl_ -= rln(udScr_tl_); dcdd144598 2011-02-23 kinaba: udScr_tl_++; 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: // パターン3:現在の画面上端より上で更新された場合 dcdd144598 2011-02-23 kinaba: // 表示内容を変えないように頑張る dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: if( e.tl < udScr_tl_ ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // パターン3-1:変更範囲の終端も、現在行より上の場合 dcdd144598 2011-02-23 kinaba: // 行番号は変わるが表示内容は変わらないで済む dcdd144598 2011-02-23 kinaba: udScr_.nPos += vl_dif; dcdd144598 2011-02-23 kinaba: udScr_tl_ += (e2.tl - e.tl); dcdd144598 2011-02-23 kinaba: ans = LNAREA; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: else dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // パターン3-2: dcdd144598 2011-02-23 kinaba: // どうしよーもないので適当な位置にスクロール dcdd144598 2011-02-23 kinaba: ForceScrollTo( e2.tl ); dcdd144598 2011-02-23 kinaba: ans = ALL; 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: return (rlScrolled ? ALL : ans); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void ViewImpl::ScrollTo( const VPos& vp ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // 横フォーカス dcdd144598 2011-02-23 kinaba: int dx=0; dcdd144598 2011-02-23 kinaba: if( vp.vx < (signed)rlScr_.nPos ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: dx = vp.vx - rlScr_.nPos; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: else dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: const int W = cvs_.getPainter().W(); dcdd144598 2011-02-23 kinaba: if( rlScr_.nPos + (signed)(rlScr_.nPage-W) <= vp.vx ) dcdd144598 2011-02-23 kinaba: dx = vp.vx - (rlScr_.nPos + rlScr_.nPage) + W; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 縦フォーカス dcdd144598 2011-02-23 kinaba: int dy=0; dcdd144598 2011-02-23 kinaba: if( vp.vl < (unsigned)udScr_.nPos ) dcdd144598 2011-02-23 kinaba: dy = vp.vl - udScr_.nPos; dcdd144598 2011-02-23 kinaba: else if( udScr_.nPos + (udScr_.nPage-1) <= vp.vl ) dcdd144598 2011-02-23 kinaba: dy = vp.vl - (udScr_.nPos + udScr_.nPage) + 2; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // スクロール dcdd144598 2011-02-23 kinaba: if( dy!=0 ) UpDown( dy, dx==0 ); dcdd144598 2011-02-23 kinaba: if( dx!=0 ) ScrollView( dx, 0, true ); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void ViewImpl::GetDrawPosInfo( VDrawInfo& v ) const dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: const int H = cvs_.getPainter().H(); dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: long most_under = (vln()-udScr_.nPos)*H; dcdd144598 2011-02-23 kinaba: if( most_under <= v.rc.top ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: v.YMIN = v.rc.top; dcdd144598 2011-02-23 kinaba: v.YMAX = most_under; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: else dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: int y = -(signed)udScr_vrl_; dcdd144598 2011-02-23 kinaba: ulong tl = udScr_tl_; dcdd144598 2011-02-23 kinaba: int top = v.rc.top / H; dcdd144598 2011-02-23 kinaba: while( y + (signed)rln(tl) <= top ) dcdd144598 2011-02-23 kinaba: y += rln( tl++ ); dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 縦座標 dcdd144598 2011-02-23 kinaba: v.YMIN = y * H; dcdd144598 2011-02-23 kinaba: v.YMAX = Min( v.rc.bottom, most_under ); dcdd144598 2011-02-23 kinaba: v.TLMIN = tl; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 横座標 dcdd144598 2011-02-23 kinaba: v.XBASE = left() - rlScr_.nPos; dcdd144598 2011-02-23 kinaba: v.XMIN = v.rc.left - v.XBASE; dcdd144598 2011-02-23 kinaba: v.XMAX = v.rc.right - v.XBASE; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 選択範囲 dcdd144598 2011-02-23 kinaba: v.SXB = v.SXE = v.SYB = v.SYE = 0x7fffffff; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: const VPos *bg, *ed; dcdd144598 2011-02-23 kinaba: if( cur_.getCurPos( &bg, &ed ) ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: v.SXB = bg->vx - rlScr_.nPos + left(); dcdd144598 2011-02-23 kinaba: v.SXE = ed->vx - rlScr_.nPos + left(); dcdd144598 2011-02-23 kinaba: v.SYB = (bg->vl - udScr_.nPos) * H; dcdd144598 2011-02-23 kinaba: v.SYE = (ed->vl - udScr_.nPos) * H; 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::ScrollView( int dx, int dy, bool update ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // スクロール開始通知 dcdd144598 2011-02-23 kinaba: cur_.on_scroll_begin(); dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: const RECT* clip = (dy==0 ? &cvs_.zone() : NULL); dcdd144598 2011-02-23 kinaba: const int H = cvs_.getPainter().H(); dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // スクロールバー更新 dcdd144598 2011-02-23 kinaba: if( dx != 0 ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // 範囲チェック dcdd144598 2011-02-23 kinaba: if( rlScr_.nPos+dx < 0 ) dcdd144598 2011-02-23 kinaba: dx = -rlScr_.nPos; dcdd144598 2011-02-23 kinaba: else if( rlScr_.nMax-(signed)rlScr_.nPage < rlScr_.nPos+dx ) dcdd144598 2011-02-23 kinaba: dx = rlScr_.nMax-rlScr_.nPage-rlScr_.nPos+1; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: rlScr_.nPos += dx; dcdd144598 2011-02-23 kinaba: ::SetScrollInfo( hwnd_, SB_HORZ, &rlScr_, TRUE ); dcdd144598 2011-02-23 kinaba: dx = -dx; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: if( dy != 0 ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // 範囲チェック…は前処理で終わってる。 dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: udScr_.nPos += dy; dcdd144598 2011-02-23 kinaba: ::SetScrollInfo( hwnd_, SB_VERT, &udScr_, TRUE ); dcdd144598 2011-02-23 kinaba: dy *= -H; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: if( dx!=0 || dy!=0 ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: if( -dx>=right() || dx>=right() dcdd144598 2011-02-23 kinaba: || -dy>=bottom() || dy>=bottom() ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // 全画面再描画 dcdd144598 2011-02-23 kinaba: // ちょうど65536の倍数くらいスクロールしたときに、 dcdd144598 2011-02-23 kinaba: // ScrollWindowEx on Win9x だと再描画が変なのを回避。 dcdd144598 2011-02-23 kinaba: ::InvalidateRect( hwnd_, NULL, FALSE ); 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: ::ScrollWindowEx( hwnd_, dx, dy, NULL, dcdd144598 2011-02-23 kinaba: clip, NULL, NULL, SW_INVALIDATE ); dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 即時再描画? dcdd144598 2011-02-23 kinaba: if( update ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // 縦スクロールは高速化したいので一工夫 dcdd144598 2011-02-23 kinaba: if( dy != 0 ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // 再描画の必要な領域を自分で計算 dcdd144598 2011-02-23 kinaba: RECT rc = {0,0,right(),bottom()}; dcdd144598 2011-02-23 kinaba: if( dy < 0 ) rc.top = rc.bottom + dy; dcdd144598 2011-02-23 kinaba: else rc.bottom = dy; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // インテリマウスの中ボタンクリックによる dcdd144598 2011-02-23 kinaba: // オートスクロール用カーソルの下の部分を先に描く dcdd144598 2011-02-23 kinaba: // 2回に分けることで、小さな矩形部分二つで済むので高速 dcdd144598 2011-02-23 kinaba: ::ValidateRect( hwnd_, &rc ); dcdd144598 2011-02-23 kinaba: ::UpdateWindow( hwnd_ ); dcdd144598 2011-02-23 kinaba: ::InvalidateRect( hwnd_, &rc, FALSE ); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: ::UpdateWindow( hwnd_ ); 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: cur_.on_scroll_end(); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void ViewImpl::on_hscroll( int code ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // 変化量を計算 dcdd144598 2011-02-23 kinaba: int dx; dcdd144598 2011-02-23 kinaba: switch( code ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: default: return; dcdd144598 2011-02-23 kinaba: case SB_LINELEFT: dx= -cvs_.getPainter().W(); break; dcdd144598 2011-02-23 kinaba: case SB_LINERIGHT: dx= +cvs_.getPainter().W(); break; dcdd144598 2011-02-23 kinaba: case SB_PAGELEFT: dx= -(cx()>>1); break; dcdd144598 2011-02-23 kinaba: case SB_PAGERIGHT: dx= +(cx()>>1); break; dcdd144598 2011-02-23 kinaba: case SB_THUMBTRACK: dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS }; dcdd144598 2011-02-23 kinaba: ::GetScrollInfo( hwnd_, SB_HORZ, &si ); dcdd144598 2011-02-23 kinaba: dx = si.nTrackPos - rlScr_.nPos; dcdd144598 2011-02-23 kinaba: break; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: case SB_LEFT: dx = -rlScr_.nPos; break; dcdd144598 2011-02-23 kinaba: case SB_RIGHT: dx = rlScr_.nMax+1-(signed)rlScr_.nPage-rlScr_.nPos; break; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // スクロール dcdd144598 2011-02-23 kinaba: ScrollView( dx, 0, code!=SB_THUMBTRACK ); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void ViewImpl::on_vscroll( int code ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // 変化量を計算 dcdd144598 2011-02-23 kinaba: int dy; dcdd144598 2011-02-23 kinaba: switch( code ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: default: return; dcdd144598 2011-02-23 kinaba: case SB_LINEUP: dy= -1; break; dcdd144598 2011-02-23 kinaba: case SB_LINEDOWN: dy= +1; break; dcdd144598 2011-02-23 kinaba: case SB_PAGEUP: dy= -(cy() / cvs_.getPainter().H()); break; dcdd144598 2011-02-23 kinaba: case SB_PAGEDOWN: dy= +(cy() / cvs_.getPainter().H()); break; dcdd144598 2011-02-23 kinaba: case SB_THUMBTRACK: dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS }; dcdd144598 2011-02-23 kinaba: ::GetScrollInfo( hwnd_, SB_VERT, &si ); dcdd144598 2011-02-23 kinaba: dy = si.nTrackPos - udScr_.nPos; dcdd144598 2011-02-23 kinaba: break; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: case SB_TOP: dy = -udScr_.nPos; break; dcdd144598 2011-02-23 kinaba: case SB_BOTTOM: dy = udScr_.nMax+1-(signed)udScr_.nPage-udScr_.nPos; break; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // スクロール dcdd144598 2011-02-23 kinaba: UpDown( dy, code==SB_THUMBTRACK ); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void ViewImpl::on_wheel( short delta ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // スクロール dcdd144598 2011-02-23 kinaba: UpDown( -delta / WHEEL_DELTA * 3, false ); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void ViewImpl::UpDown( int dy, bool thumb ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // 1.udScr_.nPos + dy が正常範囲に収まるように補正 dcdd144598 2011-02-23 kinaba: if( udScr_.nPos+dy < 0 ) dcdd144598 2011-02-23 kinaba: dy = -udScr_.nPos; dcdd144598 2011-02-23 kinaba: else if( udScr_.nMax+1-(signed)udScr_.nPage < udScr_.nPos+dy ) dcdd144598 2011-02-23 kinaba: dy = udScr_.nMax+1-udScr_.nPage-udScr_.nPos; dcdd144598 2011-02-23 kinaba: if( dy==0 ) dcdd144598 2011-02-23 kinaba: return; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 2−1.折り返し無しの場合は一気にジャンプ出来る dcdd144598 2011-02-23 kinaba: if( !wrapexists() ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: udScr_tl_ = udScr_.nPos + dy; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 2−2.でなけりゃ、現在位置からの相対サーチ dcdd144598 2011-02-23 kinaba: // ScrollBarを連続的にドラッグせず一度に一気に飛んだ場合は dcdd144598 2011-02-23 kinaba: // 1行目や最終行からの相対サーチの方が有効な可能性があるが、 dcdd144598 2011-02-23 kinaba: // その場合は多少速度が遅くなっても描画が引っかかることはないのでOK dcdd144598 2011-02-23 kinaba: else dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: int rl = dy + udScr_vrl_; dcdd144598 2011-02-23 kinaba: ulong tl = udScr_tl_; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: if( dy<0 ) // 上へ戻る場合 dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // ジャンプ先論理行の行頭へDash! dcdd144598 2011-02-23 kinaba: while( rl < 0 ) dcdd144598 2011-02-23 kinaba: rl += rln(--tl); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: else if( dy>0 ) // 下へ進む場合 dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: // ジャンプ先論理行の行頭へDash! dcdd144598 2011-02-23 kinaba: while( rl > 0 ) dcdd144598 2011-02-23 kinaba: rl -= rln(tl++); dcdd144598 2011-02-23 kinaba: if( rl < 0 ) dcdd144598 2011-02-23 kinaba: rl += rln(--tl); //行き過ぎ修正 dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: udScr_tl_ = tl; dcdd144598 2011-02-23 kinaba: udScr_vrl_= static_cast<ulong>(rl); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 4.画面をスクロール dcdd144598 2011-02-23 kinaba: ScrollView( 0, dy, !thumb ); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: void ViewImpl::InvalidateView( const DPos& dp, bool afterall ) const dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: const int H = cvs_.getPainter().H(); dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 表示域より上での更新 dcdd144598 2011-02-23 kinaba: if( dp.tl < udScr_tl_ ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: if( afterall ) dcdd144598 2011-02-23 kinaba: ::InvalidateRect( hwnd_, NULL, FALSE ); dcdd144598 2011-02-23 kinaba: return; dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 開始y座標計算 dcdd144598 2011-02-23 kinaba: int r=0, yb=-(signed)udScr_vrl_; dcdd144598 2011-02-23 kinaba: for( int t=udScr_tl_, ybe=cy()/H; (unsigned)t<dp.tl; yb+=rln(t++) ) dcdd144598 2011-02-23 kinaba: if( yb >= ybe ) dcdd144598 2011-02-23 kinaba: return; dcdd144598 2011-02-23 kinaba: for( ; dp.ad>rlend(dp.tl,r); ++r,++yb ); dcdd144598 2011-02-23 kinaba: yb = H * Max( yb, -100 ); // 上にはみ出し過ぎないよう調整 dcdd144598 2011-02-23 kinaba: if( yb >= cy() ) dcdd144598 2011-02-23 kinaba: return; dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 1行目を再描画 dcdd144598 2011-02-23 kinaba: int rb = (r==0 ? 0 : rlend(dp.tl,r-1)); dcdd144598 2011-02-23 kinaba: int xb = left() + Max( 0UL, dcdd144598 2011-02-23 kinaba: CalcLineWidth(doc_.tl(dp.tl)+rb,dp.ad-rb) -rlScr_.nPos ); dcdd144598 2011-02-23 kinaba: if( xb < right() ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: RECT rc={xb,yb,right(),yb+H}; dcdd144598 2011-02-23 kinaba: ::InvalidateRect( hwnd_, &rc, FALSE ); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: dcdd144598 2011-02-23 kinaba: // 残り dcdd144598 2011-02-23 kinaba: int ye; dcdd144598 2011-02-23 kinaba: yb += H; dcdd144598 2011-02-23 kinaba: if( afterall ) dcdd144598 2011-02-23 kinaba: xb=0, ye=cy(); dcdd144598 2011-02-23 kinaba: else dcdd144598 2011-02-23 kinaba: xb=left(), ye=Min(cy(),yb+(int)(H*(rln(dp.tl)-r-1))); dcdd144598 2011-02-23 kinaba: if( yb < ye ) dcdd144598 2011-02-23 kinaba: { dcdd144598 2011-02-23 kinaba: RECT rc={xb,yb,right(),ye}; dcdd144598 2011-02-23 kinaba: ::InvalidateRect( hwnd_, &rc, FALSE ); dcdd144598 2011-02-23 kinaba: } dcdd144598 2011-02-23 kinaba: }