Index: sakura_core/COpe.h =================================================================== --- sakura_core/COpe.h (リビジョン 50499) +++ sakura_core/COpe.h (リビジョン 50608) @@ -11,12 +11,12 @@ Please contact the copyright holder to use this code for other purpose. */ -class COpe; - #ifndef _COPE_H_ #define _COPE_H_ +class COpe; class CMemory;// 2002/2/10 aroka +#include "basis/SakuraBasis.h" // CLogicRange // アンドゥバッファ用 操作コード @@ -25,6 +25,8 @@ OPE_INSERT = 1, OPE_DELETE = 2, OPE_MOVECARET = 3, + OPE_SELECT, + OPE_SELECT_L }; @@ -86,9 +88,34 @@ } }; +template +class TSelectOpe +: public COpe +{ +public: + TSelectOpe(const RangeT& selectRange, bool boxSelecting, const CLogicPoint& caretPos) + : COpe(OPE), selectRange(selectRange), boxSelecting(boxSelecting) + { + this->m_ptCaretPos_PHY_After = this->m_ptCaretPos_PHY_Before = caretPos; + } + RangeT selectRange; // fromと toの関係。fromは選択始点。toは fromより前にも後ろにもなりうる。 + bool boxSelecting; +}; +/** 選択範囲/矩形選択範囲とキャレット位置 + Insert/Deleteの直前のものを保存し、アンドゥ・リドゥのときに復元できるようにする。 + 選択範囲の*変化*ではない。主役は挿入や削除という操作で、その前後の付加情報として存在する。 + キャレットが選択範囲の端点にいないことが全選択で起こる。 +*/ +typedef TSelectOpe CSelectOpe; +/** CSelectOpeの CLayoutRange版。矩形選択にどうぞ。 + Logic単位で位置情報を保存すると、レイアウトの変化には強くなるが + 文字のない部分を選択することもある矩形選択では情報が失われる。 + 矩形選択のときはレイアウト単位で記録した方がうまくいくことが多いかも。 +*/ +typedef TSelectOpe CSelectLOpe; Index: sakura_core/CViewCommander_New.cpp =================================================================== --- sakura_core/CViewCommander_New.cpp (リビジョン 50499) +++ sakura_core/CViewCommander_New.cpp (リビジョン 50608) @@ -60,6 +60,20 @@ CLayoutPoint ptCaretPos_After; + const struct // OPE_SELECTと OPE_SELECT_Lのためのサブルーチン。 + { + CEditView* view; + void operator()(const CLayoutRange& selectRange, bool boxSelecting) const + { + this->view->GetSelectionInfo().DisableSelectArea(false); + this->view->GetCaret().MoveCursor(selectRange.GetFrom(), false); + this->view->GetSelectionInfo().BeginSelectArea(); + this->view->GetSelectionInfo().SetBoxSelect(boxSelecting); + this->view->GetCaret().MoveCursor(selectRange.GetTo(), false); + this->view->GetSelectionInfo().ChangeSelectAreaByCurrentCursor(this->view->GetCaret().GetCaretLayoutPos()); + } + } RestoreSelectArea = {this->m_pCommanderView}; + /* 各種モードの取り消し */ Command_CANCEL_MODE(); @@ -135,7 +149,23 @@ /* カーソルを移動 */ GetCaret().MoveCursor( ptCaretPos_After, false ); break; + case OPE_SELECT: /* OPE_INSERTや OPE_DELETE前後の選択範囲とキャレット位置を復元する。 */ + { + CSelectOpe* pSelectOpe = dynamic_cast(pcOpe); + + CLayoutRange selectRange; + this->GetDocument()->m_cLayoutMgr.LogicToLayout(pSelectOpe->selectRange, &selectRange); + + RestoreSelectArea(selectRange, pSelectOpe->boxSelecting); + // キャレット位置の復元は COpe共通のタスクらしいのでここではやらない。 + break; } + case OPE_SELECT_L: /* OPE_INSERTや OPE_DELETE前後の選択範囲とキャレット位置を復元する。 */ + CSelectLOpe* pSelectOpe = dynamic_cast(pcOpe); + RestoreSelectArea(pSelectOpe->selectRange, pSelectOpe->boxSelecting); + // キャレット位置の復元は COpe共通のタスクらしいのでここではやらない。 + break; + } GetDocument()->m_cLayoutMgr.LogicToLayout( pcOpe->m_ptCaretPos_PHY_Before, @@ -217,6 +247,19 @@ CLayoutPoint ptCaretPos_To; CLayoutPoint ptCaretPos_After; + const struct // OPE_SELECTと OPE_SELECT_Lのためのサブルーチン。 + { + CEditView* view; + void operator()(const CLayoutRange& selectRange, bool boxSelecting) const + { + this->view->GetSelectionInfo().DisableSelectArea(false); + this->view->GetCaret().MoveCursor(selectRange.GetFrom(), false); + this->view->GetSelectionInfo().BeginSelectArea(); + this->view->GetSelectionInfo().SetBoxSelect(boxSelecting); + this->view->GetCaret().MoveCursor(selectRange.GetTo(), false); + this->view->GetSelectionInfo().ChangeSelectAreaByCurrentCursor(this->view->GetCaret().GetCaretLayoutPos()); + } + } RestoreSelectArea = {this->m_pCommanderView}; /* 各種モードの取り消し */ Command_CANCEL_MODE(); @@ -292,7 +335,23 @@ break; case OPE_MOVECARET: break; + case OPE_SELECT: /* OPE_INSERTや OPE_DELETE前後の選択範囲とキャレット位置を復元する。 */ + { + CSelectOpe* pSelectOpe = dynamic_cast(pcOpe); + + CLayoutRange selectRange; + this->GetDocument()->m_cLayoutMgr.LogicToLayout(pSelectOpe->selectRange, &selectRange); + + RestoreSelectArea(selectRange, pSelectOpe->boxSelecting); + // キャレット位置の復元は COpe共通のタスクらしいのでここではやらない。 + break; } + case OPE_SELECT_L: /* OPE_INSERTや OPE_DELETE前後の選択範囲とキャレット位置を復元する。 */ + CSelectLOpe* pSelectOpe = dynamic_cast(pcOpe); + RestoreSelectArea(pSelectOpe->selectRange, pSelectOpe->boxSelecting); + // キャレット位置の復元は COpe共通のタスクらしいのでここではやらない。 + break; + } GetDocument()->m_cLayoutMgr.LogicToLayout( pcOpe->m_ptCaretPos_PHY_After, &ptCaretPos_After Index: sakura_core/view/CEditView_Command_New.cpp =================================================================== --- sakura_core/view/CEditView_Command_New.cpp (リビジョン 50499) +++ sakura_core/view/CEditView_Command_New.cpp (リビジョン 50608) @@ -436,13 +436,18 @@ if( GetSelectionInfo().IsTextSelected() ){ CWaitCursor cWaitCursor( this->GetHwnd() ); // 2002.02.05 hor if( !m_bDoing_UndoRedo ){ /* アンドゥ・リドゥの実行中か */ - /* 操作の追加 */ - m_pcOpeBlk->AppendOpe( - new CMoveCaretOpe( - GetCaret().GetCaretLogicPos(), // 操作前のキャレット位置 - GetCaret().GetCaretLogicPos() // 操作後のキャレット位置 - ) - ); + /* 操作の追加(選択範囲とキャレット位置の保存) */ + CLayoutRange selectLayoutRange = this->GetSelectionInfo().m_sSelect.GetFrom() == this->GetSelectionInfo().m_sSelectBgn.GetFrom() ? this->GetSelectionInfo().m_sSelect : CLayoutRange(this->GetSelectionInfo().m_sSelect.GetTo(), this->GetSelectionInfo().m_sSelect.GetFrom()); + if(this->GetSelectionInfo().IsBoxSelecting()) { + // 矩形選択のときは選択終点が改行より後ろにある場合にそなえてレイアウト座標で + // 選択範囲を保存する。レイアウトの変更には弱くなるので、折り返し桁を変更する頻度と + // 改行の後ろにカーソルを持って行く頻度のどちらが多いかの問題。 + m_pcOpeBlk->AppendOpe(new CSelectLOpe(selectLayoutRange, true, this->GetCaret().GetCaretLogicPos())); + } else { + CLogicRange selectLogicRange; + this->GetDocument()->m_cLayoutMgr.LayoutToLogic(selectLayoutRange, &selectLogicRange); + m_pcOpeBlk->AppendOpe(new CSelectOpe(selectLogicRange, false, this->GetCaret().GetCaretLogicPos())); + } } /* 矩形範囲選択中か */