Index: sakura_core/doc/CLayoutMgr.h =================================================================== --- sakura_core/doc/CLayoutMgr.h (.../sakura/trunk2) (リビジョン 42526) +++ sakura_core/doc/CLayoutMgr.h (.../fix_rectangular_selection_area) (リビジョン 42526) @@ -106,6 +106,8 @@ //先頭と末尾 CLayout* GetTopLayout() { return m_pLayoutTop; } CLayout* GetBottomLayout() { return m_pLayoutBot; } + const CLayout* GetTopLayout() const { return m_pLayoutTop; } + const CLayout* GetBottomLayout() const { return m_pLayoutBot; } //レイアウトを探す const CLayout* SearchLineByLayoutY( CLayoutInt nLineLayout ) const; /* 指定された物理行のレイアウトデータ(CLayout)へのポインタを返す */ Index: sakura_core/CViewCommander.h =================================================================== --- sakura_core/CViewCommander.h (.../sakura/trunk2) (リビジョン 42526) +++ sakura_core/CViewCommander.h (.../fix_rectangular_selection_area) (リビジョン 42526) @@ -261,7 +261,7 @@ /* モード切り替え系 */ void Command_CHGMOD_INS( void ); /* 挿入/上書きモード切り替え */ void Command_CHGMOD_EOL( enumEOLType ); /* 入力する改行コードを設定 2003.06.23 moca */ - void Command_CANCEL_MODE( void ); /* 各種モードの取り消し */ + void Command_CANCEL_MODE( int whereCursorIs = 0 ); /* 各種モードの取り消し */ /* 設定系 */ void Command_SHOWTOOLBAR( void ); /* ツールバーの表示/非表示 */ Index: sakura_core/CViewCommander.cpp =================================================================== --- sakura_core/CViewCommander.cpp (.../sakura/trunk2) (リビジョン 42526) +++ sakura_core/CViewCommander.cpp (.../fix_rectangular_selection_area) (リビジョン 42526) @@ -784,56 +784,31 @@ */ int CViewCommander::Command_LEFT( bool bSelect, bool bRepeat ) { - int nRepCount; - int nRepeat; + int nRepeat = bRepeat ? 2 : 1; int nRes; - if( bRepeat ){ - nRepeat = 2; - }else{ - nRepeat = 1; - } - for( nRepCount = 0; nRepCount < nRepeat; ++nRepCount ){ - CLayoutPoint ptPos(CLayoutInt(0), GetCaret().GetCaretLayoutPos().GetY2()); - const CLayout* pcLayout; - if( bSelect ){ - if( !m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 現在のカーソル位置から選択を開始する */ - m_pCommanderView->GetSelectionInfo().BeginSelectArea(); - } - }else{ - if( m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 矩形範囲選択中か */ - if( m_pCommanderView->GetSelectionInfo().IsBoxSelecting() ){ - /* 2点を対角とする矩形を求める */ - CLayoutRange rcSel; - TwoPointToRange( - &rcSel, - GetSelect().GetFrom(), // 範囲選択開始 - GetSelect().GetTo() // 範囲選択終了 - ); - /* 現在の選択範囲を非選択状態に戻す */ - m_pCommanderView->GetSelectionInfo().DisableSelectArea( TRUE ); - /* カーソルを選択開始位置に移動 */ - GetCaret().MoveCursor( rcSel.GetFrom(), TRUE ); - GetCaret().m_nCaretPosX_Prev = GetCaret().GetCaretLayoutPos().GetX2(); - } - else{ - ptPos = GetSelect().GetFrom(); - /* 現在の選択範囲を非選択状態に戻す */ - m_pCommanderView->GetSelectionInfo().DisableSelectArea( TRUE ); - /* カーソルを選択開始位置に移動 */ - GetCaret().MoveCursor( ptPos, TRUE ); - GetCaret().m_nCaretPosX_Prev = GetCaret().GetCaretLayoutPos().GetX2(); - } - nRes = 1; - goto end_of_func; - } + for( int nRepCount = 0; nRepCount < nRepeat; ++nRepCount ) { + + if( bSelect && ! m_pCommanderView->GetSelectionInfo().IsTextSelected() ) { + /* 現在のカーソル位置から選択を開始する */ + m_pCommanderView->GetSelectionInfo().BeginSelectArea(); } + if( ! bSelect && m_pCommanderView->GetSelectionInfo().IsTextSelected() ) { + this->Command_CANCEL_MODE( 1 ); + nRes = 1; + continue; // 選択のキャンセルで左移動を 1消費。この後の移動処理はスキップする。 + } + + // (これから求める)カーソルの移動先。 + CLayoutPoint ptPos(CLayoutInt(0), GetCaret().GetCaretLayoutPos().GetY2()); + /* 現在行のデータを取得 */ - pcLayout = GetDocument()->m_cLayoutMgr.SearchLineByLayoutY( GetCaret().GetCaretLayoutPos().GetY2() ); + const CLayout* pcLayout = GetDocument()->m_cLayoutMgr.SearchLineByLayoutY( GetCaret().GetCaretLayoutPos().GetY2() ); /* カーソルが左端にある */ - if( GetCaret().GetCaretLayoutPos().GetX2() == (pcLayout ? pcLayout->GetIndent() : CLayoutInt(0))){ - if( GetCaret().GetCaretLayoutPos().GetY2() > 0 ){ + if( GetCaret().GetCaretLayoutPos().GetX2() == (pcLayout ? pcLayout->GetIndent() : CLayoutInt(0))) { + if( 0 < GetCaret().GetCaretLayoutPos().GetY2() + && ! m_pCommanderView->GetSelectionInfo().IsBoxSelecting() + ) { + // 前のレイアウト行の、折り返し桁一つ手前または改行文字の手前に移動する。 pcLayout = GetDocument()->m_cLayoutMgr.SearchLineByLayoutY( GetCaret().GetCaretLayoutPos().GetY2() - CLayoutInt(1) ); CMemoryIterator it( pcLayout, GetDocument()->m_cLayoutMgr.GetTabSpace() ); while( !it.end() ){ @@ -846,13 +821,13 @@ } ptPos.x += it.getColumn() - it.getColumnDelta(); ptPos.y --; - }else{ + } else { nRes = 0; - goto end_of_func; + break; // これ以上左に動けぬ。 } } // 2004.03.28 Moca EOFだけの行以降の途中にカーソルがあると落ちるバグ修正 - else if( pcLayout ){ + else if( pcLayout ) { CMemoryIterator it( pcLayout, GetDocument()->m_cLayoutMgr.GetTabSpace() ); while( !it.end() ){ it.scanNext(); @@ -868,11 +843,11 @@ ptPos.x = GetCaret().GetCaretLayoutPos().GetX2() - CLayoutInt(1); } } + GetCaret().MoveCursor( ptPos, TRUE ); GetCaret().m_nCaretPosX_Prev = GetCaret().GetCaretLayoutPos().GetX2(); - if( bSelect ){ + if( bSelect ) { /* 現在のカーソル位置によって選択範囲を変更. - 2004.04.02 Moca キャレット位置が不正だった場合にMoveCursorの移動結果が 引数で与えた座標とは異なることがあるため, @@ -881,8 +856,6 @@ m_pCommanderView->GetSelectionInfo().ChangeSelectAreaByCurrentCursor( GetCaret().GetCaretLayoutPos() ); } nRes = 1; - goto end_of_func; -end_of_func:; } return nRes; } @@ -893,160 +866,104 @@ /* カーソル右移動 */ void CViewCommander::Command_RIGHT( bool bSelect, bool bIgnoreCurrentSelection, bool bRepeat ) { - int nRepeat; //押した回数 - if( bRepeat ){ - nRepeat = 2; - }else{ - nRepeat = 1; - } - for( int nRepCount = 0; nRepCount < nRepeat; ++nRepCount ){ - CLayoutPoint ptPos; - ptPos.y = GetCaret().GetCaretLayoutPos().GetY2(); - const CLayout* pcLayout; - + int nRepeat = bRepeat ? 2 : 1; // 移動する回数 + for( int nRepCount = 0; nRepCount < nRepeat; ++nRepCount ) { // 2003.06.28 Moca [EOF]のみの行にカーソルがあるときに右を押しても選択を解除できない問題に // 対応するため、現在行のデータを取得を移動 - if( !bIgnoreCurrentSelection ){ - if( bSelect ){ - if( !m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 現在のカーソル位置から選択を開始する */ - m_pCommanderView->GetSelectionInfo().BeginSelectArea(); - } + if( ! bIgnoreCurrentSelection ) { + if( bSelect && ! m_pCommanderView->GetSelectionInfo().IsTextSelected() ) { + /* 現在のカーソル位置から選択を開始する */ + m_pCommanderView->GetSelectionInfo().BeginSelectArea(); } - else{ - if( m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 矩形範囲選択中か */ - if( m_pCommanderView->GetSelectionInfo().IsBoxSelecting() ){ - /* 2点を対角とする矩形を求める */ - CLayoutRange rcSel; - TwoPointToRange( - &rcSel, - GetSelect().GetFrom(), // 範囲選択開始 - GetSelect().GetTo() // 範囲選択終了 - ); - - /* 現在の選択範囲を非選択状態に戻す */ - m_pCommanderView->GetSelectionInfo().DisableSelectArea( TRUE ); - - /* カーソルを選択終了位置に移動 */ - GetCaret().MoveCursor( rcSel.GetFrom(), TRUE ); - GetCaret().m_nCaretPosX_Prev = GetCaret().GetCaretLayoutPos().GetX2(); - } - else{ - ptPos = GetSelect().GetTo(); - - /* 現在の選択範囲を非選択状態に戻す */ - m_pCommanderView->GetSelectionInfo().DisableSelectArea( TRUE ); - if( ptPos.y >= GetDocument()->m_cLayoutMgr.GetLineCount() ){ - /* ファイルの最後に移動 */ - Command_GOFILEEND(FALSE); - } - else{ - /* カーソルを選択終了位置に移動 */ - GetCaret().MoveCursor( ptPos, TRUE ); - GetCaret().m_nCaretPosX_Prev = GetCaret().GetCaretLayoutPos().GetX2(); - } - } - goto end_of_func; - } + if( ! bSelect && m_pCommanderView->GetSelectionInfo().IsTextSelected() ) { + this->Command_CANCEL_MODE( 2 ); + continue; // 選択のキャンセルで右移動を 1消費。この後の移動処理はスキップする。 } } // 2003.06.28 Moca [EOF]のみの行にカーソルがあるときに右を押しても選択を解除できない問題に対応 + // (これから求める)カーソルの移動先。 + CLayoutPoint ptTo( 0, 0 ); + const CLayoutPoint ptCaret = GetCaret().GetCaretLayoutPos(); + /* 現在行のデータを取得 */ - pcLayout = GetDocument()->m_cLayoutMgr.SearchLineByLayoutY( GetCaret().GetCaretLayoutPos().GetY2() ); + const CLayout* const pLayout = GetDocument()->m_cLayoutMgr.SearchLineByLayoutY( ptCaret.y ); // 2004.04.02 EOF以降にカーソルがあったときに右を押しても何も起きなかったのを、EOFに移動するように - if( pcLayout ) + if( pLayout ) { - int nIndex = 0; - CMemoryIterator it( pcLayout, GetDocument()->m_cLayoutMgr.GetTabSpace() ); - while( !it.end() ){ - it.scanNext(); - if ( it.getColumn() > GetCaret().GetCaretLayoutPos().GetX2() ){ + // キャレット位置のレイアウト行について。 + const CLayoutInt x_wrap = pLayout->GetIndent() + pLayout->CalcLayoutWidth( GetDocument()->m_cLayoutMgr ); // 改行文字、または折り返しの位置。 + const bool wrapped = EOL_NONE == pLayout->GetLayoutEol(); // 折り返しているか、改行文字で終わっているか。これにより x_wrapの意味が変わる。 + const bool nextline_exists = pLayout->GetNextLayout() || pLayout->GetLayoutEol() != EOL_NONE; // EOFのみの行も含め、キャレットが移動可能な次行が存在するか。 + + // 現在のキャレットの右の位置( to_x )を求める。 + CMemoryIterator it( pLayout, GetDocument()->m_cLayoutMgr.GetTabSpace() ); + for( ; ! it.end(); it.scanNext(), it.addDelta() ) { + if( ptCaret.x < it.getColumn() ) { break; } - if ( it.getIndex() + it.getIndexDelta() > pcLayout->GetLengthWithoutEOL() ){ - nIndex += it.getIndexDelta(); - break; - } - it.addDelta(); } - ptPos.x = it.getColumn(); //新しいキャレット位置 - nIndex += it.getIndex(); - if( nIndex >= pcLayout->GetLengthWithEOL() ){ - /* フリーカーソルモードか */ - if( ( - GetDllShareData().m_Common.m_sGeneral.m_bIsFreeCursorMode - || m_pCommanderView->GetSelectionInfo().IsTextSelected() && m_pCommanderView->GetSelectionInfo().IsBoxSelecting() /* 矩形範囲選択中 */ - ) - && - /* 改行で終わっているか */ - ( EOL_NONE != pcLayout->GetLayoutEol() ) - ){ - /*-- フリーカーソルモードの場合 --*/ - if( ptPos.x <= GetCaret().GetCaretLayoutPos().GetX2() ){ - /* 最終行か */ - if( GetCaret().GetCaretLayoutPos().GetY2() + 1 == GetDocument()->m_cLayoutMgr.GetLineCount() ){ - /* 改行で終わっているか */ - if( EOL_NONE != pcLayout->GetLayoutEol().GetType() ){ - ptPos.x = GetCaret().GetCaretLayoutPos().GetX2() + 1; - }else{ - ptPos.x = GetCaret().GetCaretLayoutPos().GetX2(); - } - }else{ - ptPos.x = GetCaret().GetCaretLayoutPos().GetX2() + 1; - } - }else{ - ptPos.x = ptPos.x; + const CLayoutInt to_x = std::max( it.getColumn(), ptCaret.x + 1 ); + + // キャレットの右端( x_max )と、そこでの扱い( on_x_max )を決める。 + CLayoutInt x_max; + enum { + STOP, + MOVE_NEXTLINE_IMMEDIATELY, // 右端に止まらず次の行頭に移動する。(折り返しなど) + MOVE_NEXTLINE_NEXTTIME, // 右端に止まり、次に次の行頭に移動する。(改行を超えるときなど) + MOVE_NEXTLINE_NEXTTIME_AND_MOVE_RIGHT // 右端に止まり、次に次の行頭の一つ右に移動する。(折り返しなど) + } on_x_max; + + if( m_pCommanderView->GetSelectionInfo().IsBoxSelecting() ) { + x_max = std::max( x_wrap, GetDocument()->m_cLayoutMgr.GetMaxLineKetas() ); + on_x_max = STOP; + } else if( GetDllShareData().m_Common.m_sGeneral.m_bIsFreeCursorMode ) { + // フリーカーソルモードでは折り返し位置だけをみて、改行文字の位置はみない。 + if( wrapped ) { + x_max = x_wrap; + on_x_max = MOVE_NEXTLINE_IMMEDIATELY; + } else { + if( x_wrap < GetDocument()->m_cLayoutMgr.GetMaxLineKetas() ) { + x_max = GetDocument()->m_cLayoutMgr.GetMaxLineKetas(); + on_x_max = MOVE_NEXTLINE_IMMEDIATELY; + } else { // 改行文字がぶら下がっているときは例外。 + x_max = x_wrap; + on_x_max = MOVE_NEXTLINE_NEXTTIME; } } - else{ - /*-- フリーカーソルモードではない場合 --*/ - /* 最終行か */ - if( GetCaret().GetCaretLayoutPos().GetY2() + 1 == GetDocument()->m_cLayoutMgr.GetLineCount() ){ - /* 改行で終わっているか */ - if( EOL_NONE != pcLayout->GetLayoutEol().GetType() ){ - ptPos.x = pcLayout->GetNextLayout() ? pcLayout->GetNextLayout()->GetIndent() : CLayoutInt(0); - ++ptPos.y; - } - else{ - } - } - else{ - if( ptPos.x <= GetCaret().GetCaretLayoutPos().GetX2() - && EOL_NONE == pcLayout->GetLayoutEol() - && pcLayout->GetNextLayout() - ){ - nRepeat++; // レイアウト行の右端は次の行の先頭と論理的に同等なのでさらに右へ // 2007.02.19 ryoji - } - ptPos.x = pcLayout->GetNextLayout() ? pcLayout->GetNextLayout()->GetIndent() : CLayoutInt(0); - ++ptPos.y; - } + } else { + x_max = x_wrap; + on_x_max = wrapped ? MOVE_NEXTLINE_IMMEDIATELY : MOVE_NEXTLINE_NEXTTIME; + } + + // キャレットの移動先を決める。 + if( nextline_exists + && ( on_x_max == MOVE_NEXTLINE_IMMEDIATELY && x_max <= to_x + || on_x_max == MOVE_NEXTLINE_NEXTTIME && x_max < to_x + || on_x_max == MOVE_NEXTLINE_NEXTTIME_AND_MOVE_RIGHT && x_max < to_x + ) + ) { + ptTo.y = ptCaret.y + 1; + ptTo.x = pLayout->GetNextLayout() ? pLayout->GetNextLayout()->GetIndent() : CLayoutInt(0); + if( on_x_max == MOVE_NEXTLINE_NEXTTIME_AND_MOVE_RIGHT ) { + ++nRepeat; } - // キャレット位置が折り返し位置より右側だった場合の処理 - // Aug. 14, 2005 genta 折り返し幅をLayoutMgrから取得するように - if( ptPos.x >= GetDocument()->m_cLayoutMgr.GetMaxLineKetas() ){ - if( GetCaret().GetCaretLayoutPos().GetX2() >= GetDocument()->m_cLayoutMgr.GetMaxLineKetas() - && pcLayout->GetNextLayout() - ){ - nRepeat++; // レイアウト行の右端は次の行の先頭と論理的に同等なのでさらに右へ // 2007.02.19 ryoji - } - ptPos.x = pcLayout->GetNextLayout() ? pcLayout->GetNextLayout()->GetIndent() : CLayoutInt(0); - ++ptPos.y; - } + } else { + ptTo.y = ptCaret.y; + ptTo.x = std::min( to_x, x_max ); } - }else{ + } else { // pcLayoutがNULLの場合はptPos.x=0に調整 - ptPos.x = CLayoutInt(0); + ptTo.y = ptCaret.y; + ptTo.x = 0; } - GetCaret().MoveCursor( ptPos, TRUE ); + + GetCaret().MoveCursor( ptTo, TRUE ); GetCaret().m_nCaretPosX_Prev = GetCaret().GetCaretLayoutPos().GetX2(); if( bSelect ){ /* 現在のカーソル位置によって選択範囲を変更 */ m_pCommanderView->GetSelectionInfo().ChangeSelectAreaByCurrentCursor( GetCaret().GetCaretLayoutPos() ); } - -end_of_func:; } return; } @@ -3332,15 +3249,43 @@ -/* 各種モードの取り消し */ -void CViewCommander::Command_CANCEL_MODE( void ) +/** 各種モードの取り消し + @param whereCursorIs 選択をキャンセルした後、キャレットをどこに置くか。0=動かさない。1=左上。2=右下。 +*/ +void CViewCommander::Command_CANCEL_MODE( int whereCursorIs ) { - if( m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ + if( m_pCommanderView->GetSelectionInfo().IsTextSelected() ) { + // 選択解除後のカーソル位置を決める。 + CLayoutPoint ptTo ; + if( m_pCommanderView->GetSelectionInfo().IsBoxSelecting() ) { // 矩形選択ではキャレットが改行の後ろに取り残されないように、左上。 + /* 2点を対角とする矩形を求める */ + CLayoutRange rcSel; + TwoPointToRange( + &rcSel, + GetSelect().GetFrom(), // 範囲選択開始 + GetSelect().GetTo() // 範囲選択終了 + ); + ptTo = rcSel.GetFrom(); + } else if( 1 == whereCursorIs ) { // 左上 + ptTo = GetSelect().GetFrom(); + } else if( 2 == whereCursorIs ) { // 右下 + ptTo = GetSelect().GetTo(); + } else { + ptTo = GetCaret().GetCaretLayoutPos(); + } + /* 現在の選択範囲を非選択状態に戻す */ m_pCommanderView->GetSelectionInfo().DisableSelectArea( TRUE ); + + /* カーソルを移動 */ + if( ptTo.y >= GetDocument()->m_cLayoutMgr.GetLineCount() ){ + /* ファイルの最後に移動 */ + Command_GOFILEEND(FALSE); + } else { + GetCaret().MoveCursor( ptTo, TRUE ); + GetCaret().m_nCaretPosX_Prev = GetCaret().GetCaretLayoutPos().GetX2(); + } } - m_pCommanderView->GetSelectionInfo().m_bSelectingLock = FALSE; /* 選択状態のロック */ - return; } Index: sakura_core/view/CCaret.cpp =================================================================== --- sakura_core/view/CCaret.cpp (.../sakura/trunk2) (リビジョン 42526) +++ sakura_core/view/CCaret.cpp (.../fix_rectangular_selection_area) (リビジョン 42526) @@ -1,4 +1,6 @@ #include "stdafx.h" +#include +#include #include "CCaret.h" #include "CTextArea.h" #include "view/CEditView.h" @@ -9,7 +11,6 @@ #include "charset/charcode.h" #include "charset/CCodeFactory.h" #include "window/CEditWnd.h" -#include #include "view/colors/CColorStrategy.h" using namespace std; @@ -768,126 +769,77 @@ CLayoutInt CCaret::Cursor_UPDOWN( CLayoutInt nMoveLines, bool bSelect ) { //必要なインターフェース - const CLayoutMgr* pLayoutMgr=&m_pEditDoc->m_cLayoutMgr; -// const STypeConfig* pTypes=&m_pEditDoc->m_cDocType.GetDocumentAttribute(); - CommonSetting* pCommon=&GetDllShareData().m_Common; + const CLayoutMgr* const pLayoutMgr = &m_pEditDoc->m_cLayoutMgr; + const CommonSetting* const pCommon = &GetDllShareData().m_Common; + const CLayoutPoint ptCaret = GetCaretLayoutPos(); - const wchar_t* pLine; - CLogicInt nLineLen; - int i; - CLayoutInt nLineCols; - CLayoutInt nScrollLines; - const CLayout* pcLayout; - nScrollLines = CLayoutInt(0); + // 現在のキャレットY座標 + nMoveLinesが正しいレイアウト行の範囲内に収まるように nMoveLinesを調整する。 + if( nMoveLines > 0 ) { // 下移動。 + const bool existsEOFOnlyLine = pLayoutMgr->GetBottomLayout() && pLayoutMgr->GetBottomLayout()->GetLayoutEol() != EOL_NONE; + const CLayoutInt maxLayoutLine = pLayoutMgr->GetLineCount() + (existsEOFOnlyLine ? 1 : 0 ) - 1; + // 移動先が EOFのみの行を含めたレイアウト行数未満になるように移動量を規正する。 + nMoveLines = std::min( nMoveLines, maxLayoutLine - ptCaret.y ); + if( ptCaret.y + nMoveLines == maxLayoutLine && existsEOFOnlyLine // 移動先が EOFのみの行 + && m_pEditView->GetSelectionInfo().IsBoxSelecting() && 0 != ptCaret.x // かつ矩形選択中なら、 + ) { + // EOFのみの行には移動しない。下移動でキャレットの X座標を動かしたくないので。 + nMoveLines = std::max( CLayoutInt(0), nMoveLines - 1 ); // うっかり上移動しないように 0以上を守る。 + } + } else { // 上移動。 + // 移動先が 0行目より小さくならないように移動量を規制。 + nMoveLines = std::max( nMoveLines, - GetCaretLayoutPos().GetY() ); + } - CLayoutPoint ptPosXY(CLayoutInt(0), GetCaretLayoutPos().GetY()); + if( bSelect && ! m_pEditView->GetSelectionInfo().IsTextSelected() ) { + /* 現在のカーソル位置から選択を開始する */ + m_pEditView->GetSelectionInfo().BeginSelectArea(); + } + if( ! bSelect && m_pEditView->GetSelectionInfo().IsTextSelected() ) { + /* 現在の選択範囲を非選択状態に戻す */ + m_pEditView->GetSelectionInfo().DisableSelectArea( TRUE ); + } - if( nMoveLines > 0 ){ - /* カーソルがテキスト最下端行にあるか */ - if( GetCaretLayoutPos().GetY() + nMoveLines >= pLayoutMgr->GetLineCount() ){ - nMoveLines = pLayoutMgr->GetLineCount() - GetCaretLayoutPos().GetY() - 1; - } - if( nMoveLines <= 0 ){ - pLine = pLayoutMgr->GetLineStr( GetCaretLayoutPos().GetY2(), &nLineLen, &pcLayout ); - if( NULL != pLine ){ - nLineCols = m_pEditView->LineIndexToColmn( pcLayout, nLineLen ); - /* 改行で終わっているか */ - // Aug. 14, 2005 genta 折り返し幅をLayoutMgrから取得するように - if( ( EOL_NONE != pcLayout->GetLayoutEol() ) -// if( ( pLine[ nLineLen - 1 ] == L'\n' || pLine[ nLineLen - 1 ] == L'\r' ) - // [EOF]のみ折り返すのはやめる // 2009.02.17 ryoji - //|| nLineCols >= pLayoutMgr->GetMaxLineKetas() - ){ - if( bSelect ){ - if( !m_pEditView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 現在のカーソル位置から選択を開始する */ - m_pEditView->GetSelectionInfo().BeginSelectArea(); - } - }else{ - if( m_pEditView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 現在の選択範囲を非選択状態に戻す */ - m_pEditView->GetSelectionInfo().DisableSelectArea( TRUE ); - } - } - ptPosXY.x = CLayoutInt(0); - ++ptPosXY.y; - nScrollLines = MoveCursor( ptPosXY, m_pEditView->GetDrawSwitch() /* TRUE */ ); // YAZAKI. - if( bSelect ){ - /* 現在のカーソル位置によって選択範囲を変更 */ - m_pEditView->GetSelectionInfo().ChangeSelectAreaByCurrentCursor( ptPosXY ); - } - } + // (これから求める)キャレットの移動先。 + CLayoutPoint ptTo( CLayoutInt(0), ptCaret.y + nMoveLines ); + + /* 移動先の行のデータを取得 */ + const CLayout* const pLayout = pLayoutMgr->SearchLineByLayoutY( ptTo.y ); + const CLogicInt nLineLen = pLayout ? pLayout->GetLengthWithEOL() : CLogicInt(0); + int i = 0; ///< 何? + if( pLayout ) { + CMemoryIterator it( pLayout, pLayoutMgr->GetTabSpace() ); + while( ! it.end() ){ + it.scanNext(); + if ( it.getIndex() + it.getIndexDelta() > pLayout->GetLengthWithoutEOL() ){ + i = nLineLen; + break; } - // Sep. 11, 2004 genta 同期スクロールの関数化 - // MoveCursorでスクロール位置調整済み - //SyncScrollV( nScrollLines ); - return nScrollLines; + if( it.getColumn() + it.getColumnDelta() > m_nCaretPosX_Prev ){ + i = it.getIndex(); + break; + } + it.addDelta(); } - }else{ - /* カーソルがテキスト最上端行にあるか */ - if( GetCaretLayoutPos().GetY() + nMoveLines < 0 ){ - nMoveLines = - GetCaretLayoutPos().GetY(); - } - if( nMoveLines >= 0 ){ - // Sep. 11, 2004 genta 同期スクロールの関数化 - m_pEditView->SyncScrollV( nScrollLines ); - return nScrollLines; - } - } - if( bSelect ){ - if( !m_pEditView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 現在のカーソル位置から選択を開始する */ - m_pEditView->GetSelectionInfo().BeginSelectArea(); - } - }else{ - if( m_pEditView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 現在の選択範囲を非選択状態に戻す */ - m_pEditView->GetSelectionInfo().DisableSelectArea( TRUE ); - } - } - /* 次の行のデータを取得 */ - pLine = pLayoutMgr->GetLineStr( GetCaretLayoutPos().GetY2() + CLayoutInt(nMoveLines), &nLineLen, &pcLayout ); - CMemoryIterator it( pcLayout, pLayoutMgr->GetTabSpace() ); - while( !it.end() ){ - it.scanNext(); - if ( it.getIndex() + it.getIndexDelta() > pcLayout->GetLengthWithoutEOL() ){ - i = nLineLen; - break; - } - if( it.getColumn() + it.getColumnDelta() > m_nCaretPosX_Prev ){ + ptTo.x += it.getColumn(); + if( it.end() ) { i = it.getIndex(); - break; } - it.addDelta(); } - ptPosXY.x += it.getColumn(); - if ( it.end() ){ - i = it.getIndex(); - } - - if( i >= nLineLen ){ - /* フリーカーソルモードか */ + if( i >= nLineLen ) { + /* フリーカーソルモードと矩形選択中は、キャレットの位置を改行や EOFの前に制限しない */ if( pCommon->m_sGeneral.m_bIsFreeCursorMode - || m_pEditView->GetSelectionInfo().IsTextSelected() && m_pEditView->GetSelectionInfo().IsBoxSelecting() /* 矩形範囲選択中 */ - ){ - if( GetCaretLayoutPos().GetY() + nMoveLines + 1 == pLayoutMgr->GetLineCount() ){ - if( NULL != pLine ){ - if( pLine[nLineLen - 1] == WCODE::CR || pLine[nLineLen - 1] == WCODE::LF ){ - ptPosXY.x = m_nCaretPosX_Prev; - } - } - }else{ - ptPosXY.x = m_nCaretPosX_Prev; - } + || m_pEditView->GetSelectionInfo().IsBoxSelecting() + ) { + ptTo.x = ptCaret.x; } } - nScrollLines = MoveCursor( CLayoutPoint(ptPosXY.x, GetCaretLayoutPos().GetY() + nMoveLines), m_pEditView->GetDrawSwitch() /* TRUE */ ); // YAZAKI. - if( bSelect ){ + + const CLayoutInt nScrollLines = MoveCursor( ptTo, m_pEditView->GetDrawSwitch() /* TRUE */ ); // YAZAKI. + if( bSelect ) { /* 現在のカーソル位置によって選択範囲を変更 */ - m_pEditView->GetSelectionInfo().ChangeSelectAreaByCurrentCursor( CLayoutPoint(ptPosXY.x, GetCaretLayoutPos().GetY()) ); + m_pEditView->GetSelectionInfo().ChangeSelectAreaByCurrentCursor( GetCaretLayoutPos() ); } - return nScrollLines; }