From 25d84e2826de81d1e7a55ff0fdab7845b7a78e74 Mon Sep 17 00:00:00 2001 From: Oliver-Rainer Wittmann Date: Wed, 26 Jun 2013 12:15:55 +0000 Subject: Resolves: #i121751# restore cursor/selection on Undo/Redo language... change for all text - group intrinsic actions of language change for all text into one Undo action - secure - catch NULL pointer - correct - really restore the cursor (cherry picked from commit 4207db473430e02a65a5f4d57db6e46a8db29a19) Conflicts: svl/inc/svl/undo.hxx svl/source/undo/undo.cxx sw/inc/IDocumentUndoRedo.hxx sw/source/core/edit/edundo.cxx sw/source/core/inc/UndoManager.hxx sw/source/core/layout/trvlfrm.cxx sw/source/core/undo/docundo.cxx Change-Id: I972988bbc21a519e0956ff196aa93a46287b9a2e --- include/svl/undo.hxx | 2 ++ svl/source/undo/undo.cxx | 21 ++++++++++++- sw/inc/IDocumentUndoRedo.hxx | 6 ++-- sw/source/core/edit/edundo.cxx | 15 ++++++++-- sw/source/core/inc/UndoManager.hxx | 6 ++-- sw/source/core/layout/trvlfrm.cxx | 61 ++++++++++++++++++++------------------ sw/source/core/undo/docundo.cxx | 21 ++++++++++--- sw/source/ui/shells/textsh1.cxx | 5 ++++ 8 files changed, 95 insertions(+), 42 deletions(-) diff --git a/include/svl/undo.hxx b/include/svl/undo.hxx index c1054a6ac3bf..3e59baa693db 100644 --- a/include/svl/undo.hxx +++ b/include/svl/undo.hxx @@ -240,6 +240,7 @@ namespace svl virtual size_t GetRedoActionCount( bool const i_currentLevel = CurrentLevel ) const = 0; virtual OUString GetRedoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const = 0; + virtual SfxUndoAction* GetRedoAction( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const = 0; virtual sal_Bool Undo() = 0; virtual sal_Bool Redo() = 0; @@ -358,6 +359,7 @@ public: virtual SfxUndoAction* GetUndoAction( size_t nNo=0 ) const; virtual size_t GetRedoActionCount( bool const i_currentLevel = CurrentLevel ) const; virtual OUString GetRedoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const; + virtual SfxUndoAction* GetRedoAction( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const; virtual sal_Bool Undo(); virtual sal_Bool Redo(); virtual void Clear(); diff --git a/svl/source/undo/undo.cxx b/svl/source/undo/undo.cxx index dac5dc3d37dc..d27de22e266e 100644 --- a/svl/source/undo/undo.cxx +++ b/svl/source/undo/undo.cxx @@ -830,11 +830,30 @@ size_t SfxUndoManager::ImplGetRedoActionCount_Lock( bool const i_currentLevel ) //------------------------------------------------------------------------ +SfxUndoAction* SfxUndoManager::GetRedoAction( size_t nNo, bool const i_currentLevel ) const +{ + UndoManagerGuard aGuard( *m_pData ); + + const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData->pActUndoArray : m_pData->pUndoArray; + if ( (pUndoArray->nCurUndoAction + nNo) > pUndoArray->aUndoActions.size() ) + { + return NULL; + } + return pUndoArray->aUndoActions[ pUndoArray->nCurUndoAction + nNo ].pAction; +} + +//------------------------------------------------------------------------ + OUString SfxUndoManager::GetRedoActionComment( size_t nNo, bool const i_currentLevel ) const { + String sComment; UndoManagerGuard aGuard( *m_pData ); const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData->pActUndoArray : m_pData->pUndoArray; - return pUndoArray->aUndoActions[ pUndoArray->nCurUndoAction + nNo ].pAction->GetComment(); + if ( (pUndoArray->nCurUndoAction + nNo) < pUndoArray->aUndoActions.size() ) + { + sComment = pUndoArray->aUndoActions[ pUndoArray->nCurUndoAction + nNo ].pAction->GetComment(); + } + return sComment; } //------------------------------------------------------------------------ diff --git a/sw/inc/IDocumentUndoRedo.hxx b/sw/inc/IDocumentUndoRedo.hxx index 26e76f0b838f..a50a4f0dcbb4 100644 --- a/sw/inc/IDocumentUndoRedo.hxx +++ b/sw/inc/IDocumentUndoRedo.hxx @@ -156,11 +156,13 @@ public: */ virtual sal_Bool Redo() = 0; - /** Get comment of first Redo action. + /** Get Id and comment of first Redo action. @param o_pStr if not 0, receives comment of first Redo action. + @param o_pId if not 0, receives Id of first Redo action. @return true if there is a Redo action, false if none */ - virtual bool GetFirstRedoInfo(OUString *const o_pStr) const = 0; + virtual bool GetFirstRedoInfo(OUString *const o_pStr, + SwUndoId *const o_pId = 0) const = 0; /** Get comments of Redo actions. @return comments of all top-level Redo actions. diff --git a/sw/source/core/edit/edundo.cxx b/sw/source/core/edit/edundo.cxx index bd27446a374f..4fa0ceef53be 100644 --- a/sw/source/core/edit/edundo.cxx +++ b/sw/source/core/edit/edundo.cxx @@ -111,9 +111,11 @@ bool SwEditShell::Undo(sal_uInt16 const nCount) // Keep Cursor - so that we're able to set it at // the same position for autoformat or autocorrection SwUndoId nLastUndoId(UNDO_EMPTY); - GetDoc()->GetIDocumentUndoRedo().GetLastUndoInfo(0, & nLastUndoId); - bool bRestoreCrsr = 1 == nCount && (UNDO_AUTOFORMAT == nLastUndoId || - UNDO_AUTOCORRECT == nLastUndoId ); + GetLastUndoInfo(0, & nLastUndoId); + const bool bRestoreCrsr = nCount == 1 + && ( UNDO_AUTOFORMAT == nLastUndoId + || UNDO_AUTOCORRECT == nLastUndoId + || UNDO_SETDEFTATTR == nLastUndoId ); Push(); // Destroy stored TableBoxPtr. A dection is only permitted for the new "Box"! @@ -168,6 +170,11 @@ bool SwEditShell::Redo(sal_uInt16 const nCount) SetMark(); // Bound1 and Bound2 in the same Node ClearMark(); + SwUndoId nFirstRedoId(UNDO_EMPTY); + GetDoc()->GetIDocumentUndoRedo().GetFirstRedoInfo(0, & nFirstRedoId); + const bool bRestoreCrsr = nCount == 1 && UNDO_SETDEFTATTR == nFirstRedoId; + Push(); + // Destroy stored TableBoxPtr. A dection is only permitted for the new "Box"! ClearTblBoxCntnt(); @@ -185,6 +192,8 @@ bool SwEditShell::Redo(sal_uInt16 const nCount) .getStr()); } + Pop( !bRestoreCrsr ); + GetDoc()->SetRedlineMode( eOld ); GetDoc()->CompressRedlines(); diff --git a/sw/source/core/inc/UndoManager.hxx b/sw/source/core/inc/UndoManager.hxx index 0db18261bf60..3b7d1136418d 100644 --- a/sw/source/core/inc/UndoManager.hxx +++ b/sw/source/core/inc/UndoManager.hxx @@ -59,10 +59,10 @@ public: SwRewriter const*const pRewriter); virtual void DelAllUndoObj(); virtual bool GetLastUndoInfo(OUString *const o_pStr, - SwUndoId *const o_pId) const; + SwUndoId *const o_pId) const; virtual SwUndoComments_t GetUndoComments() const; - - virtual bool GetFirstRedoInfo(OUString *const o_pStr) const; + virtual bool GetFirstRedoInfo(OUString *const o_pStr, + SwUndoId *const o_pId = 0) const; virtual SwUndoComments_t GetRedoComments() const; virtual bool Repeat(::sw::RepeatContext & rContext, sal_uInt16 const nRepeatCnt); diff --git a/sw/source/core/layout/trvlfrm.cxx b/sw/source/core/layout/trvlfrm.cxx index 1a2bb5c32228..e4318507167e 100644 --- a/sw/source/core/layout/trvlfrm.cxx +++ b/sw/source/core/layout/trvlfrm.cxx @@ -2097,8 +2097,7 @@ inline void Sub( SwRegionRects& rRegion, const SwRect& rRect ) void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) { SwPosition *pStartPos = rCrsr.Start(), - *pEndPos = rCrsr.GetPoint() == pStartPos ? - rCrsr.GetMark() : rCrsr.GetPoint(); + *pEndPos = rCrsr.GetPoint() == pStartPos ? rCrsr.GetMark() : rCrsr.GetPoint(); ViewShell *pSh = GetCurrShell(); @@ -2134,8 +2133,11 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) OSL_ENSURE( pObj, "No Start Object." ); if (pObj) aSortObjs.Insert( *(const_cast(pObj)) ); const SwAnchoredObject* pObj2 = pEndFrm->FindFlyFrm(); - OSL_ENSURE( pObj2, "No Start Object." ); - if (pObj2) aSortObjs.Insert( *(const_cast(pObj2)) ); + OSL_ENSURE( pObj2, "SwRootFrm::CalcFrmRects(..) - FlyFrame missing - looks like an invalid selection" ); + if ( pObj2 != NULL && pObj2 != pObj ) + { + aSortObjs.Insert( *(const_cast(pObj2)) ); + } } //Fall 4: Tabellenselection @@ -2170,7 +2172,7 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) break; OSL_ENSURE( pEndLFrm->GetType() == pSttLFrm->GetType(), - "Selection ueber unterschiedliche Inhalte" ); + "Selection ueber unterschiedliche Inhalte" ); switch( pSttLFrm->GetType() ) { case FRM_HEADER: @@ -2193,11 +2195,11 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) { const SwTabFrm* pTabFrm = (SwTabFrm*)pSttLFrm; if( ( pTabFrm->GetFollow() || - ((SwTabFrm*)pEndLFrm)->GetFollow() ) && + ((SwTabFrm*)pEndLFrm)->GetFollow() ) && pTabFrm->GetTable()->GetRowsToRepeat() > 0 && pTabFrm->GetLower() != ((SwTabFrm*)pEndLFrm)->GetLower() && ( lcl_IsInRepeatedHeadline( pStartFrm ) || - lcl_IsInRepeatedHeadline( pEndFrm ) ) ) + lcl_IsInRepeatedHeadline( pEndFrm ) ) ) { // End- auf den Start-CntntFrame setzen if( pStartPos == rCrsr.GetPoint() ) @@ -2227,10 +2229,11 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) SwRect aStFrm ( pStartFrm->UnionFrm( sal_True ) ); aStFrm.Intersection( pStartFrm->PaintArea() ); - SwRect aEndFrm( pStartFrm == pEndFrm ? aStFrm : - pEndFrm->UnionFrm( sal_True ) ); + SwRect aEndFrm( pStartFrm == pEndFrm ? aStFrm : pEndFrm->UnionFrm( sal_True ) ); if( pStartFrm != pEndFrm ) + { aEndFrm.Intersection( pEndFrm->PaintArea() ); + } SWRECTFN( pStartFrm ) const sal_Bool bR2L = pStartFrm->IsRightToLeft(); const sal_Bool bEndR2L = pEndFrm->IsRightToLeft(); @@ -2251,8 +2254,8 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) // BiDi-Portions are swimming against the current. const sal_Bool bPorR2L = ( MT_BIDI == pSt2Pos->nMultiType ) ? - ! bR2L : - bR2L; + ! bR2L : + bR2L; if( MT_BIDI == pSt2Pos->nMultiType && (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() ) @@ -2502,9 +2505,9 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) { OutputDevice* pOut = pSh->GetOut(); long nCrsrWidth = pOut->GetSettings().GetStyleSettings(). - GetCursorSize(); + GetCursorSize(); (aTmp.*fnRect->fnSetWidth)( pOut->PixelToLogic( - Size( nCrsrWidth, 0 ) ).Width() ); + Size( nCrsrWidth, 0 ) ).Width() ); } aTmp.Intersection( aStFrm ); Sub( aRegion, aTmp ); @@ -2521,9 +2524,9 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) else { lLeft = (pStartFrm->Frm().*fnRect->fnGetLeft)() + - (pStartFrm->Prt().*fnRect->fnGetLeft)(); + (pStartFrm->Prt().*fnRect->fnGetLeft)(); lRight = (pStartFrm->Frm().*fnRect->fnGetLeft)() + - (pStartFrm->Prt().*fnRect->fnGetRight)(); + (pStartFrm->Prt().*fnRect->fnGetRight)(); } if( lLeft < (aStFrm.*fnRect->fnGetLeft)() ) lLeft = (aStFrm.*fnRect->fnGetLeft)(); @@ -2579,15 +2582,12 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) //Now the frames between, if there are any bool const bBody = pStartFrm->IsInDocBody(); const SwTableBox* pCellBox = pStartFrm->GetUpper()->IsCellFrm() ? - ((SwCellFrm*)pStartFrm->GetUpper())->GetTabBox() : 0; + ((SwCellFrm*)pStartFrm->GetUpper())->GetTabBox() : 0; const SwCntntFrm *pCntnt = pStartFrm->GetNextCntntFrm(); SwRect aPrvRect; - // #123908# - introduce robust code - // The stacktrace issue reveals that could be NULL. - // One root cause found by AMA - see #130650# OSL_ENSURE( pCntnt, - " - no content frame. This is a serious defect -> please inform OD" ); + " - no content frame. This is a serious defect -> please inform OD" ); while ( pCntnt && pCntnt != pEndFrm ) { if ( pCntnt->IsInFly() ) @@ -2600,7 +2600,7 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) // If pStartFrm is inside a SwCellFrm, consider only frames which are inside the // same cell frame (or its follow cell) const SwTableBox* pTmpCellBox = pCntnt->GetUpper()->IsCellFrm() ? - ((SwCellFrm*)pCntnt->GetUpper())->GetTabBox() : 0; + ((SwCellFrm*)pCntnt->GetUpper())->GetTabBox() : 0; if ( bBody == pCntnt->IsInDocBody() && ( !pCellBox || pCellBox == pTmpCellBox ) ) { @@ -2625,9 +2625,8 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) } } pCntnt = pCntnt->GetNextCntntFrm(); - // #123908# OSL_ENSURE( pCntnt, - " - no content frame. This is a serious defect -> please inform OD" ); + " - no content frame. This is a serious defect -> please inform OD" ); } if ( aPrvRect.HasArea() ) Sub( aRegion, aPrvRect ); @@ -2637,7 +2636,7 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) bRev = pEndFrm->IsReverse(); //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin fnRect = bVert ? ( bRev ? fnRectVL2R : ( pEndFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) ) : - ( bRev ? fnRectB2T : fnRectHori ); + ( bRev ? fnRectB2T : fnRectHori ); nTmpTwips = (aEndRect.*fnRect->fnGetTop)(); if( (aEndFrm.*fnRect->fnGetTop)() != nTmpTwips ) { @@ -2653,7 +2652,6 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) Sub( aRegion, aSubRect ); } -// aRegion.Compress( sal_False ); aRegion.Invert(); delete pSt2Pos; delete pEnd2Pos; @@ -2681,8 +2679,8 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) const SwVirtFlyDrawObj* pObj = pFly->GetVirtDrawObj(); const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround(); if ( !pFly->IsAnLower( pStartFrm ) && - (rSur.GetSurround() != SURROUND_THROUGHT && - !rSur.IsContour()) ) + (rSur.GetSurround() != SURROUND_THROUGHT && + !rSur.IsContour()) ) { if ( aSortObjs.Contains( *pAnchoredObj ) ) continue; @@ -2692,13 +2690,18 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode ) for ( sal_uInt16 k = 0; bSub && k < aSortObjs.Count(); ++k ) { OSL_ENSURE( aSortObjs[k]->ISA(SwFlyFrm), - " - object in of unexcepted type" ); + " - object in of unexcepted type" ); const SwFlyFrm* pTmp = static_cast(aSortObjs[k]); do - { if ( nPos < pTmp->GetVirtDrawObj()->GetOrdNumDirect() ) + { + if ( nPos < pTmp->GetVirtDrawObj()->GetOrdNumDirect() ) + { bSub = sal_False; + } else + { pTmp = pTmp->GetAnchorFrm()->FindFlyFrm(); + } } while ( bSub && pTmp ); } if ( bSub ) diff --git a/sw/source/core/undo/docundo.cxx b/sw/source/core/undo/docundo.cxx index 79ad862c675f..fff78e4da186 100644 --- a/sw/source/core/undo/docundo.cxx +++ b/sw/source/core/undo/docundo.cxx @@ -332,16 +332,29 @@ SwUndoComments_t UndoManager::GetUndoComments() const /**************** REDO ******************/ -bool UndoManager::GetFirstRedoInfo(OUString *const o_pStr) const + +bool UndoManager::GetFirstRedoInfo(OUString *const o_pStr, + SwUndoId *const o_pId) const { if (!SdrUndoManager::GetRedoActionCount(CurrentLevel)) { return false; } + SfxUndoAction *const pAction( SdrUndoManager::GetRedoAction(0, CurrentLevel) ); + if ( pAction == NULL ) + { + return false; + } + if (o_pStr) { - *o_pStr = SdrUndoManager::GetRedoActionComment(0, CurrentLevel); + *o_pStr = pAction->GetComment(); + } + if (o_pId) + { + sal_uInt16 const nId(pAction->GetId()); + *o_pId = static_cast(nId); } return true; @@ -443,7 +456,7 @@ public: { if (m_bSaveCursor) { - m_rShell.Pop(); + m_rShell.Pop( sal_False ); } } private: @@ -468,7 +481,7 @@ bool UndoManager::impl_DoUndoRedo(UndoOrRedo_t const undoOrRedo) // in case the model has controllers locked, the Undo should not // change the view cursors! bool const bSaveCursors(pEditShell->CursorsLocked()); - CursorGuard(*pEditShell, bSaveCursors); + CursorGuard aCursorGuard(*pEditShell, bSaveCursors); if (!bSaveCursors) { // (in case Undo was called via API) clear the cursors: diff --git a/sw/source/ui/shells/textsh1.cxx b/sw/source/ui/shells/textsh1.cxx index 340e938ddac6..2ac65fd9f2a3 100644 --- a/sw/source/ui/shells/textsh1.cxx +++ b/sw/source/ui/shells/textsh1.cxx @@ -328,6 +328,7 @@ void SwTextShell::Execute(SfxRequest &rReq) rWrtSh.StartAction(); // prevent view from jumping because of (temporary) selection changes rWrtSh.LockView( sal_True ); + // save selection for later restoration rWrtSh.Push(); @@ -377,12 +378,16 @@ void SwTextShell::Execute(SfxRequest &rReq) rWrtSh.SelAll(); rWrtSh.ExtendedSelectAll(); } + + rWrtSh.StartUndo( ( !bForParagraph && !bForSelection ) ? UNDO_SETDEFTATTR : UNDO_EMPTY ); if (aNewLangTxt == aStrNone) SwLangHelper::SetLanguage_None( rWrtSh, bForSelection, aCoreSet ); else if (aNewLangTxt == aStrResetLangs) SwLangHelper::ResetLanguages( rWrtSh, bForSelection ); else SwLangHelper::SetLanguage( rWrtSh, aNewLangTxt, bForSelection, aCoreSet ); + rWrtSh.EndUndo(); + } // restore selection... -- cgit