summaryrefslogtreecommitdiff
path: root/sw/source/core/undo
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/undo')
-rw-r--r--sw/source/core/undo/SwRewriter.cxx80
-rw-r--r--sw/source/core/undo/SwUndoField.cxx160
-rw-r--r--sw/source/core/undo/SwUndoFmt.cxx513
-rw-r--r--sw/source/core/undo/SwUndoPageDesc.cxx477
-rw-r--r--sw/source/core/undo/SwUndoTOXChange.cxx74
-rw-r--r--sw/source/core/undo/docundo.cxx1027
-rw-r--r--sw/source/core/undo/makefile.mk86
-rw-r--r--sw/source/core/undo/rolbck.cxx1522
-rw-r--r--sw/source/core/undo/unattr.cxx1320
-rw-r--r--sw/source/core/undo/unbkmk.cxx111
-rw-r--r--sw/source/core/undo/undel.cxx1008
-rw-r--r--sw/source/core/undo/undo.hrc185
-rw-r--r--sw/source/core/undo/undo.src657
-rw-r--r--sw/source/core/undo/undobj.cxx1402
-rw-r--r--sw/source/core/undo/undobj1.cxx706
-rw-r--r--sw/source/core/undo/undoflystrattr.cxx107
-rw-r--r--sw/source/core/undo/undraw.cxx644
-rw-r--r--sw/source/core/undo/unfmco.cxx134
-rw-r--r--sw/source/core/undo/unins.cxx1102
-rw-r--r--sw/source/core/undo/unmove.cxx358
-rw-r--r--sw/source/core/undo/unnum.cxx468
-rw-r--r--sw/source/core/undo/unoutl.cxx72
-rw-r--r--sw/source/core/undo/unovwr.cxx514
-rw-r--r--sw/source/core/undo/unredln.cxx545
-rw-r--r--sw/source/core/undo/unsect.cxx501
-rw-r--r--sw/source/core/undo/unsort.cxx302
-rw-r--r--sw/source/core/undo/unspnd.cxx218
-rw-r--r--sw/source/core/undo/untbl.cxx3256
-rw-r--r--sw/source/core/undo/untblk.cxx369
29 files changed, 17918 insertions, 0 deletions
diff --git a/sw/source/core/undo/SwRewriter.cxx b/sw/source/core/undo/SwRewriter.cxx
new file mode 100644
index 000000000000..9db43b4ee85b
--- /dev/null
+++ b/sw/source/core/undo/SwRewriter.cxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <algorithm>
+#include <SwRewriter.hxx>
+
+using namespace std;
+
+bool operator == (const SwRewriteRule & a, const SwRewriteRule & b)
+{
+ return a.first == b.first;
+}
+
+SwRewriter::SwRewriter()
+{
+}
+
+SwRewriter::SwRewriter(const SwRewriter & rSrc)
+ : mRules(rSrc.mRules)
+{
+}
+
+SwRewriter::~SwRewriter()
+{
+}
+
+void SwRewriter::AddRule(const String & rWhat, const String & rWith)
+{
+ SwRewriteRule aRule(rWhat, rWith);
+
+ vector<SwRewriteRule>::iterator aIt;
+
+ aIt = find(mRules.begin(), mRules.end(), aRule);
+
+ if (aIt != mRules.end())
+ *aIt = aRule;
+ else
+ mRules.push_back(aRule);
+}
+
+String SwRewriter::Apply(const String & rStr) const
+{
+ String aResult = rStr;
+ vector<SwRewriteRule>::const_iterator aIt;
+
+ for (aIt = mRules.begin(); aIt != mRules.end(); aIt++)
+ aResult.SearchAndReplaceAll(aIt->first, aIt->second);
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/SwUndoField.cxx b/sw/source/core/undo/SwUndoField.cxx
new file mode 100644
index 000000000000..7bb38c30d814
--- /dev/null
+++ b/sw/source/core/undo/SwUndoField.cxx
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <tools/rtti.hxx>
+#include <SwUndoField.hxx>
+#include <swundo.hxx>
+#include <doc.hxx>
+#include <txtfld.hxx>
+#include <fldbas.hxx>
+#include <ndtxt.hxx>
+#include <fmtfld.hxx>
+#include <dbfld.hxx>
+#include <docsh.hxx>
+
+using namespace ::com::sun::star::uno;
+
+SwUndoField::SwUndoField(const SwPosition & rPos, SwUndoId _nId )
+ : SwUndo(_nId)
+{
+ nNodeIndex = rPos.nNode.GetIndex();
+ nOffset = rPos.nContent.GetIndex();
+ pDoc = rPos.GetDoc();
+}
+
+SwUndoField::~SwUndoField()
+{
+}
+
+SwPosition SwUndoField::GetPosition()
+{
+ SwNode * pNode = pDoc->GetNodes()[nNodeIndex];
+ SwNodeIndex aNodeIndex(*pNode);
+ SwIndex aIndex(pNode->GetCntntNode(), nOffset);
+ SwPosition aResult(aNodeIndex, aIndex);
+
+ return aResult;
+}
+
+SwUndoFieldFromDoc::SwUndoFieldFromDoc(const SwPosition & rPos,
+ const SwField & rOldField,
+ const SwField & rNewField,
+ SwMsgPoolItem * _pHnt, BOOL _bUpdate, SwUndoId _nId)
+ : SwUndoField(rPos,_nId)
+ , pOldField(rOldField.CopyField())
+ , pNewField(rNewField.CopyField())
+ , pHnt(_pHnt)
+ , bUpdate(_bUpdate)
+{
+ OSL_ENSURE(pOldField, "No old field!");
+ OSL_ENSURE(pNewField, "No new field!");
+ OSL_ENSURE(pDoc, "No document!");
+}
+
+SwUndoFieldFromDoc::~SwUndoFieldFromDoc()
+{
+ delete pOldField;
+ delete pNewField;
+}
+
+void SwUndoFieldFromDoc::Undo( SwUndoIter& )
+{
+ SwTxtFld * pTxtFld = SwDoc::GetTxtFld(GetPosition());
+
+ const SwField * pField = pTxtFld ? pTxtFld->GetFld().GetFld() : NULL;
+
+ if (pField)
+ {
+ BOOL bUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ pDoc->UpdateFld(pTxtFld, *pOldField, pHnt, bUpdate);
+ pDoc->DoUndo(bUndo);
+ }
+}
+
+void SwUndoFieldFromDoc::Redo( SwUndoIter& )
+{
+ SwTxtFld * pTxtFld = SwDoc::GetTxtFld(GetPosition());
+ const SwField * pField = pTxtFld ? pTxtFld->GetFld().GetFld() : NULL;
+
+ if (pField)
+ {
+ BOOL bUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ pDoc->UpdateFld(pTxtFld, *pNewField, pHnt, bUpdate);
+ SwFmtFld* pDstFmtFld = (SwFmtFld*)&pTxtFld->GetFld();
+
+ if ( pDoc->GetFldType(RES_POSTITFLD, aEmptyStr,false) == pDstFmtFld->GetFld()->GetTyp() )
+ pDoc->GetDocShell()->Broadcast( SwFmtFldHint( pDstFmtFld, SWFMTFLD_INSERTED ) );
+ pDoc->DoUndo(bUndo);
+ }
+}
+
+void SwUndoFieldFromDoc::Repeat(SwUndoIter & rIt)
+{
+ Redo(rIt);
+}
+
+SwUndoFieldFromAPI::SwUndoFieldFromAPI(const SwPosition & rPos,
+ const Any & rOldVal, const Any & rNewVal,
+ USHORT _nWhich)
+ : SwUndoField(rPos), aOldVal(rOldVal), aNewVal(rNewVal), nWhich(_nWhich)
+{
+}
+
+SwUndoFieldFromAPI::~SwUndoFieldFromAPI()
+{
+}
+
+void SwUndoFieldFromAPI::Undo( SwUndoIter& )
+{
+ SwField * pField = SwDoc::GetField(GetPosition());
+
+ if (pField)
+ pField->PutValue(aOldVal, nWhich);
+}
+
+void SwUndoFieldFromAPI::Redo( SwUndoIter& )
+{
+ SwField * pField = SwDoc::GetField(GetPosition());
+
+ if (pField)
+ pField->PutValue(aNewVal, nWhich);
+}
+
+
+void SwUndoFieldFromAPI::Repeat(SwUndoIter & rIter)
+{
+ Redo(rIter);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/SwUndoFmt.cxx b/sw/source/core/undo/SwUndoFmt.cxx
new file mode 100644
index 000000000000..d123f7514b28
--- /dev/null
+++ b/sw/source/core/undo/SwUndoFmt.cxx
@@ -0,0 +1,513 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/resid.hxx>
+#include <poolfmt.hxx>
+#include <charfmt.hxx>
+#include <frmfmt.hxx>
+#include <SwUndoFmt.hxx>
+#include <SwRewriter.hxx>
+#include <swundo.hxx>
+#include <undobj.hxx>
+#include <fmtcol.hxx>
+#include <tools/string.hxx>
+#include <doc.hxx>
+#include <comcore.hrc>
+
+SwUndoFmtCreate::SwUndoFmtCreate
+(SwUndoId nUndoId, SwFmt * _pNew, SwFmt * _pDerivedFrom, SwDoc * _pDoc)
+ : SwUndo(nUndoId), pNew(_pNew),
+ pDoc(_pDoc), pNewSet(NULL), nId(0), bAuto(FALSE)
+{
+ if (_pDerivedFrom)
+ sDerivedFrom = _pDerivedFrom->GetName();
+}
+
+SwUndoFmtCreate::~SwUndoFmtCreate()
+{
+}
+
+void SwUndoFmtCreate::Undo(SwUndoIter &)
+{
+ if (pNew)
+ {
+ if (sNewName.Len() == 0 && pNew)
+ sNewName = pNew->GetName();
+
+ if (sNewName.Len() > 0)
+ pNew = Find(sNewName);
+
+ if (pNew)
+ {
+ pNewSet = new SfxItemSet(pNew->GetAttrSet());
+ nId = pNew->GetPoolFmtId() & COLL_GET_RANGE_BITS;
+ bAuto = pNew->IsAuto();
+
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ Delete();
+ pDoc->DoUndo(bDoesUndo);
+ }
+ }
+}
+
+void SwUndoFmtCreate::Redo(SwUndoIter &)
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ SwFmt * pDerivedFrom = Find(sDerivedFrom);
+ SwFmt * pFmt = Create(pDerivedFrom);
+
+ if (pFmt && pNewSet)
+ {
+ pFmt->SetAuto(bAuto);
+ pDoc->ChgFmt(*pFmt, *pNewSet);
+ pFmt->SetPoolFmtId((pFmt->GetPoolFmtId()
+ & ~COLL_GET_RANGE_BITS)
+ | nId);
+
+ pNew = pFmt;
+ }
+ else
+ pNew = NULL;
+
+ pDoc->DoUndo(bDoesUndo);
+}
+
+SwRewriter SwUndoFmtCreate::GetRewriter() const
+{
+ if (sNewName.Len() == 0 && pNew)
+ sNewName = pNew->GetName();
+
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, sNewName);
+
+ return aRewriter;
+}
+
+SwUndoFmtDelete::SwUndoFmtDelete
+(SwUndoId nUndoId, SwFmt * _pOld, SwDoc * _pDoc)
+ : SwUndo(nUndoId),
+ pDoc(_pDoc), sOldName(_pOld->GetName()),
+ aOldSet(_pOld->GetAttrSet())
+{
+ sDerivedFrom = _pOld->DerivedFrom()->GetName();
+ nId = _pOld->GetPoolFmtId() & COLL_GET_RANGE_BITS;
+ bAuto = _pOld->IsAuto();
+}
+
+SwUndoFmtDelete::~SwUndoFmtDelete()
+{
+}
+
+void SwUndoFmtDelete::Undo(SwUndoIter &)
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+
+ SwFmt * pDerivedFrom = Find(sDerivedFrom);
+
+ SwFmt * pFmt = Create(pDerivedFrom);
+
+ if (pFmt)
+ {
+ pDoc->ChgFmt(*pFmt, aOldSet);
+ pFmt->SetAuto(bAuto);
+ pFmt->SetPoolFmtId((pFmt->GetPoolFmtId() &
+ ~COLL_GET_RANGE_BITS)
+ | nId);
+
+ }
+
+ pDoc->DoUndo(bDoesUndo);
+}
+
+void SwUndoFmtDelete::Redo(SwUndoIter &)
+{
+ SwFmt * pOld = Find(sOldName);
+
+ if (pOld)
+ {
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ Delete(pOld);
+ pDoc->DoUndo(bDoesUndo);
+ }
+}
+
+SwRewriter SwUndoFmtDelete::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, sOldName);
+
+ return aRewriter;
+}
+
+SwUndoRenameFmt::SwUndoRenameFmt(SwUndoId nUndoId,
+ const String & _sOldName,
+ const String & _sNewName,
+ SwDoc * _pDoc)
+ : SwUndo(nUndoId), sOldName(_sOldName),
+ sNewName(_sNewName), pDoc(_pDoc)
+{
+}
+
+
+SwUndoRenameFmt::~SwUndoRenameFmt()
+{
+}
+
+void SwUndoRenameFmt::Undo(SwUndoIter &)
+{
+ SwFmt * pFmt = Find(sNewName);
+
+ if (pFmt)
+ {
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ pDoc->RenameFmt(*pFmt, sOldName, TRUE);
+ pDoc->DoUndo(bDoesUndo);
+ }
+}
+
+void SwUndoRenameFmt::Redo(SwUndoIter &)
+{
+ SwFmt * pFmt = Find(sOldName);
+
+ if (pFmt)
+ {
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ pDoc->RenameFmt(*pFmt, sNewName, TRUE);
+ pDoc->DoUndo(bDoesUndo);
+ }
+}
+
+SwRewriter SwUndoRenameFmt::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, sOldName);
+ aRewriter.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS));
+ aRewriter.AddRule(UNDO_ARG3, sNewName);
+
+ return aRewriter;
+}
+
+SwUndoTxtFmtCollCreate::SwUndoTxtFmtCollCreate
+(SwTxtFmtColl * _pNew, SwTxtFmtColl * _pDerivedFrom, SwDoc * _pDoc)
+ : SwUndoFmtCreate(UNDO_TXTFMTCOL_CREATE, _pNew, _pDerivedFrom, _pDoc)
+{
+}
+
+SwFmt * SwUndoTxtFmtCollCreate::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeTxtFmtColl(sNewName, (SwTxtFmtColl *)pDerivedFrom, TRUE);
+}
+
+void SwUndoTxtFmtCollCreate::Delete()
+{
+ pDoc->DelTxtFmtColl((SwTxtFmtColl *) pNew, TRUE);
+}
+
+SwFmt * SwUndoTxtFmtCollCreate::Find(const String & rName) const
+{
+ return pDoc->FindTxtFmtCollByName(rName);
+}
+
+SwUndoTxtFmtCollDelete::SwUndoTxtFmtCollDelete(SwTxtFmtColl * _pOld,
+ SwDoc * _pDoc)
+ : SwUndoFmtDelete(UNDO_TXTFMTCOL_DELETE, _pOld, _pDoc)
+{
+}
+
+SwFmt * SwUndoTxtFmtCollDelete::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeTxtFmtColl(sOldName, (SwTxtFmtColl *) pDerivedFrom, TRUE);
+}
+
+void SwUndoTxtFmtCollDelete::Delete(SwFmt * pOld)
+{
+ pDoc->DelTxtFmtColl((SwTxtFmtColl *) pOld, TRUE);
+}
+
+SwFmt * SwUndoTxtFmtCollDelete::Find(const String & rName) const
+{
+ return pDoc->FindTxtFmtCollByName(rName);
+}
+
+SwUndoRenameFmtColl::SwUndoRenameFmtColl(const String & sInitOldName,
+ const String & sInitNewName,
+ SwDoc * _pDoc)
+ : SwUndoRenameFmt(UNDO_TXTFMTCOL_RENAME, sInitOldName, sInitNewName, _pDoc)
+{
+}
+
+SwFmt * SwUndoRenameFmtColl::Find(const String & rName) const
+{
+ return pDoc->FindTxtFmtCollByName(rName);
+}
+
+SwUndoCharFmtCreate::SwUndoCharFmtCreate(SwCharFmt * pNewFmt,
+ SwCharFmt * pDerivedFrom,
+ SwDoc * pDocument)
+ : SwUndoFmtCreate(UNDO_CHARFMT_CREATE, pNewFmt, pDerivedFrom, pDocument)
+{
+}
+
+SwFmt * SwUndoCharFmtCreate::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeCharFmt(sNewName, (SwCharFmt *) pDerivedFrom, TRUE);
+}
+
+void SwUndoCharFmtCreate::Delete()
+{
+ pDoc->DelCharFmt((SwCharFmt *) pNew, TRUE);
+}
+
+SwFmt * SwUndoCharFmtCreate::Find(const String & rName) const
+{
+ return pDoc->FindCharFmtByName(rName);
+}
+
+SwUndoCharFmtDelete::SwUndoCharFmtDelete(SwCharFmt * pOld, SwDoc * pDocument)
+ : SwUndoFmtDelete(UNDO_CHARFMT_DELETE, pOld, pDocument)
+{
+}
+
+SwFmt * SwUndoCharFmtDelete::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeCharFmt(sOldName, (SwCharFmt *) pDerivedFrom, TRUE);
+}
+
+void SwUndoCharFmtDelete::Delete(SwFmt * pFmt)
+{
+ pDoc->DelCharFmt((SwCharFmt *) pFmt, TRUE);
+}
+
+SwFmt * SwUndoCharFmtDelete::Find(const String & rName) const
+{
+ return pDoc->FindCharFmtByName(rName);
+}
+
+SwUndoRenameCharFmt::SwUndoRenameCharFmt(const String & sInitOldName,
+ const String & sInitNewName,
+ SwDoc * pDocument)
+ : SwUndoRenameFmt(UNDO_CHARFMT_RENAME, sInitOldName, sInitNewName, pDocument)
+{
+}
+
+SwFmt * SwUndoRenameCharFmt::Find(const String & rName) const
+{
+ return pDoc->FindCharFmtByName(rName);
+}
+
+SwUndoFrmFmtCreate::SwUndoFrmFmtCreate(SwFrmFmt * pNewFmt,
+ SwFrmFmt * pDerivedFrom,
+ SwDoc * pDocument)
+ : SwUndoFmtCreate(UNDO_FRMFMT_CREATE, pNewFmt, pDerivedFrom, pDocument),
+ bAuto(pNewFmt->IsAuto())
+{
+}
+
+SwFmt * SwUndoFrmFmtCreate::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeFrmFmt(sNewName, (SwFrmFmt *) pDerivedFrom, TRUE, bAuto);
+}
+
+void SwUndoFrmFmtCreate::Delete()
+{
+ pDoc->DelFrmFmt((SwFrmFmt *) pNew, TRUE);
+}
+
+SwFmt * SwUndoFrmFmtCreate::Find(const String & rName) const
+{
+ return pDoc->FindFrmFmtByName(rName);
+}
+
+SwUndoFrmFmtDelete::SwUndoFrmFmtDelete(SwFrmFmt * pOld, SwDoc * pDocument)
+ : SwUndoFmtDelete(UNDO_FRMFMT_DELETE, pOld, pDocument)
+{
+}
+
+SwFmt * SwUndoFrmFmtDelete::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeFrmFmt(sOldName, (SwFrmFmt *) pDerivedFrom, TRUE);
+}
+
+void SwUndoFrmFmtDelete::Delete(SwFmt * pFmt)
+{
+ pDoc->DelFrmFmt((SwFrmFmt *) pFmt, TRUE);
+}
+
+SwFmt * SwUndoFrmFmtDelete::Find(const String & rName) const
+{
+ return pDoc->FindFrmFmtByName(rName);
+}
+
+SwUndoRenameFrmFmt::SwUndoRenameFrmFmt(const String & sInitOldName,
+ const String & sInitNewName,
+ SwDoc * pDocument)
+ : SwUndoRenameFmt(UNDO_FRMFMT_RENAME, sInitOldName, sInitNewName, pDocument)
+{
+}
+
+SwFmt * SwUndoRenameFrmFmt::Find(const String & rName) const
+{
+ return pDoc->FindFrmFmtByName(rName);
+}
+
+SwUndoNumruleCreate::SwUndoNumruleCreate(const SwNumRule * _pNew,
+ SwDoc * _pDoc)
+ : SwUndo(UNDO_NUMRULE_CREATE), pNew(_pNew), aNew(*_pNew), pDoc(_pDoc),
+ bInitialized(false)
+{
+}
+
+void SwUndoNumruleCreate::Undo(SwUndoIter &)
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+
+ if (! bInitialized)
+ {
+ aNew = *pNew;
+ bInitialized = true;
+ }
+
+ pDoc->DelNumRule(aNew.GetName(), TRUE);
+ pDoc->DoUndo(bDoesUndo);
+}
+
+void SwUndoNumruleCreate::Redo(SwUndoIter &)
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ pDoc->MakeNumRule(aNew.GetName(), &aNew, TRUE);
+ pDoc->DoUndo(bDoesUndo);
+}
+
+SwRewriter SwUndoNumruleCreate::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ if (! bInitialized)
+ {
+ aNew = *pNew;
+ bInitialized = true;
+ }
+
+ aResult.AddRule(UNDO_ARG1, aNew.GetName());
+
+ return aResult;
+}
+
+SwUndoNumruleDelete::SwUndoNumruleDelete(const SwNumRule & rRule,
+ SwDoc * _pDoc)
+ : SwUndo(UNDO_NUMRULE_DELETE), aOld(rRule), pDoc(_pDoc)
+{
+}
+
+void SwUndoNumruleDelete::Undo(SwUndoIter &)
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ pDoc->MakeNumRule(aOld.GetName(), &aOld, TRUE);
+ pDoc->DoUndo(bDoesUndo);
+}
+
+void SwUndoNumruleDelete::Redo(SwUndoIter &)
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ pDoc->DelNumRule(aOld.GetName(), TRUE);
+ pDoc->DoUndo(bDoesUndo);
+}
+
+SwRewriter SwUndoNumruleDelete::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ aResult.AddRule(UNDO_ARG1, aOld.GetName());
+
+ return aResult;
+}
+
+SwUndoNumruleRename::SwUndoNumruleRename(const String & _aOldName,
+ const String & _aNewName,
+ SwDoc * _pDoc)
+ : SwUndo(UNDO_NUMRULE_RENAME), aOldName(_aOldName), aNewName(_aNewName),
+ pDoc(_pDoc)
+{
+}
+
+void SwUndoNumruleRename::Undo(SwUndoIter &)
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ pDoc->RenameNumRule(aNewName, aOldName, TRUE);
+ pDoc->DoUndo(bDoesUndo);
+}
+
+void SwUndoNumruleRename::Redo(SwUndoIter &)
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ pDoc->RenameNumRule(aOldName, aNewName, TRUE);
+ pDoc->DoUndo(bDoesUndo);
+}
+
+SwRewriter SwUndoNumruleRename::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, aOldName);
+ aRewriter.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS));
+ aRewriter.AddRule(UNDO_ARG3, aNewName);
+
+ return aRewriter;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/SwUndoPageDesc.cxx b/sw/source/core/undo/SwUndoPageDesc.cxx
new file mode 100644
index 000000000000..893cb248bf7a
--- /dev/null
+++ b/sw/source/core/undo/SwUndoPageDesc.cxx
@@ -0,0 +1,477 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/resid.hxx>
+#include <doc.hxx>
+#include <swundo.hxx>
+#include <pagedesc.hxx>
+#include <SwUndoPageDesc.hxx>
+#include <SwRewriter.hxx>
+#include <undobj.hxx>
+#include <comcore.hrc>
+#include <fmtcntnt.hxx>
+#include <fmthdft.hxx>
+
+#ifdef DEBUG
+#include <ndindex.hxx>
+#endif
+
+
+#ifdef DEBUG
+// Pure debug help function to have a quick look at the header/footer attributes.
+void DebugHeaderFooterContent( const SwPageDesc& rPageDesc )
+{
+ ULONG nHeaderMaster = ULONG_MAX;
+ ULONG nHeaderLeft = ULONG_MAX;
+ ULONG nFooterMaster = ULONG_MAX;
+ ULONG nFooterLeft = ULONG_MAX;
+ int nHeaderCount = 0;
+ int nLeftHeaderCount = 0;
+ int nFooterCount = 0;
+ int nLeftFooterCount = 0;
+ bool bSharedHeader = false;
+ bool bSharedFooter = false;
+
+ SwFmtHeader& rHead = (SwFmtHeader&)rPageDesc.GetMaster().GetHeader();
+ SwFmtFooter& rFoot = (SwFmtFooter&)rPageDesc.GetMaster().GetFooter();
+ SwFmtHeader& rLeftHead = (SwFmtHeader&)rPageDesc.GetLeft().GetHeader();
+ SwFmtFooter& rLeftFoot = (SwFmtFooter&)rPageDesc.GetLeft().GetFooter();
+ if( rHead.IsActive() )
+ {
+ SwFrmFmt* pHeaderFmt = rHead.GetHeaderFmt();
+ if( pHeaderFmt )
+ {
+ SwClientIter aIter( *pHeaderFmt );
+ SwClient *pLast = aIter.GoStart();
+ if( pLast )
+ do
+ {
+ ++nHeaderCount;
+ } while( 0 != ( pLast = aIter++ ));
+ const SwFmtCntnt* pCntnt = &pHeaderFmt->GetCntnt();
+ if( pCntnt->GetCntntIdx() )
+ nHeaderMaster = pCntnt->GetCntntIdx()->GetIndex();
+ else
+ nHeaderMaster = 0;
+ }
+ bSharedHeader = rPageDesc.IsHeaderShared();
+ SwFrmFmt* pLeftHeaderFmt = rLeftHead.GetHeaderFmt();
+ if( pLeftHeaderFmt )
+ {
+ SwClientIter aIter( *pLeftHeaderFmt );
+ SwClient *pLast = aIter.GoStart();
+ if( pLast )
+ do
+ {
+ ++nLeftHeaderCount;
+ } while( 0 != ( pLast = aIter++ ));
+ const SwFmtCntnt* pLeftCntnt = &pLeftHeaderFmt->GetCntnt();
+ if( pLeftCntnt->GetCntntIdx() )
+ nHeaderLeft = pLeftCntnt->GetCntntIdx()->GetIndex();
+ else
+ nHeaderLeft = 0;
+ }
+ }
+ if( rFoot.IsActive() )
+ {
+ SwFrmFmt* pFooterFmt = rFoot.GetFooterFmt();
+ if( pFooterFmt )
+ {
+ SwClientIter aIter( *pFooterFmt );
+ SwClient *pLast = aIter.GoStart();
+ if( pLast )
+ do
+ {
+ ++nFooterCount;
+ } while( 0 != ( pLast = aIter++ ));
+ const SwFmtCntnt* pCntnt = &pFooterFmt->GetCntnt();
+ if( pCntnt->GetCntntIdx() )
+ nFooterMaster = pCntnt->GetCntntIdx()->GetIndex();
+ else
+ nFooterMaster = 0;
+ }
+ bSharedFooter = rPageDesc.IsFooterShared();
+ SwFrmFmt* pLeftFooterFmt = rLeftFoot.GetFooterFmt();
+ if( pLeftFooterFmt )
+ {
+ SwClientIter aIter( *pLeftFooterFmt );
+ SwClient *pLast = aIter.GoStart();
+ if( pLast )
+ do
+ {
+ ++nLeftFooterCount;
+ } while( 0 != ( pLast = aIter++ ));
+ const SwFmtCntnt* pLeftCntnt = &pLeftFooterFmt->GetCntnt();
+ if( pLeftCntnt->GetCntntIdx() )
+ nFooterLeft = pLeftCntnt->GetCntntIdx()->GetIndex();
+ else
+ nFooterLeft = 0;
+ }
+ }
+ int i = 0;
+ ++i; // To set a breakpoint
+}
+#endif
+
+SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc & _aOld,
+ const SwPageDesc & _aNew,
+ SwDoc * _pDoc)
+ : SwUndo( _aOld.GetName() != _aNew.GetName() ?
+ UNDO_RENAME_PAGEDESC :
+ UNDO_CHANGE_PAGEDESC ),
+ aOld(_aOld, _pDoc), aNew(_aNew, _pDoc), pDoc(_pDoc), bExchange( false )
+{
+ OSL_ENSURE(0 != pDoc, "no document?");
+
+#ifdef DEBUG
+ DebugHeaderFooterContent( (SwPageDesc&)aOld );
+ DebugHeaderFooterContent( (SwPageDesc&)aNew );
+#endif
+
+ /*
+ The page description changes.
+ If there are no header/footer content changes like header on/off or change from shared content
+ to unshared etc., there is no reason to duplicate the content nodes (Crash i55547)
+ But this happens, this Undo Ctor will destroy the unnecessary duplicate and manipulate the
+ content pointer of the both page descriptions.
+ */
+ SwPageDesc &rOldDesc = (SwPageDesc&)aOld;
+ SwPageDesc &rNewDesc = (SwPageDesc&)aNew;
+ const SwFmtHeader& rOldHead = rOldDesc.GetMaster().GetHeader();
+ const SwFmtHeader& rNewHead = rNewDesc.GetMaster().GetHeader();
+ const SwFmtFooter& rOldFoot = rOldDesc.GetMaster().GetFooter();
+ const SwFmtFooter& rNewFoot = rNewDesc.GetMaster().GetFooter();
+ /* bExchange must not be set, if the old page descriptor will stay active.
+ Two known situations:
+ #i67735#: renaming a page descriptor
+ #i67334#: changing the follow style
+ If header/footer will be activated or deactivated, this undo will not work.
+ */
+ bExchange = ( aOld.GetName() == aNew.GetName() ) &&
+ ( _aOld.GetFollow() == _aNew.GetFollow() ) &&
+ ( rOldHead.IsActive() == rNewHead.IsActive() ) &&
+ ( rOldFoot.IsActive() == rNewFoot.IsActive() );
+ if( rOldHead.IsActive() && ( rOldDesc.IsHeaderShared() != rNewDesc.IsHeaderShared() ) )
+ bExchange = false;
+ if( rOldFoot.IsActive() && ( rOldDesc.IsFooterShared() != rNewDesc.IsFooterShared() ) )
+ bExchange = false;
+ if( bExchange )
+ {
+ if( rNewHead.IsActive() )
+ {
+ SwFrmFmt* pFormat = new SwFrmFmt( *rNewHead.GetHeaderFmt() );
+ // The Ctor of this object will remove the duplicate!
+ SwFmtHeader aFmtHeader( pFormat );
+ if( !rNewDesc.IsHeaderShared() )
+ {
+ pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetHeader().GetHeaderFmt() );
+ // The Ctor of this object will remove the duplicate!
+ SwFmtHeader aFormatHeader( pFormat );
+ }
+ }
+ // Same procedure for footers...
+ if( rNewFoot.IsActive() )
+ {
+ SwFrmFmt* pFormat = new SwFrmFmt( *rNewFoot.GetFooterFmt() );
+ // The Ctor of this object will remove the duplicate!
+ SwFmtFooter aFmtFooter( pFormat );
+ if( !rNewDesc.IsFooterShared() )
+ {
+ pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetFooter().GetFooterFmt() );
+ // The Ctor of this object will remove the duplicate!
+ SwFmtFooter aFormatFooter( pFormat );
+ }
+ }
+
+ // After this exchange method the old page description will point to zero,
+ // the new one will point to the node position of the original content nodes.
+ ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew );
+#ifdef DEBUG
+ DebugHeaderFooterContent( (SwPageDesc&)aOld );
+ DebugHeaderFooterContent( (SwPageDesc&)aNew );
+#endif
+ }
+}
+
+SwUndoPageDesc::~SwUndoPageDesc()
+{
+}
+
+
+void SwUndoPageDesc::ExchangeContentNodes( SwPageDesc& rSource, SwPageDesc &rDest )
+{
+ OSL_ENSURE( bExchange, "You shouldn't do that." );
+ const SwFmtHeader& rDestHead = rDest.GetMaster().GetHeader();
+ const SwFmtHeader& rSourceHead = rSource.GetMaster().GetHeader();
+ if( rDestHead.IsActive() )
+ {
+ // Let the destination page descrition point to the source node position,
+ // from now on this descriptor is responsible for the content nodes!
+ const SfxPoolItem* pItem;
+ rDest.GetMaster().GetAttrSet().GetItemState( RES_HEADER, FALSE, &pItem );
+ SfxPoolItem *pNewItem = pItem->Clone();
+ SwFrmFmt* pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
+#ifdef DEBUG
+ const SwFmtCntnt& rSourceCntnt = rSourceHead.GetHeaderFmt()->GetCntnt();
+ (void)rSourceCntnt;
+ const SwFmtCntnt& rDestCntnt = rDestHead.GetHeaderFmt()->GetCntnt();
+ (void)rDestCntnt;
+#endif
+ pNewFmt->SetFmtAttr( rSourceHead.GetHeaderFmt()->GetCntnt() );
+ delete pNewItem;
+
+ // Let the source page description point to zero node position,
+ // it loses the responsible and can be destroyed without removing the content nodes.
+ rSource.GetMaster().GetAttrSet().GetItemState( RES_HEADER, FALSE, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
+ pNewFmt->SetFmtAttr( SwFmtCntnt() );
+ delete pNewItem;
+
+ if( !rDest.IsHeaderShared() )
+ {
+ // Same procedure for unshared header..
+ const SwFmtHeader& rSourceLeftHead = rSource.GetLeft().GetHeader();
+ rDest.GetLeft().GetAttrSet().GetItemState( RES_HEADER, FALSE, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
+#ifdef DEBUG
+ const SwFmtCntnt& rSourceCntnt1 = rSourceLeftHead.GetHeaderFmt()->GetCntnt();
+ (void)rSourceCntnt1;
+ const SwFmtCntnt& rDestCntnt1 = rDest.GetLeft().GetHeader().GetHeaderFmt()->GetCntnt();
+ (void)rDestCntnt1;
+#endif
+ pNewFmt->SetFmtAttr( rSourceLeftHead.GetHeaderFmt()->GetCntnt() );
+ delete pNewItem;
+ rSource.GetLeft().GetAttrSet().GetItemState( RES_HEADER, FALSE, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
+ pNewFmt->SetFmtAttr( SwFmtCntnt() );
+ delete pNewItem;
+ }
+ }
+ // Same procedure for footers...
+ const SwFmtFooter& rDestFoot = rDest.GetMaster().GetFooter();
+ const SwFmtFooter& rSourceFoot = rSource.GetMaster().GetFooter();
+ if( rDestFoot.IsActive() )
+ {
+ const SfxPoolItem* pItem;
+ rDest.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, FALSE, &pItem );
+ SfxPoolItem *pNewItem = pItem->Clone();
+ SwFrmFmt *pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
+ pNewFmt->SetFmtAttr( rSourceFoot.GetFooterFmt()->GetCntnt() );
+ delete pNewItem;
+
+#ifdef DEBUG
+ const SwFmtCntnt& rFooterSourceCntnt = rSourceFoot.GetFooterFmt()->GetCntnt();
+ (void)rFooterSourceCntnt;
+ const SwFmtCntnt& rFooterDestCntnt = rDestFoot.GetFooterFmt()->GetCntnt();
+ (void)rFooterDestCntnt;
+#endif
+ rSource.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, FALSE, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
+ pNewFmt->SetFmtAttr( SwFmtCntnt() );
+ delete pNewItem;
+
+ if( !rDest.IsFooterShared() )
+ {
+ const SwFmtFooter& rSourceLeftFoot = rSource.GetLeft().GetFooter();
+#ifdef DEBUG
+ const SwFmtCntnt& rFooterSourceCntnt2 = rSourceLeftFoot.GetFooterFmt()->GetCntnt();
+ const SwFmtCntnt& rFooterDestCntnt2 =
+ rDest.GetLeft().GetFooter().GetFooterFmt()->GetCntnt();
+ (void)rFooterSourceCntnt2;
+ (void)rFooterDestCntnt2;
+#endif
+ rDest.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, FALSE, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
+ pNewFmt->SetFmtAttr( rSourceLeftFoot.GetFooterFmt()->GetCntnt() );
+ delete pNewItem;
+ rSource.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, FALSE, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
+ pNewFmt->SetFmtAttr( SwFmtCntnt() );
+ delete pNewItem;
+ }
+ }
+}
+
+void SwUndoPageDesc::Undo(SwUndoIter &)
+{
+ BOOL bUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+
+ // Move (header/footer)content node responsibility from new page descriptor to old one again.
+ if( bExchange )
+ ExchangeContentNodes( (SwPageDesc&)aNew, (SwPageDesc&)aOld );
+ pDoc->ChgPageDesc(aOld.GetName(), aOld);
+ pDoc->DoUndo(bUndo);
+}
+
+void SwUndoPageDesc::Redo(SwUndoIter &)
+{
+ BOOL bUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+
+ // Move (header/footer)content node responsibility from old page descriptor to new one again.
+ if( bExchange )
+ ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew );
+ pDoc->ChgPageDesc(aNew.GetName(), aNew);
+ pDoc->DoUndo(bUndo);
+}
+
+void SwUndoPageDesc::Repeat(SwUndoIter &)
+{
+}
+
+SwRewriter SwUndoPageDesc::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ aResult.AddRule(UNDO_ARG1, aOld.GetName());
+ aResult.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS));
+ aResult.AddRule(UNDO_ARG3, aNew.GetName());
+
+ return aResult;
+}
+
+// #116530#
+SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc * pNew,
+ SwDoc * _pDoc)
+ : SwUndo(UNDO_CREATE_PAGEDESC), pDesc(pNew), aNew(*pNew, _pDoc),
+ pDoc(_pDoc)
+{
+ OSL_ENSURE(0 != pDoc, "no document?");
+}
+
+SwUndoPageDescCreate::~SwUndoPageDescCreate()
+{
+}
+
+void SwUndoPageDescCreate::Undo(SwUndoIter &)
+{
+ BOOL bUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+
+ // -> #116530#
+ if (pDesc)
+ {
+ aNew = *pDesc;
+ pDesc = NULL;
+ }
+ // <- #116530#
+
+ pDoc->DelPageDesc(aNew.GetName(), TRUE);
+ pDoc->DoUndo(bUndo);
+}
+
+
+void SwUndoPageDescCreate::Redo(SwUndoIter &)
+{
+ BOOL bUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+
+ SwPageDesc aPageDesc = aNew;
+ pDoc->MakePageDesc(aNew.GetName(), &aPageDesc, FALSE, TRUE); // #116530#
+
+ pDoc->DoUndo(bUndo);
+}
+
+void SwUndoPageDescCreate::Repeat(SwUndoIter & rIt)
+{
+ Redo(rIt);
+}
+
+SwRewriter SwUndoPageDescCreate::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ if (pDesc)
+ aResult.AddRule(UNDO_ARG1, pDesc->GetName());
+ else
+ aResult.AddRule(UNDO_ARG1, aNew.GetName());
+
+
+ return aResult;
+}
+
+SwUndoPageDescDelete::SwUndoPageDescDelete(const SwPageDesc & _aOld,
+ SwDoc * _pDoc)
+ : SwUndo(UNDO_DELETE_PAGEDESC), aOld(_aOld, _pDoc), pDoc(_pDoc)
+{
+ OSL_ENSURE(0 != pDoc, "no document?");
+}
+
+SwUndoPageDescDelete::~SwUndoPageDescDelete()
+{
+}
+
+void SwUndoPageDescDelete::Undo(SwUndoIter &)
+{
+ BOOL bUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+
+ SwPageDesc aPageDesc = aOld;
+ pDoc->MakePageDesc(aOld.GetName(), &aPageDesc, FALSE, TRUE); // #116530#
+ pDoc->DoUndo(bUndo);
+}
+
+void SwUndoPageDescDelete::Redo(SwUndoIter &)
+{
+ BOOL bUndo = pDoc->DoesUndo();
+
+ pDoc->DoUndo(FALSE);
+ pDoc->DelPageDesc(aOld.GetName(), TRUE); // #116530#
+ pDoc->DoUndo(bUndo);
+}
+
+void SwUndoPageDescDelete::Repeat(SwUndoIter & rIt)
+{
+ Redo(rIt);
+}
+
+SwRewriter SwUndoPageDescDelete::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ aResult.AddRule(UNDO_ARG1, aOld.GetName());
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/SwUndoTOXChange.cxx b/sw/source/core/undo/SwUndoTOXChange.cxx
new file mode 100644
index 000000000000..a6d56fce5ad0
--- /dev/null
+++ b/sw/source/core/undo/SwUndoTOXChange.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <SwUndoTOXChange.hxx>
+#include <swundo.hxx>
+#include <doctxm.hxx>
+
+SwUndoTOXChange::SwUndoTOXChange(SwTOXBase * _pTOX, const SwTOXBase & rNew)
+ : SwUndo(UNDO_TOXCHANGE), pTOX(_pTOX), aOld(*_pTOX), aNew(rNew)
+{
+}
+
+SwUndoTOXChange::~SwUndoTOXChange()
+{
+}
+
+void SwUndoTOXChange::UpdateTOXBaseSection()
+{
+ if (pTOX->ISA(SwTOXBaseSection))
+ {
+ SwTOXBaseSection * pTOXBase = static_cast<SwTOXBaseSection *>(pTOX);
+
+ pTOXBase->Update();
+ pTOXBase->UpdatePageNum();
+ }
+}
+
+void SwUndoTOXChange::Undo(SwUndoIter &)
+{
+ *pTOX = aOld;
+
+ UpdateTOXBaseSection();
+}
+
+void SwUndoTOXChange::Redo(SwUndoIter &)
+{
+ *pTOX = aNew;
+
+ UpdateTOXBaseSection();
+}
+
+void SwUndoTOXChange::Repeat(SwUndoIter & rIter)
+{
+ Redo(rIter);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/docundo.cxx b/sw/source/core/undo/docundo.cxx
new file mode 100644
index 000000000000..ec1c0e68750f
--- /dev/null
+++ b/sw/source/core/undo/docundo.cxx
@@ -0,0 +1,1027 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svx/svdmodel.hxx>
+
+#include <vcl/wrkwin.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <undobj.hxx>
+#include <rolbck.hxx>
+#include <docary.hxx>
+#include <undo.hrc>
+
+
+using namespace ::com::sun::star;
+
+
+USHORT SwDoc::nUndoActions = UNDO_ACTION_COUNT; // anzahl von Undo-Action
+
+// the undo array should never grow beyond this limit:
+#define UNDO_ACTION_LIMIT (USHRT_MAX - 1000)
+
+
+SV_IMPL_PTRARR( SwUndoIds, SwUndoIdAndNamePtr )
+
+//#define _SHOW_UNDORANGE
+#ifdef _SHOW_UNDORANGE
+
+
+class UndoArrStatus : public WorkWindow
+{
+ USHORT nUndo, nUndoNds;
+ virtual void Paint( const Rectangle& );
+public:
+ UndoArrStatus();
+ void Set( USHORT, USHORT );
+};
+static UndoArrStatus* pUndoMsgWin = 0;
+
+
+UndoArrStatus::UndoArrStatus()
+ : WorkWindow( APP_GETAPPWINDOW() ), nUndo(0), nUndoNds(0)
+{
+ SetSizePixel( Size( 200, 100 ));
+ SetFont( Font( "Courier", Size( 0, 10 )) );
+ Show();
+}
+
+
+void UndoArrStatus::Set( USHORT n1, USHORT n2 )
+{
+ nUndo = n1; nUndoNds = n2;
+ Invalidate();
+}
+
+
+void UndoArrStatus::Paint( const Rectangle& )
+{
+ String s;
+ DrawRect( Rectangle( Point(0,0), GetOutputSize() ));
+ ( s = "Undos: " ) += nUndo;
+ DrawText( Point( 0, 0 ), s );
+ ( s = "UndoNodes: " ) += nUndoNds;
+ DrawText( Point( 0, 15 ), s );
+}
+
+#endif
+
+void SwDoc::SetUndoNoResetModified()
+{
+ nUndoSavePos = USHRT_MAX;
+}
+
+bool SwDoc::IsUndoNoResetModified() const
+{
+ return USHRT_MAX == nUndoSavePos;
+}
+
+void SwDoc::DoUndo(bool bUn)
+{
+ mbUndo = bUn;
+
+ SdrModel* pSdrModel = GetDrawModel();
+ if( pSdrModel )
+ pSdrModel->EnableUndo(bUn);
+}
+
+bool SwDoc::DoesUndo() const
+{
+ return mbUndo;
+}
+
+void SwDoc::DoGroupUndo(bool bUn)
+{
+ mbGroupUndo = bUn;
+}
+
+bool SwDoc::DoesGroupUndo() const
+{
+ return mbGroupUndo;
+}
+
+sal_uInt16 SwDoc::GetUndoActionCount()
+{
+ return nUndoActions;
+}
+
+void SwDoc::SetUndoActionCount( sal_uInt16 nNew )
+{
+ nUndoActions = nNew;
+}
+
+const SwNodes* SwDoc::GetUndoNds() const
+{
+ return &aUndoNodes;
+}
+
+void SwDoc::AppendUndo( SwUndo* pUndo )
+{
+ if( nsRedlineMode_t::REDLINE_NONE == pUndo->GetRedlineMode() )
+ pUndo->SetRedlineMode( GetRedlineMode() );
+
+ // Unfortunately, the silly SvPtrArr can only store a little less than
+ // USHRT_MAX elements. Of course it doesn't see any necessity for asserting
+ // or even doing error handling. pUndos should definitely be replaced by an
+ // STL container that doesn't have this problem. cf #95884#
+ DBG_ASSERT( pUndos->Count() < USHRT_MAX - 16,
+ "Writer will crash soon. I apologize for the inconvenience." );
+
+ pUndos->Insert( pUndo, nUndoPos );
+ ++nUndoPos;
+ switch( pUndo->GetId() )
+ {
+ case UNDO_START: ++nUndoSttEnd;
+ break;
+
+ case UNDO_END: OSL_ENSURE( nUndoSttEnd, "Undo-Ende ohne Start" );
+ --nUndoSttEnd;
+ // kein break !!!
+ default:
+ if( pUndos->Count() != nUndoPos && UNDO_END != pUndo->GetId() )
+ ClearRedo();
+ else {
+ OSL_ENSURE( pUndos->Count() == nUndoPos || UNDO_END == pUndo->GetId(),
+ "Redo history not deleted!" );
+ }
+ if( !nUndoSttEnd )
+ ++nUndoCnt;
+ break;
+ }
+
+#ifdef _SHOW_UNDORANGE
+ // zur Anzeige der aktuellen Undo-Groessen
+ if( !pUndoMsgWin )
+ pUndoMsgWin = new UndoArrStatus;
+ pUndoMsgWin->Set( pUndos->Count(), aUndoNodes.Count() );
+#endif
+
+ // noch eine offene Klammerung, kann man sich den Rest schenken
+ if( nUndoSttEnd )
+ return;
+
+ // folgende Array-Grenzen muessen ueberwacht werden:
+ // - Undo, Grenze: fester Wert oder USHRT_MAX - 1000
+ // - UndoNodes, Grenze: USHRT_MAX - 1000
+ // - AttrHistory Grenze: USHRT_MAX - 1000
+ // (defined in UNDO_ACTION_LIMIT at the top of this file)
+
+ USHORT nEnde = UNDO_ACTION_LIMIT;
+
+// nur zum Testen der neuen DOC-Member
+#if OSL_DEBUG_LEVEL > 1
+{
+ SwUndoId nId = UNDO_EMPTY;
+ USHORT nUndosCnt = 0, nSttEndCnt = 0;
+ for( USHORT nCnt = 0; nCnt < nUndoPos; ++nCnt )
+ {
+ if( UNDO_START == ( nId = (*pUndos)[ nCnt ]->GetId()) )
+ ++nSttEndCnt;
+ else if( UNDO_END == nId )
+ --nSttEndCnt;
+ if( !nSttEndCnt )
+ ++nUndosCnt;
+ }
+ OSL_ENSURE( nSttEndCnt == nUndoSttEnd, "Start-Ende Count ungleich" );
+ OSL_ENSURE( nUndosCnt == nUndoCnt, "Undo Count ungleich" );
+}
+#endif
+
+ if( SwDoc::nUndoActions < nUndoCnt )
+ // immer 1/10 loeschen
+ //JP 23.09.95: oder wenn neu eingestellt wurde um die Differenz
+ //JP 29.5.2001: Task #83891#: remove only the overlapping actions
+ DelUndoObj( nUndoCnt - SwDoc::nUndoActions );
+ else
+ {
+ USHORT nUndosCnt = nUndoCnt;
+ // immer 1/10 loeschen bis der "Ausloeser" behoben ist
+ while( aUndoNodes.Count() && nEnde < aUndoNodes.Count() )
+ DelUndoObj( nUndosCnt / 10 );
+ }
+}
+
+
+
+void SwDoc::ClearRedo()
+{
+ if( DoesUndo() && nUndoPos != pUndos->Count() )
+ {
+//?? why ?? if( !nUndoSttEnd )
+ {
+ // setze UndoCnt auf den neuen Wert
+ SwUndo* pUndo;
+ for( USHORT nCnt = pUndos->Count(); nUndoPos < nCnt; --nUndoCnt )
+ // Klammerung ueberspringen
+ if( UNDO_END == (pUndo = (*pUndos)[ --nCnt ])->GetId() )
+ nCnt = nCnt - ((SwUndoEnd*)pUndo)->GetSttOffset();
+ }
+
+ // loesche die Undo-Aktionen (immer von hinten !)
+ pUndos->DeleteAndDestroy( nUndoPos, pUndos->Count() - nUndoPos );
+ }
+}
+
+
+ // loescht die gesamten UndoObjecte
+void SwDoc::DelAllUndoObj()
+{
+ ClearRedo();
+
+ DoUndo( FALSE );
+
+ // Offene Undo-Klammerungen erhalten !!
+ SwUndo* pUndo;
+ USHORT nSize = pUndos->Count();
+ while( nSize )
+ if( UNDO_START != ( pUndo = (*pUndos)[ --nSize ] )->GetId() ||
+ ((SwUndoStart*)pUndo)->GetEndOffset() )
+ // keine offenen Gruppierung ?
+ pUndos->DeleteAndDestroy( nSize, 1 );
+
+ nUndoCnt = 0;
+ nUndoPos = pUndos->Count();
+
+/*
+ while( nUndoPos )
+ aUndos.DelDtor( --nUndoPos, 1 );
+ nUndoCnt = nUndoSttEnd = nUndoPos = 0;
+*/
+ nUndoSavePos = USHRT_MAX;
+ DoUndo( TRUE );
+}
+
+
+ // loescht alle UndoObjecte vom Anfang bis zum angegebenen Ende
+BOOL SwDoc::DelUndoObj( USHORT nEnde )
+{
+ if( !nEnde ) // sollte mal 0 uebergeben werden,
+ {
+ if( !pUndos->Count() )
+ return FALSE;
+ ++nEnde; // dann korrigiere es auf 1
+ }
+
+ DoUndo( FALSE );
+
+ // pruefe erstmal, wo das Ende steht
+ SwUndoId nId = UNDO_EMPTY;
+ USHORT nSttEndCnt = 0;
+ USHORT nCnt;
+
+ for( nCnt = 0; nEnde && nCnt < nUndoPos; ++nCnt )
+ {
+ if( UNDO_START == ( nId = (*pUndos)[ nCnt ]->GetId() ))
+ ++nSttEndCnt;
+ else if( UNDO_END == nId )
+ --nSttEndCnt;
+ if( !nSttEndCnt )
+ --nEnde, --nUndoCnt;
+ }
+
+ OSL_ENSURE( nCnt < nUndoPos || nUndoPos == pUndos->Count(),
+ "Undo-Del-Ende liegt in einer Redo-Aktion" );
+
+ // dann setze ab Ende bis Undo-Ende bei allen Undo-Objecte die Werte um
+ nSttEndCnt = nCnt; // Position merken
+ if( nUndoSavePos < nSttEndCnt ) // SavePos wird aufgegeben
+ nUndoSavePos = USHRT_MAX;
+ else if( nUndoSavePos != USHRT_MAX )
+ nUndoSavePos = nUndoSavePos - nSttEndCnt;
+
+ while( nSttEndCnt )
+ pUndos->DeleteAndDestroy( --nSttEndCnt, 1 );
+ nUndoPos = pUndos->Count();
+
+ DoUndo( TRUE );
+ return TRUE;
+}
+
+/**************** UNDO ******************/
+
+void SwDoc::setUndoNoModifiedPosition( SwUndoNoModifiedPosition nNew )
+{
+ nUndoSavePos = nNew;
+ if( !pUndos->Count() || nUndoSavePos > pUndos->Count() - 1 )
+ nUndoSavePos = USHRT_MAX;
+}
+
+SwUndoNoModifiedPosition SwDoc::getUndoNoModifiedPosition() const
+{
+ return nUndoSavePos;
+}
+
+
+bool SwDoc::HasUndoId(SwUndoId eId) const
+{
+ USHORT nSize = nUndoPos;
+ SwUndo * pUndo;
+ while( nSize-- )
+ if( ( pUndo = (*pUndos)[nSize])->GetId() == eId ||
+ ( UNDO_START == pUndo->GetId() &&
+ ((SwUndoStart*)pUndo)->GetUserId() == eId )
+ || ( UNDO_END == pUndo->GetId() &&
+ ((SwUndoEnd*)pUndo)->GetUserId() == eId ) )
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+bool SwDoc::Undo( SwUndoIter& rUndoIter )
+{
+ if ( (rUndoIter.GetId()!=0) && (!HasUndoId(rUndoIter.GetId())) )
+ {
+ rUndoIter.bWeiter = FALSE;
+ return FALSE;
+ }
+ if( !nUndoPos )
+ {
+ rUndoIter.bWeiter = FALSE;
+ return FALSE;
+ }
+
+ SwUndo *pUndo = (*pUndos)[ --nUndoPos ];
+
+ RedlineMode_t eOld = GetRedlineMode();
+ RedlineMode_t eTmpMode = (RedlineMode_t)pUndo->GetRedlineMode();
+ if( (nsRedlineMode_t::REDLINE_SHOW_MASK & eTmpMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eOld) &&
+ UNDO_START != pUndo->GetId() && UNDO_END != pUndo->GetId() )
+ SetRedlineMode( eTmpMode );
+
+ SetRedlineMode_intern((RedlineMode_t)(eTmpMode | nsRedlineMode_t::REDLINE_IGNORE));
+ // Undo ausfuehren
+
+ // zum spaeteren ueberpruefen
+ SwUndoId nAktId = pUndo->GetId();
+ //JP 11.05.98: FlyFormate ueber die EditShell selektieren, nicht aus dem
+ // Undo heraus
+ switch( nAktId )
+ {
+ case UNDO_START:
+ case UNDO_END:
+ case UNDO_INSDRAWFMT:
+ break;
+
+ default:
+ rUndoIter.ClearSelections();
+ }
+
+ pUndo->Undo( rUndoIter );
+
+ SetRedlineMode( eOld );
+
+ // Besonderheit von Undo-Replace (interne History)
+ if( UNDO_REPLACE == nAktId && ((SwUndoReplace*)pUndo)->nAktPos )
+ {
+ ++nUndoPos;
+ return TRUE;
+ }
+
+ // Objekt aus History entfernen und zerstoeren
+ if( nUndoPos && !rUndoIter.bWeiter &&
+ UNDO_START == ( pUndo = (*pUndos)[ nUndoPos-1 ] )->GetId() )
+ --nUndoPos;
+
+ // JP 29.10.96: Start und End setzen kein Modify-Flag.
+ // Sonst gibt es Probleme mit der autom. Aufnahme von Ausnahmen
+ // bei der Autokorrektur
+ if( UNDO_START != nAktId && UNDO_END != nAktId )
+ SetModified(); // default: immer setzen, kann zurueck gesetzt werden
+
+ // ist die History leer und wurde nicht wegen Speichermangel
+ // verworfen, so kann das Dokument als unveraendert gelten
+ if( nUndoSavePos == nUndoPos )
+ ResetModified();
+
+ return TRUE;
+}
+
+
+// setzt Undoklammerung auf, liefert nUndoId der Klammerung
+
+
+SwUndoId SwDoc::StartUndo( SwUndoId eUndoId, const SwRewriter * pRewriter )
+{
+ if( !mbUndo )
+ return UNDO_EMPTY;
+
+ if( !eUndoId )
+ eUndoId = UNDO_START;
+
+ SwUndoStart * pUndo = new SwUndoStart( eUndoId );
+
+ if (pRewriter)
+ pUndo->SetRewriter(*pRewriter);
+
+ AppendUndo(pUndo);
+
+ return eUndoId;
+}
+// schliesst Klammerung der nUndoId, nicht vom UI benutzt
+
+
+SwUndoId SwDoc::EndUndo(SwUndoId eUndoId, const SwRewriter * pRewriter)
+{
+ USHORT nSize = nUndoPos;
+ if( !mbUndo || !nSize-- )
+ return UNDO_EMPTY;
+
+ if( UNDO_START == eUndoId || !eUndoId )
+ eUndoId = UNDO_END;
+
+ SwUndo* pUndo = (*pUndos)[ nSize ];
+ if( UNDO_START == pUndo->GetId() )
+ {
+ // leere Start/End-Klammerung ??
+ pUndos->DeleteAndDestroy( nSize );
+ --nUndoPos;
+ --nUndoSttEnd;
+ return UNDO_EMPTY;
+ }
+
+ // exist above any redo objects? If yes, delete them
+ if( nUndoPos != pUndos->Count() )
+ {
+ // setze UndoCnt auf den neuen Wert
+ for( USHORT nCnt = pUndos->Count(); nUndoPos < nCnt; --nUndoCnt )
+ // Klammerung ueberspringen
+ if( UNDO_END == (pUndo = (*pUndos)[ --nCnt ])->GetId() )
+ nCnt = nCnt - ((SwUndoEnd*)pUndo)->GetSttOffset();
+
+ pUndos->DeleteAndDestroy( nUndoPos, pUndos->Count() - nUndoPos );
+ }
+
+ // suche den Anfang dieser Klammerung
+ SwUndoId nId = UNDO_EMPTY;
+ while( nSize )
+ if( UNDO_START == ( nId = (pUndo = (*pUndos)[ --nSize ] )->GetId()) &&
+ !((SwUndoStart*)pUndo)->GetEndOffset() )
+ break; // Start gefunden
+
+ if( nId != UNDO_START )
+ {
+ // kann eigentlich nur beim Abspielen von Macros passieren, die
+ // Undo/Redo/Repeat benutzen und die eine exitierende Selection
+ // durch Einfuegen loeschen
+ OSL_ENSURE( !this, "kein entsprechendes Ende gefunden" );
+ // kein entsprechenden Start gefunden -> Ende nicht einfuegen
+ // und die Member am Doc updaten
+
+ nUndoSttEnd = 0;
+ nUndoCnt = 0;
+ // setze UndoCnt auf den neuen Wert
+ SwUndo* pTmpUndo;
+ for( USHORT nCnt = 0; nCnt < pUndos->Count(); ++nCnt, ++nUndoCnt )
+ // Klammerung ueberspringen
+ if( UNDO_START == (pTmpUndo = (*pUndos)[ nCnt ])->GetId() )
+ nCnt = nCnt + ((SwUndoStart*)pTmpUndo)->GetEndOffset();
+ return UNDO_EMPTY;
+
+ }
+
+ // Klammerung um eine einzelne Action muss nicht sein!
+ // Aussnahme: es ist eine eigene ID definiert
+ if( 2 == pUndos->Count() - nSize &&
+ (UNDO_END == eUndoId || eUndoId == (*pUndos)[ nSize+1 ]->GetId() ))
+ {
+ pUndos->DeleteAndDestroy( nSize );
+ nUndoPos = pUndos->Count();
+ if( !--nUndoSttEnd )
+ {
+ ++nUndoCnt;
+ if( SwDoc::nUndoActions < nUndoCnt )
+ // immer 1/10 loeschen
+ //JP 23.09.95: oder wenn neu eingestellt wurde um die Differenz
+ //JP 29.5.2001: Task #83891#: remove only the overlapping actions
+ DelUndoObj( nUndoCnt - SwDoc::nUndoActions );
+ else
+ {
+ USHORT nEnde = USHRT_MAX - 1000;
+ USHORT nUndosCnt = nUndoCnt;
+ // immer 1/10 loeschen bis der "Ausloeser" behoben ist
+ while( aUndoNodes.Count() && nEnde < aUndoNodes.Count() )
+ DelUndoObj( nUndosCnt / 10 );
+ }
+ }
+ return eUndoId;
+ }
+
+ // setze die Klammerung am Start/End-Undo
+ nSize = pUndos->Count() - nSize;
+ ((SwUndoStart*)pUndo)->SetEndOffset( nSize );
+
+ SwUndoEnd* pUndoEnd = new SwUndoEnd( eUndoId );
+ pUndoEnd->SetSttOffset( nSize );
+
+// nur zum Testen der Start/End-Verpointerung vom Start/End Undo
+#if OSL_DEBUG_LEVEL > 1
+ {
+ USHORT nEndCnt = 1, nCnt = pUndos->Count();
+ SwUndoId nTmpId = UNDO_EMPTY;
+ while( nCnt )
+ {
+ if( UNDO_START == ( nTmpId = (*pUndos)[ --nCnt ]->GetId()) )
+ {
+ if( !nEndCnt ) // falls mal ein Start ohne Ende vorhanden ist
+ continue;
+ --nEndCnt;
+ if( !nEndCnt ) // hier ist der Anfang
+ break;
+ }
+ else if( UNDO_END == nTmpId )
+ ++nEndCnt;
+ else if( !nEndCnt )
+ break;
+ }
+ OSL_ENSURE( nCnt == pUndos->Count() - nSize,
+ "Start-Ende falsch geklammert" );
+ }
+#endif
+
+ if (pRewriter)
+ {
+ ((SwUndoStart *) pUndo)->SetRewriter(*pRewriter);
+ pUndoEnd->SetRewriter(*pRewriter);
+ }
+ else
+ pUndoEnd->SetRewriter(((SwUndoStart *) pUndo)->GetRewriter());
+
+ AppendUndo( pUndoEnd );
+ return eUndoId;
+}
+
+// liefert die Id der letzten Undofaehigen Aktion zurueck oder 0
+// fuellt ggf. VARARR mit User-UndoIds
+
+String SwDoc::GetUndoIdsStr( String* pStr, SwUndoIds *pUndoIds) const
+{
+ String aTmpStr;
+
+ if (pStr != NULL)
+ {
+ GetUndoIds( pStr, pUndoIds);
+ aTmpStr = *pStr;
+ }
+ else
+ GetUndoIds( &aTmpStr, pUndoIds);
+
+ return aTmpStr;
+}
+
+/*-- 24.11.2004 16:11:21---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+sal_Bool SwDoc::RestoreInvisibleContent()
+{
+ sal_Bool bRet = sal_False;
+ if(nUndoPos > 0 )
+ {
+ SwUndo * pUndo = (*pUndos)[ nUndoPos - 1 ];
+ if( ( pUndo->GetId() == UNDO_END &&
+ static_cast<SwUndoEnd *>(pUndo)->GetUserId() == UNDO_UI_DELETE_INVISIBLECNTNT) )
+ {
+ SwPaM aPam( GetNodes().GetEndOfPostIts() );
+ SwUndoIter aUndoIter( &aPam );
+ do
+ {
+ Undo( aUndoIter );
+ }
+ while ( aUndoIter.IsNextUndo() );
+ ClearRedo();
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+
+/**
+ Returns id and comment for a certain undo object in an undo stack.
+
+ Remark: In the following the object type referred to is always the
+ effective object type. If an UNDO_START or UNDO_END has a user type
+ it is referred to as this type.
+
+ If the queried object is an UNDO_END and has no user id the result
+ is taken from the first object that is not an UNDO_END nor an
+ UNDO_START preceeding the queried object.
+
+ If the queried object is an UNDO_START and has no user id the
+ result is taken from the first object that is not an UNDO_END nor
+ an UNDO_START preceeding the UNDO_END object belonging to the
+ queried object.
+
+ In all other cases the result is taken from the queried object.
+
+ @param rUndos the undo stack
+ @param nPos position of the undo object to query
+
+ @return SwUndoIdAndName object containing the query result
+ */
+SwUndoIdAndName * lcl_GetUndoIdAndName(const SwUndos & rUndos, sal_uInt16 nPos )
+{
+ SwUndo * pUndo = rUndos[ nPos ];
+ SwUndoId nId = UNDO_EMPTY;
+ String sStr("??", RTL_TEXTENCODING_ASCII_US);
+
+ OSL_ENSURE( nPos < rUndos.Count(), "nPos out of range");
+
+ switch (pUndo->GetId())
+ {
+ case UNDO_START:
+ {
+ SwUndoStart * pUndoStart = (SwUndoStart *) pUndo;
+ nId = pUndoStart->GetUserId();
+
+ if (nId <= UNDO_END)
+ {
+ /**
+ Start at the according UNDO_END. Search backwards
+ for first objects that is not a UNDO_END.
+ */
+ int nTmpPos = nPos + pUndoStart->GetEndOffset();
+ int nSubstitute = -1;
+
+ // --> OD 2009-09-30 #i105457#
+ if ( nTmpPos > 0 )
+ // <--
+ {
+ SwUndo * pTmpUndo;
+ do
+ {
+ nTmpPos--;
+ pTmpUndo = rUndos[ static_cast<USHORT>(nTmpPos) ];
+
+ if (pTmpUndo->GetEffectiveId() > UNDO_END)
+ nSubstitute = nTmpPos;
+ }
+ while (nSubstitute < 0 && nTmpPos > nPos);
+
+ if (nSubstitute >= 0)
+ {
+ SwUndo * pSubUndo = rUndos[ static_cast<USHORT>(nSubstitute) ];
+ nId = pSubUndo->GetEffectiveId();
+ sStr = pSubUndo->GetComment();
+ }
+ }
+ }
+ else
+ sStr = pUndo->GetComment();
+ }
+
+ break;
+
+ case UNDO_END:
+ {
+ SwUndoEnd * pUndoEnd = (SwUndoEnd *) pUndo;
+ nId = pUndoEnd->GetUserId();
+
+ if (nId <= UNDO_END)
+ {
+ /**
+ Start at this UNDO_END. Search backwards
+ for first objects that is not a UNDO_END.
+ */
+
+ int nTmpPos = nPos;
+ int nUndoStart = nTmpPos - pUndoEnd->GetSttOffset();
+ int nSubstitute = -1;
+
+ if (nTmpPos > 0)
+ {
+ SwUndo * pTmpUndo;
+
+ do
+ {
+ nTmpPos--;
+ pTmpUndo = rUndos[ static_cast<USHORT>(nTmpPos) ];
+
+ if (pTmpUndo->GetEffectiveId() > UNDO_END)
+ nSubstitute = nTmpPos;
+ }
+ while (nSubstitute < 0 && nTmpPos > nUndoStart);
+
+ if (nSubstitute >= 0)
+ {
+ SwUndo * pSubUndo = rUndos[ static_cast<USHORT>(nSubstitute) ];
+ nId = pSubUndo->GetEffectiveId();
+ sStr = pSubUndo->GetComment();
+ }
+ }
+ }
+ else
+ sStr = pUndo->GetComment();
+ }
+
+ break;
+
+ default:
+ nId = pUndo->GetId();
+ sStr = pUndo->GetComment();
+ }
+
+ return new SwUndoIdAndName(nId, &sStr);
+}
+
+SwUndoId SwDoc::GetUndoIds( String* pStr, SwUndoIds *pUndoIds) const
+{
+ int nTmpPos = nUndoPos - 1;
+ SwUndoId nId = UNDO_EMPTY;
+
+ while (nTmpPos >= 0)
+ {
+ SwUndo * pUndo = (*pUndos)[ static_cast<USHORT>(nTmpPos) ];
+
+ SwUndoIdAndName * pIdAndName = lcl_GetUndoIdAndName( *pUndos, static_cast<sal_uInt16>(nTmpPos) );
+
+ if (nTmpPos == nUndoPos - 1)
+ {
+ nId = pIdAndName->GetUndoId();
+
+ if (pStr)
+ *pStr = *pIdAndName->GetUndoStr();
+ }
+
+ if (pUndoIds)
+ pUndoIds->Insert(pIdAndName, pUndoIds->Count());
+ else
+ break;
+
+ if (pUndo->GetId() == UNDO_END)
+ nTmpPos -= ((SwUndoEnd *) pUndo)->GetSttOffset();
+
+ nTmpPos--;
+ }
+
+ return nId;
+}
+
+bool SwDoc::HasTooManyUndos() const
+{
+ // AppendUndo checks the UNDO_ACTION_LIMIT, unless there's a nested undo.
+ // So HasTooManyUndos() may only occur when undos are nested; else
+ // AppendUndo has some sort of bug.
+ DBG_ASSERT( (nUndoSttEnd != 0) || (pUndos->Count() < UNDO_ACTION_LIMIT),
+ "non-nested undos should have been handled in AppendUndo" );
+ return (pUndos->Count() >= UNDO_ACTION_LIMIT);
+}
+
+
+/**************** REDO ******************/
+
+
+bool SwDoc::Redo( SwUndoIter& rUndoIter )
+{
+ if( rUndoIter.GetId() && !HasUndoId( rUndoIter.GetId() ) )
+ {
+ rUndoIter.bWeiter = FALSE;
+ return FALSE;
+ }
+ if( nUndoPos == pUndos->Count() )
+ {
+ rUndoIter.bWeiter = FALSE;
+ return FALSE;
+ }
+
+ SwUndo *pUndo = (*pUndos)[ nUndoPos++ ];
+
+ RedlineMode_t eOld = GetRedlineMode();
+ RedlineMode_t eTmpMode = (RedlineMode_t)pUndo->GetRedlineMode();
+ if( (nsRedlineMode_t::REDLINE_SHOW_MASK & eTmpMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eOld) &&
+ UNDO_START != pUndo->GetId() && UNDO_END != pUndo->GetId() )
+ SetRedlineMode( eTmpMode );
+ SetRedlineMode_intern( (RedlineMode_t)(eTmpMode | nsRedlineMode_t::REDLINE_IGNORE));
+
+ //JP 11.05.98: FlyFormate ueber die EditShell selektieren, nicht aus dem
+ // Undo heraus
+ if( UNDO_START != pUndo->GetId() && UNDO_END != pUndo->GetId() )
+ rUndoIter.ClearSelections();
+
+ pUndo->Redo( rUndoIter );
+
+ SetRedlineMode( eOld );
+
+ // Besonderheit von Undo-Replace (interne History)
+ if( UNDO_REPLACE == pUndo->GetId() &&
+ USHRT_MAX != ((SwUndoReplace*)pUndo)->nAktPos )
+ {
+ --nUndoPos;
+ return TRUE;
+ }
+
+ if( rUndoIter.bWeiter && nUndoPos >= pUndos->Count() )
+ rUndoIter.bWeiter = FALSE;
+
+ // ist die History leer und wurde nicht wegen Speichermangel
+ // verworfen, so kann das Dokument als unveraendert gelten
+ if( nUndoSavePos == nUndoPos )
+ ResetModified();
+ else
+ SetModified();
+ return TRUE;
+}
+
+
+// liefert die Id der letzten Redofaehigen Aktion zurueck oder 0
+// fuellt ggf. VARARR mit User-RedoIds
+
+String SwDoc::GetRedoIdsStr( String* pStr, SwUndoIds *pRedoIds ) const
+{
+ String aTmpStr;
+
+ if (pStr != NULL)
+ {
+ GetRedoIds( pStr, pRedoIds );
+ aTmpStr = *pStr;
+ }
+ else
+ GetRedoIds( &aTmpStr, pRedoIds );
+
+
+ return aTmpStr;
+}
+
+
+SwUndoId SwDoc::GetRedoIds( String* pStr, SwUndoIds *pRedoIds ) const
+{
+ sal_uInt16 nTmpPos = nUndoPos;
+ SwUndoId nId = UNDO_EMPTY;
+
+ while (nTmpPos < pUndos->Count())
+ {
+ SwUndo * pUndo = (*pUndos)[nTmpPos];
+
+ SwUndoIdAndName * pIdAndName = lcl_GetUndoIdAndName(*pUndos, nTmpPos);
+
+ if (nTmpPos == nUndoPos)
+ {
+ nId = pIdAndName->GetUndoId();
+
+ if (pStr)
+ *pStr = *pIdAndName->GetUndoStr();
+ }
+
+ if (pRedoIds)
+ pRedoIds->Insert(pIdAndName, pRedoIds->Count());
+ else
+ break;
+
+ if (pUndo->GetId() == UNDO_START)
+ nTmpPos = nTmpPos + ((SwUndoStart *) pUndo)->GetEndOffset();
+
+ nTmpPos++;
+ }
+
+ return nId;
+}
+
+/**************** REPEAT ******************/
+
+
+bool SwDoc::Repeat( SwUndoIter& rUndoIter, sal_uInt16 nRepeatCnt )
+{
+ if( rUndoIter.GetId() && !HasUndoId( rUndoIter.GetId() ) )
+ {
+ rUndoIter.bWeiter = FALSE;
+ return FALSE;
+ }
+ USHORT nSize = nUndoPos;
+ if( !nSize )
+ {
+ rUndoIter.bWeiter = FALSE;
+ return FALSE;
+ }
+
+ // dann suche jetzt ueber die End/Start-Gruppen die gueltige Repeat-Aktion
+ SwUndo *pUndo = (*pUndos)[ --nSize ];
+ if( UNDO_END == pUndo->GetId() )
+ nSize = nSize - ((SwUndoEnd*)pUndo)->GetSttOffset();
+
+ USHORT nEndCnt = nUndoPos;
+ BOOL bOneUndo = nSize + 1 == nUndoPos;
+
+ SwPaM* pTmpCrsr = rUndoIter.pAktPam;
+ SwUndoId nId = UNDO_EMPTY;
+
+ if( pTmpCrsr != pTmpCrsr->GetNext() || !bOneUndo ) // Undo-Klammerung aufbauen
+ {
+ if (pUndo->GetId() == UNDO_END)
+ {
+ SwUndoStart * pStartUndo =
+ (SwUndoStart *) (*pUndos)[nSize];
+
+ nId = pStartUndo->GetUserId();
+ }
+
+ StartUndo( nId, NULL );
+ }
+ do { // dann durchlaufe mal den gesamten Ring
+ for( USHORT nRptCnt = nRepeatCnt; nRptCnt > 0; --nRptCnt )
+ {
+ rUndoIter.pLastUndoObj = 0;
+ for( USHORT nCnt = nSize; nCnt < nEndCnt; ++nCnt )
+ (*pUndos)[ nCnt ]->Repeat( rUndoIter ); // Repeat ausfuehren
+ }
+ } while( pTmpCrsr !=
+ ( rUndoIter.pAktPam = (SwPaM*)rUndoIter.pAktPam->GetNext() ));
+ if( pTmpCrsr != pTmpCrsr->GetNext() || !bOneUndo )
+ EndUndo( nId, NULL );
+
+ return TRUE;
+}
+
+// liefert die Id der letzten Repeatfaehigen Aktion zurueck oder 0
+// fuellt ggf. VARARR mit User-RedoIds
+
+String SwDoc::GetRepeatIdsStr(String* pStr, SwUndoIds *pRepeatIds) const
+{
+ String aTmpStr;
+ SwUndoId nId;
+
+ if ( pStr != NULL)
+ {
+ nId = GetRepeatIds(pStr, pRepeatIds);
+ aTmpStr = *pStr;
+ }
+ else
+ nId = GetRepeatIds(&aTmpStr, pRepeatIds);
+
+ if (nId <= UNDO_END)
+ return String();
+
+ return aTmpStr;
+}
+
+SwUndoId SwDoc::GetRepeatIds(String* pStr, SwUndoIds *pRepeatIds) const
+{
+ SwUndoId nRepeatId = GetUndoIds( pStr, pRepeatIds );
+ if( REPEAT_START <= nRepeatId && REPEAT_END > nRepeatId )
+ return nRepeatId;
+ return UNDO_EMPTY;
+}
+
+
+SwUndo* SwDoc::RemoveLastUndo( SwUndoId eUndoId )
+{
+ SwUndo* pUndo = (*pUndos)[ nUndoPos - 1 ];
+ if( eUndoId == pUndo->GetId() && nUndoPos == pUndos->Count() )
+ {
+ if( !nUndoSttEnd )
+ --nUndoCnt;
+ --nUndoPos;
+ pUndos->Remove( nUndoPos, 1 );
+ }
+ else
+ {
+ pUndo = 0;
+ OSL_ENSURE( !this, "falsches Undo-Object" );
+ }
+ return pUndo;
+}
+
+SwUndoIdAndName::SwUndoIdAndName( SwUndoId nId, const String* pStr )
+ : eUndoId( nId ), pUndoStr( pStr ? new String( *pStr ) : 0 )
+{
+}
+
+SwUndoIdAndName::~SwUndoIdAndName()
+{
+ delete pUndoStr;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/makefile.mk b/sw/source/core/undo/makefile.mk
new file mode 100644
index 000000000000..c381761adba1
--- /dev/null
+++ b/sw/source/core/undo/makefile.mk
@@ -0,0 +1,86 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=sw
+TARGET=undo
+
+AUTOSEG=true
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : $(PRJ)$/inc$/swpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/inc$/sw.mk
+
+# --- Files --------------------------------------------------------
+
+SRS1NAME=$(TARGET)
+SRC1FILES = \
+ undo.src
+
+EXCEPTIONSFILES = \
+ $(SLO)$/SwRewriter.obj \
+ $(SLO)$/unattr.obj \
+ $(SLO)$/undobj.obj \
+ $(SLO)$/undraw.obj \
+ $(SLO)$/unovwr.obj \
+ $(SLO)$/untbl.obj
+
+SLOFILES = \
+ $(SLO)$/SwRewriter.obj \
+ $(SLO)$/SwUndoField.obj \
+ $(SLO)$/SwUndoPageDesc.obj \
+ $(SLO)$/SwUndoFmt.obj \
+ $(SLO)$/SwUndoTOXChange.obj \
+ $(SLO)$/docundo.obj \
+ $(SLO)$/rolbck.obj \
+ $(SLO)$/unattr.obj \
+ $(SLO)$/unbkmk.obj \
+ $(SLO)$/undel.obj \
+ $(SLO)$/undobj.obj \
+ $(SLO)$/undobj1.obj \
+ $(SLO)$/undoflystrattr.obj \
+ $(SLO)$/undraw.obj \
+ $(SLO)$/unfmco.obj \
+ $(SLO)$/unins.obj \
+ $(SLO)$/unmove.obj \
+ $(SLO)$/unnum.obj \
+ $(SLO)$/unoutl.obj \
+ $(SLO)$/unovwr.obj \
+ $(SLO)$/unredln.obj \
+ $(SLO)$/unsect.obj \
+ $(SLO)$/unsort.obj \
+ $(SLO)$/unspnd.obj \
+ $(SLO)$/untbl.obj \
+ $(SLO)$/untblk.obj
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sw/source/core/undo/rolbck.cxx b/sw/source/core/undo/rolbck.cxx
new file mode 100644
index 000000000000..4214c1c22abb
--- /dev/null
+++ b/sw/source/core/undo/rolbck.cxx
@@ -0,0 +1,1522 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <svl/itemiter.hxx>
+#include <fmtftn.hxx>
+#include <fchrfmt.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtrfmrk.hxx>
+#include <fmtfld.hxx>
+#include <fmtpdsc.hxx>
+#include <txtfld.hxx>
+#include <txtrfmrk.hxx>
+#include <txttxmrk.hxx>
+#include <txtftn.hxx>
+#include <txtflcnt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcnct.hxx>
+#include <frmfmt.hxx>
+#include <ftnidx.hxx>
+#include <doc.hxx> // SwDoc.GetNodes()
+#include <docary.hxx>
+#include <ndtxt.hxx> // SwTxtNode
+#include <paratr.hxx> //
+#include <cellatr.hxx> //
+#include <fldbas.hxx> // fuer Felder
+#include <pam.hxx> // fuer SwPaM
+#include <swtable.hxx>
+#include <rolbck.hxx>
+#include <ndgrf.hxx> // SwGrfNode
+#include <undobj.hxx> // fuer UndoDelete
+#include <IMark.hxx> // fuer SwBookmark
+#include <charfmt.hxx> // #i27615#
+#include <comcore.hrc>
+#include <tools/resid.hxx>
+#include <undo.hrc>
+#include <editeng/brkitem.hxx>
+#include <bookmrk.hxx>
+
+SV_IMPL_PTRARR( SwpHstry, SwHistoryHintPtr)
+
+String SwHistoryHint::GetDescription() const
+{
+ return String();
+}
+
+
+SwHistorySetFmt::SwHistorySetFmt( const SfxPoolItem* pFmtHt, ULONG nNd )
+ : SwHistoryHint( HSTRY_SETFMTHNT )
+ , m_pAttr( pFmtHt->Clone() )
+ , m_nNodeIndex( nNd )
+{
+ switch ( m_pAttr->Which() )
+ {
+ case RES_PAGEDESC:
+ static_cast<SwFmtPageDesc&>(*m_pAttr).ChgDefinedIn( 0 );
+ break;
+ case RES_PARATR_DROP:
+ static_cast<SwFmtDrop&>(*m_pAttr).ChgDefinedIn( 0 );
+ break;
+ case RES_BOXATR_FORMULA:
+ {
+ //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern
+ SwTblBoxFormula& rNew = static_cast<SwTblBoxFormula&>(*m_pAttr);
+ if ( rNew.IsIntrnlName() )
+ {
+ const SwTblBoxFormula& rOld =
+ *static_cast<const SwTblBoxFormula*>(pFmtHt);
+ const SwNode* pNd = rOld.GetNodeOfFormula();
+ if ( pNd )
+ {
+ const SwTableNode* pTableNode = pNd->FindTableNode();
+ if (pTableNode)
+ {
+ SwTableFmlUpdate aMsgHnt( &pTableNode->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXNAME;
+ rNew.ChgDefinedIn( rOld.GetDefinedIn() );
+ rNew.ChangeState( &aMsgHnt );
+ }
+ }
+ }
+ rNew.ChgDefinedIn( 0 );
+ }
+ break;
+ }
+}
+
+String SwHistorySetFmt::GetDescription() const
+{
+ String aResult ;
+
+ USHORT nWhich = m_pAttr->Which();
+ switch (nWhich)
+ {
+ case RES_BREAK:
+ switch ((static_cast<SvxFmtBreakItem &>(*m_pAttr)).GetBreak())
+ {
+ case SVX_BREAK_PAGE_BEFORE:
+ case SVX_BREAK_PAGE_AFTER:
+ case SVX_BREAK_PAGE_BOTH:
+ aResult = SW_RES(STR_UNDO_PAGEBREAKS);
+
+ break;
+ case SVX_BREAK_COLUMN_BEFORE:
+ case SVX_BREAK_COLUMN_AFTER:
+ case SVX_BREAK_COLUMN_BOTH:
+ aResult = SW_RES(STR_UNDO_COLBRKS);
+
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return aResult;
+}
+
+void SwHistorySetFmt::SetInDoc( SwDoc* pDoc, bool bTmpSet )
+{
+ SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
+ if ( pNode->IsCntntNode() )
+ {
+ static_cast<SwCntntNode*>(pNode)->SetAttr( *m_pAttr );
+ }
+ else if ( pNode->IsTableNode() )
+ {
+ static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt()->SetFmtAttr(
+ *m_pAttr );
+ }
+ else if ( pNode->IsStartNode() && (SwTableBoxStartNode ==
+ static_cast<SwStartNode*>(pNode)->GetStartNodeType()) )
+ {
+ SwTableNode* pTNd = pNode->FindTableNode();
+ if ( pTNd )
+ {
+ SwTableBox* pBox = pTNd->GetTable().GetTblBox( m_nNodeIndex );
+ if (pBox)
+ {
+ pBox->ClaimFrmFmt()->SetFmtAttr( *m_pAttr );
+ }
+ }
+ }
+
+ if ( !bTmpSet )
+ {
+ m_pAttr.reset();
+ }
+}
+
+SwHistorySetFmt::~SwHistorySetFmt()
+{
+}
+
+
+// --> OD 2008-02-27 #refactorlists# - removed <rDoc>
+SwHistoryResetFmt::SwHistoryResetFmt(const SfxPoolItem* pFmtHt, ULONG nNodeIdx)
+// <--
+ : SwHistoryHint( HSTRY_RESETFMTHNT )
+ , m_nNodeIndex( nNodeIdx )
+ , m_nWhich( pFmtHt->Which() )
+{
+}
+
+
+void SwHistoryResetFmt::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
+ if ( pNode->IsCntntNode() )
+ {
+ static_cast<SwCntntNode*>(pNode)->ResetAttr( m_nWhich );
+ }
+ else if ( pNode->IsTableNode() )
+ {
+ static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt()->
+ ResetFmtAttr( m_nWhich );
+ }
+}
+
+
+SwHistorySetTxt::SwHistorySetTxt( SwTxtAttr* pTxtHt, ULONG nNodePos )
+ : SwHistoryHint( HSTRY_SETTXTHNT )
+ , m_nNodeIndex( nNodePos )
+ , m_nStart( *pTxtHt->GetStart() )
+ , m_nEnd( *pTxtHt->GetAnyEnd() )
+{
+ // !! Achtung: folgende Attribute erzeugen keine FormatAttribute:
+ // - NoLineBreak, NoHypen, Inserted, Deleted
+ // Dafuer muessen Sonderbehandlungen gemacht werden !!!
+
+ // ein bisschen kompliziert, aber ist Ok so: erst vom default
+ // eine Kopie und dann die Werte aus dem Text Attribut zuweisen
+ USHORT nWhich = pTxtHt->Which();
+ if ( RES_TXTATR_CHARFMT == nWhich )
+ {
+ m_pAttr.reset( new SwFmtCharFmt( pTxtHt->GetCharFmt().GetCharFmt() ) );
+ }
+ else
+ {
+ m_pAttr.reset( pTxtHt->GetAttr().Clone() );
+ }
+}
+
+
+SwHistorySetTxt::~SwHistorySetTxt()
+{
+}
+
+
+void SwHistorySetTxt::SetInDoc( SwDoc* pDoc, bool )
+{
+ if ( !m_pAttr.get() )
+ return;
+
+ if ( RES_TXTATR_CHARFMT == m_pAttr->Which() )
+ {
+ // ask the Doc if the CharFmt still exists
+ if ( USHRT_MAX == pDoc->GetCharFmts()->GetPos(
+ (static_cast<SwFmtCharFmt&>(*m_pAttr)).GetCharFmt() ) )
+ return; // do not set, format does not exist
+ }
+
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistorySetTxt::SetInDoc: not a TextNode" );
+
+ if ( pTxtNd )
+ {
+ pTxtNd->InsertItem( *m_pAttr, m_nStart, m_nEnd,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR |
+ nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+}
+
+
+SwHistorySetTxtFld::SwHistorySetTxtFld( SwTxtFld* pTxtFld, ULONG nNodePos )
+ : SwHistoryHint( HSTRY_SETTXTFLDHNT )
+ , m_pFldType( 0 )
+ , m_pFld( new SwFmtFld( *pTxtFld->GetFld().GetFld() ) )
+{
+ // only copy if not Sys-FieldType
+ SwDoc* pDoc = pTxtFld->GetTxtNode().GetDoc();
+
+ m_nFldWhich = m_pFld->GetFld()->GetTyp()->Which();
+ if (m_nFldWhich == RES_DBFLD ||
+ m_nFldWhich == RES_USERFLD ||
+ m_nFldWhich == RES_SETEXPFLD ||
+ m_nFldWhich == RES_DDEFLD ||
+ !pDoc->GetSysFldType( m_nFldWhich ))
+ {
+ m_pFldType.reset( m_pFld->GetFld()->GetTyp()->Copy() );
+ m_pFld->GetFld()->ChgTyp( m_pFldType.get() ); // change field type
+ }
+ m_nNodeIndex = nNodePos;
+ m_nPos = *pTxtFld->GetStart();
+}
+
+String SwHistorySetTxtFld::GetDescription() const
+{
+ return m_pFld->GetFld()->GetDescription();;
+}
+
+SwHistorySetTxtFld::~SwHistorySetTxtFld()
+{
+}
+
+
+void SwHistorySetTxtFld::SetInDoc( SwDoc* pDoc, bool )
+{
+ if ( !m_pFld.get() )
+ return;
+
+ SwFieldType* pNewFldType = m_pFldType.get();
+ if ( !pNewFldType )
+ {
+ pNewFldType = pDoc->GetSysFldType( m_nFldWhich );
+ }
+ else
+ {
+ // register type with the document
+ pNewFldType = pDoc->InsertFldType( *m_pFldType );
+ }
+
+ m_pFld->GetFld()->ChgTyp( pNewFldType ); // change field type
+
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistorySetTxtFld: no TextNode" );
+
+ if ( pTxtNd )
+ {
+ pTxtNd->InsertItem( *m_pFld, m_nPos, m_nPos,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR );
+ }
+}
+
+
+
+SwHistorySetRefMark::SwHistorySetRefMark( SwTxtRefMark* pTxtHt, ULONG nNodePos )
+ : SwHistoryHint( HSTRY_SETREFMARKHNT )
+ , m_RefName( pTxtHt->GetRefMark().GetRefName() )
+ , m_nNodeIndex( nNodePos )
+ , m_nStart( *pTxtHt->GetStart() )
+ , m_nEnd( *pTxtHt->GetAnyEnd() )
+{
+}
+
+
+void SwHistorySetRefMark::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistorySetRefMark: no TextNode" );
+ if ( !pTxtNd )
+ return;
+
+ SwFmtRefMark aRefMark( m_RefName );
+
+ // if a reference mark without an end already exists here: must not insert!
+ if ( m_nStart != m_nEnd ||
+ !pTxtNd->GetTxtAttrForCharAt( m_nStart, RES_TXTATR_REFMARK ) )
+ {
+ pTxtNd->InsertItem( aRefMark, m_nStart, m_nEnd,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR );
+ }
+}
+
+
+SwHistorySetTOXMark::SwHistorySetTOXMark( SwTxtTOXMark* pTxtHt, ULONG nNodePos )
+ : SwHistoryHint( HSTRY_SETTOXMARKHNT )
+ , m_TOXMark( pTxtHt->GetTOXMark() )
+ , m_TOXName( m_TOXMark.GetTOXType()->GetTypeName() )
+ , m_eTOXTypes( m_TOXMark.GetTOXType()->GetType() )
+ , m_nNodeIndex( nNodePos )
+ , m_nStart( *pTxtHt->GetStart() )
+ , m_nEnd( *pTxtHt->GetAnyEnd() )
+{
+ const_cast<SwModify*>(m_TOXMark.GetRegisteredIn())->Remove( &m_TOXMark );
+}
+
+
+void SwHistorySetTOXMark::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistorySetTOXMark: no TextNode" );
+ if ( !pTxtNd )
+ return;
+
+ // search for respective TOX type
+ USHORT nCnt = pDoc->GetTOXTypeCount( m_eTOXTypes );
+ SwTOXType* pToxType = 0;
+ for ( USHORT n = 0; n < nCnt; ++n )
+ {
+ pToxType = const_cast<SwTOXType*>(pDoc->GetTOXType( m_eTOXTypes, n ));
+ if ( pToxType->GetTypeName() == m_TOXName )
+ break;
+ pToxType = 0;
+ }
+
+ if ( !pToxType ) // TOX type not found, create new
+ {
+ pToxType = const_cast<SwTOXType*>(
+ pDoc->InsertTOXType( SwTOXType( m_eTOXTypes, m_TOXName )));
+ }
+
+ SwTOXMark aNew( m_TOXMark );
+ pToxType->Add( &aNew );
+
+ pTxtNd->InsertItem( aNew, m_nStart, m_nEnd,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR );
+}
+
+
+int SwHistorySetTOXMark::IsEqual( const SwTOXMark& rCmp ) const
+{
+ return m_TOXName == rCmp.GetTOXType()->GetTypeName() &&
+ m_eTOXTypes == rCmp.GetTOXType()->GetType() &&
+ m_TOXMark.GetAlternativeText() == rCmp.GetAlternativeText() &&
+ ( (TOX_INDEX == m_eTOXTypes)
+ ? ( m_TOXMark.GetPrimaryKey() == rCmp.GetPrimaryKey() &&
+ m_TOXMark.GetSecondaryKey() == rCmp.GetSecondaryKey() )
+ : m_TOXMark.GetLevel() == rCmp.GetLevel()
+ );
+}
+
+
+SwHistoryResetTxt::SwHistoryResetTxt( USHORT nWhich,
+ xub_StrLen nAttrStart, xub_StrLen nAttrEnd, ULONG nNodePos )
+ : SwHistoryHint( HSTRY_RESETTXTHNT )
+ , m_nNodeIndex( nNodePos ), m_nStart( nAttrStart ), m_nEnd( nAttrEnd )
+ , m_nAttr( nWhich )
+{
+}
+
+
+void SwHistoryResetTxt::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistoryResetTxt: no TextNode" );
+ if ( pTxtNd )
+ {
+ pTxtNd->DeleteAttributes( m_nAttr, m_nStart, m_nEnd );
+ }
+}
+
+
+SwHistorySetFootnote::SwHistorySetFootnote( SwTxtFtn* pTxtFtn, ULONG nNodePos )
+ : SwHistoryHint( HSTRY_SETFTNHNT )
+ , m_pUndo( new SwUndoSaveSection )
+ , m_FootnoteNumber( pTxtFtn->GetFtn().GetNumStr() )
+ , m_nNodeIndex( nNodePos )
+ , m_nStart( *pTxtFtn->GetStart() )
+ , m_bEndNote( pTxtFtn->GetFtn().IsEndNote() )
+{
+ OSL_ENSURE( pTxtFtn->GetStartNode(),
+ "SwHistorySetFootnote: Footnote without Section" );
+
+ // merke die alte NodePos, denn wer weiss was alles in der SaveSection
+ // gespeichert (geloescht) wird
+ SwDoc* pDoc = const_cast<SwDoc*>(pTxtFtn->GetTxtNode().GetDoc());
+ SwNode* pSaveNd = pDoc->GetNodes()[ m_nNodeIndex ];
+
+ //Pointer auf StartNode der FtnSection merken und erstmal den Pointer im
+ //Attribut zuruecksetzen -> Damit werden automatisch die Frms vernichtet.
+ SwNodeIndex aSttIdx( *pTxtFtn->GetStartNode() );
+ pTxtFtn->SetStartNode( 0, FALSE );
+
+ m_pUndo->SaveSection( pDoc, aSttIdx );
+ m_nNodeIndex = pSaveNd->GetIndex();
+}
+
+SwHistorySetFootnote::SwHistorySetFootnote( const SwTxtFtn &rTxtFtn )
+ : SwHistoryHint( HSTRY_SETFTNHNT )
+ , m_pUndo( 0 )
+ , m_FootnoteNumber( rTxtFtn.GetFtn().GetNumStr() )
+ , m_nNodeIndex( _SwTxtFtn_GetIndex( (&rTxtFtn) ) )
+ , m_nStart( *rTxtFtn.GetStart() )
+ , m_bEndNote( rTxtFtn.GetFtn().IsEndNote() )
+{
+ OSL_ENSURE( rTxtFtn.GetStartNode(),
+ "SwHistorySetFootnote: Footnote without Section" );
+}
+
+String SwHistorySetFootnote::GetDescription() const
+{
+ return SW_RES(STR_FOOTNOTE);
+}
+
+SwHistorySetFootnote::~SwHistorySetFootnote()
+{
+}
+
+
+void SwHistorySetFootnote::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistorySetFootnote: no TextNode" );
+ if ( !pTxtNd )
+ return;
+
+ if ( m_pUndo.get() )
+ {
+ // set the footnote in the TextNode
+ SwFmtFtn aTemp( m_bEndNote );
+ SwFmtFtn& rNew = const_cast<SwFmtFtn&>(
+ static_cast<const SwFmtFtn&>(pDoc->GetAttrPool().Put(aTemp)) );
+ if ( m_FootnoteNumber.Len() )
+ {
+ rNew.SetNumStr( m_FootnoteNumber );
+ }
+ SwTxtFtn* pTxtFtn = new SwTxtFtn( rNew, m_nStart );
+
+ // create the section of the Footnote
+ SwNodeIndex aIdx( *pTxtNd );
+ m_pUndo->RestoreSection( pDoc, &aIdx, SwFootnoteStartNode );
+ pTxtFtn->SetStartNode( &aIdx );
+ if ( m_pUndo->GetHistory() )
+ {
+ // create frames only now
+ m_pUndo->GetHistory()->Rollback( pDoc );
+ }
+
+ pTxtNd->InsertHint( pTxtFtn );
+ }
+ else
+ {
+ SwTxtFtn * const pFtn =
+ const_cast<SwTxtFtn*>( static_cast<const SwTxtFtn*>(
+ pTxtNd->GetTxtAttrForCharAt( m_nStart )));
+ SwFmtFtn &rFtn = const_cast<SwFmtFtn&>(pFtn->GetFtn());
+ rFtn.SetNumStr( m_FootnoteNumber );
+ if ( rFtn.IsEndNote() != m_bEndNote )
+ {
+ rFtn.SetEndNote( m_bEndNote );
+ pFtn->CheckCondColl();
+ }
+ }
+}
+
+
+SwHistoryChangeFmtColl::SwHistoryChangeFmtColl( SwFmtColl* pFmtColl, ULONG nNd,
+ BYTE nNodeWhich )
+ : SwHistoryHint( HSTRY_CHGFMTCOLL )
+ , m_pColl( pFmtColl )
+ , m_nNodeIndex( nNd )
+ , m_nNodeType( nNodeWhich )
+{
+}
+
+void SwHistoryChangeFmtColl::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode();
+ OSL_ENSURE( pCntntNd, "SwHistoryChangeFmtColl: no ContentNode" );
+
+ // before setting the format, check if it is still available in the
+ // document. if it has been deleted, there is no undo!
+ if ( pCntntNd && m_nNodeType == pCntntNd->GetNodeType() )
+ {
+ if ( ND_TEXTNODE == m_nNodeType )
+ {
+ if ( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos(
+ static_cast<SwTxtFmtColl * const>(m_pColl) ))
+ {
+ pCntntNd->ChgFmtColl( m_pColl );
+ }
+ }
+ else if ( USHRT_MAX != pDoc->GetGrfFmtColls()->GetPos(
+ static_cast<SwGrfFmtColl * const>(m_pColl) ))
+ {
+ pCntntNd->ChgFmtColl( m_pColl );
+ }
+ }
+}
+
+
+SwHistoryTxtFlyCnt::SwHistoryTxtFlyCnt( SwFrmFmt* const pFlyFmt )
+ : SwHistoryHint( HSTRY_FLYCNT )
+ , m_pUndo( new SwUndoDelLayFmt( pFlyFmt ) )
+{
+ OSL_ENSURE( pFlyFmt, "SwHistoryTxtFlyCnt: no Format" );
+ m_pUndo->ChgShowSel( FALSE );
+}
+
+
+SwHistoryTxtFlyCnt::~SwHistoryTxtFlyCnt()
+{
+}
+
+
+void SwHistoryTxtFlyCnt::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwPaM aPam( pDoc->GetNodes().GetEndOfPostIts() );
+ SwUndoIter aUndoIter( &aPam );
+ m_pUndo->Undo( aUndoIter );
+}
+
+
+
+SwHistoryBookmark::SwHistoryBookmark(
+ const ::sw::mark::IMark& rBkmk,
+ bool bSavePos,
+ bool bSaveOtherPos)
+ : SwHistoryHint(HSTRY_BOOKMARK)
+ , m_aName(rBkmk.GetName())
+ , m_aShortName()
+ , m_aKeycode()
+ , m_nNode(bSavePos ?
+ rBkmk.GetMarkPos().nNode.GetIndex() : 0)
+ , m_nOtherNode(bSaveOtherPos ?
+ rBkmk.GetOtherMarkPos().nNode.GetIndex() : 0)
+ , m_nCntnt(bSavePos ?
+ rBkmk.GetMarkPos().nContent.GetIndex() : 0)
+ , m_nOtherCntnt(bSaveOtherPos ?
+ rBkmk.GetOtherMarkPos().nContent.GetIndex() :0)
+ , m_bSavePos(bSavePos)
+ , m_bSaveOtherPos(bSaveOtherPos)
+ , m_bHadOtherPos(rBkmk.IsExpanded())
+ , m_eBkmkType(IDocumentMarkAccess::GetType(rBkmk))
+{
+ const ::sw::mark::IBookmark* const pBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(&rBkmk);
+ if(pBookmark)
+ {
+ m_aKeycode = pBookmark->GetKeyCode();
+ m_aShortName = pBookmark->GetShortName();
+
+ ::sfx2::Metadatable const*const pMetadatable(
+ dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
+ if (pMetadatable)
+ {
+ m_pMetadataUndo = pMetadatable->CreateUndo();
+ }
+ }
+}
+
+
+void SwHistoryBookmark::SetInDoc( SwDoc* pDoc, bool )
+{
+ bool bDoesUndo = pDoc->DoesUndo();
+ pDoc->DoUndo(false);
+
+ SwNodes& rNds = pDoc->GetNodes();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ ::std::auto_ptr<SwPaM> pPam;
+ ::sw::mark::IMark* pMark = NULL;
+
+ if(m_bSavePos)
+ {
+ SwCntntNode* const pCntntNd = rNds[m_nNode]->GetCntntNode();
+ OSL_ENSURE(pCntntNd,
+ "<SwHistoryBookmark::SetInDoc(..)>"
+ " - wrong node for a mark");
+
+ // #111660# don't crash when nNode1 doesn't point to content node.
+ if(pCntntNd)
+ pPam = ::std::auto_ptr<SwPaM>(new SwPaM(*pCntntNd, m_nCntnt));
+ }
+ else
+ {
+ pMark = pMarkAccess->findMark(m_aName)->get();
+ pPam = ::std::auto_ptr<SwPaM>(new SwPaM(pMark->GetMarkPos()));
+ }
+
+ if(m_bSaveOtherPos)
+ {
+ SwCntntNode* const pCntntNd = rNds[m_nOtherNode]->GetCntntNode();
+ OSL_ENSURE(pCntntNd,
+ "<SwHistoryBookmark::SetInDoc(..)>"
+ " - wrong node for a mark");
+
+ if(pPam.get() != NULL && pCntntNd)
+ {
+ pPam->SetMark();
+ pPam->GetMark()->nNode = m_nOtherNode;
+ pPam->GetMark()->nContent.Assign(pCntntNd, m_nOtherCntnt);
+ }
+ }
+ else if(m_bHadOtherPos)
+ {
+ if(!pMark)
+ pMark = pMarkAccess->findMark(m_aName)->get();
+ OSL_ENSURE(pMark->IsExpanded(),
+ "<SwHistoryBookmark::SetInDoc(..)>"
+ " - missing pos on old mark");
+ pPam->SetMark();
+ *pPam->GetMark() = pMark->GetOtherMarkPos();
+ }
+
+ if(pPam.get())
+ {
+ if(pMark)
+ pMarkAccess->deleteMark(pMark);
+ ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(
+ pMarkAccess->makeMark(*pPam, m_aName, m_eBkmkType));
+ if(pBookmark)
+ {
+ pBookmark->SetKeyCode(m_aKeycode);
+ pBookmark->SetShortName(m_aShortName);
+ if (m_pMetadataUndo)
+ {
+ ::sfx2::Metadatable * const pMeta(
+ dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
+ OSL_ENSURE(pMeta, "metadata undo, but not metadatable?");
+ if (pMeta)
+ {
+ pMeta->RestoreMetadata(m_pMetadataUndo);
+ }
+ }
+ }
+ }
+ pDoc->DoUndo(bDoesUndo);
+}
+
+
+bool SwHistoryBookmark::IsEqualBookmark(const ::sw::mark::IMark& rBkmk)
+{
+ return m_nNode == rBkmk.GetMarkPos().nNode.GetIndex()
+ && m_nCntnt == rBkmk.GetMarkPos().nContent.GetIndex()
+ && m_aName == rBkmk.GetName();
+}
+
+const ::rtl::OUString& SwHistoryBookmark::GetName() const
+{
+ return m_aName;
+}
+
+/*************************************************************************/
+
+
+SwHistorySetAttrSet::SwHistorySetAttrSet( const SfxItemSet& rSet,
+ ULONG nNodePos, const SvUShortsSort& rSetArr )
+ : SwHistoryHint( HSTRY_SETATTRSET )
+ , m_OldSet( rSet )
+ , m_ResetArray( 0, 4 )
+ , m_nNodeIndex( nNodePos )
+{
+ SfxItemIter aIter( m_OldSet ), aOrigIter( rSet );
+ const SfxPoolItem* pItem = aIter.FirstItem(),
+ * pOrigItem = aOrigIter.FirstItem();
+ do {
+ if( !rSetArr.Seek_Entry( pOrigItem->Which() ))
+ {
+ m_ResetArray.Insert( pOrigItem->Which(), m_ResetArray.Count() );
+ m_OldSet.ClearItem( pOrigItem->Which() );
+ }
+ else
+ {
+ switch ( pItem->Which() )
+ {
+ case RES_PAGEDESC:
+ static_cast<SwFmtPageDesc*>(
+ const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 );
+ break;
+
+ case RES_PARATR_DROP:
+ static_cast<SwFmtDrop*>(
+ const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 );
+ break;
+
+ case RES_BOXATR_FORMULA:
+ {
+ //JP 20.04.98: Bug 49502 - wenn eine Formel gesetzt ist, nie den
+ // Value mit sichern. Der muss gegebenfalls neu
+ // errechnet werden!
+ //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern
+ m_OldSet.ClearItem( RES_BOXATR_VALUE );
+
+ SwTblBoxFormula& rNew =
+ *static_cast<SwTblBoxFormula*>(
+ const_cast<SfxPoolItem*>(pItem));
+ if ( rNew.IsIntrnlName() )
+ {
+ const SwTblBoxFormula& rOld =
+ static_cast<const SwTblBoxFormula&>(
+ rSet.Get( RES_BOXATR_FORMULA ));
+ const SwNode* pNd = rOld.GetNodeOfFormula();
+ if ( pNd )
+ {
+ const SwTableNode* pTableNode
+ = pNd->FindTableNode();
+ if (pTableNode)
+ {
+ SwTableFmlUpdate aMsgHnt(
+ &pTableNode->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXNAME;
+ rNew.ChgDefinedIn( rOld.GetDefinedIn() );
+ rNew.ChangeState( &aMsgHnt );
+ }
+ }
+ }
+ rNew.ChgDefinedIn( 0 );
+ }
+ break;
+ }
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ pOrigItem = aOrigIter.NextItem();
+ } while( TRUE );
+}
+
+void SwHistorySetAttrSet::SetInDoc( SwDoc* pDoc, bool )
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+
+ SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
+ if ( pNode->IsCntntNode() )
+ {
+ static_cast<SwCntntNode*>(pNode)->SetAttr( m_OldSet );
+ if ( m_ResetArray.Count() )
+ {
+ static_cast<SwCntntNode*>(pNode)->ResetAttr( m_ResetArray );
+ }
+ }
+ else if ( pNode->IsTableNode() )
+ {
+ SwFmt& rFmt =
+ *static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt();
+ rFmt.SetFmtAttr( m_OldSet );
+ if ( m_ResetArray.Count() )
+ {
+ rFmt.ResetFmtAttr( *m_ResetArray.GetData() );
+ }
+ }
+
+ pDoc->DoUndo( bDoesUndo );
+}
+
+/*************************************************************************/
+
+
+SwHistoryResetAttrSet::SwHistoryResetAttrSet( const SfxItemSet& rSet,
+ ULONG nNodePos, xub_StrLen nAttrStt, xub_StrLen nAttrEnd )
+ : SwHistoryHint( HSTRY_RESETATTRSET )
+ , m_nNodeIndex( nNodePos ), m_nStart( nAttrStt ), m_nEnd( nAttrEnd )
+ , m_Array( (BYTE)rSet.Count() )
+{
+ SfxItemIter aIter( rSet );
+ bool bAutoStyle = false;
+
+ while( TRUE )
+ {
+ const USHORT nWhich = aIter.GetCurItem()->Which();
+
+#ifndef PRODUCT
+ switch (nWhich)
+ {
+ case RES_TXTATR_REFMARK:
+ case RES_TXTATR_TOXMARK:
+ if (m_nStart != m_nEnd) break; // else: fall through!
+ case RES_TXTATR_FIELD:
+ case RES_TXTATR_FLYCNT:
+ case RES_TXTATR_FTN:
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ OSL_ENSURE(rSet.Count() == 1,
+ "text attribute with CH_TXTATR, but not the only one:"
+ "\nnot such a good idea");
+ break;
+ }
+#endif
+
+ // Character attribute cannot be inserted into the hints array
+ // anymore. Therefore we have to treat them as one RES_TXTATR_AUTOFMT:
+ if (isCHRATR(nWhich))
+ {
+ bAutoStyle = true;
+ }
+ else
+ {
+ m_Array.Insert( aIter.GetCurItem()->Which(), m_Array.Count() );
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+
+ aIter.NextItem();
+ }
+
+ if ( bAutoStyle )
+ {
+ m_Array.Insert( RES_TXTATR_AUTOFMT, m_Array.Count() );
+ }
+}
+
+
+void SwHistoryResetAttrSet::SetInDoc( SwDoc* pDoc, bool )
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+
+ SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode();
+ OSL_ENSURE( pCntntNd, "SwHistoryResetAttrSet: no CntntNode" );
+
+ if (pCntntNd)
+ {
+ const USHORT* pArr = m_Array.GetData();
+ if ( USHRT_MAX == m_nEnd && USHRT_MAX == m_nStart )
+ {
+ // no area: use ContentNode
+ for ( USHORT n = m_Array.Count(); n; --n, ++pArr )
+ {
+ pCntntNd->ResetAttr( *pArr );
+ }
+ }
+ else
+ {
+ // area: use TextNode
+ for ( USHORT n = m_Array.Count(); n; --n, ++pArr )
+ {
+ static_cast<SwTxtNode*>(pCntntNd)->
+ DeleteAttributes( *pArr, m_nStart, m_nEnd );
+ }
+ }
+ }
+
+ pDoc->DoUndo( bDoesUndo );
+}
+
+
+/*************************************************************************/
+
+
+SwHistoryChangeFlyAnchor::SwHistoryChangeFlyAnchor( SwFrmFmt& rFmt )
+ : SwHistoryHint( HSTRY_CHGFLYANCHOR )
+ , m_rFmt( rFmt )
+ , m_nOldNodeIndex( rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex() )
+ , m_nOldContentIndex( (FLY_AT_CHAR == rFmt.GetAnchor().GetAnchorId())
+ ? rFmt.GetAnchor().GetCntntAnchor()->nContent.GetIndex()
+ : STRING_MAXLEN )
+{
+}
+
+
+void SwHistoryChangeFlyAnchor::SetInDoc( SwDoc* pDoc, bool )
+{
+ BOOL bDoesUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+
+ USHORT nPos = pDoc->GetSpzFrmFmts()->GetPos( &m_rFmt );
+ if ( USHRT_MAX != nPos ) // Format does still exist
+ {
+ SwFmtAnchor aTmp( m_rFmt.GetAnchor() );
+
+ SwNode* pNd = pDoc->GetNodes()[ m_nOldNodeIndex ];
+ SwCntntNode* pCNd = pNd->GetCntntNode();
+ SwPosition aPos( *pNd );
+ if ( STRING_MAXLEN != m_nOldContentIndex )
+ {
+ OSL_ENSURE(pCNd, "SwHistoryChangeFlyAnchor: no ContentNode");
+ if (pCNd)
+ {
+ aPos.nContent.Assign( pCNd, m_nOldContentIndex );
+ }
+ }
+ aTmp.SetAnchor( &aPos );
+
+ // so the Layout does not get confused
+ if ( !pCNd || !pCNd->GetFrm( 0, 0, FALSE ) )
+ {
+ m_rFmt.DelFrms();
+ }
+
+ m_rFmt.SetFmtAttr( aTmp );
+ }
+ pDoc->DoUndo( bDoesUndo );
+}
+
+
+/*************************************************************************/
+
+SwHistoryChangeFlyChain::SwHistoryChangeFlyChain( SwFlyFrmFmt& rFmt,
+ const SwFmtChain& rAttr )
+ : SwHistoryHint( HSTRY_CHGFLYCHAIN )
+ , m_pPrevFmt( rAttr.GetPrev() )
+ , m_pNextFmt( rAttr.GetNext() )
+ , m_pFlyFmt( &rFmt )
+{
+}
+
+
+void SwHistoryChangeFlyChain::SetInDoc( SwDoc* pDoc, bool )
+{
+ if ( USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pFlyFmt ) )
+ {
+ SwFmtChain aChain;
+
+ if ( m_pPrevFmt &&
+ USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pPrevFmt ) )
+ {
+ aChain.SetPrev( m_pPrevFmt );
+ SwFmtChain aTmp( m_pPrevFmt->GetChain() );
+ aTmp.SetNext( m_pFlyFmt );
+ m_pPrevFmt->SetFmtAttr( aTmp );
+ }
+
+ if ( m_pNextFmt &&
+ USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pNextFmt ) )
+ {
+ aChain.SetNext( m_pNextFmt );
+ SwFmtChain aTmp( m_pNextFmt->GetChain() );
+ aTmp.SetPrev( m_pFlyFmt );
+ m_pNextFmt->SetFmtAttr( aTmp );
+ }
+
+ if ( aChain.GetNext() || aChain.GetPrev() )
+ {
+ m_pFlyFmt->SetFmtAttr( aChain );
+ }
+ }
+}
+
+
+// -> #i27615#
+SwHistoryChangeCharFmt::SwHistoryChangeCharFmt(const SfxItemSet & rSet,
+ const String & sFmt)
+ : SwHistoryHint(HSTRY_CHGCHARFMT)
+ , m_OldSet(rSet), m_Fmt(sFmt)
+{
+}
+
+void SwHistoryChangeCharFmt::SetInDoc(SwDoc * pDoc, bool )
+{
+ SwCharFmt * pCharFmt = pDoc->FindCharFmtByName(m_Fmt);
+
+ if (pCharFmt)
+ {
+ pCharFmt->SetFmtAttr(m_OldSet);
+ }
+}
+// <- #i27615#
+
+/* */
+
+
+SwHistory::SwHistory( USHORT nInitSz, USHORT nGrowSz )
+ : m_SwpHstry( (BYTE)nInitSz, (BYTE)nGrowSz )
+ , m_nEndDiff( 0 )
+{}
+
+
+SwHistory::~SwHistory()
+{
+ Delete( 0 );
+}
+
+
+/*************************************************************************
+|*
+|* void SwHistory::Add()
+|*
+|* Beschreibung Dokument 1.0
+|* Ersterstellung JP 18.02.91
+|* Letzte Aenderung JP 18.02.91
+|*
+*************************************************************************/
+
+// --> OD 2008-02-27 #refactorlists# - removed <rDoc>
+void SwHistory::Add( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue,
+ ULONG nNodeIdx )
+// <--
+{
+ OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
+
+ USHORT nWhich = pNewValue->Which();
+ if( (nWhich >= POOLATTR_END) || (nWhich == RES_TXTATR_FIELD) )
+ return;
+
+ // no default Attribute?
+ SwHistoryHint * pHt;
+ if ( pOldValue && pOldValue != GetDfltAttr( pOldValue->Which() ) )
+ {
+ pHt = new SwHistorySetFmt( pOldValue, nNodeIdx );
+ }
+ else
+ {
+ pHt = new SwHistoryResetFmt( pNewValue, nNodeIdx );
+ }
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+
+void SwHistory::Add( SwTxtAttr* pHint, ULONG nNodeIdx, bool bNewAttr )
+{
+ OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
+
+ SwHistoryHint * pHt;
+ USHORT nAttrWhich = pHint->Which();
+
+ if( !bNewAttr )
+ {
+ switch ( nAttrWhich )
+ {
+ case RES_TXTATR_FTN:
+ pHt = new SwHistorySetFootnote(
+ static_cast<SwTxtFtn*>(pHint), nNodeIdx );
+ break;
+ case RES_TXTATR_FLYCNT:
+ pHt = new SwHistoryTxtFlyCnt( static_cast<SwTxtFlyCnt*>(pHint)
+ ->GetFlyCnt().GetFrmFmt() );
+ break;
+ case RES_TXTATR_FIELD:
+ pHt = new SwHistorySetTxtFld(
+ static_cast<SwTxtFld*>(pHint), nNodeIdx );
+ break;
+ case RES_TXTATR_TOXMARK:
+ pHt = new SwHistorySetTOXMark(
+ static_cast<SwTxtTOXMark*>(pHint), nNodeIdx );
+ break;
+ case RES_TXTATR_REFMARK:
+ pHt = new SwHistorySetRefMark(
+ static_cast<SwTxtRefMark*>(pHint), nNodeIdx );
+ break;
+ default:
+ pHt = new SwHistorySetTxt(
+ static_cast<SwTxtAttr*>(pHint), nNodeIdx );
+ }
+ }
+ else
+ {
+ pHt = new SwHistoryResetTxt( pHint->Which(), *pHint->GetStart(),
+ *pHint->GetAnyEnd(), nNodeIdx );
+ }
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+
+void SwHistory::Add( SwFmtColl* pColl, ULONG nNodeIdx, BYTE nWhichNd )
+{
+ OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
+
+ SwHistoryHint * pHt =
+ new SwHistoryChangeFmtColl( pColl, nNodeIdx, nWhichNd );
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+
+void SwHistory::Add(const ::sw::mark::IMark& rBkmk, bool bSavePos, bool bSaveOtherPos)
+{
+ OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
+
+ SwHistoryHint * pHt = new SwHistoryBookmark(rBkmk, bSavePos, bSaveOtherPos);
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+
+void SwHistory::Add( SwFrmFmt& rFmt )
+{
+ SwHistoryHint * pHt = new SwHistoryChangeFlyAnchor( rFmt );
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+void SwHistory::Add( SwFlyFrmFmt& rFmt, USHORT& rSetPos )
+{
+ OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
+
+ SwHistoryHint * pHint;
+ const USHORT nWh = rFmt.Which();
+ if( RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh )
+ {
+ pHint = new SwHistoryTxtFlyCnt( &rFmt );
+ m_SwpHstry.Insert( pHint, Count() );
+
+ const SwFmtChain* pChainItem;
+ if( SFX_ITEM_SET == rFmt.GetItemState( RES_CHAIN, FALSE,
+ (const SfxPoolItem**)&pChainItem ))
+ {
+ if( pChainItem->GetNext() || pChainItem->GetPrev() )
+ {
+ SwHistoryHint * pHt =
+ new SwHistoryChangeFlyChain( rFmt, *pChainItem );
+ m_SwpHstry.Insert( pHt, rSetPos++ );
+ if ( pChainItem->GetNext() )
+ {
+ SwFmtChain aTmp( pChainItem->GetNext()->GetChain() );
+ aTmp.SetPrev( 0 );
+ pChainItem->GetNext()->SetFmtAttr( aTmp );
+ }
+ if ( pChainItem->GetPrev() )
+ {
+ SwFmtChain aTmp( pChainItem->GetPrev()->GetChain() );
+ aTmp.SetNext( 0 );
+ pChainItem->GetPrev()->SetFmtAttr( aTmp );
+ }
+ }
+ rFmt.ResetFmtAttr( RES_CHAIN );
+ }
+ }
+}
+
+void SwHistory::Add( const SwTxtFtn& rFtn )
+{
+ SwHistoryHint *pHt = new SwHistorySetFootnote( rFtn );
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+// #i27615#
+void SwHistory::Add(const SfxItemSet & rSet, const SwCharFmt & rFmt)
+{
+ SwHistoryHint * pHt = new SwHistoryChangeCharFmt(rSet, rFmt.GetName());
+ m_SwpHstry.Insert(pHt, Count());
+}
+
+/*************************************************************************
+|*
+|* BOOL SwHistory::Rollback()
+|*
+|* Beschreibung Dokument 1.0
+|* Ersterstellung JP 18.02.91
+|* Letzte Aenderung JP 18.02.91
+|*
+*************************************************************************/
+
+
+bool SwHistory::Rollback( SwDoc* pDoc, USHORT nStart )
+{
+ if ( !Count() )
+ return false;
+
+ SwHistoryHint * pHHt;
+ USHORT i;
+ for ( i = Count(); i > nStart ; )
+ {
+ pHHt = m_SwpHstry[ --i ];
+ pHHt->SetInDoc( pDoc, false );
+ delete pHHt;
+ }
+ m_SwpHstry.Remove( nStart, Count() - nStart );
+ m_nEndDiff = 0;
+ return true;
+}
+
+
+
+bool SwHistory::TmpRollback( SwDoc* pDoc, USHORT nStart, bool bToFirst )
+{
+ USHORT nEnd = Count() - m_nEndDiff;
+ if ( !Count() || !nEnd || nStart >= nEnd )
+ return false;
+
+ SwHistoryHint * pHHt;
+ if ( bToFirst )
+ {
+ for ( ; nEnd > nStart; ++m_nEndDiff )
+ {
+ pHHt = m_SwpHstry[ --nEnd ];
+ pHHt->SetInDoc( pDoc, true );
+ }
+ }
+ else
+ {
+ for ( ; nStart < nEnd; ++m_nEndDiff, ++nStart )
+ {
+ pHHt = m_SwpHstry[ nStart ];
+ pHHt->SetInDoc( pDoc, true );
+ }
+ }
+ return true;
+}
+
+
+void SwHistory::Delete( USHORT nStart )
+{
+ for ( USHORT n = Count(); n > nStart; )
+ {
+ m_SwpHstry.DeleteAndDestroy( --n, 1 );
+ }
+ m_nEndDiff = 0;
+}
+
+
+USHORT SwHistory::SetTmpEnd( USHORT nNewTmpEnd )
+{
+ OSL_ENSURE( nNewTmpEnd <= Count(), "SwHistory::SetTmpEnd: out of bounds" );
+
+ USHORT nOld = Count() - m_nEndDiff;
+ m_nEndDiff = Count() - nNewTmpEnd;
+
+ // for every SwHistoryFlyCnt, call the Redo of its UndoObject.
+ // this saves the formats of the flys!
+ for ( USHORT n = nOld; n < nNewTmpEnd; n++ )
+ {
+ if ( HSTRY_FLYCNT == (*this)[ n ]->Which() )
+ {
+ static_cast<SwHistoryTxtFlyCnt*>((*this)[ n ])
+ ->GetUDelLFmt()->Redo();
+ }
+ }
+
+ return nOld;
+}
+
+void SwHistory::CopyFmtAttr( const SfxItemSet& rSet, ULONG nNodeIdx )
+{
+ if( rSet.Count() )
+ {
+ SfxItemIter aIter( rSet );
+ do {
+ if( (SfxPoolItem*)-1 != aIter.GetCurItem() )
+ {
+ const SfxPoolItem* pNew = aIter.GetCurItem();
+ Add( pNew, pNew, nNodeIdx );
+ }
+ if( aIter.IsAtEnd() )
+ break;
+ aIter.NextItem();
+ } while( TRUE );
+ }
+}
+
+void SwHistory::CopyAttr( SwpHints* pHts, ULONG nNodeIdx,
+ xub_StrLen nStart, xub_StrLen nEnd, bool bFields )
+{
+ if( !pHts )
+ return;
+
+ // copy all attributes of the TextNode in the area from nStart to nEnd
+ SwTxtAttr* pHt;
+ xub_StrLen nAttrStt;
+ const xub_StrLen * pEndIdx;
+ for( USHORT n = 0; n < pHts->Count(); n++ )
+ {
+ // BP: nAttrStt muss auch bei !pEndIdx gesetzt werden
+ pHt = pHts->GetTextHint(n);
+ nAttrStt = *pHt->GetStart();
+// JP: ???? wieso nAttrStt >= nEnd
+// if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt >= nEnd )
+ if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt > nEnd )
+ break;
+
+ // Flys und Ftn nie kopieren !!
+ BOOL bNextAttr = FALSE;
+ switch( pHt->Which() )
+ {
+ case RES_TXTATR_FIELD:
+ // keine Felder, .. kopieren ??
+ if( !bFields )
+ bNextAttr = TRUE;
+ break;
+ case RES_TXTATR_FLYCNT:
+ case RES_TXTATR_FTN:
+ bNextAttr = TRUE;
+ break;
+ }
+
+ if( bNextAttr )
+ continue;
+
+ // save all attributes that are somehow in this area
+ if ( nStart <= nAttrStt )
+ {
+ if ( nEnd > nAttrStt
+// JP: ???? wieso nAttrStt >= nEnd
+// || (nEnd == nAttrStt && (!pEndIdx || nEnd == pEndIdx->GetIndex()))
+ )
+ {
+ Add( pHt, nNodeIdx, false );
+ }
+ }
+ else if ( pEndIdx && nStart < *pEndIdx )
+ {
+ Add( pHt, nNodeIdx, false );
+ }
+ }
+}
+
+
+/*************************************************************************/
+
+// Klasse zum Registrieren der History am Node, Format, HintsArray, ...
+
+SwRegHistory::SwRegHistory( SwHistory* pHst )
+ : SwClient( 0 )
+ , m_pHistory( pHst )
+ , m_nNodeIndex( ULONG_MAX )
+{
+ _MakeSetWhichIds();
+}
+
+SwRegHistory::SwRegHistory( SwModify* pRegIn, const SwNode& rNd,
+ SwHistory* pHst )
+ : SwClient( pRegIn )
+ , m_pHistory( pHst )
+ , m_nNodeIndex( rNd.GetIndex() )
+{
+ _MakeSetWhichIds();
+}
+
+SwRegHistory::SwRegHistory( const SwNode& rNd, SwHistory* pHst )
+ : SwClient( 0 )
+ , m_pHistory( pHst )
+ , m_nNodeIndex( rNd.GetIndex() )
+{
+ _MakeSetWhichIds();
+}
+
+void SwRegHistory::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
+{
+ if ( m_pHistory && ( pOld || pNew ) )
+ {
+ if ( pNew->Which() < POOLATTR_END )
+ {
+ m_pHistory->Add( pOld, pNew, m_nNodeIndex );
+ }
+ else if ( RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SwHistoryHint* pNewHstr;
+ const SfxItemSet& rSet =
+ *static_cast<SwAttrSetChg*>(pOld)->GetChgSet();
+ if ( 1 < rSet.Count() )
+ {
+ pNewHstr =
+ new SwHistorySetAttrSet( rSet, m_nNodeIndex, m_WhichIdSet );
+ }
+ else
+ {
+ const SfxPoolItem* pItem = SfxItemIter( rSet ).FirstItem();
+ if ( m_WhichIdSet.Seek_Entry( pItem->Which() ) )
+ {
+ pNewHstr = new SwHistorySetFmt( pItem, m_nNodeIndex );
+ }
+ else
+ {
+ pNewHstr = new SwHistoryResetFmt( pItem, m_nNodeIndex );
+ }
+ }
+ m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() );
+ }
+ }
+}
+
+
+
+void SwRegHistory::AddHint( SwTxtAttr* pHt, const bool bNew )
+{
+ m_pHistory->Add( pHt, m_nNodeIndex, bNew );
+}
+
+
+bool SwRegHistory::InsertItems( const SfxItemSet& rSet,
+ xub_StrLen const nStart, xub_StrLen const nEnd, SetAttrMode const nFlags )
+{
+ if( !rSet.Count() )
+ return false;
+
+ SwTxtNode * const pTxtNode =
+ dynamic_cast<SwTxtNode *>(const_cast<SwModify *>(GetRegisteredIn()));
+
+ OSL_ENSURE(pTxtNode, "SwRegHistory not registered at text node?");
+ if (!pTxtNode)
+ return false;
+
+ if ( pTxtNode->GetpSwpHints() && m_pHistory )
+ {
+ pTxtNode->GetpSwpHints()->Register( this );
+ }
+
+ const bool bInserted = pTxtNode->SetAttr( rSet, nStart, nEnd, nFlags );
+
+ // Achtung: Durch das Einfuegen eines Attributs kann das Array
+ // geloescht werden!!! Wenn das einzufuegende zunaechst ein vorhandenes
+ // loescht, selbst aber nicht eingefuegt werden braucht, weil die
+ // Absatzattribute identisch sind( -> bForgetAttr in SwpHints::Insert )
+ if ( pTxtNode->GetpSwpHints() && m_pHistory )
+ {
+ pTxtNode->GetpSwpHints()->DeRegister();
+ }
+
+ if ( m_pHistory && bInserted )
+ {
+ SwHistoryHint* pNewHstr = new SwHistoryResetAttrSet( rSet,
+ pTxtNode->GetIndex(), nStart, nEnd );
+ // der NodeIndex kann verschoben sein !!
+
+ m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() );
+ }
+
+ return bInserted;
+}
+
+void SwRegHistory::RegisterInModify( SwModify* pRegIn, const SwNode& rNd )
+{
+ if ( m_pHistory && pRegIn )
+ {
+ pRegIn->Add( this );
+ m_nNodeIndex = rNd.GetIndex();
+ _MakeSetWhichIds();
+ }
+ else if ( m_WhichIdSet.Count() )
+ {
+ m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() );
+ }
+}
+
+void SwRegHistory::_MakeSetWhichIds()
+{
+ if (!m_pHistory) return;
+
+ if ( m_WhichIdSet.Count() )
+ {
+ m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() );
+ }
+
+ if( GetRegisteredIn() )
+ {
+ const SfxItemSet* pSet = 0;
+ if( GetRegisteredIn()->ISA( SwCntntNode ) )
+ {
+ pSet = static_cast<SwCntntNode*>(
+ const_cast<SwModify*>(GetRegisteredIn()))->GetpSwAttrSet();
+ }
+ else if ( GetRegisteredIn()->ISA( SwFmt ) )
+ {
+ pSet = &static_cast<SwFmt*>(
+ const_cast<SwModify*>(GetRegisteredIn()))->GetAttrSet();
+ }
+ if( pSet && pSet->Count() )
+ {
+ SfxItemIter aIter( *pSet );
+ USHORT nW = aIter.FirstItem()->Which();
+ while( TRUE )
+ {
+ m_WhichIdSet.Insert( nW );
+ if( aIter.IsAtEnd() )
+ break;
+ nW = aIter.NextItem()->Which();
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unattr.cxx b/sw/source/core/undo/unattr.cxx
new file mode 100644
index 000000000000..959fbbfb2748
--- /dev/null
+++ b/sw/source/core/undo/unattr.cxx
@@ -0,0 +1,1320 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTSSORT
+#include <hintids.hxx>
+#include <svx/svdmodel.hxx>
+#include <editeng/tstpitem.hxx>
+#include <svx/svdpage.hxx>
+#include <svl/itemiter.hxx>
+
+
+#include <fmtflcnt.hxx>
+#include <txtftn.hxx>
+#include <fmtornt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <frmfmt.hxx>
+#include <fmtcntnt.hxx>
+#include <ftnidx.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <swtblfmt.hxx>
+#include <undobj.hxx>
+#include <rolbck.hxx>
+#include <ndnotxt.hxx>
+#include <dcontact.hxx>
+#include <ftninfo.hxx>
+#include <redline.hxx>
+#include <section.hxx>
+#include <charfmt.hxx>
+
+
+
+inline SwDoc& SwUndoIter::GetDoc() const
+{ return *pAktPam->GetDoc(); }
+
+// -----------------------------------------------------
+
+SwUndoFmtAttrHelper::SwUndoFmtAttrHelper( SwFmt& rFmt, bool bSvDrwPt )
+ : SwClient( &rFmt )
+ , m_pUndo( 0 )
+ , m_bSaveDrawPt( bSvDrwPt )
+{
+}
+
+void SwUndoFmtAttrHelper::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
+{
+ if( pOld && pNew )
+ {
+ if( POOLATTR_END >= pOld->Which() )
+ {
+ if ( GetUndo() )
+ {
+ m_pUndo->PutAttr( *pOld );
+ }
+ else
+ {
+ m_pUndo.reset( new SwUndoFmtAttr( *pOld,
+ *static_cast<SwFmt*>(pRegisteredIn), m_bSaveDrawPt ) );
+ }
+ }
+ else if ( RES_ATTRSET_CHG == pOld->Which() )
+ {
+ if ( GetUndo() )
+ {
+ SfxItemIter aIter(
+ *(static_cast<SwAttrSetChg*>(pOld))->GetChgSet() );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while ( pItem )
+ {
+ m_pUndo->PutAttr( *pItem );
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ }
+ else
+ {
+ m_pUndo.reset( new SwUndoFmtAttr(
+ *static_cast<SwAttrSetChg*>(pOld)->GetChgSet(),
+ *static_cast<SwFmt*>(pRegisteredIn), m_bSaveDrawPt ) );
+ }
+ }
+ else
+ SwClient::Modify( pOld, pNew );
+ }
+ else
+ SwClient::Modify( pOld, pNew );
+}
+
+// -----------------------------------------------------
+
+SwUndoFmtAttr::SwUndoFmtAttr( const SfxItemSet& rOldSet,
+ SwFmt& rChgFmt,
+ bool bSaveDrawPt )
+ : SwUndo( UNDO_INSFMTATTR )
+ , m_pFmt( &rChgFmt )
+ // --> OD 2007-07-11 #i56253#
+ , m_pOldSet( new SfxItemSet( rOldSet ) )
+ // <--
+ , m_nNodeIndex( 0 )
+ , m_nFmtWhich( rChgFmt.Which() )
+ , m_bSaveDrawPt( bSaveDrawPt )
+{
+ Init();
+}
+
+SwUndoFmtAttr::SwUndoFmtAttr( const SfxPoolItem& rItem, SwFmt& rChgFmt,
+ bool bSaveDrawPt )
+ : SwUndo( UNDO_INSFMTATTR )
+ , m_pFmt( &rChgFmt )
+ , m_pOldSet( m_pFmt->GetAttrSet().Clone( FALSE ) )
+ , m_nNodeIndex( 0 )
+ , m_nFmtWhich( rChgFmt.Which() )
+ , m_bSaveDrawPt( bSaveDrawPt )
+{
+ m_pOldSet->Put( rItem );
+ Init();
+}
+
+void SwUndoFmtAttr::Init()
+{
+ // treat change of anchor specially
+ if ( SFX_ITEM_SET == m_pOldSet->GetItemState( RES_ANCHOR, FALSE ))
+ {
+ SaveFlyAnchor( m_bSaveDrawPt );
+ }
+ else if ( RES_FRMFMT == m_nFmtWhich )
+ {
+ SwDoc* pDoc = m_pFmt->GetDoc();
+ if (USHRT_MAX != pDoc->GetTblFrmFmts()->GetPos(
+ static_cast<const SwFrmFmtPtr>(m_pFmt)))
+ {
+ // Table Format: save table position, table formats are volatile!
+ SwTable * pTbl = static_cast<SwTable*>(
+ SwClientIter( *m_pFmt ).First( TYPE( SwTable )) );
+ if ( pTbl )
+ {
+ m_nNodeIndex = pTbl->GetTabSortBoxes()[ 0 ]->GetSttNd()
+ ->FindTableNode()->GetIndex();
+ }
+ }
+ else if (USHRT_MAX != pDoc->GetSections().GetPos(
+ static_cast<const SwSectionFmtPtr>(m_pFmt)))
+ {
+ m_nNodeIndex = m_pFmt->GetCntnt().GetCntntIdx()->GetIndex();
+ }
+ else if ( 0 != dynamic_cast< SwTableBoxFmt* >( m_pFmt ) )
+ {
+ SwTableBox* pTblBox = static_cast< SwTableBox* >(
+ SwClientIter( *m_pFmt ).First( TYPE( SwTableBox )));
+ if ( pTblBox )
+ {
+ m_nNodeIndex = pTblBox->GetSttIdx();
+ }
+ }
+ }
+}
+
+SwUndoFmtAttr::~SwUndoFmtAttr()
+{
+}
+
+void SwUndoFmtAttr::Undo( SwUndoIter& rUndoIter)
+{
+ // OD 2004-10-26 #i35443#
+ // Important note: <Undo(..)> also called by <ReDo(..)>
+
+ if ( !m_pOldSet.get() || !m_pFmt || !IsFmtInDoc( &rUndoIter.GetDoc() ))
+ return;
+
+ // --> OD 2004-10-26 #i35443# - If anchor attribute has been successfull
+ // restored, all other attributes are also restored.
+ // Thus, keep track of its restoration
+ bool bAnchorAttrRestored( false );
+ if ( SFX_ITEM_SET == m_pOldSet->GetItemState( RES_ANCHOR, FALSE ))
+ {
+ bAnchorAttrRestored = RestoreFlyAnchor( rUndoIter );
+ if ( bAnchorAttrRestored )
+ {
+ // Anchor attribute successfull restored.
+ // Thus, keep anchor position for redo
+ SaveFlyAnchor();
+ }
+ else
+ {
+ // Anchor attribute not restored due to invalid anchor position.
+ // Thus, delete anchor attribute.
+ m_pOldSet->ClearItem( RES_ANCHOR );
+ }
+ }
+
+ if ( !bAnchorAttrRestored )
+ // <--
+ {
+ SwUndoFmtAttrHelper aTmp( *m_pFmt, m_bSaveDrawPt );
+ m_pFmt->SetFmtAttr( *m_pOldSet );
+ if ( aTmp.GetUndo() )
+ {
+ // transfer ownership of helper object's old set
+ m_pOldSet = aTmp.GetUndo()->m_pOldSet;
+ }
+ else
+ {
+ m_pOldSet->ClearItem();
+ }
+
+ if ( RES_FLYFRMFMT == m_nFmtWhich || RES_DRAWFRMFMT == m_nFmtWhich )
+ {
+ rUndoIter.pSelFmt = static_cast<SwFrmFmt*>(m_pFmt);
+ }
+ }
+}
+
+bool SwUndoFmtAttr::IsFmtInDoc( SwDoc* pDoc )
+{
+ // search for the Format in the Document; if it does not exist any more,
+ // the attribute is not restored!
+ USHORT nPos = USHRT_MAX;
+ switch ( m_nFmtWhich )
+ {
+ case RES_TXTFMTCOLL:
+ nPos = pDoc->GetTxtFmtColls()->GetPos(
+ static_cast<const SwTxtFmtCollPtr>(m_pFmt) );
+ break;
+
+ case RES_GRFFMTCOLL:
+ nPos = pDoc->GetGrfFmtColls()->GetPos(
+ static_cast<const SwGrfFmtCollPtr>(m_pFmt) );
+ break;
+
+ case RES_CHRFMT:
+ nPos = pDoc->GetCharFmts()->GetPos(
+ static_cast<SwCharFmtPtr>(m_pFmt) );
+ break;
+
+ case RES_FRMFMT:
+ if ( m_nNodeIndex && (m_nNodeIndex < pDoc->GetNodes().Count()) )
+ {
+ SwNode* pNd = pDoc->GetNodes()[ m_nNodeIndex ];
+ if ( pNd->IsTableNode() )
+ {
+ m_pFmt =
+ static_cast<SwTableNode*>(pNd)->GetTable().GetFrmFmt();
+ nPos = 0;
+ break;
+ }
+ else if ( pNd->IsSectionNode() )
+ {
+ m_pFmt =
+ static_cast<SwSectionNode*>(pNd)->GetSection().GetFmt();
+ nPos = 0;
+ break;
+ }
+ else if ( pNd->IsStartNode() && (SwTableBoxStartNode ==
+ static_cast< SwStartNode* >(pNd)->GetStartNodeType()) )
+ {
+ SwTableNode* pTblNode = pNd->FindTableNode();
+ if ( pTblNode )
+ {
+ SwTableBox* pBox =
+ pTblNode->GetTable().GetTblBox( m_nNodeIndex );
+ if ( pBox )
+ {
+ m_pFmt = pBox->GetFrmFmt();
+ nPos = 0;
+ break;
+ }
+ }
+ }
+ }
+ // no break!
+ case RES_DRAWFRMFMT:
+ case RES_FLYFRMFMT:
+ nPos = pDoc->GetSpzFrmFmts()->GetPos(
+ static_cast<const SwFrmFmtPtr>(m_pFmt) );
+ if ( USHRT_MAX == nPos )
+ {
+ nPos = pDoc->GetFrmFmts()->GetPos(
+ static_cast<const SwFrmFmtPtr>(m_pFmt) );
+ }
+ break;
+ }
+
+ if ( USHRT_MAX == nPos )
+ {
+ // Format does not exist; reset
+ m_pFmt = 0;
+ }
+
+ return 0 != m_pFmt;
+}
+
+// prueft, ob es noch im Doc ist!
+SwFmt* SwUndoFmtAttr::GetFmt( SwDoc& rDoc )
+{
+ return m_pFmt && IsFmtInDoc( &rDoc ) ? m_pFmt : 0;
+}
+
+void SwUndoFmtAttr::Redo( SwUndoIter& rUndoIter)
+{
+ // --> OD 2004-10-26 #i35443# - Because the undo stores the attributes for
+ // redo, the same code as for <Undo(..)> can be applied for <Redo(..)>
+ Undo( rUndoIter );
+ // <--
+}
+
+void SwUndoFmtAttr::Repeat( SwUndoIter& rUndoIter)
+{
+ if ( !m_pOldSet.get() )
+ return;
+
+ if ( UNDO_INSFMTATTR == rUndoIter.GetLastUndoId())
+ {
+ SwUndoFmtAttr* pLast
+ = static_cast<SwUndoFmtAttr*>(rUndoIter.pLastUndoObj);
+ if (pLast->m_pOldSet.get() && pLast->m_pFmt)
+ {
+ return;
+ }
+ }
+
+ switch ( m_nFmtWhich )
+ {
+ case RES_GRFFMTCOLL:
+ {
+ SwNoTxtNode * pNd = rUndoIter.pAktPam->GetNode()->GetNoTxtNode();
+ if( pNd )
+ {
+ rUndoIter.GetDoc().SetAttr( m_pFmt->GetAttrSet(),
+ *pNd->GetFmtColl() );
+ }
+ }
+ break;
+
+ case RES_TXTFMTCOLL:
+ {
+ SwTxtNode * pNd = rUndoIter.pAktPam->GetNode()->GetTxtNode();
+ if( pNd )
+ {
+ rUndoIter.GetDoc().SetAttr( m_pFmt->GetAttrSet(),
+ *pNd->GetFmtColl() );
+ }
+ }
+ break;
+
+// case RES_CHRFMT:
+// case RES_FRMFMT:
+
+ case RES_FLYFRMFMT:
+ {
+ // erstal pruefen, ob der Cursor ueberhaupt in einem fliegenden
+ // Rahmen steht. Der Weg ist: suche in allen FlyFrmFormaten
+ // nach dem FlyCntnt-Attribut und teste ob der Cursor in der
+ // entsprechenden Section liegt.
+ SwFrmFmt* pFly = rUndoIter.pAktPam->GetNode()->GetFlyFmt();
+ if( pFly )
+ {
+ // Bug 43672: es duerfen nicht alle Attribute gesetzt werden!
+ if (SFX_ITEM_SET ==
+ m_pFmt->GetAttrSet().GetItemState( RES_CNTNT ))
+ {
+ SfxItemSet aTmpSet( m_pFmt->GetAttrSet() );
+ aTmpSet.ClearItem( RES_CNTNT );
+ if( aTmpSet.Count() )
+ rUndoIter.GetDoc().SetAttr( aTmpSet, *pFly );
+ }
+ else
+ {
+ rUndoIter.GetDoc().SetAttr( m_pFmt->GetAttrSet(), *pFly );
+ }
+ }
+ break;
+ }
+ }
+
+ rUndoIter.pLastUndoObj = this;
+}
+
+SwRewriter SwUndoFmtAttr::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ if (m_pFmt)
+ {
+ aRewriter.AddRule(UNDO_ARG1, m_pFmt->GetName());
+ }
+
+ return aRewriter;
+}
+
+void SwUndoFmtAttr::PutAttr( const SfxPoolItem& rItem )
+{
+ m_pOldSet->Put( rItem );
+ if ( RES_ANCHOR == rItem.Which() )
+ {
+ SaveFlyAnchor( m_bSaveDrawPt );
+ }
+}
+
+void SwUndoFmtAttr::SaveFlyAnchor( bool bSvDrwPt )
+{
+ // das Format ist gueltig, sonst wuerde man gar bis hier kommen
+ if( bSvDrwPt )
+ {
+ if ( RES_DRAWFRMFMT == m_pFmt->Which() )
+ {
+ Point aPt( static_cast<SwFrmFmt*>(m_pFmt)->FindSdrObject()
+ ->GetRelativePos() );
+ // store old value as attribute, to keep SwUndoFmtAttr small
+ m_pOldSet->Put( SwFmtFrmSize( ATT_VAR_SIZE, aPt.X(), aPt.Y() ) );
+ }
+/* else
+ {
+ pOldSet->Put( pFmt->GetVertOrient() );
+ pOldSet->Put( pFmt->GetHoriOrient() );
+ }
+*/ }
+
+ const SwFmtAnchor& rAnchor =
+ static_cast<const SwFmtAnchor&>( m_pOldSet->Get( RES_ANCHOR, FALSE ) );
+ if( !rAnchor.GetCntntAnchor() )
+ return;
+
+ xub_StrLen nCntnt = 0;
+ switch( rAnchor.GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ case FLY_AT_CHAR:
+ nCntnt = rAnchor.GetCntntAnchor()->nContent.GetIndex();
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ m_nNodeIndex = rAnchor.GetCntntAnchor()->nNode.GetIndex();
+ break;
+ default:
+ return;
+ }
+
+ SwFmtAnchor aAnchor( rAnchor.GetAnchorId(), nCntnt );
+ m_pOldSet->Put( aAnchor );
+}
+
+// --> OD 2004-10-26 #i35443# - Add return value, type <bool>.
+// Return value indicates, if anchor attribute is restored.
+// Note: If anchor attribute is restored, all other existing attributes
+// are also restored.
+bool SwUndoFmtAttr::RestoreFlyAnchor( SwUndoIter& rIter )
+{
+ SwDoc* pDoc = &rIter.GetDoc();
+ SwFlyFrmFmt* pFrmFmt = static_cast<SwFlyFrmFmt*>(m_pFmt);
+ const SwFmtAnchor& rAnchor =
+ static_cast<const SwFmtAnchor&>( m_pOldSet->Get( RES_ANCHOR, FALSE ) );
+
+ SwFmtAnchor aNewAnchor( rAnchor.GetAnchorId() );
+ if (FLY_AT_PAGE != rAnchor.GetAnchorId())
+ {
+ SwNode* pNd = pDoc->GetNodes()[ m_nNodeIndex ];
+
+ if ( (FLY_AT_FLY == rAnchor.GetAnchorId())
+ ? ( !pNd->IsStartNode() || (SwFlyStartNode !=
+ static_cast<SwStartNode*>(pNd)->GetStartNodeType()) )
+ : !pNd->IsTxtNode() )
+ {
+ // --> OD 2004-10-26 #i35443# - invalid position.
+ // Thus, anchor attribute not restored
+ return false;
+ // <--
+ }
+
+ SwPosition aPos( *pNd );
+ if ((FLY_AS_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()))
+ {
+ aPos.nContent.Assign( (SwTxtNode*)pNd, rAnchor.GetPageNum() );
+ if ( aPos.nContent.GetIndex() >
+ static_cast<SwTxtNode*>(pNd)->GetTxt().Len() )
+ {
+ // --> OD 2004-10-26 #i35443# - invalid position.
+ // Thus, anchor attribute not restored
+ return false;
+ // <--
+ }
+ }
+ aNewAnchor.SetAnchor( &aPos );
+ }
+ else
+ aNewAnchor.SetPageNum( rAnchor.GetPageNum() );
+
+ Point aDrawSavePt, aDrawOldPt;
+ if( pDoc->GetRootFrm() )
+ {
+ if( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ // den alten zwischengespeicherten Wert herausholen.
+ const SwFmtFrmSize& rOldSize = static_cast<const SwFmtFrmSize&>(
+ m_pOldSet->Get( RES_FRM_SIZE ) );
+ aDrawSavePt.X() = rOldSize.GetWidth();
+ aDrawSavePt.Y() = rOldSize.GetHeight();
+ m_pOldSet->ClearItem( RES_FRM_SIZE );
+
+ // den akt. wieder zwischenspeichern
+ aDrawOldPt = pFrmFmt->FindSdrObject()->GetRelativePos();
+//JP 08.10.97: ist laut AMA/MA nicht mehr noetig
+// pCont->DisconnectFromLayout();
+ }
+ else
+ {
+ pFrmFmt->DelFrms(); // delete Frms
+ }
+ }
+
+ const SwFmtAnchor &rOldAnch = pFrmFmt->GetAnchor();
+ // --> OD 2006-03-13 #i54336#
+ // Consider case, that as-character anchored object has moved its anchor position.
+ if (FLY_AS_CHAR == rOldAnch.GetAnchorId())
+ // <--
+ {
+ //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
+ //werden. Leider reisst dies neben den Frms auch noch das Format mit
+ //in sein Grab. Um dass zu unterbinden loesen wir vorher die
+ //Verbindung zwischen Attribut und Format.
+ const SwPosition *pPos = rOldAnch.GetCntntAnchor();
+ SwTxtNode *pTxtNode = (SwTxtNode*)&pPos->nNode.GetNode();
+ OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
+ OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ OSL_ENSURE( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFrmFmt,
+ "Wrong TxtFlyCnt-Hint." );
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
+
+ //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
+ //werden.
+ pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
+ }
+
+ {
+ m_pOldSet->Put( aNewAnchor );
+ SwUndoFmtAttrHelper aTmp( *m_pFmt, m_bSaveDrawPt );
+ m_pFmt->SetFmtAttr( *m_pOldSet );
+ if ( aTmp.GetUndo() )
+ {
+ m_nNodeIndex = aTmp.GetUndo()->m_nNodeIndex;
+ // transfer ownership of helper object's old set
+ m_pOldSet = aTmp.GetUndo()->m_pOldSet;
+ }
+ else
+ {
+ m_pOldSet->ClearItem();
+ }
+ }
+
+ if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ SwDrawContact *pCont =
+ static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
+ // das Draw-Model hat auch noch ein Undo-Object fuer die
+ // richtige Position vorbereitet; dieses ist aber relativ.
+ // Darum verhinder hier, das durch setzen des Ankers das
+ // Contact-Object seine Position aendert.
+//JP 08.10.97: ist laut AMA/MA nicht mehr noetig
+// pCont->ConnectToLayout();
+ SdrObject* pObj = pCont->GetMaster();
+
+ if( pCont->GetAnchorFrm() && !pObj->IsInserted() )
+ {
+ OSL_ENSURE( pDoc->GetDrawModel(), "RestoreFlyAnchor without DrawModel" );
+ pDoc->GetDrawModel()->GetPage( 0 )->InsertObject( pObj );
+ }
+ pObj->SetRelativePos( aDrawSavePt );
+
+ // den alten Wert wieder zwischenspeichern.
+ m_pOldSet->Put(
+ SwFmtFrmSize( ATT_VAR_SIZE, aDrawOldPt.X(), aDrawOldPt.Y() ) );
+ }
+
+ if (FLY_AS_CHAR == aNewAnchor.GetAnchorId())
+ {
+ const SwPosition* pPos = aNewAnchor.GetCntntAnchor();
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "no Text Node at position." );
+ SwFmtFlyCnt aFmt( pFrmFmt );
+ pTxtNd->InsertItem( aFmt, pPos->nContent.GetIndex(), 0 );
+ }
+
+
+ if( RES_DRAWFRMFMT != pFrmFmt->Which() )
+ pFrmFmt->MakeFrms();
+
+ rIter.pSelFmt = pFrmFmt;
+
+ // --> OD 2004-10-26 #i35443# - anchor attribute restored.
+ return true;
+ // <--
+}
+
+// -----------------------------------------------------
+
+// --> OD 2008-02-12 #newlistlevelattrs#
+SwUndoFmtResetAttr::SwUndoFmtResetAttr( SwFmt& rChangedFormat,
+ const USHORT nWhichId )
+ : SwUndo( UNDO_RESETATTR )
+ , m_pChangedFormat( &rChangedFormat )
+ , m_nWhichId( nWhichId )
+ , m_pOldItem( 0 )
+{
+ const SfxPoolItem* pItem = 0;
+ if (rChangedFormat.GetItemState( nWhichId, FALSE, &pItem ) == SFX_ITEM_SET)
+ {
+ m_pOldItem.reset( pItem->Clone() );
+ }
+}
+
+SwUndoFmtResetAttr::~SwUndoFmtResetAttr()
+{
+}
+
+void SwUndoFmtResetAttr::Undo( SwUndoIter& )
+{
+ if ( m_pOldItem.get() )
+ {
+ m_pChangedFormat->SetFmtAttr( *m_pOldItem );
+ }
+}
+
+void SwUndoFmtResetAttr::Redo( SwUndoIter& )
+{
+ if ( m_pOldItem.get() )
+ {
+ m_pChangedFormat->ResetFmtAttr( m_nWhichId );
+ }
+}
+// <--
+
+// -----------------------------------------------------
+
+SwUndoResetAttr::SwUndoResetAttr( const SwPaM& rRange, USHORT nFmtId )
+ : SwUndo( UNDO_RESETATTR ), SwUndRng( rRange )
+ , m_pHistory( new SwHistory )
+ , m_nFormatId( nFmtId )
+{
+}
+
+SwUndoResetAttr::SwUndoResetAttr( const SwPosition& rPos, USHORT nFmtId )
+ : SwUndo( UNDO_RESETATTR )
+ , m_pHistory( new SwHistory )
+ , m_nFormatId( nFmtId )
+{
+ nSttNode = nEndNode = rPos.nNode.GetIndex();
+ nSttCntnt = nEndCntnt = rPos.nContent.GetIndex();
+}
+
+SwUndoResetAttr::~SwUndoResetAttr()
+{
+}
+
+void SwUndoResetAttr::Undo( SwUndoIter& rUndoIter )
+{
+ // reset old values
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ m_pHistory->TmpRollback( &rDoc, 0 );
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+
+ if ((RES_CONDTXTFMTCOLL == m_nFormatId) &&
+ (nSttNode == nEndNode) && (nSttCntnt == nEndCntnt))
+ {
+ SwTxtNode* pTNd = rDoc.GetNodes()[ nSttNode ]->GetTxtNode();
+ if( pTNd )
+ {
+ SwIndex aIdx( pTNd, nSttCntnt );
+ pTNd->DontExpandFmt( aIdx, FALSE );
+ }
+ }
+
+ // setze noch den Cursor auf den Undo-Bereich
+ SetPaM( rUndoIter );
+}
+
+void SwUndoResetAttr::Redo( SwUndoIter& rUndoIter )
+{
+ // setze Attribut in dem Bereich:
+ SetPaM( rUndoIter );
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ rUndoIter.pLastUndoObj = 0;
+ SvUShortsSort* pIdArr = m_Ids.Count() ? &m_Ids : 0;
+
+ switch ( m_nFormatId )
+ {
+ case RES_CHRFMT:
+ rUndoIter.GetDoc().RstTxtAttrs( *rUndoIter.pAktPam );
+ break;
+ case RES_TXTFMTCOLL:
+ rUndoIter.GetDoc().ResetAttrs( *rUndoIter.pAktPam, FALSE, pIdArr );
+ break;
+ case RES_CONDTXTFMTCOLL:
+ rUndoIter.GetDoc().ResetAttrs( *rUndoIter.pAktPam, TRUE, pIdArr );
+
+ break;
+ case RES_TXTATR_TOXMARK:
+ // special treatment for TOXMarks
+ {
+ SwTOXMarks aArr;
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
+ SwPosition aPos( aIdx, SwIndex( aIdx.GetNode().GetCntntNode(),
+ nSttCntnt ));
+
+ USHORT nCnt = rDoc.GetCurTOXMark( aPos, aArr );
+ if( nCnt )
+ {
+ if( 1 < nCnt )
+ {
+ // search for the right one
+ SwHistoryHint* pHHint = (GetHistory())[ 0 ];
+ if( pHHint && HSTRY_SETTOXMARKHNT == pHHint->Which() )
+ {
+ while( nCnt )
+ {
+ if ( static_cast<SwHistorySetTOXMark*>(pHHint)
+ ->IsEqual( *aArr[ --nCnt ] ) )
+ {
+ ++nCnt;
+ break;
+ }
+ }
+ }
+ else
+ nCnt = 0;
+ }
+ // gefunden, also loeschen
+ if( nCnt-- )
+ {
+ rDoc.DeleteTOXMark( aArr[ nCnt ] );
+ }
+ }
+ }
+ break;
+ }
+ rUndoIter.pLastUndoObj = 0;
+}
+
+void SwUndoResetAttr::Repeat( SwUndoIter& rUndoIter )
+{
+ if ( (RES_FMT_BEGIN > m_nFormatId) ||
+ ( (UNDO_RESETATTR == rUndoIter.GetLastUndoId()) &&
+ (m_nFormatId == static_cast<SwUndoResetAttr*>(rUndoIter.pLastUndoObj)
+ ->m_nFormatId) ) )
+ {
+ return;
+ }
+
+ SvUShortsSort* pIdArr = m_Ids.Count() ? &m_Ids : 0;
+ switch ( m_nFormatId )
+ {
+ case RES_CHRFMT:
+ rUndoIter.GetDoc().RstTxtAttrs( *rUndoIter.pAktPam );
+ break;
+ case RES_TXTFMTCOLL:
+ rUndoIter.GetDoc().ResetAttrs( *rUndoIter.pAktPam, FALSE, pIdArr );
+ break;
+ case RES_CONDTXTFMTCOLL:
+ rUndoIter.GetDoc().ResetAttrs( *rUndoIter.pAktPam, TRUE, pIdArr );
+ break;
+ }
+ rUndoIter.pLastUndoObj = this;
+}
+
+
+void SwUndoResetAttr::SetAttrs( const SvUShortsSort& rArr )
+{
+ if ( m_Ids.Count() )
+ {
+ m_Ids.Remove( 0, m_Ids.Count() );
+ }
+ m_Ids.Insert( &rArr );
+}
+
+// -----------------------------------------------------
+
+
+SwUndoAttr::SwUndoAttr( const SwPaM& rRange, const SfxPoolItem& rAttr,
+ const SetAttrMode nFlags )
+ : SwUndo( UNDO_INSATTR ), SwUndRng( rRange )
+ , m_AttrSet( rRange.GetDoc()->GetAttrPool(), rAttr.Which(), rAttr.Which() )
+ , m_pHistory( new SwHistory )
+ , m_pRedlineData( 0 )
+ , m_pRedlineSaveData( 0 )
+ , m_nNodeIndex( ULONG_MAX )
+ , m_nInsertFlags( nFlags )
+{
+ m_AttrSet.Put( rAttr );
+}
+
+SwUndoAttr::SwUndoAttr( const SwPaM& rRange, const SfxItemSet& rSet,
+ const SetAttrMode nFlags )
+ : SwUndo( UNDO_INSATTR ), SwUndRng( rRange )
+ , m_AttrSet( rSet )
+ , m_pHistory( new SwHistory )
+ , m_pRedlineData( 0 )
+ , m_pRedlineSaveData( 0 )
+ , m_nNodeIndex( ULONG_MAX )
+ , m_nInsertFlags( nFlags )
+{
+}
+
+SwUndoAttr::~SwUndoAttr()
+{
+}
+
+void SwUndoAttr::SaveRedlineData( const SwPaM& rPam, BOOL bIsCntnt )
+{
+ SwDoc* pDoc = rPam.GetDoc();
+ if ( pDoc->IsRedlineOn() )
+ {
+ m_pRedlineData.reset( new SwRedlineData( bIsCntnt
+ ? nsRedlineType_t::REDLINE_INSERT
+ : nsRedlineType_t::REDLINE_FORMAT,
+ pDoc->GetRedlineAuthor() ) );
+ }
+
+ m_pRedlineSaveData.reset( new SwRedlineSaveDatas );
+ if ( !FillSaveDataForFmt( rPam, *m_pRedlineSaveData ))
+ {
+ m_pRedlineSaveData.reset(0);
+ }
+
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ if ( bIsCntnt )
+ {
+ m_nNodeIndex = rPam.GetPoint()->nNode.GetIndex();
+ }
+}
+
+void SwUndoAttr::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc* pDoc = &rUndoIter.GetDoc();
+
+ RemoveIdx( *pDoc );
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ SwPaM& rPam = *rUndoIter.pAktPam;
+ if ( ULONG_MAX != m_nNodeIndex )
+ {
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = m_nNodeIndex;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), nSttCntnt );
+ rPam.SetMark();
+ rPam.GetPoint()->nContent++;
+ pDoc->DeleteRedline( rPam, false, USHRT_MAX );
+ }
+ else
+ {
+ // alle Format-Redlines entfernen, werden ggfs. neu gesetzt
+ SetPaM( rUndoIter );
+ pDoc->DeleteRedline( rPam, false, nsRedlineType_t::REDLINE_FORMAT );
+ if ( m_pRedlineSaveData.get() )
+ {
+ SetSaveData( *pDoc, *m_pRedlineSaveData );
+ }
+ }
+ }
+
+ const bool bToLast = (1 == m_AttrSet.Count())
+ && (RES_TXTATR_FIELD <= *m_AttrSet.GetRanges())
+ && (*m_AttrSet.GetRanges() <= RES_TXTATR_FTN);
+
+ // restore old values
+ m_pHistory->TmpRollback( pDoc, 0, !bToLast );
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+
+ // set cursor onto Undo area
+ SetPaM( rUndoIter );
+}
+
+int lcl_HasEqualItems( const SfxItemSet& rSet1, const SfxItemSet& rSet2 )
+{
+ int nRet = -1;
+ SfxItemIter aIter1( rSet1 ), aIter2( rSet2 );
+ const SfxPoolItem *pI1 = aIter1.FirstItem(), *pI2 = aIter2.FirstItem();
+
+ while( pI1 && pI2 )
+ {
+ if( pI1->Which() != pI2->Which() ||
+ aIter1.IsAtEnd() != aIter2.IsAtEnd() )
+ {
+ nRet = 0;
+ break;
+ }
+ if( aIter1.IsAtEnd() )
+ break;
+ pI1 = aIter1.NextItem();
+ pI2 = aIter2.NextItem();
+ }
+ return nRet;
+}
+
+void SwUndoAttr::Repeat( SwUndoIter& rUndoIter )
+{
+ if ( UNDO_INSATTR == rUndoIter.GetLastUndoId() )
+ {
+ SwUndoAttr* pLast = static_cast<SwUndoAttr*>(rUndoIter.pLastUndoObj);
+ if ((pLast->m_AttrSet.Count() == m_AttrSet.Count()) &&
+ (pLast->m_nInsertFlags == m_nInsertFlags ) &&
+ lcl_HasEqualItems( m_AttrSet, pLast->m_AttrSet ))
+ {
+ return;
+ }
+ }
+
+
+ // RefMarks are not repeat capable
+ if ( SFX_ITEM_SET != m_AttrSet.GetItemState( RES_TXTATR_REFMARK, FALSE ) )
+ {
+ rUndoIter.GetDoc().InsertItemSet( *rUndoIter.pAktPam,
+ m_AttrSet, m_nInsertFlags );
+ }
+ else if ( 1 < m_AttrSet.Count() )
+ {
+ SfxItemSet aTmpSet( m_AttrSet );
+ aTmpSet.ClearItem( RES_TXTATR_REFMARK );
+ rUndoIter.GetDoc().InsertItemSet( *rUndoIter.pAktPam,
+ aTmpSet, m_nInsertFlags );
+ }
+ rUndoIter.pLastUndoObj = this;
+}
+
+void SwUndoAttr::Redo( SwUndoIter& rUndoIter )
+{
+ // setze Attribut in dem Bereich:
+ SetPaM( rUndoIter );
+ SwPaM& rPam = *rUndoIter.pAktPam;
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ if ( m_pRedlineData.get() &&
+ IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern(static_cast<RedlineMode_t>(
+ eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+ rDoc.InsertItemSet( rPam, m_AttrSet, m_nInsertFlags );
+
+ if ( ULONG_MAX != m_nNodeIndex )
+ {
+ rPam.SetMark();
+ if ( rPam.Move( fnMoveBackward ) )
+ {
+ rDoc.AppendRedline( new SwRedline( *m_pRedlineData, rPam ),
+ true);
+ }
+ rPam.DeleteMark();
+ }
+ else
+ {
+ rDoc.AppendRedline( new SwRedline( *m_pRedlineData, rPam ), true);
+ }
+
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else
+ {
+ rDoc.InsertItemSet( rPam, m_AttrSet, m_nInsertFlags );
+ }
+
+ rUndoIter.pLastUndoObj = 0;
+}
+
+
+void SwUndoAttr::RemoveIdx( SwDoc& rDoc )
+{
+ if ( SFX_ITEM_SET != m_AttrSet.GetItemState( RES_TXTATR_FTN, FALSE ))
+ return ;
+
+ SwHistoryHint* pHstHnt;
+ SwNodes& rNds = rDoc.GetNodes();
+ for ( USHORT n = 0; n < m_pHistory->Count(); ++n )
+ {
+ xub_StrLen nCntnt = 0;
+ ULONG nNode = 0;
+ pHstHnt = (*m_pHistory)[ n ];
+ switch ( pHstHnt->Which() )
+ {
+ case HSTRY_RESETTXTHNT:
+ {
+ SwHistoryResetTxt * pHistoryHint
+ = static_cast<SwHistoryResetTxt*>(pHstHnt);
+ if ( RES_TXTATR_FTN == pHistoryHint->GetWhich() )
+ {
+ nNode = pHistoryHint->GetNode();
+ nCntnt = pHistoryHint->GetCntnt();
+ }
+ }
+ break;
+
+ case HSTRY_RESETATTRSET:
+ {
+ SwHistoryResetAttrSet * pHistoryHint
+ = static_cast<SwHistoryResetAttrSet*>(pHstHnt);
+ nCntnt = pHistoryHint->GetCntnt();
+ if ( STRING_MAXLEN != nCntnt )
+ {
+ const SvUShorts& rArr = pHistoryHint->GetArr();
+ for ( USHORT i = rArr.Count(); i; )
+ {
+ if ( RES_TXTATR_FTN == rArr[ --i ] )
+ {
+ nNode = pHistoryHint->GetNode();
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if( nNode )
+ {
+ SwTxtNode* pTxtNd = rNds[ nNode ]->GetTxtNode();
+ if( pTxtNd )
+ {
+ SwTxtAttr *const pTxtHt =
+ pTxtNd->GetTxtAttrForCharAt(nCntnt, RES_TXTATR_FTN);
+ if( pTxtHt )
+ {
+ // ok, dann hole mal die Werte
+ SwTxtFtn* pFtn = static_cast<SwTxtFtn*>(pTxtHt);
+ RemoveIdxFromSection( rDoc, pFtn->GetStartNode()->GetIndex() );
+ return ;
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------
+
+SwUndoDefaultAttr::SwUndoDefaultAttr( const SfxItemSet& rSet )
+ : SwUndo( UNDO_SETDEFTATTR )
+ , m_pOldSet( 0 )
+ , m_pTabStop( 0 )
+{
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_PARATR_TABSTOP, FALSE, &pItem ) )
+ {
+ // store separately, because it may change!
+ m_pTabStop.reset( static_cast<SvxTabStopItem*>(pItem->Clone()) );
+ if ( 1 != rSet.Count() ) // are there more attributes?
+ {
+ m_pOldSet.reset( new SfxItemSet( rSet ) );
+ }
+ }
+ else
+ {
+ m_pOldSet.reset( new SfxItemSet( rSet ) );
+ }
+}
+
+SwUndoDefaultAttr::~SwUndoDefaultAttr()
+{
+}
+
+void SwUndoDefaultAttr::Undo( SwUndoIter& rUndoIter)
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ if ( m_pOldSet.get() )
+ {
+ SwUndoFmtAttrHelper aTmp(
+ *const_cast<SwTxtFmtColl*>(rDoc.GetDfltTxtFmtColl()) );
+ rDoc.SetDefault( *m_pOldSet );
+ m_pOldSet.reset( 0 );
+ if ( aTmp.GetUndo() )
+ {
+ // transfer ownership of helper object's old set
+ m_pOldSet = aTmp.GetUndo()->m_pOldSet;
+ }
+ }
+ if ( m_pTabStop.get() )
+ {
+ SvxTabStopItem* pOld = static_cast<SvxTabStopItem*>(
+ rDoc.GetDefault( RES_PARATR_TABSTOP ).Clone() );
+ rDoc.SetDefault( *m_pTabStop );
+ m_pTabStop.reset( pOld );
+ }
+}
+
+void SwUndoDefaultAttr::Redo( SwUndoIter& rUndoIter)
+{
+ Undo( rUndoIter );
+}
+
+// -----------------------------------------------------
+
+SwUndoMoveLeftMargin::SwUndoMoveLeftMargin(
+ const SwPaM& rPam, BOOL bFlag, BOOL bMod )
+ : SwUndo( bFlag ? UNDO_INC_LEFTMARGIN : UNDO_DEC_LEFTMARGIN )
+ , SwUndRng( rPam )
+ , m_pHistory( new SwHistory )
+ , m_bModulus( bMod )
+{
+}
+
+SwUndoMoveLeftMargin::~SwUndoMoveLeftMargin()
+{
+}
+
+void SwUndoMoveLeftMargin::Undo( SwUndoIter& rIter )
+{
+ SwDoc* pDoc = &rIter.GetDoc();
+ BOOL bUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+
+ // restore old values
+ m_pHistory->TmpRollback( pDoc, 0 );
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+
+ pDoc->DoUndo( bUndo );
+ SetPaM( rIter );
+}
+
+void SwUndoMoveLeftMargin::Redo( SwUndoIter& rIter )
+{
+ SwDoc* pDoc = &rIter.GetDoc();
+ SetPaM( rIter );
+ pDoc->MoveLeftMargin( *rIter.pAktPam, GetId() == UNDO_INC_LEFTMARGIN,
+ m_bModulus );
+}
+
+void SwUndoMoveLeftMargin::Repeat( SwUndoIter& rIter )
+{
+ SwDoc* pDoc = &rIter.GetDoc();
+ pDoc->MoveLeftMargin( *rIter.pAktPam, GetId() == UNDO_INC_LEFTMARGIN,
+ m_bModulus );
+ rIter.pLastUndoObj = this;
+}
+
+// -----------------------------------------------------
+
+SwUndoChangeFootNote::SwUndoChangeFootNote(
+ const SwPaM& rRange, const String& rTxt,
+ USHORT nNum, bool bIsEndNote )
+ : SwUndo( UNDO_CHGFTN ), SwUndRng( rRange )
+ , m_pHistory( new SwHistory() )
+ , m_Text( rTxt )
+ , m_nNumber( nNum )
+ , m_bEndNote( bIsEndNote )
+{
+}
+
+SwUndoChangeFootNote::~SwUndoChangeFootNote()
+{
+}
+
+void SwUndoChangeFootNote::Undo( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+ SetPaM( rIter );
+
+ BOOL bUndo = rDoc.DoesUndo();
+ rDoc.DoUndo( FALSE );
+
+ m_pHistory->TmpRollback( &rDoc, 0 );
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+
+ rDoc.GetFtnIdxs().UpdateAllFtn();
+
+ SetPaM( rIter );
+ rDoc.DoUndo( bUndo );
+}
+
+void SwUndoChangeFootNote::Redo( SwUndoIter& rIter )
+{
+ SetPaM( rIter );
+ rIter.GetDoc().SetCurFtn( *rIter.pAktPam, m_Text, m_nNumber, m_bEndNote );
+ SetPaM( rIter );
+}
+
+void SwUndoChangeFootNote::Repeat( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+ rDoc.SetCurFtn( *rIter.pAktPam, m_Text, m_nNumber, m_bEndNote );
+ rIter.pLastUndoObj = this;
+}
+
+
+// -----------------------------------------------------
+
+
+SwUndoFootNoteInfo::SwUndoFootNoteInfo( const SwFtnInfo &rInfo )
+ : SwUndo( UNDO_FTNINFO )
+ , m_pFootNoteInfo( new SwFtnInfo( rInfo ) )
+{
+}
+
+SwUndoFootNoteInfo::~SwUndoFootNoteInfo()
+{
+}
+
+void SwUndoFootNoteInfo::Undo( SwUndoIter &rIter )
+{
+ SwDoc &rDoc = rIter.GetDoc();
+ SwFtnInfo *pInf = new SwFtnInfo( rDoc.GetFtnInfo() );
+ rDoc.SetFtnInfo( *m_pFootNoteInfo );
+ m_pFootNoteInfo.reset( pInf );
+}
+
+void SwUndoFootNoteInfo::Redo( SwUndoIter &rIter )
+{
+ SwDoc &rDoc = rIter.GetDoc();
+ SwFtnInfo *pInf = new SwFtnInfo( rDoc.GetFtnInfo() );
+ rDoc.SetFtnInfo( *m_pFootNoteInfo );
+ m_pFootNoteInfo.reset( pInf );
+}
+
+
+// -----------------------------------------------------
+
+SwUndoEndNoteInfo::SwUndoEndNoteInfo( const SwEndNoteInfo &rInfo )
+ : SwUndo( UNDO_FTNINFO )
+ , m_pEndNoteInfo( new SwEndNoteInfo( rInfo ) )
+{
+}
+
+SwUndoEndNoteInfo::~SwUndoEndNoteInfo()
+{
+}
+
+void SwUndoEndNoteInfo::Undo( SwUndoIter &rIter )
+{
+ SwDoc &rDoc = rIter.GetDoc();
+ SwEndNoteInfo *pInf = new SwEndNoteInfo( rDoc.GetEndNoteInfo() );
+ rDoc.SetEndNoteInfo( *m_pEndNoteInfo );
+ m_pEndNoteInfo.reset( pInf );
+}
+
+void SwUndoEndNoteInfo::Redo( SwUndoIter &rIter )
+{
+ SwDoc &rDoc = rIter.GetDoc();
+ SwEndNoteInfo *pInf = new SwEndNoteInfo( rDoc.GetEndNoteInfo() );
+ rDoc.SetEndNoteInfo( *m_pEndNoteInfo );
+ m_pEndNoteInfo.reset( pInf );
+}
+
+// -----------------------------------------------------
+
+SwUndoDontExpandFmt::SwUndoDontExpandFmt( const SwPosition& rPos )
+ : SwUndo( UNDO_DONTEXPAND )
+ , m_nNodeIndex( rPos.nNode.GetIndex() )
+ , m_nContentIndex( rPos.nContent.GetIndex() )
+{
+}
+
+void SwUndoDontExpandFmt::Undo( SwUndoIter& rIter )
+{
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+
+ SwPosition& rPos = *pPam->GetPoint();
+ rPos.nNode = m_nNodeIndex;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), m_nContentIndex);
+ pDoc->DontExpandFmt( rPos, FALSE );
+}
+
+
+void SwUndoDontExpandFmt::Redo( SwUndoIter& rIter )
+{
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+
+ SwPosition& rPos = *pPam->GetPoint();
+ rPos.nNode = m_nNodeIndex;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), m_nContentIndex);
+ pDoc->DontExpandFmt( rPos );
+}
+
+void SwUndoDontExpandFmt::Repeat( SwUndoIter& rIter )
+{
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+ pDoc->DontExpandFmt( *pPam->GetPoint() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unbkmk.cxx b/sw/source/core/undo/unbkmk.cxx
new file mode 100644
index 000000000000..817f5d242ac5
--- /dev/null
+++ b/sw/source/core/undo/unbkmk.cxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "doc.hxx"
+#include "docary.hxx"
+#include "swundo.hxx" // fuer die UndoIds
+#include "pam.hxx"
+
+#include "undobj.hxx"
+#include "IMark.hxx"
+#include "rolbck.hxx"
+
+#include "SwRewriter.hxx"
+
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+
+SwUndoBookmark::SwUndoBookmark( SwUndoId nUndoId,
+ const ::sw::mark::IMark& rBkmk )
+ : SwUndo( nUndoId )
+ , m_pHistoryBookmark(new SwHistoryBookmark(rBkmk, true, rBkmk.IsExpanded()))
+{
+}
+
+SwUndoBookmark::~SwUndoBookmark()
+{
+}
+
+void SwUndoBookmark::SetInDoc( SwDoc* pDoc )
+{
+ m_pHistoryBookmark->SetInDoc( pDoc, false );
+}
+
+
+void SwUndoBookmark::ResetInDoc( SwDoc* pDoc )
+{
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ for (IDocumentMarkAccess::const_iterator_t ppBkmk =
+ pMarkAccess->getMarksBegin();
+ ppBkmk != pMarkAccess->getMarksEnd();
+ ++ppBkmk)
+ {
+ if ( m_pHistoryBookmark->IsEqualBookmark( **ppBkmk ) )
+ {
+ pMarkAccess->deleteMark( ppBkmk );
+ break;
+ }
+ }
+}
+
+SwRewriter SwUndoBookmark::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ aResult.AddRule(UNDO_ARG1, m_pHistoryBookmark->GetName());
+
+ return aResult;
+}
+
+//----------------------------------------------------------------------
+
+
+SwUndoInsBookmark::SwUndoInsBookmark( const ::sw::mark::IMark& rBkmk )
+ : SwUndoBookmark( UNDO_INSBOOKMARK, rBkmk )
+{
+}
+
+
+void SwUndoInsBookmark::Undo( SwUndoIter& rUndoIter )
+{
+ ResetInDoc( &rUndoIter.GetDoc() );
+}
+
+
+void SwUndoInsBookmark::Redo( SwUndoIter& rUndoIter )
+{
+ SetInDoc( &rUndoIter.GetDoc() );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
new file mode 100644
index 000000000000..480d9243f8b3
--- /dev/null
+++ b/sw/source/core/undo/undel.cxx
@@ -0,0 +1,1008 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <unotools/charclass.hxx>
+#include <editeng/brkitem.hxx>
+#include <fmtpdsc.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <doc.hxx>
+#include <swtable.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <rolbck.hxx>
+#include <poolfmt.hxx>
+#include <mvsave.hxx>
+#include <redline.hxx>
+#include <docary.hxx>
+#include <sfx2/app.hxx>
+
+#include <fldbas.hxx>
+#include <fmtfld.hxx>
+#include <comcore.hrc> // #111827#
+#include <undo.hrc>
+
+// using namespace comphelper;
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+
+// DELETE
+/* lcl_MakeAutoFrms has to call MakeFrms for objects bounded "AtChar" ( == AUTO ),
+ if the anchor frame has be moved via _MoveNodes(..) and DelFrms(..)
+*/
+
+void lcl_MakeAutoFrms( const SwSpzFrmFmts& rSpzArr, ULONG nMovedIndex )
+{
+ if( rSpzArr.Count() )
+ {
+ SwFlyFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+ for( USHORT n = 0; n < rSpzArr.Count(); ++n )
+ {
+ pFmt = (SwFlyFrmFmt*)rSpzArr[n];
+ pAnchor = &pFmt->GetAnchor();
+ if (pAnchor->GetAnchorId() == FLY_AT_CHAR)
+ {
+ const SwPosition* pAPos = pAnchor->GetCntntAnchor();
+ if( pAPos && nMovedIndex == pAPos->nNode.GetIndex() )
+ pFmt->MakeFrms();
+ }
+ }
+ }
+}
+
+/*
+SwUndoDelete has to perform a deletion and to record anything that is needed to restore the
+situation before the deletion. Unfortunately a part of the deletion will be done after calling
+this Ctor, this has to be kept in mind! In this Ctor only the complete paragraphs will be deleted,
+the joining of the first and last paragraph of the selection will be handled outside this function.
+Here are the main steps of the function:
+1. Deletion/recording of content indizes of the selection: footnotes, fly frames and bookmarks
+Step 1 could shift all nodes by deletion of footnotes => nNdDiff will be set.
+2. If the paragraph where the selection ends, is the last content of a section so that this
+section becomes empty when the paragraphs will be joined we have to do some smart actions ;-)
+The paragraph will be moved outside the section and replaced by a dummy text node, the complete
+section will be deleted in step 3. The difference between replacement dummy and original is
+nReplacementDummy.
+3. Moving complete selected nodes into the UndoArray. Before this happens the selection has to be
+extended if there are sections which would become empty otherwise. BTW: sections will be moved into
+the UndoArray if they are complete part of the selection. Sections starting or ending outside of the
+selection will not be removed from the DocNodeArray even they got a "dummy"-copy in the UndoArray.
+4. We have to anticipate the joining of the two paragraphs if the start paragraph is inside a
+section and the end paragraph not. Then we have to move the paragraph into this section and to
+record this in nSectDiff.
+*/
+
+SwUndoDelete::SwUndoDelete( SwPaM& rPam, BOOL bFullPara, BOOL bCalledByTblCpy )
+ : SwUndo(UNDO_DELETE), SwUndRng( rPam ),
+ pMvStt( 0 ), pSttStr(0), pEndStr(0), pRedlData(0), pRedlSaveData(0),
+ nNode(0), nNdDiff(0), nSectDiff(0), nReplaceDummy(0), nSetPos(0),
+ bGroup( FALSE ), bBackSp( FALSE ), bJoinNext( FALSE ), bTblDelLastNd( FALSE ),
+ bDelFullPara( bFullPara ), bResetPgDesc( FALSE ), bResetPgBrk( FALSE ),
+ bFromTableCopy( bCalledByTblCpy )
+{
+ bDelFullPara = bFullPara; // This is set e.g. if an empty paragraph before a table is deleted
+
+ bCacheComment = false;
+
+ SwDoc * pDoc = rPam.GetDoc();
+
+ if( !pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() )
+ {
+ pRedlSaveData = new SwRedlineSaveDatas;
+ if( !FillSaveData( rPam, *pRedlSaveData ))
+ delete pRedlSaveData, pRedlSaveData = 0;
+ }
+
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ // loesche erstmal alle Fussnoten
+ const SwPosition *pStt = rPam.Start(),
+ *pEnd = rPam.GetPoint() == pStt
+ ? rPam.GetMark()
+ : rPam.GetPoint();
+
+ // Step 1. deletion/record of content indizes
+ if( bDelFullPara )
+ {
+ OSL_ENSURE( rPam.HasMark(), "PaM ohne Mark" );
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
+ DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
+
+ BOOL bDoesUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+ _DelBookmarks(pStt->nNode, pEnd->nNode);
+ pDoc->DoUndo( bDoesUndo );
+ }
+ else
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+
+ nSetPos = pHistory ? pHistory->Count() : 0;
+
+ // wurde schon was geloescht ??
+ nNdDiff = nSttNode - pStt->nNode.GetIndex();
+
+ bJoinNext = !bFullPara && pEnd == rPam.GetPoint();
+ bBackSp = !bFullPara && !bJoinNext;
+
+ SwTxtNode *pSttTxtNd = 0, *pEndTxtNd = 0;
+ if( !bFullPara )
+ {
+ pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ pEndTxtNd = nSttNode == nEndNode
+ ? pSttTxtNd
+ : pEnd->nNode.GetNode().GetTxtNode();
+ }
+
+ BOOL bMoveNds = *pStt == *pEnd // noch ein Bereich vorhanden ??
+ ? FALSE
+ : ( SaveCntnt( pStt, pEnd, pSttTxtNd, pEndTxtNd ) || bFromTableCopy );
+
+ if( pSttTxtNd && pEndTxtNd && pSttTxtNd != pEndTxtNd )
+ {
+ // zwei unterschiedliche TextNodes, also speicher noch die
+ // TextFormatCollection fuers
+ pHistory->Add( pSttTxtNd->GetTxtColl(),pStt->nNode.GetIndex(), ND_TEXTNODE );
+ pHistory->Add( pEndTxtNd->GetTxtColl(),pEnd->nNode.GetIndex(), ND_TEXTNODE );
+
+ if( !bJoinNext ) // Selection von Unten nach Oben
+ {
+ // Beim JoinPrev() werden die AUTO-PageBreak's richtig
+ // kopiert. Um diese beim Undo wieder herzustellen, muss das
+ // Auto-PageBreak aus dem EndNode zurueckgesetzt werden.
+ // - fuer die PageDesc, ColBreak dito !
+ if( pEndTxtNd->HasSwAttrSet() )
+ {
+ SwRegHistory aRegHist( *pEndTxtNd, pHistory );
+ if( SFX_ITEM_SET == pEndTxtNd->GetpSwAttrSet()->GetItemState(
+ RES_BREAK, FALSE ) )
+ pEndTxtNd->ResetAttr( RES_BREAK );
+ if( pEndTxtNd->HasSwAttrSet() &&
+ SFX_ITEM_SET == pEndTxtNd->GetpSwAttrSet()->GetItemState(
+ RES_PAGEDESC, FALSE ) )
+ pEndTxtNd->ResetAttr( RES_PAGEDESC );
+ }
+ }
+ }
+
+
+ // verschiebe jetzt noch den PaM !!!
+ // der SPoint steht am Anfang der SSelection
+ if( pEnd == rPam.GetPoint() && ( !bFullPara || pSttTxtNd || pEndTxtNd ) )
+ rPam.Exchange();
+
+ if( !pSttTxtNd && !pEndTxtNd )
+ rPam.GetPoint()->nNode--;
+ rPam.DeleteMark(); // der SPoint ist aus dem Bereich
+
+ if( !pEndTxtNd )
+ nEndCntnt = 0;
+ if( !pSttTxtNd )
+ nSttCntnt = 0;
+
+ if( bMoveNds ) // sind noch Nodes zu verschieben ?
+ {
+ SwNodes& rNds = (SwNodes&)*pDoc->GetUndoNds();
+ SwNodes& rDocNds = pDoc->GetNodes();
+ SwNodeRange aRg( rDocNds, nSttNode - nNdDiff,
+ rDocNds, nEndNode - nNdDiff );
+ if( !bFullPara && !pEndTxtNd &&
+ &aRg.aEnd.GetNode() != &pDoc->GetNodes().GetEndOfContent() )
+ {
+ SwNode* pNode = aRg.aEnd.GetNode().StartOfSectionNode();
+ if( pNode->GetIndex() >= nSttNode - nNdDiff )
+ aRg.aEnd++; // Deletion of a complete table
+ }
+ SwNode* pTmpNd;
+ // Step 2: Expand selection if necessary
+ if( bJoinNext || bFullPara )
+ {
+ // If all content of a section will be moved into Undo,
+ // the section itself should be moved complete.
+ while( aRg.aEnd.GetIndex() + 2 < rDocNds.Count() &&
+ ( (pTmpNd = rDocNds[ aRg.aEnd.GetIndex()+1 ])->IsEndNode() &&
+ pTmpNd->StartOfSectionNode()->IsSectionNode() &&
+ pTmpNd->StartOfSectionNode()->GetIndex() >= aRg.aStart.GetIndex() ) )
+ aRg.aEnd++;
+ nReplaceDummy = aRg.aEnd.GetIndex() + nNdDiff - nEndNode;
+ if( nReplaceDummy )
+ { // The selection has been expanded, because
+ aRg.aEnd++;
+ if( pEndTxtNd )
+ {
+ // The end text node has to leave the (expanded) selection
+ // The dummy is needed because _MoveNodes deletes empty sections
+ ++nReplaceDummy;
+ SwNodeRange aMvRg( *pEndTxtNd, 0, *pEndTxtNd, 1 );
+ SwPosition aSplitPos( *pEndTxtNd );
+ BOOL bDoesUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+ pDoc->SplitNode( aSplitPos, false );
+ rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aEnd, TRUE );
+ pDoc->DoUndo( bDoesUndo );
+ aRg.aEnd--;
+ }
+ else
+ nReplaceDummy = 0;
+ }
+ }
+ if( bBackSp || bFullPara )
+ {
+ //See above, the selection has to expanded if there are "nearly empty" sections
+ // and a replacement dummy has to be set if needed.
+ while( 1 < aRg.aStart.GetIndex() &&
+ ( (pTmpNd = rDocNds[ aRg.aStart.GetIndex()-1 ])->IsSectionNode() &&
+ pTmpNd->EndOfSectionIndex() < aRg.aEnd.GetIndex() ) )
+ aRg.aStart--;
+ if( pSttTxtNd )
+ {
+ nReplaceDummy = nSttNode - nNdDiff - aRg.aStart.GetIndex();
+ if( nReplaceDummy )
+ {
+ SwNodeRange aMvRg( *pSttTxtNd, 0, *pSttTxtNd, 1 );
+ SwPosition aSplitPos( *pSttTxtNd );
+ BOOL bDoesUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+ pDoc->SplitNode( aSplitPos, false );
+ rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aStart, TRUE );
+ pDoc->DoUndo( bDoesUndo );
+ aRg.aStart--;
+ }
+ }
+ }
+
+ if( bFromTableCopy )
+ {
+ if( !pEndTxtNd )
+ {
+ if( pSttTxtNd )
+ aRg.aStart++;
+ else if( !bFullPara && !aRg.aEnd.GetNode().IsCntntNode() )
+ aRg.aEnd--;
+ }
+ }
+ else if( pSttTxtNd && ( pEndTxtNd || pSttTxtNd->GetTxt().Len() ) )
+ aRg.aStart++;
+
+ // Step 3: Moving into UndoArray...
+ nNode = rNds.GetEndOfContent().GetIndex();
+ rDocNds._MoveNodes( aRg, rNds, SwNodeIndex( rNds.GetEndOfContent() ));
+ pMvStt = new SwNodeIndex( rNds, nNode );
+ nNode = rNds.GetEndOfContent().GetIndex() - nNode; // Differenz merken !
+ if( pSttTxtNd && pEndTxtNd )
+ {
+ //Step 4: Moving around sections
+ nSectDiff = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
+ // nSect is the number of sections which starts(ends) between start and end node of the
+ // selection. The "loser" paragraph has to be moved into the section(s) of the
+ // "winner" paragraph
+ if( nSectDiff )
+ {
+ if( bJoinNext )
+ {
+ SwNodeRange aMvRg( *pEndTxtNd, 0, *pEndTxtNd, 1 );
+ rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aStart, TRUE );
+ }
+ else
+ {
+ SwNodeRange aMvRg( *pSttTxtNd, 0, *pSttTxtNd, 1 );
+ rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aEnd, TRUE );
+ }
+ }
+ }
+ if( nSectDiff || nReplaceDummy )
+ lcl_MakeAutoFrms( *pDoc->GetSpzFrmFmts(),
+ bJoinNext ? pEndTxtNd->GetIndex() : pSttTxtNd->GetIndex() );
+ }
+ else
+ nNode = 0; // kein Node verschoben -> keine Differenz zum Ende
+
+ // wurden davor noch Nodes geloescht ?? (FootNotes haben ContentNodes!)
+ if( !pSttTxtNd && !pEndTxtNd )
+ {
+ nNdDiff = nSttNode - rPam.GetPoint()->nNode.GetIndex() - (bFullPara ? 0 : 1);
+ rPam.Move( fnMoveForward, fnGoNode );
+ }
+ else
+ {
+ nNdDiff = nSttNode;
+ if( nSectDiff && bBackSp )
+ nNdDiff += nSectDiff;
+ nNdDiff -= rPam.GetPoint()->nNode.GetIndex();
+ }
+
+ if( !rPam.GetNode()->IsCntntNode() )
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+
+ // wird die History ueberhaupt benoetigt ??
+ if( pHistory && !pHistory->Count() )
+ DELETEZ( pHistory );
+}
+
+BOOL SwUndoDelete::SaveCntnt( const SwPosition* pStt, const SwPosition* pEnd,
+ SwTxtNode* pSttTxtNd, SwTxtNode* pEndTxtNd )
+{
+ ULONG nNdIdx = pStt->nNode.GetIndex();
+ // 1 - kopiere den Anfang in den Start-String
+ if( pSttTxtNd )
+ {
+ BOOL bOneNode = nSttNode == nEndNode;
+ xub_StrLen nLen = bOneNode ? nEndCntnt - nSttCntnt
+ : pSttTxtNd->GetTxt().Len() - nSttCntnt;
+ SwRegHistory aRHst( *pSttTxtNd, pHistory );
+ // always save all text atttibutes because of possibly overlapping
+ // areas of on/off
+ pHistory->CopyAttr( pSttTxtNd->GetpSwpHints(), nNdIdx,
+ 0, pSttTxtNd->GetTxt().Len(), true );
+ if( !bOneNode && pSttTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pSttTxtNd->GetpSwAttrSet(), nNdIdx );
+
+ // die Laenge kann sich veraendert haben (!!Felder!!)
+ nLen = ( bOneNode ? pEnd->nContent.GetIndex() : pSttTxtNd->GetTxt().Len() )
+ - pStt->nContent.GetIndex();
+
+
+ // loesche jetzt noch den Text (alle Attribut-Aenderungen kommen in
+ // die Undo-History
+ pSttStr = (String*)new String( pSttTxtNd->GetTxt().Copy( nSttCntnt, nLen ));
+ pSttTxtNd->EraseText( pStt->nContent, nLen );
+ if( pSttTxtNd->GetpSwpHints() )
+ pSttTxtNd->GetpSwpHints()->DeRegister();
+
+ // METADATA: store
+ bool emptied( pSttStr->Len() && !pSttTxtNd->Len() );
+ if (!bOneNode || emptied) // merging may overwrite xmlids...
+ {
+ m_pMetadataUndoStart = (emptied)
+ ? pSttTxtNd->CreateUndoForDelete()
+ : pSttTxtNd->CreateUndo();
+ }
+
+ if( bOneNode )
+ return FALSE; // keine Nodes mehr verschieben
+ }
+
+
+ // 2 - kopiere das Ende in den End-String
+ if( pEndTxtNd )
+ {
+ SwIndex aEndIdx( pEndTxtNd );
+ nNdIdx = pEnd->nNode.GetIndex();
+ SwRegHistory aRHst( *pEndTxtNd, pHistory );
+
+ // always save all text atttibutes because of possibly overlapping
+ // areas of on/off
+ pHistory->CopyAttr( pEndTxtNd->GetpSwpHints(), nNdIdx, 0,
+ pEndTxtNd->GetTxt().Len(), true );
+
+ if( pEndTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pEndTxtNd->GetpSwAttrSet(), nNdIdx );
+
+
+ // loesche jetzt noch den Text (alle Attribut-Aenderungen kommen in
+ // die Undo-History
+ pEndStr = (String*)new String( pEndTxtNd->GetTxt().Copy( 0,
+ pEnd->nContent.GetIndex() ));
+ pEndTxtNd->EraseText( aEndIdx, pEnd->nContent.GetIndex() );
+ if( pEndTxtNd->GetpSwpHints() )
+ pEndTxtNd->GetpSwpHints()->DeRegister();
+
+ // METADATA: store
+ bool emptied( pEndStr->Len() && !pEndTxtNd->Len() );
+
+ m_pMetadataUndoEnd = (emptied)
+ ? pEndTxtNd->CreateUndoForDelete()
+ : pEndTxtNd->CreateUndo();
+ }
+
+ // sind es nur zwei Nodes, dann ist schon alles erledigt.
+ if( ( pSttTxtNd || pEndTxtNd ) && nSttNode + 1 == nEndNode )
+ return FALSE; // keine Nodes mehr verschieben
+
+ return TRUE; // verschiebe die dazwischen liegenden Nodes
+}
+
+
+BOOL SwUndoDelete::CanGrouping( SwDoc* pDoc, const SwPaM& rDelPam )
+{
+ // ist das Undo groesser als 1 Node ? (sprich: Start und EndString)
+ if( pSttStr ? !pSttStr->Len() || pEndStr : TRUE )
+ return FALSE;
+
+ // es kann nur das Loeschen von einzelnen char's zusammengefasst werden
+ if( nSttNode != nEndNode || ( !bGroup && nSttCntnt+1 != nEndCntnt ))
+ return FALSE;
+
+ const SwPosition *pStt = rDelPam.Start(),
+ *pEnd = rDelPam.GetPoint() == pStt
+ ? rDelPam.GetMark()
+ : rDelPam.GetPoint();
+
+ if( pStt->nNode != pEnd->nNode ||
+ pStt->nContent.GetIndex()+1 != pEnd->nContent.GetIndex() ||
+ pEnd->nNode != nSttNode )
+ return FALSE;
+
+ // untercheide zwischen BackSpace und Delete. Es muss dann das
+ // Undo-Array unterschiedlich aufgebaut werden !!
+ if( pEnd->nContent == nSttCntnt )
+ {
+ if( bGroup && !bBackSp ) return FALSE;
+ bBackSp = TRUE;
+ }
+ else if( pStt->nContent == nSttCntnt )
+ {
+ if( bGroup && bBackSp ) return FALSE;
+ bBackSp = FALSE;
+ }
+ else
+ return FALSE;
+
+ // sind die beiden Nodes (Nodes-/Undo-Array) ueberhaupt TextNodes?
+ SwTxtNode * pDelTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ if( !pDelTxtNd ) return FALSE;
+
+ xub_StrLen nUChrPos = bBackSp ? 0 : pSttStr->Len()-1;
+ sal_Unicode cDelChar = pDelTxtNd->GetTxt().GetChar( pStt->nContent.GetIndex() );
+ CharClass& rCC = GetAppCharClass();
+ if( ( CH_TXTATR_BREAKWORD == cDelChar || CH_TXTATR_INWORD == cDelChar ) ||
+ rCC.isLetterNumeric( String( cDelChar ), 0 ) !=
+ rCC.isLetterNumeric( *pSttStr, nUChrPos ) )
+ return FALSE;
+
+ {
+ SwRedlineSaveDatas* pTmpSav = new SwRedlineSaveDatas;
+ if( !FillSaveData( rDelPam, *pTmpSav, FALSE ))
+ delete pTmpSav, pTmpSav = 0;
+
+ BOOL bOk = ( !pRedlSaveData && !pTmpSav ) ||
+ ( pRedlSaveData && pTmpSav &&
+ SwUndo::CanRedlineGroup( *pRedlSaveData, *pTmpSav, bBackSp ));
+ delete pTmpSav;
+ if( !bOk )
+ return FALSE;
+
+ pDoc->DeleteRedline( rDelPam, false, USHRT_MAX );
+ }
+
+ // Ok, die beiden 'Deletes' koennen zusammen gefasst werden, also
+ // 'verschiebe' das enstprechende Zeichen
+ if( bBackSp )
+ nSttCntnt--; // BackSpace: Zeichen in Array einfuegen !!
+ else
+ {
+ nEndCntnt++; // Delete: Zeichen am Ende anhaengen
+ nUChrPos++;
+ }
+ pSttStr->Insert( cDelChar, nUChrPos );
+ pDelTxtNd->EraseText( pStt->nContent, 1 );
+
+ bGroup = TRUE;
+ return TRUE;
+}
+
+
+
+SwUndoDelete::~SwUndoDelete()
+{
+ delete pSttStr;
+ delete pEndStr;
+ if( pMvStt ) // loesche noch den Bereich aus dem UndoNodes Array
+ {
+ // Insert speichert den Inhalt in der IconSection
+ pMvStt->GetNode().GetNodes().Delete( *pMvStt, nNode );
+ delete pMvStt;
+ }
+ delete pRedlData;
+ delete pRedlSaveData;
+}
+
+static SwRewriter lcl_RewriterFromHistory(SwHistory & rHistory)
+{
+ SwRewriter aRewriter;
+
+ bool bDone = false;
+
+ for ( USHORT n = 0; n < rHistory.Count(); n++)
+ {
+ String aDescr = rHistory[n]->GetDescription();
+
+ if (aDescr.Len() > 0)
+ {
+ aRewriter.AddRule(UNDO_ARG2, aDescr);
+
+ bDone = true;
+ break;
+ }
+ }
+
+ if (! bDone)
+ {
+ aRewriter.AddRule(UNDO_ARG2, SW_RES(STR_FIELD));
+ }
+
+ return aRewriter;
+}
+
+SwRewriter SwUndoDelete::GetRewriter() const
+{
+ SwRewriter aResult;
+ String * pStr = NULL;
+
+ if (nNode != 0)
+ {
+ if (sTableName.Len() > 0)
+ {
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, SW_RES(STR_START_QUOTE));
+ aRewriter.AddRule(UNDO_ARG2, sTableName);
+ aRewriter.AddRule(UNDO_ARG3, SW_RES(STR_END_QUOTE));
+
+ String sTmp = aRewriter.Apply(SW_RES(STR_TABLE_NAME));
+ aResult.AddRule(UNDO_ARG1, sTmp);
+ }
+ else
+ aResult.AddRule(UNDO_ARG1, String(SW_RES(STR_PARAGRAPHS)));
+ }
+ else
+ {
+ String aStr;
+
+ if (pSttStr != NULL && pEndStr != NULL && pSttStr->Len() == 0 &&
+ pEndStr->Len() == 0)
+ {
+ aStr = SW_RES(STR_PARAGRAPH_UNDO);
+ }
+ else
+ {
+ if (pSttStr != NULL)
+ pStr = pSttStr;
+ else if (pEndStr != NULL)
+ pStr = pEndStr;
+
+ if (pStr != NULL)
+ {
+ aStr = DenoteSpecialCharacters(*pStr);
+ }
+ else
+ {
+ aStr = UNDO_ARG2;
+ }
+ }
+
+ aStr = ShortenString(aStr, nUndoStringLength, String(SW_RES(STR_LDOTS)));
+ if (pHistory)
+ {
+ SwRewriter aRewriter = lcl_RewriterFromHistory(*pHistory);
+ aStr = aRewriter.Apply(aStr);
+ }
+
+ aResult.AddRule(UNDO_ARG1, aStr);
+ }
+
+ return aResult;
+}
+
+// Every object, anchored "AtCntnt" will be reanchored at rPos
+void lcl_ReAnchorAtCntntFlyFrames( const SwSpzFrmFmts& rSpzArr, SwPosition &rPos, ULONG nOldIdx )
+{
+ if( rSpzArr.Count() )
+ {
+ SwFlyFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+ const SwPosition* pAPos;
+ for( USHORT n = 0; n < rSpzArr.Count(); ++n )
+ {
+ pFmt = (SwFlyFrmFmt*)rSpzArr[n];
+ pAnchor = &pFmt->GetAnchor();
+ if (pAnchor->GetAnchorId() == FLY_AT_PARA)
+ {
+ pAPos = pAnchor->GetCntntAnchor();
+ if( pAPos && nOldIdx == pAPos->nNode.GetIndex() )
+ {
+ SwFmtAnchor aAnch( *pAnchor );
+ aAnch.SetAnchor( &rPos );
+ pFmt->SetFmtAttr( aAnch );
+ }
+ }
+ }
+ }
+}
+
+void SwUndoDelete::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc* pDoc = &rUndoIter.GetDoc();
+ BOOL bUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+
+ ULONG nCalcStt = nSttNode - nNdDiff;
+
+ if( nSectDiff && bBackSp )
+ nCalcStt += nSectDiff;
+
+ SwNodeIndex aIdx( pDoc->GetNodes(), nCalcStt );
+ SwNode* pInsNd = &aIdx.GetNode();
+
+ { // Block, damit der SwPosition beim loeschen vom Node
+ // abgemeldet ist
+ SwPosition aPos( aIdx );
+ if( !bDelFullPara )
+ {
+ if( pInsNd->IsTableNode() )
+ {
+ pInsNd = pDoc->GetNodes().MakeTxtNode( aIdx,
+ (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
+ aIdx--;
+ aPos.nNode = aIdx;
+ aPos.nContent.Assign( pInsNd->GetCntntNode(), nSttCntnt );
+ }
+ else
+ {
+ if( pInsNd->IsCntntNode() )
+ aPos.nContent.Assign( (SwCntntNode*)pInsNd, nSttCntnt );
+ if( !bTblDelLastNd )
+ pInsNd = 0; // Node nicht loeschen !!
+ }
+ }
+ else
+ pInsNd = 0; // Node nicht loeschen !!
+
+ SwNodes* pUNds = (SwNodes*)pDoc->GetUndoNds();
+ BOOL bNodeMove = 0 != nNode;
+
+ if( pEndStr )
+ {
+ // alle Attribute verwerfen, wurden alle gespeichert!
+ SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+
+ if( pTxtNd && pTxtNd->HasSwAttrSet() )
+ pTxtNd->ResetAllAttr();
+
+ if( pTxtNd && pTxtNd->GetpSwpHints() )
+ pTxtNd->ClearSwpHintsArr( true );
+
+ if( pSttStr && !bFromTableCopy )
+ {
+ ULONG nOldIdx = aPos.nNode.GetIndex();
+ pDoc->SplitNode( aPos, false );
+ // After the split all objects are anchored at the first paragraph,
+ // but the pHistory of the fly frame formats relies on anchoring at
+ // the start of the selection => selection backwards needs a correction.
+ if( bBackSp )
+ lcl_ReAnchorAtCntntFlyFrames( *pDoc->GetSpzFrmFmts(), aPos, nOldIdx );
+ pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+ }
+ if( pTxtNd )
+ {
+ pTxtNd->InsertText( *pEndStr, aPos.nContent,
+ IDocumentContentOperations::INS_NOHINTEXPAND );
+ // METADATA: restore
+ pTxtNd->RestoreMetadata(m_pMetadataUndoEnd);
+ }
+ }
+ else if( pSttStr && bNodeMove )
+ {
+ SwTxtNode * pNd = aPos.nNode.GetNode().GetTxtNode();
+ if( pNd )
+ {
+ if( nSttCntnt < pNd->GetTxt().Len() )
+ {
+ ULONG nOldIdx = aPos.nNode.GetIndex();
+ pDoc->SplitNode( aPos, false );
+ if( bBackSp )
+ lcl_ReAnchorAtCntntFlyFrames( *pDoc->GetSpzFrmFmts(), aPos, nOldIdx );
+ }
+ else
+ aPos.nNode++;
+ }
+ }
+ SwNode* pMovedNode = NULL;
+ if( nSectDiff )
+ {
+ ULONG nMoveIndex = aPos.nNode.GetIndex();
+ int nDiff = 0;
+ if( bJoinNext )
+ {
+ nMoveIndex += nSectDiff + 1;
+ pMovedNode = &aPos.nNode.GetNode();
+ }
+ else
+ {
+ nMoveIndex -= nSectDiff + 1;
+ ++nDiff;
+ }
+ SwNodeIndex aMvIdx( pDoc->GetNodes(), nMoveIndex );
+ SwNodeRange aRg( aPos.nNode, 0 - nDiff, aPos.nNode, 1 - nDiff );
+ aPos.nNode--;
+ if( !bJoinNext )
+ pMovedNode = &aPos.nNode.GetNode();
+ pDoc->GetNodes()._MoveNodes( aRg, pDoc->GetNodes(), aMvIdx, TRUE );
+ aPos.nNode++;
+ }
+
+ if( bNodeMove )
+ {
+ SwNodeRange aRange( *pMvStt, 0, *pMvStt, nNode );
+ SwNodeIndex aCopyIndex( aPos.nNode, -1 );
+ pUNds->_Copy( aRange, aPos.nNode );
+
+ if( nReplaceDummy )
+ {
+ ULONG nMoveIndex;
+ if( bJoinNext )
+ {
+ nMoveIndex = nEndNode - nNdDiff;
+ aPos.nNode = nMoveIndex + nReplaceDummy;
+ }
+ else
+ {
+ aPos = SwPosition( aCopyIndex );
+ nMoveIndex = aPos.nNode.GetIndex() + nReplaceDummy + 1;
+ }
+ SwNodeIndex aMvIdx( pDoc->GetNodes(), nMoveIndex );
+ SwNodeRange aRg( aPos.nNode, 0, aPos.nNode, 1 );
+ pMovedNode = &aPos.nNode.GetNode();
+ pDoc->GetNodes()._MoveNodes( aRg, pDoc->GetNodes(), aMvIdx, TRUE );
+ pDoc->GetNodes().Delete( aMvIdx, 1 );
+ }
+ }
+
+ if( pMovedNode )
+ lcl_MakeAutoFrms( *pDoc->GetSpzFrmFmts(), pMovedNode->GetIndex() );
+
+ if( pSttStr )
+ {
+ aPos.nNode = nSttNode - nNdDiff + ( bJoinNext ? 0 : nReplaceDummy );
+ SwTxtNode * pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+ // wenn mehr als ein Node geloescht wurde, dann wurden auch
+ // alle "Node"-Attribute gespeichert
+
+ if (pTxtNd != NULL)
+ {
+ if( pTxtNd->HasSwAttrSet() && bNodeMove && !pEndStr )
+ pTxtNd->ResetAllAttr();
+
+ if( pTxtNd->GetpSwpHints() )
+ pTxtNd->ClearSwpHintsArr( true );
+
+ // SectionNode-Modus und von oben nach unten selektiert:
+ // -> im StartNode steht noch der Rest vom Join => loeschen
+ aPos.nContent.Assign( pTxtNd, nSttCntnt );
+ pTxtNd->InsertText( *pSttStr, aPos.nContent,
+ IDocumentContentOperations::INS_NOHINTEXPAND );
+ // METADATA: restore
+ pTxtNd->RestoreMetadata(m_pMetadataUndoStart);
+ }
+ }
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( pDoc, nSetPos, false );
+ if( nSetPos ) // es gab Fussnoten/FlyFrames
+ {
+ // gibts ausser diesen noch andere ?
+ if( nSetPos < pHistory->Count() )
+ {
+ // dann sicher die Attribute anderen Attribute
+ SwHistory aHstr;
+ aHstr.Move( 0, pHistory, nSetPos );
+ pHistory->Rollback( pDoc );
+ pHistory->Move( 0, &aHstr );
+ }
+ else
+ {
+ pHistory->Rollback( pDoc );
+ DELETEZ( pHistory );
+ }
+ }
+ }
+
+ if( bResetPgDesc || bResetPgBrk )
+ {
+ USHORT nStt = static_cast<USHORT>( bResetPgDesc ? RES_PAGEDESC : RES_BREAK );
+ USHORT nEnd = static_cast<USHORT>( bResetPgBrk ? RES_BREAK : RES_PAGEDESC );
+
+ SwNode* pNode = pDoc->GetNodes()[ nEndNode + 1 ];
+ if( pNode->IsCntntNode() )
+ ((SwCntntNode*)pNode)->ResetAttr( nStt, nEnd );
+ else if( pNode->IsTableNode() )
+ ((SwTableNode*)pNode)->GetTable().GetFrmFmt()->ResetFmtAttr( nStt, nEnd );
+ }
+ }
+ // den temp. eingefuegten Node noch loeschen !!
+ if( pInsNd )
+ pDoc->GetNodes().Delete( aIdx, 1 );
+ if( pRedlSaveData )
+ SetSaveData( *pDoc, *pRedlSaveData );
+
+ pDoc->DoUndo( bUndo ); // Undo wieder einschalten
+ SetPaM( rUndoIter, TRUE );
+}
+
+void SwUndoDelete::Redo( SwUndoIter& rUndoIter )
+{
+ rUndoIter.SetUpdateAttr( TRUE );
+
+ SwPaM& rPam = *rUndoIter.pAktPam;
+ SwDoc& rDoc = *rPam.GetDoc();
+
+ SetPaM( rPam );
+
+ if( pRedlSaveData )
+ {
+ bool bSuccess = FillSaveData(rPam, *pRedlSaveData, TRUE);
+ OSL_ENSURE(bSuccess,
+ "SwUndoDelete::Redo: used to have redline data, but now none?");
+ if (!bSuccess)
+ {
+ delete pRedlSaveData, pRedlSaveData = 0;
+ }
+ }
+
+ if( !bDelFullPara )
+ {
+ SwUndRng aTmpRng( rPam );
+ RemoveIdxFromRange( rPam, FALSE );
+ aTmpRng.SetPaM( rPam );
+
+ if( !bJoinNext ) // Dann Selektion von unten nach oben
+ rPam.Exchange(); // wieder herstellen!
+ }
+
+ if( pHistory ) // wurden Attribute gesichert ?
+ {
+ pHistory->SetTmpEnd( pHistory->Count() );
+ SwHistory aHstr;
+ aHstr.Move( 0, pHistory );
+
+ if( bDelFullPara )
+ {
+ OSL_ENSURE( rPam.HasMark(), "PaM ohne Mark" );
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
+ DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
+
+ _DelBookmarks(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
+ }
+ else
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+ nSetPos = pHistory ? pHistory->Count() : 0;
+
+ pHistory->Move( nSetPos, &aHstr );
+ }
+ else
+ {
+ if( bDelFullPara )
+ {
+ OSL_ENSURE( rPam.HasMark(), "PaM ohne Mark" );
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
+ DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
+
+ _DelBookmarks( rPam.GetMark()->nNode, rPam.GetPoint()->nNode );
+ }
+ else
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+ nSetPos = pHistory ? pHistory->Count() : 0;
+ }
+
+ if( !pSttStr && !pEndStr )
+ {
+ SwNodeIndex aSttIdx = ( bDelFullPara || bJoinNext )
+ ? rPam.GetMark()->nNode
+ : rPam.GetPoint()->nNode;
+ SwTableNode* pTblNd = aSttIdx.GetNode().GetTableNode();
+ if( pTblNd )
+ {
+ if( bTblDelLastNd )
+ {
+ // dann am Ende wieder einen Node einfuegen
+ const SwNodeIndex aTmpIdx( *pTblNd->EndOfSectionNode(), 1 );
+ rDoc.GetNodes().MakeTxtNode( aTmpIdx,
+ rDoc.GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
+ }
+
+ SwCntntNode* pNextNd = rDoc.GetNodes()[
+ pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode();
+ if( pNextNd )
+ {
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
+ FALSE, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
+ FALSE, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+ }
+ pTblNd->DelFrms();
+ }
+
+ rPam.SetMark();
+ rPam.DeleteMark();
+
+ rDoc.GetNodes().Delete( aSttIdx, nEndNode - nSttNode );
+
+ // setze den Cursor immer in einen ContentNode !!
+ if( !rPam.Move( fnMoveBackward, fnGoCntnt ) &&
+ !rPam.Move( fnMoveForward, fnGoCntnt ) )
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 );
+ }
+ else if( bDelFullPara )
+ {
+ // der Pam wurde am Point( == Ende) um eins erhoeht, um einen
+ // Bereich fuers Undo zu haben. Der muss jetzt aber wieder entfernt
+ // werden!!!
+ rPam.End()->nNode--;
+ if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode )
+ *rPam.GetMark() = *rPam.GetPoint();
+ rDoc.DelFullPara( rPam );
+ }
+ else
+ rDoc.DeleteAndJoin( rPam );
+}
+
+void SwUndoDelete::Repeat( SwUndoIter& rUndoIter )
+{
+ if( UNDO_DELETE == rUndoIter.GetLastUndoId() )
+ return;
+
+ SwPaM& rPam = *rUndoIter.pAktPam;
+ SwDoc& rDoc = *rPam.GetDoc();
+ BOOL bGroupUndo = rDoc.DoesGroupUndo();
+ rDoc.DoGroupUndo( FALSE );
+ if( !rPam.HasMark() )
+ {
+ rPam.SetMark();
+ rPam.Move( fnMoveForward, fnGoCntnt );
+ }
+ if( bDelFullPara )
+ rDoc.DelFullPara( rPam );
+ else
+ rDoc.DeleteAndJoin( rPam );
+ rDoc.DoGroupUndo( bGroupUndo );
+ rUndoIter.pLastUndoObj = this;
+}
+
+
+void SwUndoDelete::SetTableName(const String & rName)
+{
+ sTableName = rName;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undo.hrc b/sw/source/core/undo/undo.hrc
new file mode 100644
index 000000000000..707ff307be48
--- /dev/null
+++ b/sw/source/core/undo/undo.hrc
@@ -0,0 +1,185 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <rcid.hrc>
+// Undo
+#define UNDO_BASE (RC_WRTSH_BEGIN + 8)
+#define STR_CANT_UNDO (UNDO_BASE + 0)
+
+// im enun folgen hier START & END fuer die Klammerungen,
+
+// Id's fuer die Undo/Redo/Repeat faehigen "Funktionen"
+#define STR_DELETE_UNDO (UNDO_BASE + 3)
+#define STR_INSERT_UNDO (UNDO_BASE + 4)
+#define STR_OVR_UNDO (UNDO_BASE + 5)
+#define STR_SPLITNODE_UNDO (UNDO_BASE + 6)
+#define STR_INSATTR_UNDO (UNDO_BASE + 7)
+#define STR_SETFMTCOLL_UNDO (UNDO_BASE + 8)
+#define STR_RESET_ATTR_UNDO (UNDO_BASE + 9)
+#define STR_INSFMT_ATTR_UNDO (UNDO_BASE +10)
+#define STR_INSERT_DOC_UNDO (UNDO_BASE +11)
+#define STR_COPY_UNDO (UNDO_BASE +12)
+#define STR_INSTABLE_UNDO (UNDO_BASE +13)
+#define STR_TABLETOTEXT_UNDO (UNDO_BASE +14)
+#define STR_TEXTTOTABLE_UNDO (UNDO_BASE +15)
+#define STR_SORT_TXT (UNDO_BASE +16)
+#define STR_INSERTFLY (UNDO_BASE +17)
+#define STR_TABLEHEADLINE (UNDO_BASE +18)
+#define STR_INSERTSECTION (UNDO_BASE +19)
+#define STR_OUTLINE_LR (UNDO_BASE +20)
+#define STR_OUTLINE_UD (UNDO_BASE +21)
+#define STR_INSNUM (UNDO_BASE +22)
+#define STR_NUMUP (UNDO_BASE +23)
+#define STR_MOVENUM (UNDO_BASE +24)
+#define STR_INSERTDRAW (UNDO_BASE +25)
+#define STR_NUMORNONUM (UNDO_BASE +26)
+#define STR_INC_LEFTMARGIN (UNDO_BASE +27)
+#define STR_DEC_LEFTMARGIN (UNDO_BASE +28)
+#define STR_INSERTLABEL (UNDO_BASE +29)
+#define STR_SETNUMRULESTART (UNDO_BASE +30)
+#define STR_CHANGEFTN (UNDO_BASE +31)
+#define STR_REDLINE (UNDO_BASE +32)
+#define STR_ACCEPT_REDLINE (UNDO_BASE +33)
+#define STR_REJECT_REDLINE (UNDO_BASE +34)
+#define STR_SPLIT_TABLE (UNDO_BASE +35)
+#define STR_DONTEXPAND (UNDO_BASE +36)
+#define STR_AUTOCORRECT (UNDO_BASE +37)
+#define STR_MERGE_TABLE (UNDO_BASE +38)
+#define STR_TRANSLITERATE (UNDO_BASE +39)
+#define STR_PASTE_CLIPBOARD_UNDO (UNDO_BASE +40)
+#define STR_TYPING_UNDO (UNDO_BASE +41)
+
+#define STR_REPEAT_DUMMY_6 (UNDO_BASE +42)
+#define STR_REPEAT_DUMMY_7 (UNDO_BASE +43)
+#define STR_REPEAT_DUMMY_8 (UNDO_BASE +44)
+#define STR_REPEAT_DUMMY_9 (UNDO_BASE +45)
+// !!!!!! umsetzen !!!!!!!!!!! umsetzen !!!!!!!!!!! umsetzen !!!!
+#define CORE_REPEAT_END STR_REPEAT_DUMMY_9// !!!! umsetzen !!!
+
+
+// Id's nur fuer die Undo/Redo faehigen "Funktionen"
+#define STR_MOVE_UNDO (CORE_REPEAT_END + 1)
+#define STR_INSERT_GLOSSARY (CORE_REPEAT_END + 2)
+#define STR_DELBOOKMARK (CORE_REPEAT_END + 3)
+#define STR_INSBOOKMARK (CORE_REPEAT_END + 4)
+#define STR_SORT_TBL (CORE_REPEAT_END + 5)
+#define STR_DELETEFLY (CORE_REPEAT_END + 6)
+#define STR_AUTOFORMAT (CORE_REPEAT_END + 7)
+#define STR_REPLACE (CORE_REPEAT_END + 8)
+#define STR_DELETESECTION (CORE_REPEAT_END + 9)
+#define STR_CHANGESECTION (CORE_REPEAT_END +10)
+#define STR_CHANGESECTPASSWD (CORE_REPEAT_END +11)
+#define STR_CHANGEDEFATTR (CORE_REPEAT_END +12)
+#define STR_DELNUM (CORE_REPEAT_END +13)
+#define STR_DRAWUNDO (CORE_REPEAT_END +14)
+#define STR_DRAWGROUP (CORE_REPEAT_END +15)
+#define STR_DRAWUNGROUP (CORE_REPEAT_END +16)
+#define STR_DRAWDELETE (CORE_REPEAT_END +17)
+#define STR_REREAD (CORE_REPEAT_END +18)
+#define STR_DELGRF (CORE_REPEAT_END +19)
+#define STR_DELOLE (CORE_REPEAT_END +20)
+#define STR_TABLE_ATTR (CORE_REPEAT_END +21)
+#define STR_TABLE_AUTOFMT (CORE_REPEAT_END +22)
+#define STR_TABLE_INSCOL (CORE_REPEAT_END +23)
+#define STR_TABLE_INSROW (CORE_REPEAT_END +24)
+#define STR_TABLE_DELBOX (CORE_REPEAT_END +25)
+#define STR_TABLE_SPLIT (CORE_REPEAT_END +26)
+#define STR_TABLE_MERGE (CORE_REPEAT_END +27)
+#define STR_TABLE_NUMFORMAT (CORE_REPEAT_END +28)
+#define STR_INSERT_TOX (CORE_REPEAT_END +29)
+#define STR_CLEAR_TOX_RANGE (CORE_REPEAT_END +30)
+#define STR_TABLE_TBLCPYTBL (CORE_REPEAT_END +31)
+#define STR_TABLE_CPYTBL (CORE_REPEAT_END +32)
+#define STR_INS_FROM_SHADOWCRSR (CORE_REPEAT_END +33)
+#define STR_UNDO_CHAIN (CORE_REPEAT_END +34)
+#define STR_UNDO_UNCHAIN (CORE_REPEAT_END +35)
+#define STR_UNDO_FTNINFO (CORE_REPEAT_END +36)
+#define STR_UNDO_ENDNOTEINFO (CORE_REPEAT_END +37)
+#define STR_UNDO_COMPAREDOC (CORE_REPEAT_END +38)
+#define STR_UNDO_SETFLYFRMFMT (CORE_REPEAT_END +39)
+#define STR_UNDO_SETRUBYATTR (CORE_REPEAT_END +40)
+// #102505#
+#define STR_UNDO_TMPAUTOCORR (CORE_REPEAT_END +41)
+
+#define STR_TOXCHANGE (CORE_REPEAT_END +42)
+#define STR_UNDO_PAGEDESC_CREATE (CORE_REPEAT_END +43)
+#define STR_UNDO_PAGEDESC (CORE_REPEAT_END +44)
+#define STR_UNDO_PAGEDESC_DELETE (CORE_REPEAT_END +45)
+#define STR_UNDO_HEADER_FOOTER (CORE_REPEAT_END +46) // #i7983#
+#define STR_UNDO_FIELD (CORE_REPEAT_END +47) // #111840#
+#define STR_UNDO_TXTFMTCOL_CREATE (CORE_REPEAT_END +48)
+#define STR_UNDO_TXTFMTCOL_DELETE (CORE_REPEAT_END +49)
+#define STR_UNDO_TXTFMTCOL_RENAME (CORE_REPEAT_END +50)
+#define STR_UNDO_CHARFMT_CREATE (CORE_REPEAT_END +51)
+#define STR_UNDO_CHARFMT_DELETE (CORE_REPEAT_END +52)
+#define STR_UNDO_CHARFMT_RENAME (CORE_REPEAT_END +53)
+#define STR_UNDO_FRMFMT_CREATE (CORE_REPEAT_END +54)
+#define STR_UNDO_FRMFMT_DELETE (CORE_REPEAT_END +55)
+#define STR_UNDO_FRMFMT_RENAME (CORE_REPEAT_END +56)
+#define STR_UNDO_NUMRULE_CREATE (CORE_REPEAT_END +57)
+#define STR_UNDO_NUMRULE_DELETE (CORE_REPEAT_END +58)
+#define STR_UNDO_NUMRULE_RENAME (CORE_REPEAT_END +59)
+#define STR_UNDO_BOOKMARK_RENAME (CORE_REPEAT_END +60)
+#define STR_UNDO_INDEX_ENTRY_INSERT (CORE_REPEAT_END +61)
+#define STR_UNDO_INDEX_ENTRY_DELETE (CORE_REPEAT_END +62)
+#define STR_UNDO_COL_DELETE (CORE_REPEAT_END +63)
+#define STR_UNDO_ROW_DELETE (CORE_REPEAT_END +64)
+#define STR_UNDO_PAGEDESC_RENAME (CORE_REPEAT_END +65)
+#define STR_NUMDOWN (CORE_REPEAT_END +66)
+#define STR_UNDO_FLYFRMFMT_TITLE (CORE_REPEAT_END +67)
+#define STR_UNDO_FLYFRMFMT_DESCRITPTION (CORE_REPEAT_END +68)
+
+// !!!!!! umsetzen !!!!!!!!!!! umsetzen !!!!!!!!!!! umsetzen !!!!
+#define CORE_UNDO_END STR_UNDO_FLYFRMFMT_DESCRITPTION// !!!! umsetzen !!!
+
+// UI-Undo Klammerungen
+#define UI_UNDO_BEGIN (CORE_UNDO_END + 1)
+#define STR_REPLACE_UNDO (UI_UNDO_BEGIN)
+#define STR_INSERT_PAGE_BREAK_UNDO (UI_UNDO_BEGIN + 1)
+#define STR_INSERT_COLUMN_BREAK_UNDO (UI_UNDO_BEGIN + 2)
+#define STR_PLAY_MACRO_UNDO (UI_UNDO_BEGIN + 3)
+#define STR_INSERT_ENV_UNDO (UI_UNDO_BEGIN + 4)
+#define STR_DRAG_AND_COPY (UI_UNDO_BEGIN + 5)
+#define STR_DRAG_AND_MOVE (UI_UNDO_BEGIN + 6)
+#define STR_INSERT_RULER (UI_UNDO_BEGIN + 7)
+#define STR_INSERT_CHART (UI_UNDO_BEGIN + 8)
+#define STR_INSERT_FOOTNOTE (UI_UNDO_BEGIN + 9)
+#define STR_INSERT_URLBTN (UI_UNDO_BEGIN + 10)
+#define STR_INSERT_URLTXT (UI_UNDO_BEGIN + 11)
+#define STR_DELETE_INVISIBLECNTNT (UI_UNDO_BEGIN + 12)
+#define STR_REPLACE_STYLE (UI_UNDO_BEGIN + 13)
+#define UI_UNDO_END STR_REPLACE_STYLE
+
+#define UNDO_MORE_STRINGS_BEGIN (UI_UNDO_END + 1)
+#define STR_OCCURRENCES_OF (UNDO_MORE_STRINGS_BEGIN)
+#define STR_UNDO_TABS (UNDO_MORE_STRINGS_BEGIN + 1)
+#define STR_UNDO_NLS (UNDO_MORE_STRINGS_BEGIN + 2)
+#define STR_UNDO_PAGEBREAKS (UNDO_MORE_STRINGS_BEGIN + 3)
+#define STR_UNDO_COLBRKS (UNDO_MORE_STRINGS_BEGIN + 4)
+#define STR_UNDO_SPECIALCHAR (UNDO_MORE_STRINGS_BEGIN + 5)
+
+#define UNDO_ACT_END STR_UNDO_TABLE_NAME
diff --git a/sw/source/core/undo/undo.src b/sw/source/core/undo/undo.src
new file mode 100644
index 000000000000..4ad1e70b7869
--- /dev/null
+++ b/sw/source/core/undo/undo.src
@@ -0,0 +1,657 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <comcore.hrc>
+#include <undo.hrc>
+
+ // Undo
+String STR_CANT_UNDO
+{
+ Text [ en-US ] = "not possible" ;
+};
+String STR_DELETE_UNDO
+{
+ Text [ en-US ] = "Delete $1" ;
+};
+String STR_INSERT_UNDO
+{
+ Text [ en-US ] = "Insert $1" ;
+};
+String STR_OVR_UNDO
+{
+ Text [ en-US ] = "Overwrite: $1" ;
+};
+String STR_SPLITNODE_UNDO
+{
+ Text [ en-US ] = "New Paragraph" ;
+};
+String STR_MOVE_UNDO
+{
+ Text [ en-US ] = "Move" ;
+};
+String STR_INSATTR_UNDO
+{
+ Text [ en-US ] = "Apply attributes" ;
+};
+String STR_SETFMTCOLL_UNDO
+{
+ Text [ en-US ] = "Apply Styles: $1" ;
+};
+String STR_RESET_ATTR_UNDO
+{
+ Text [ en-US ] = "Reset attributes" ;
+};
+String STR_INSFMT_ATTR_UNDO
+{
+ Text [ en-US ] = "Change style: $1" ;
+};
+String STR_INSERT_DOC_UNDO
+{
+ Text [ en-US ] = "Insert file" ;
+};
+String STR_INSERT_GLOSSARY
+{
+ Text [ en-US ] = "Insert AutoText" ;
+};
+String STR_DELBOOKMARK
+{
+ Text [ en-US ] = "Delete bookmark: $1" ;
+};
+String STR_INSBOOKMARK
+{
+ Text [ en-US ] = "Insert bookmark: $1" ;
+};
+String STR_SORT_TBL
+{
+ Text [ en-US ] = "Sort table" ;
+};
+String STR_SORT_TXT
+{
+ Text [ en-US ] = "Sort text" ;
+};
+String STR_INSTABLE_UNDO
+{
+ Text [ en-US ] = "Insert table: $1$2$3" ;
+};
+String STR_TEXTTOTABLE_UNDO
+{
+ Text [ en-US ] = "Convert text -> table" ;
+};
+String STR_TABLETOTEXT_UNDO
+{
+ Text [ en-US ] = "Convert table -> text" ;
+};
+String STR_COPY_UNDO
+{
+ Text [ en-US ] = "Copy: $1" ;
+};
+String STR_REPLACE_UNDO
+{
+ Text [ en-US ] = "Replace $1 $2 $3" ;
+};
+String STR_INSERT_PAGE_BREAK_UNDO
+{
+ Text [ en-US ] = "Insert page break" ;
+};
+String STR_INSERT_COLUMN_BREAK_UNDO
+{
+ Text [ en-US ] = "Insert column break" ;
+};
+String STR_PLAY_MACRO_UNDO
+{
+ Text [ en-US ] = "Run macro" ;
+};
+String STR_INSERT_ENV_UNDO
+{
+ Text [ en-US ] = "Insert Envelope" ;
+};
+String STR_DRAG_AND_COPY
+{
+ Text [ en-US ] = "Copy: $1" ;
+};
+String STR_DRAG_AND_MOVE
+{
+ Text [ en-US ] = "Move: $1" ;
+};
+String STR_INSERT_RULER
+{
+ Text [ en-US ] = "Insert horizontal ruler" ;
+};
+String STR_INSERT_CHART
+{
+ Text [ en-US ] = "Insert %PRODUCTNAME Chart" ;
+};
+String STR_INSERTFLY
+{
+ Text [ en-US ] = "Insert frame" ;
+};
+String STR_DELETEFLY
+{
+ Text [ en-US ] = "Delete frame" ;
+};
+String STR_AUTOFORMAT
+{
+ Text [ en-US ] = "AutoFormat" ;
+};
+String STR_TABLEHEADLINE
+{
+ Text [ en-US ] = "Table heading" ;
+};
+String STR_REPLACE
+{
+ Text [ en-US ] = "Replace: $1 $2 $3" ;
+};
+String STR_INSERTSECTION
+{
+ Text [ en-US ] = "Insert section" ;
+};
+String STR_DELETESECTION
+{
+ Text [ en-US ] = "Delete section" ;
+};
+String STR_CHANGESECTION
+{
+ Text [ en-US ] = "Modify section" ;
+};
+String STR_CHANGESECTPASSWD
+{
+ Text [ en-US ] = "Change password protection" ;
+};
+String STR_CHANGEDEFATTR
+{
+ Text [ en-US ] = "Modify default values" ;
+};
+String STR_REPLACE_STYLE
+{
+ Text [ en-US ] = "Replace style: $1 $2 $3" ;
+};
+String STR_OUTLINE_LR
+{
+ Text [ en-US ] = "Promote/demote outline" ;
+};
+String STR_OUTLINE_UD
+{
+ Text [ en-US ] = "Move outline" ;
+};
+String STR_INSNUM
+{
+ Text [ en-US ] = "Insert numbering" ;
+};
+String STR_NUMUP
+{
+ Text [ en-US ] = "Promote level" ;
+};
+String STR_NUMDOWN
+{
+ Text [ en-US ] = "Demote level" ;
+};
+String STR_MOVENUM
+{
+ Text [ en-US ] = "Move paragraphs" ;
+};
+String STR_INSERTDRAW
+{
+ Text [ en-US ] = "Insert drawing object: $1" ;
+};
+String STR_NUMORNONUM
+{
+ Text [ en-US ] = "Number On/Off" ;
+};
+String STR_INC_LEFTMARGIN
+{
+ Text [ en-US ] = "Increase Indent" ;
+};
+String STR_DEC_LEFTMARGIN
+{
+ Text [ en-US ] = "Decrease indent" ;
+};
+String STR_INSERTLABEL
+{
+ Text [ en-US ] = "Insert caption: $1" ;
+};
+String STR_SETNUMRULESTART
+{
+ Text [ en-US ] = "Restart numbering" ;
+};
+String STR_CHANGEFTN
+{
+ Text [ en-US ] = "Modify footnote" ;
+};
+String STR_REDLINE
+{
+ /* !! sollte NIE gebraucht/uebersetzt werden !! */
+};
+String STR_ACCEPT_REDLINE
+{
+ Text [ en-US ] = "Accept change: $1" ;
+};
+String STR_REJECT_REDLINE
+{
+ Text [ en-US ] = "Reject change: $1" ;
+};
+String STR_SPLIT_TABLE
+{
+ Text [ en-US ] = "Split Table" ;
+};
+String STR_DONTEXPAND
+{
+ Text [ en-US ] = "Stop attribute" ;
+};
+String STR_AUTOCORRECT
+{
+ Text [ en-US ] = "AutoCorrect" ;
+};
+String STR_MERGE_TABLE
+{
+ Text [ en-US ] = "Merge table";
+};
+
+String STR_TRANSLITERATE
+{
+ Text [ en-US ] = "Case/Characters";
+};
+
+String STR_DELNUM
+{
+ Text [ en-US ] = "Delete numbering" ;
+};
+String STR_DRAWUNDO
+{
+ Text [ en-US ] = "Drawing objects: $1" ;
+};
+String STR_DRAWGROUP
+{
+ Text [ en-US ] = "Group draw objects" ;
+};
+String STR_DRAWUNGROUP
+{
+ Text [ en-US ] = "Ungroup drawing objects" ;
+};
+String STR_DRAWDELETE
+{
+ Text [ en-US ] = "Delete drawing objects" ;
+};
+String STR_REREAD
+{
+ Text [ en-US ] = "Replace graphics" ;
+};
+String STR_DELGRF
+{
+ Text [ en-US ] = "Delete graphics" ;
+};
+String STR_DELOLE
+{
+ Text [ en-US ] = "Delete object" ;
+};
+String STR_TABLE_ATTR
+{
+ Text [ en-US ] = "Apply table attributes" ;
+};
+String STR_TABLE_AUTOFMT
+{
+ Text [ en-US ] = "AutoFormat Table" ;
+};
+String STR_TABLE_INSCOL
+{
+ Text [ en-US ] = "Insert Column" ;
+};
+String STR_TABLE_INSROW
+{
+ Text [ en-US ] = "Insert Row" ;
+};
+String STR_TABLE_DELBOX
+{
+ Text [ en-US ] = "Delete row/column" ;
+};
+String STR_UNDO_COL_DELETE
+{
+ Text [ en-US ] = "Delete column" ;
+};
+String STR_UNDO_ROW_DELETE
+{
+ Text [ en-US ] = "Delete row" ;
+};
+String STR_TABLE_SPLIT
+{
+ Text [ en-US ] = "Split Cells" ;
+};
+String STR_TABLE_MERGE
+{
+ Text [ en-US ] = "Merge Cells" ;
+};
+String STR_TABLE_NUMFORMAT
+{
+ Text [ en-US ] = "Format cell" ;
+};
+String STR_INSERT_TOX
+{
+ Text [ en-US ] = "Insert index/table" ;
+};
+String STR_CLEAR_TOX_RANGE
+{
+ Text [ en-US ] = "Remove index/table" ;
+};
+String STR_TABLE_TBLCPYTBL{
+ Text [ en-US ] = "Copy table" ;
+};
+String STR_TABLE_CPYTBL
+{
+ Text [ en-US ] = "Copy table" ;
+};
+String STR_INS_FROM_SHADOWCRSR
+{
+ Text [ en-US ] = "Set cursor" ;
+};
+String STR_UNDO_CHAIN
+{
+ Text [ en-US ] = "Link text frames" ;
+};
+String STR_UNDO_UNCHAIN
+{
+ Text [ en-US ] = "Unlink text frames" ;
+};
+String STR_UNDO_FTNINFO
+{
+ Text [ en-US ] = "Modify footnote options" ;
+};
+String STR_UNDO_ENDNOTEINFO
+{
+ Text [ en-US ] = "Modify endnote settings" ;
+};
+String STR_UNDO_COMPAREDOC
+{
+ Text [ en-US ] = "Compare Document" ;
+};
+String STR_UNDO_SETFLYFRMFMT
+{
+ Text [ en-US ] = "Apply frame style: $1" ;
+};
+String STR_UNDO_SETRUBYATTR
+{
+ Text [ en-US ] = "Ruby Setting";
+};
+#102505#
+String STR_UNDO_TMPAUTOCORR
+{
+ Text [ en-US ] = "AutoCorrect" ;
+};
+String STR_INSERT_FOOTNOTE
+{
+ Text [ en-US ] = "Insert footnote" ;
+};
+String STR_INSERT_URLBTN
+{
+ Text [ en-US ] = "insert URL button";
+};
+String STR_INSERT_URLTXT
+{
+ Text [ en-US ] = "Insert Hyperlink";
+};
+String STR_DELETE_INVISIBLECNTNT
+{
+ Text [ en-US ] = "remove invisible content";
+};
+String STR_TOXCHANGE
+{
+ Text [ en-US ] = "Table/index changed";
+};
+String STR_START_QUOTE
+{
+ Text [ en-US ] = "'";
+};
+String STR_END_QUOTE
+{
+ Text [ en-US ] = "'";
+};
+String STR_LDOTS
+{
+ Text [ en-US ] = "...";
+};
+String STR_CLIPBOARD
+{
+ Text [ en-US ] = "clipboard";
+};
+String STR_MULTISEL
+{
+ Text [ en-US ] = "multiple selection";
+};
+String STR_TYPING_UNDO
+{
+ Text [ en-US ] = "Typing: $1";
+};
+String STR_PASTE_CLIPBOARD_UNDO
+{
+ Text [ en-US ] = "Paste clipboard";
+};
+String STR_YIELDS
+{
+ Text [ en-US ] = "->";
+};
+String STR_OCCURRENCES_OF
+{
+ Text [ en-US ] = "occurrences of";
+};
+String STR_UNDO_TABS
+{
+ Text [ en-US ] = "$1 tab(s)";
+};
+String STR_UNDO_NLS
+{
+ Text[ en-US ] = "$1 line break(s)";
+};
+String STR_UNDO_PAGEBREAKS
+{
+ Text[ en-US ] = "page break";
+};
+String STR_UNDO_COLBRKS
+{
+ Text[ en-US ] = "column break";
+};
+String STR_REDLINE_INSERT
+{
+ Text [ en-US ] = "Insert $1";
+};
+String STR_REDLINE_DELETE
+{
+ Text [ en-US ] = "Delete $1";
+};
+String STR_REDLINE_FORMAT
+{
+ Text [ en-US ] = "Attributes changed";
+};
+String STR_REDLINE_TABLE
+{
+ Text [ en-US ] = "Table changed";
+};
+String STR_REDLINE_FMTCOLL
+{
+ Text [ en-US ] = "Style changed";
+};
+String STR_REDLINE_MULTIPLE
+{
+ Text [ en-US ] = "multiple changes";
+};
+String STR_N_REDLINES
+{
+ Text [ en-US ] = "$1 changes";
+};
+String STR_UNDO_PAGEDESC
+{
+ Text [ en-US ] = "Change page style: $1";
+};
+String STR_UNDO_PAGEDESC_CREATE
+{
+ Text [ en-US ] = "Create page style: $1";
+};
+String STR_UNDO_PAGEDESC_DELETE
+{
+ Text [ en-US ] = "Delete page style: $1";
+};
+String STR_UNDO_PAGEDESC_RENAME
+{
+ Text [ en-US ] = "Rename page style: $1 $2 $3";
+};
+String STR_UNDO_HEADER_FOOTER
+{
+ Text [ en-US ] = "Header/footer changed";
+};
+String STR_UNDO_FIELD
+{
+ Text [ en-US ] = "Field changed";
+};
+String STR_UNDO_TXTFMTCOL_CREATE
+{
+ Text [ en-US ] = "Create paragraph style: $1";
+};
+String STR_UNDO_TXTFMTCOL_DELETE
+{
+ Text [ en-US ] = "Delete paragraph style: $1";
+};
+String STR_UNDO_TXTFMTCOL_RENAME
+{
+ Text [ en-US ] = "Rename paragraph style: $1 $2 $3";
+};
+String STR_UNDO_CHARFMT_CREATE
+{
+ Text [ en-US ] = "Create character style: $1";
+};
+String STR_UNDO_CHARFMT_DELETE
+{
+ Text [ en-US ] = "Delete character style: $1";
+};
+String STR_UNDO_CHARFMT_RENAME
+{
+ Text [ en-US ] = "Rename character style: $1 $2 $3";
+};
+String STR_UNDO_FRMFMT_CREATE
+{
+ Text [ en-US ] = "Create frame style: $1";
+};
+String STR_UNDO_FRMFMT_DELETE
+{
+ Text [ en-US ] = "Delete frame style: $1";
+};
+String STR_UNDO_FRMFMT_RENAME
+{
+ Text [ en-US ] = "Rename frame style: $1 $2 $3";
+};
+String STR_UNDO_NUMRULE_CREATE
+{
+ Text [ en-US ] = "Create numbering style: $1";
+};
+String STR_UNDO_NUMRULE_DELETE
+{
+ Text [ en-US ] = "Delete numbering style: $1";
+};
+String STR_UNDO_NUMRULE_RENAME
+{
+ Text [ en-US ] = "Rename numbering style: $1 $2 $3";
+};
+String STR_UNDO_BOOKMARK_RENAME
+{
+ Text[ en-US ] = "Rename bookmark: $1 $2 $3";
+};
+String STR_UNDO_INDEX_ENTRY_INSERT
+{
+ Text[ en-US ] = "Insert index entry";
+};
+String STR_UNDO_INDEX_ENTRY_DELETE
+{
+ Text[ en-US ] = "Delete index entry";
+};
+String STR_FIELD
+{
+ Text [ en-US ] = "field";
+};
+String STR_PARAGRAPHS
+{
+ Text [ en-US ] = "Paragraphs" ;
+};
+String STR_FRAME
+{
+ Text [ en-US ] = "frame";
+};
+String STR_OLE
+{
+ Text [ en-US ] = "OLE-object";
+};
+String STR_MATH_FORMULA
+{
+ Text [ en-US ] = "formula";
+};
+String STR_CHART
+{
+ Text [ en-US ] = "chart";
+};
+String STR_NOTE
+{
+ Text [ en-US ] = "comment";
+};
+String STR_REFERENCE
+{
+ Text [ en-US ] = "cross-reference";
+};
+String STR_SCRIPT
+{
+ Text [ en-US ] = "script";
+};
+String STR_AUTHORITY_ENTRY
+{
+ Text[ en-US ] = "bibliography entry";
+};
+String STR_SPECIALCHAR
+{
+ Text[ en-US ] = "special character";
+};
+String STR_FOOTNOTE
+{
+ Text[ en-US ] = "footnote";
+};
+String STR_GRAPHIC
+{
+ Text[ en-US ] = "picture";
+};
+String STR_DRAWING_OBJECTS
+{
+ Text[ en-US ] = "drawing object(s)";
+};
+String STR_TABLE_NAME
+{
+ Text[ en-US ] = "table: $1$2$3";
+};
+String STR_PARAGRAPH_UNDO
+{
+ Text[ en-US ] = "paragraph";
+};
+String STR_UNDO_FLYFRMFMT_TITLE
+{
+ Text[ en-US ] = "Change object title of $1";
+};
+String STR_UNDO_FLYFRMFMT_DESCRITPTION
+{
+ Text[ en-US ] = "Change object description of $1";
+};
diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
new file mode 100644
index 000000000000..d405afa98011
--- /dev/null
+++ b/sw/source/core/undo/undobj.cxx
@@ -0,0 +1,1402 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <txtftn.hxx>
+#include <fmtanchr.hxx>
+#include <ftnidx.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <rolbck.hxx>
+#include <ndnotxt.hxx>
+#include <IMark.hxx>
+#include <mvsave.hxx>
+#include <redline.hxx>
+#include <crossrefbookmark.hxx>
+#include <undo.hrc>
+#include <comcore.hrc>
+#include <docsh.hxx>
+
+class SwRedlineSaveData : public SwUndRng, public SwRedlineData,
+ private SwUndoSaveSection
+{
+public:
+ SwRedlineSaveData( SwComparePosition eCmpPos,
+ const SwPosition& rSttPos, const SwPosition& rEndPos,
+ SwRedline& rRedl, BOOL bCopyNext );
+ ~SwRedlineSaveData();
+ void RedlineToDoc( SwPaM& rPam );
+ SwNodeIndex* GetMvSttIdx() const
+ { return SwUndoSaveSection::GetMvSttIdx(); }
+
+#if OSL_DEBUG_LEVEL > 1
+ USHORT nRedlineCount;
+#endif
+};
+
+SV_IMPL_PTRARR( SwUndos, SwUndo*)
+SV_IMPL_PTRARR( SwRedlineSaveDatas, SwRedlineSaveDataPtr )
+
+SwUndoIter::SwUndoIter( SwPaM* pPam, SwUndoId nId )
+{
+ nUndoId = nId;
+ bWeiter = nId ? TRUE : FALSE;
+ bUpdateAttr = FALSE;
+ pAktPam = pPam;
+ nEndCnt = 0;
+ pSelFmt = 0;
+ pMarkList = 0;
+}
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+//------------------------------------------------------------
+
+// Diese Klasse speichert den Pam als USHORT's und kann diese wieder zu
+
+// einem PaM zusammensetzen
+SwUndRng::SwUndRng()
+ : nSttNode( 0 ), nEndNode( 0 ), nSttCntnt( 0 ), nEndCntnt( 0 )
+{
+}
+
+SwUndRng::SwUndRng( const SwPaM& rPam )
+{
+ SetValues( rPam );
+}
+
+void SwUndRng::SetValues( const SwPaM& rPam )
+{
+ const SwPosition *pStt = rPam.Start();
+ if( rPam.HasMark() )
+ {
+ const SwPosition *pEnd = rPam.GetPoint() == pStt
+ ? rPam.GetMark()
+ : rPam.GetPoint();
+ nEndNode = pEnd->nNode.GetIndex();
+ nEndCntnt = pEnd->nContent.GetIndex();
+ }
+ else
+ // keine Selektion !!
+ nEndNode = 0, nEndCntnt = STRING_MAXLEN;
+
+ nSttNode = pStt->nNode.GetIndex();
+ nSttCntnt = pStt->nContent.GetIndex();
+}
+
+void SwUndRng::SetPaM( SwPaM & rPam, BOOL bCorrToCntnt ) const
+{
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = nSttNode;
+ SwNode* pNd = rPam.GetNode();
+ if( pNd->IsCntntNode() )
+ rPam.GetPoint()->nContent.Assign( pNd->GetCntntNode(), nSttCntnt );
+ else if( bCorrToCntnt )
+ rPam.Move( fnMoveForward, fnGoCntnt );
+ else
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+
+ if( !nEndNode && STRING_MAXLEN == nEndCntnt ) // keine Selection
+ return ;
+
+ rPam.SetMark();
+ if( nSttNode == nEndNode && nSttCntnt == nEndCntnt )
+ return; // nichts mehr zu tun
+
+ rPam.GetPoint()->nNode = nEndNode;
+ if( (pNd = rPam.GetNode())->IsCntntNode() )
+ rPam.GetPoint()->nContent.Assign( pNd->GetCntntNode(), nEndCntnt );
+ else if( bCorrToCntnt )
+ rPam.Move( fnMoveBackward, fnGoCntnt );
+ else
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+}
+
+void SwUndRng::SetPaM( SwUndoIter& rIter, BOOL bCorrToCntnt ) const
+{
+ if( rIter.pAktPam )
+ SetPaM( *rIter.pAktPam, bCorrToCntnt );
+}
+
+//------------------------------------------------------------
+
+
+void SwUndo::RemoveIdxFromSection( SwDoc& rDoc, ULONG nSttIdx,
+ ULONG* pEndIdx )
+{
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttIdx );
+ SwNodeIndex aEndIdx( rDoc.GetNodes(), pEndIdx ? *pEndIdx
+ : aIdx.GetNode().EndOfSectionIndex() );
+ SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
+ rDoc.CorrAbs( aIdx, aEndIdx, aPos, TRUE );
+}
+
+void SwUndo::RemoveIdxFromRange( SwPaM& rPam, BOOL bMoveNext )
+{
+ const SwPosition* pEnd = rPam.End();
+ if( bMoveNext )
+ {
+ if( pEnd != rPam.GetPoint() )
+ rPam.Exchange();
+
+ SwNodeIndex aStt( rPam.GetMark()->nNode );
+ SwNodeIndex aEnd( rPam.GetPoint()->nNode );
+
+ if( !rPam.Move( fnMoveForward ) )
+ {
+ rPam.Exchange();
+ if( !rPam.Move( fnMoveBackward ) )
+ {
+ rPam.GetPoint()->nNode = rPam.GetDoc()->GetNodes().GetEndOfPostIts();
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+ }
+ }
+
+ rPam.GetDoc()->CorrAbs( aStt, aEnd, *rPam.GetPoint(), TRUE );
+ }
+ else
+ rPam.GetDoc()->CorrAbs( rPam, *pEnd, TRUE );
+}
+
+void SwUndo::RemoveIdxRel( ULONG nIdx, const SwPosition& rPos )
+{
+ // nur die Crsr verschieben; die Bookmarks/TOXMarks/.. werden vom
+ // entsp. JoinNext/JoinPrev erledigt!
+ SwNodeIndex aIdx( rPos.nNode.GetNode().GetNodes(), nIdx );
+ ::PaMCorrRel( aIdx, rPos );
+}
+
+SwUndo::SwUndo( SwUndoId nI )
+ : nId(nI), nOrigRedlineMode(nsRedlineMode_t::REDLINE_NONE),
+ bCacheComment(true), pComment(NULL)
+{
+}
+
+bool SwUndo::IsDelBox() const
+{
+ return GetId() == UNDO_COL_DELETE || GetId() == UNDO_ROW_DELETE ||
+ GetId() == UNDO_TABLE_DELBOX;
+}
+
+SwUndo::~SwUndo()
+{
+ delete pComment;
+}
+
+void SwUndo::Repeat( SwUndoIter& rIter )
+{
+ rIter.pLastUndoObj = this;
+}
+
+String SwUndo::GetComment() const
+{
+ String aResult;
+
+ if (bCacheComment)
+ {
+ if (! pComment)
+ {
+ pComment = new String(SW_RES(UNDO_BASE + nId));
+
+ SwRewriter aRewriter = GetRewriter();
+
+ *pComment = aRewriter.Apply(*pComment);
+ }
+
+ aResult = *pComment;
+ }
+ else
+ {
+ aResult = String(SW_RES(UNDO_BASE + nId));
+
+ SwRewriter aRewriter = GetRewriter();
+
+ aResult = aRewriter.Apply(aResult);
+ }
+
+ return aResult;
+}
+
+SwUndoId SwUndo::GetEffectiveId() const
+{
+ return GetId();
+}
+
+SwRewriter SwUndo::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ return aResult;
+}
+
+//------------------------------------------------------------
+
+SwUndoSaveCntnt::SwUndoSaveCntnt()
+ : pHistory( 0 )
+{}
+
+SwUndoSaveCntnt::~SwUndoSaveCntnt()
+{
+ delete pHistory;
+}
+
+ // wird fuer das Loeschen von Inhalt benoetigt. Fuer das ReDo werden
+ // Inhalte in das UndoNodesArray verschoben. Diese Methoden fuegen
+ // am Ende eines TextNodes fuer die Attribute einen Trenner ein.
+ // Dadurch werden die Attribute nicht expandiert.
+ // MoveTo.. verschiebt aus dem NodesArray in das UndoNodesArray
+ // MoveFrom.. verschiebt aus dem UndoNodesArray in das NodesArray
+
+ // 2.8.93: ist pEndNdIdx angebenen, wird vom Undo/Redo -Ins/DelFly
+ // aufgerufen. Dann soll die gesamte Section verschoben werden.
+
+void SwUndoSaveCntnt::MoveToUndoNds( SwPaM& rPaM, SwNodeIndex* pNodeIdx,
+ SwIndex* pCntIdx, ULONG* pEndNdIdx, xub_StrLen* pEndCntIdx )
+{
+ SwDoc& rDoc = *rPaM.GetDoc();
+ BOOL bUndo = rDoc.DoesUndo();
+ rDoc.DoUndo( FALSE );
+
+ SwNoTxtNode* pCpyNd = rPaM.GetNode()->GetNoTxtNode();
+
+ // jetzt kommt das eigentliche Loeschen(Verschieben)
+ SwNodes& rNds = (SwNodes&)*rDoc.GetUndoNds();
+ SwPosition aPos( pEndNdIdx ? rNds.GetEndOfPostIts()
+ : rNds.GetEndOfExtras() );
+ aPos.nNode--;
+
+ const SwPosition* pStt = rPaM.Start(), *pEnd = rPaM.End();
+
+ if( pCpyNd || pEndNdIdx || !aPos.nNode.GetNode().GetCntntNode() ||
+ (!pStt->nContent.GetIndex() && (pStt->nNode != pEnd->nNode ||
+ (!pStt->nNode.GetNode().GetCntntNode() ||
+ pStt->nNode.GetNode().GetCntntNode()->Len() ==
+ pEnd->nContent.GetIndex() ) ) ) )
+ {
+ aPos.nNode++;
+ aPos.nContent = 0;
+ }
+ else
+ aPos.nNode.GetNode().GetCntntNode()->MakeEndIndex( &aPos.nContent );
+
+ // als USHORT merken; die Indizies verschieben sich !!
+ ULONG nTmpMvNode = aPos.nNode.GetIndex();
+ xub_StrLen nTmpMvCntnt = aPos.nContent.GetIndex();
+
+ if( pCpyNd || pEndNdIdx )
+ {
+ SwNodeRange aRg( pStt->nNode, 0, pEnd->nNode, 1 );
+ rDoc.GetNodes()._MoveNodes( aRg, rNds, aPos.nNode, FALSE );
+ aPos.nContent = 0;
+ aPos.nNode--;
+ }
+ else
+ {
+ rDoc.GetNodes().MoveRange( rPaM, aPos, rNds );
+
+ SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+ if( pTxtNd ) // fuege einen Trenner fuer die Attribute ein !
+ {
+ // weil aber beim Insert die Attribute angefasst/sprich
+ // aus dem Array geloescht und wieder eingefuegt werden, koennen
+ // dadurch Attribute verschwinden (z.B "Fett aus" von 10-20,
+ // "Fett an" von 12-15, dann wird durchs Insert/Delete das
+ // "Fett an" geloescht !! Ist hier aber nicht erwuenscht !!)
+ // DARUM: nicht die Hints anfassen, direct den String manipulieren
+
+ String& rStr = (String&)pTxtNd->GetTxt();
+ // Zur Sicherheit lieber nur wenn wirklich am Ende steht
+ if( rStr.Len() == aPos.nContent.GetIndex() )
+ {
+ rStr.Insert( ' ' );
+ ++aPos.nContent;
+ }
+ else
+ {
+ pTxtNd->InsertText( sal_Unicode(' '), aPos.nContent,
+ IDocumentContentOperations::INS_NOHINTEXPAND );
+ }
+ }
+ }
+ if( pEndNdIdx )
+ *pEndNdIdx = aPos.nNode.GetIndex();
+ if( pEndCntIdx )
+ *pEndCntIdx = aPos.nContent.GetIndex();
+
+ // alte Position
+ aPos.nNode = nTmpMvNode;
+ if( pNodeIdx )
+ *pNodeIdx = aPos.nNode;
+
+ if( pCntIdx )
+ {
+ SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
+ if( pCNd )
+ pCntIdx->Assign( pCNd, nTmpMvCntnt );
+ else
+ pCntIdx->Assign( 0, 0 );
+ }
+
+ rDoc.DoUndo( bUndo );
+}
+
+void SwUndoSaveCntnt::MoveFromUndoNds( SwDoc& rDoc, ULONG nNodeIdx,
+ xub_StrLen nCntIdx, SwPosition& rInsPos,
+ ULONG* pEndNdIdx, xub_StrLen* pEndCntIdx )
+{
+ // jetzt kommt das wiederherstellen
+ SwNodes& rNds = (SwNodes&)*rDoc.GetUndoNds();
+ if( nNodeIdx == rNds.GetEndOfPostIts().GetIndex() )
+ return; // nichts gespeichert
+
+ BOOL bUndo = rDoc.DoesUndo();
+ rDoc.DoUndo( FALSE );
+
+ SwPaM aPaM( rInsPos );
+ if( pEndNdIdx ) // dann hole aus diesem den Bereich
+ aPaM.GetPoint()->nNode.Assign( rNds, *pEndNdIdx );
+ else
+ {
+ aPaM.GetPoint()->nNode = rNds.GetEndOfExtras();
+ GoInCntnt( aPaM, fnMoveBackward );
+ }
+
+ SwTxtNode* pTxtNd = aPaM.GetNode()->GetTxtNode();
+ if( !pEndNdIdx && pTxtNd ) // loesche den Trenner wieder
+ {
+ if( pEndCntIdx )
+ aPaM.GetPoint()->nContent.Assign( pTxtNd, *pEndCntIdx );
+ if( pTxtNd->GetTxt().Len() )
+ {
+ GoInCntnt( aPaM, fnMoveBackward );
+ pTxtNd->EraseText( aPaM.GetPoint()->nContent, 1 );
+ }
+
+ aPaM.SetMark();
+ aPaM.GetPoint()->nNode = nNodeIdx;
+ aPaM.GetPoint()->nContent.Assign( aPaM.GetCntntNode(), nCntIdx );
+
+ _SaveRedlEndPosForRestore aRedlRest( rInsPos.nNode, rInsPos.nContent.GetIndex() );
+
+ rNds.MoveRange( aPaM, rInsPos, rDoc.GetNodes() );
+
+ // noch den letzen Node loeschen.
+ if( !aPaM.GetPoint()->nContent.GetIndex() ||
+ ( aPaM.GetPoint()->nNode++ && // noch leere Nodes am Ende ??
+ &rNds.GetEndOfExtras() != &aPaM.GetPoint()->nNode.GetNode() ))
+ {
+ aPaM.GetPoint()->nContent.Assign( 0, 0 );
+ aPaM.SetMark();
+ rNds.Delete( aPaM.GetPoint()->nNode,
+ rNds.GetEndOfExtras().GetIndex() -
+ aPaM.GetPoint()->nNode.GetIndex() );
+ }
+
+ aRedlRest.Restore();
+ }
+ else if( pEndNdIdx || !pTxtNd )
+ {
+ SwNodeRange aRg( rNds, nNodeIdx, rNds, (pEndNdIdx
+ ? ((*pEndNdIdx) + 1)
+ : rNds.GetEndOfExtras().GetIndex() ) );
+ rNds._MoveNodes( aRg, rDoc.GetNodes(), rInsPos.nNode, 0 == pEndNdIdx );
+
+ }
+ else {
+ OSL_ENSURE( FALSE, "was ist es denn nun?" );
+ }
+
+ rDoc.DoUndo( bUndo );
+}
+
+// diese beiden Methoden bewegen den Point vom Pam zurueck/vor. Damit
+// kann fuer ein Undo/Redo ein Bereich aufgespannt werden. (Der
+// Point liegt dann vor dem manipuliertem Bereich !!)
+// Das Flag gibt an, ob noch vorm Point Inhalt steht.
+
+BOOL SwUndoSaveCntnt::MovePtBackward( SwPaM& rPam )
+{
+ rPam.SetMark();
+ if( rPam.Move( fnMoveBackward ))
+ return TRUE;
+
+ // gibt es nach vorne keinen Inhalt mehr, so setze den Point einfach
+ // auf die vorherige Position (Node und Content, damit der Content
+ // abgemeldet wird !!)
+ rPam.GetPoint()->nNode--;
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+ return FALSE;
+}
+
+void SwUndoSaveCntnt::MovePtForward( SwPaM& rPam, BOOL bMvBkwrd )
+{
+ // gab es noch Inhalt vor der Position ?
+ if( bMvBkwrd )
+ rPam.Move( fnMoveForward );
+ else
+ { // setzen Point auf die naechste Position
+ rPam.GetPoint()->nNode++;
+ SwCntntNode* pCNd = rPam.GetCntntNode();
+ if( pCNd )
+ pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
+ else
+ rPam.Move( fnMoveForward );
+ }
+}
+
+
+/*
+ JP 21.03.94: loesche alle Objecte, die ContentIndizies auf den ang.
+ Bereich besitzen.
+ Zur Zeit gibts folgende Objecte
+ - Fussnoten
+ - Flys
+ - Bookmarks
+ - Verzeichnisse
+*/
+// --> OD 2007-10-17 #i81002# - extending method:
+// delete certain (not all) cross-reference bookmarks at text node of <rMark>
+// and at text node of <rPoint>, if these text nodes aren't the same.
+void SwUndoSaveCntnt::DelCntntIndex( const SwPosition& rMark,
+ const SwPosition& rPoint,
+ DelCntntType nDelCntntType )
+{
+ const SwPosition *pStt = rMark < rPoint ? &rMark : &rPoint,
+ *pEnd = &rMark == pStt ? &rPoint : &rMark;
+
+ SwDoc* pDoc = rMark.nNode.GetNode().GetDoc();
+
+ BOOL bDoesUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+
+ // 1. Fussnoten
+ if( nsDelCntntType::DELCNT_FTN & nDelCntntType )
+ {
+ SwFtnIdxs& rFtnArr = pDoc->GetFtnIdxs();
+ if( rFtnArr.Count() )
+ {
+ const SwNode* pFtnNd;
+ USHORT nPos;
+ rFtnArr.SeekEntry( pStt->nNode, &nPos );
+ SwTxtFtn* pSrch;
+
+ // loesche erstmal alle, die dahinter stehen
+ while( nPos < rFtnArr.Count() && ( pFtnNd =
+ &( pSrch = rFtnArr[ nPos ] )->GetTxtNode())->GetIndex()
+ <= pEnd->nNode.GetIndex() )
+ {
+ xub_StrLen nFtnSttIdx = *pSrch->GetStart();
+ if( (nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType )
+ ? (&pEnd->nNode.GetNode() == pFtnNd )
+ : (( &pStt->nNode.GetNode() == pFtnNd &&
+ pStt->nContent.GetIndex() > nFtnSttIdx) ||
+ ( &pEnd->nNode.GetNode() == pFtnNd &&
+ nFtnSttIdx >= pEnd->nContent.GetIndex() )) )
+ {
+ ++nPos; // weiter suchen
+ continue;
+ }
+
+ // es muss leider ein Index angelegt werden. Sonst knallts im
+ // TextNode, weil im DTOR der SwFtn dieser geloescht wird !!
+ SwTxtNode* pTxtNd = (SwTxtNode*)pFtnNd;
+ if( !pHistory )
+ pHistory = new SwHistory;
+ SwTxtAttr* const pFtnHnt =
+ pTxtNd->GetTxtAttrForCharAt( nFtnSttIdx );
+ OSL_ENSURE( pFtnHnt, "kein FtnAttribut" );
+ SwIndex aIdx( pTxtNd, nFtnSttIdx );
+ pHistory->Add( pFtnHnt, pTxtNd->GetIndex(), false );
+ pTxtNd->EraseText( aIdx, 1 );
+ }
+
+ while( nPos-- && ( pFtnNd = &( pSrch = rFtnArr[ nPos ] )->
+ GetTxtNode())->GetIndex() >= pStt->nNode.GetIndex() )
+ {
+ xub_StrLen nFtnSttIdx = *pSrch->GetStart();
+ if( !(nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType) && (
+ ( &pStt->nNode.GetNode() == pFtnNd &&
+ pStt->nContent.GetIndex() > nFtnSttIdx ) ||
+ ( &pEnd->nNode.GetNode() == pFtnNd &&
+ nFtnSttIdx >= pEnd->nContent.GetIndex() )))
+ continue; // weiter suchen
+
+ // es muss leider ein Index angelegt werden. Sonst knallts im
+ // TextNode, weil im DTOR der SwFtn dieser geloescht wird !!
+ SwTxtNode* pTxtNd = (SwTxtNode*)pFtnNd;
+ if( !pHistory )
+ pHistory = new SwHistory;
+ SwTxtAttr* const pFtnHnt =
+ pTxtNd->GetTxtAttrForCharAt( nFtnSttIdx );
+ OSL_ENSURE( pFtnHnt, "kein FtnAttribut" );
+ SwIndex aIdx( pTxtNd, nFtnSttIdx );
+ pHistory->Add( pFtnHnt, pTxtNd->GetIndex(), false );
+ pTxtNd->EraseText( aIdx, 1 );
+ }
+ }
+ }
+
+ // 2. Flys
+ if( nsDelCntntType::DELCNT_FLY & nDelCntntType )
+ {
+ USHORT nChainInsPos = pHistory ? pHistory->Count() : 0;
+ const SwSpzFrmFmts& rSpzArr = *pDoc->GetSpzFrmFmts();
+ if( rSpzArr.Count() )
+ {
+ const BOOL bDelFwrd = rMark.nNode.GetIndex() <= rPoint.nNode.GetIndex();
+ SwFlyFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+ USHORT n = rSpzArr.Count();
+ const SwPosition* pAPos;
+
+ while( n && rSpzArr.Count() )
+ {
+ pFmt = (SwFlyFrmFmt*)rSpzArr[--n];
+ pAnchor = &pFmt->GetAnchor();
+ switch( pAnchor->GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ if( 0 != (pAPos = pAnchor->GetCntntAnchor() ) &&
+ (( nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType )
+ ? ( pStt->nNode <= pAPos->nNode &&
+ pAPos->nNode < pEnd->nNode )
+ : ( *pStt <= *pAPos && *pAPos < *pEnd )) )
+ {
+ if( !pHistory )
+ pHistory = new SwHistory;
+ SwTxtNode* pTxtNd = pDoc->GetNodes()[ pAPos->nNode]->GetTxtNode();
+ SwTxtAttr* const pFlyHnt = pTxtNd->GetTxtAttrForCharAt(
+ pAPos->nContent.GetIndex());
+ OSL_ENSURE( pFlyHnt, "kein FlyAttribut" );
+ pHistory->Add( pFlyHnt, 0, false );
+ // n wieder zurueck, damit nicht ein Format uebesprungen wird !
+ n = n >= rSpzArr.Count() ? rSpzArr.Count() : n+1;
+ }
+ break;
+ case FLY_AT_PARA:
+ {
+ pAPos = pAnchor->GetCntntAnchor();
+ if( pAPos )
+ {
+ bool bTmp;
+ if( nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType )
+ bTmp = pStt->nNode <= pAPos->nNode && pAPos->nNode < pEnd->nNode;
+ else
+ {
+ if (bDelFwrd)
+ bTmp = rMark.nNode < pAPos->nNode &&
+ pAPos->nNode <= rPoint.nNode;
+ else
+ bTmp = rPoint.nNode <= pAPos->nNode &&
+ pAPos->nNode < rMark.nNode;
+ }
+
+ if (bTmp)
+ {
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ // Moving the anchor?
+ if( !( nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType ) &&
+ ( rPoint.nNode.GetIndex() == pAPos->nNode.GetIndex() ) )
+ {
+ // Do not try to move the anchor to a table!
+ if( rMark.nNode.GetNode().GetTxtNode() )
+ {
+ pHistory->Add( *pFmt );
+ SwFmtAnchor aAnch( *pAnchor );
+ SwPosition aPos( rMark.nNode );
+ aAnch.SetAnchor( &aPos );
+ pFmt->SetFmtAttr( aAnch );
+ }
+ }
+ else
+ {
+ pHistory->Add( *pFmt, nChainInsPos );
+ // n wieder zurueck, damit nicht ein
+ // Format uebesprungen wird !
+ n = n >= rSpzArr.Count() ?
+ rSpzArr.Count() : n+1;
+ }
+ }
+ }
+ }
+ break;
+ case FLY_AT_CHAR:
+ if( 0 != (pAPos = pAnchor->GetCntntAnchor() ) &&
+ ( pStt->nNode <= pAPos->nNode && pAPos->nNode <= pEnd->nNode ) )
+ {
+ if( !pHistory )
+ pHistory = new SwHistory;
+ if (IsDestroyFrameAnchoredAtChar(
+ *pAPos, *pStt, *pEnd, nDelCntntType))
+ {
+ pHistory->Add( *pFmt, nChainInsPos );
+ n = n >= rSpzArr.Count() ? rSpzArr.Count() : n+1;
+ }
+ else if( !( nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType ) )
+ {
+ if( *pStt <= *pAPos && *pAPos < *pEnd )
+ {
+ // These are the objects anchored
+ // between section start and end position
+ // Do not try to move the anchor to a table!
+ if( rMark.nNode.GetNode().GetTxtNode() )
+ {
+ pHistory->Add( *pFmt );
+ SwFmtAnchor aAnch( *pAnchor );
+ aAnch.SetAnchor( &rMark );
+ pFmt->SetFmtAttr( aAnch );
+ }
+ }
+ }
+ }
+ break;
+ case FLY_AT_FLY:
+
+ if( 0 != (pAPos = pAnchor->GetCntntAnchor() ) &&
+ pStt->nNode == pAPos->nNode )
+ {
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ pHistory->Add( *pFmt, nChainInsPos );
+
+ // n wieder zurueck, damit nicht ein Format uebesprungen wird !
+ n = n >= rSpzArr.Count() ? rSpzArr.Count() : n+1;
+ }
+ break;
+ default: break;
+ }
+ }
+ }
+ }
+
+ // 3. Bookmarks
+ if( nsDelCntntType::DELCNT_BKM & nDelCntntType )
+ {
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ if( pMarkAccess->getMarksCount() )
+ {
+
+ for( USHORT n = 0; n < pMarkAccess->getMarksCount(); ++n )
+ {
+ // --> OD 2007-10-17 #i81002#
+ bool bSavePos = false;
+ bool bSaveOtherPos = false;
+ const ::sw::mark::IMark* pBkmk = (pMarkAccess->getMarksBegin() + n)->get();
+ if( nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType )
+ {
+ if( pStt->nNode <= pBkmk->GetMarkPos().nNode &&
+ pBkmk->GetMarkPos().nNode < pEnd->nNode )
+ bSavePos = true;
+ if( pBkmk->IsExpanded() &&
+ pStt->nNode <= pBkmk->GetOtherMarkPos().nNode &&
+ pBkmk->GetOtherMarkPos().nNode < pEnd->nNode )
+ bSaveOtherPos = true;
+ }
+ else
+ {
+ // --> OD 2009-08-06 #i92125#
+ bool bKeepCrossRefBkmk( false );
+ {
+ if ( rMark.nNode == rPoint.nNode &&
+ ( IDocumentMarkAccess::GetType(*pBkmk) ==
+ IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK ||
+ IDocumentMarkAccess::GetType(*pBkmk) ==
+ IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK ) )
+ {
+ bKeepCrossRefBkmk = true;
+ }
+ }
+ if ( !bKeepCrossRefBkmk )
+ {
+ bool bMaybe = false;
+ if ( *pStt <= pBkmk->GetMarkPos() && pBkmk->GetMarkPos() <= *pEnd )
+ {
+ if( pBkmk->GetMarkPos() == *pEnd ||
+ ( *pStt == pBkmk->GetMarkPos() && pBkmk->IsExpanded() ) )
+ bMaybe = true;
+ else
+ bSavePos = true;
+ }
+ if( pBkmk->IsExpanded() &&
+ *pStt <= pBkmk->GetOtherMarkPos() && pBkmk->GetOtherMarkPos() <= *pEnd )
+ {
+ if( bSavePos || bSaveOtherPos ||
+ ( pBkmk->GetOtherMarkPos() < *pEnd && pBkmk->GetOtherMarkPos() > *pStt ) )
+ {
+ if( bMaybe )
+ bSavePos = true;
+ bSaveOtherPos = true;
+ }
+ }
+ }
+ // <--
+
+ // --> OD 2007-10-17 #i81002#
+ const bool bDifferentTxtNodesAtMarkAndPoint(
+ rMark.nNode != rPoint.nNode &&
+ rMark.nNode.GetNode().GetTxtNode() &&
+ rPoint.nNode.GetNode().GetTxtNode() );
+ // <--
+ if( !bSavePos && !bSaveOtherPos && bDifferentTxtNodesAtMarkAndPoint &&
+ dynamic_cast< const ::sw::mark::CrossRefBookmark* >(pBkmk))
+ {
+ // delete cross-reference bookmark at <pStt>, if only part of
+ // <pEnd> text node content is deleted.
+ if( pStt->nNode == pBkmk->GetMarkPos().nNode &&
+ pEnd->nContent.GetIndex() !=
+ pEnd->nNode.GetNode().GetTxtNode()->Len() )
+ {
+ bSavePos = true;
+ bSaveOtherPos = false;
+ }
+ // delete cross-reference bookmark at <pEnd>, if only part of
+ // <pStt> text node content is deleted.
+ else if( pEnd->nNode == pBkmk->GetMarkPos().nNode &&
+ pStt->nContent.GetIndex() != 0 )
+ {
+ bSavePos = true;
+ bSaveOtherPos = false;
+ }
+ }
+ }
+ if( bSavePos || bSaveOtherPos )
+ {
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ pHistory->Add( *pBkmk, bSavePos, bSaveOtherPos );
+ if(bSavePos &&
+ (bSaveOtherPos || !pBkmk->IsExpanded()))
+ {
+ pMarkAccess->deleteMark(pMarkAccess->getMarksBegin()+n);
+ n--;
+ }
+ }
+ }
+ }
+ }
+
+ pDoc->DoUndo( bDoesUndo );
+}
+
+
+// sicher eine vollstaendige Section im Undo-Nodes-Array
+
+SwUndoSaveSection::SwUndoSaveSection()
+ : pMvStt( 0 ), pRedlSaveData( 0 ), nMvLen( 0 ), nStartPos( ULONG_MAX )
+{
+}
+
+SwUndoSaveSection::~SwUndoSaveSection()
+{
+ if( pMvStt ) // loesche noch den Bereich aus dem UndoNodes Array
+ {
+ // SaveSection speichert den Inhalt in der PostIt-Section
+ SwNodes& rUNds = pMvStt->GetNode().GetNodes();
+ rUNds.Delete( *pMvStt, nMvLen );
+
+ delete pMvStt;
+ }
+ delete pRedlSaveData;
+}
+
+void SwUndoSaveSection::SaveSection( SwDoc* pDoc, const SwNodeIndex& rSttIdx )
+{
+ SwNodeRange aRg( rSttIdx.GetNode(), *rSttIdx.GetNode().EndOfSectionNode() );
+ SaveSection( pDoc, aRg );
+}
+
+
+void SwUndoSaveSection::SaveSection( SwDoc* , const SwNodeRange& rRange )
+{
+ SwPaM aPam( rRange.aStart, rRange.aEnd );
+
+ // loesche alle Fussnoten / FlyFrames / Bookmarks / Verzeichnisse
+ DelCntntIndex( *aPam.GetMark(), *aPam.GetPoint() );
+
+ pRedlSaveData = new SwRedlineSaveDatas;
+ if( !SwUndo::FillSaveData( aPam, *pRedlSaveData, TRUE, TRUE ))
+ delete pRedlSaveData, pRedlSaveData = 0;
+
+ nStartPos = rRange.aStart.GetIndex();
+
+ aPam.GetPoint()->nNode--;
+ aPam.GetMark()->nNode++;
+
+ SwCntntNode* pCNd = aPam.GetCntntNode( FALSE );
+ if( pCNd )
+ aPam.GetMark()->nContent.Assign( pCNd, 0 );
+ if( 0 != ( pCNd = aPam.GetCntntNode( TRUE )) )
+ aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+
+ // Positionen als SwIndex merken, damit im DTOR dieser Bereich
+ // entfernt werden kann !!
+ ULONG nEnd;
+ pMvStt = new SwNodeIndex( rRange.aStart );
+ MoveToUndoNds( aPam, pMvStt, 0, &nEnd, 0 );
+ nMvLen = nEnd - pMvStt->GetIndex() + 1;
+}
+
+void SwUndoSaveSection::RestoreSection( SwDoc* pDoc, SwNodeIndex* pIdx,
+ USHORT nSectType )
+{
+ if( ULONG_MAX != nStartPos ) // gab es ueberhaupt Inhalt ?
+ {
+ // ueberpruefe, ob der Inhalt an der alten Position steht
+ SwNodeIndex aSttIdx( pDoc->GetNodes(), nStartPos );
+ OSL_ENSURE( !pDoc->GetNodes()[ aSttIdx ]->GetCntntNode(),
+ "Position in irgendeiner Section" );
+
+ // move den Inhalt aus dem UndoNodes-Array in den Fly
+ SwStartNode* pSttNd = pDoc->GetNodes().MakeEmptySection( aSttIdx,
+ (SwStartNodeType)nSectType );
+
+ RestoreSection( pDoc, SwNodeIndex( *pSttNd->EndOfSectionNode() ));
+
+ if( pIdx )
+ *pIdx = *pSttNd;
+ }
+}
+
+void SwUndoSaveSection::RestoreSection( SwDoc* pDoc, const SwNodeIndex& rInsPos )
+{
+ if( ULONG_MAX != nStartPos ) // gab es ueberhaupt Inhalt ?
+ {
+ SwPosition aInsPos( rInsPos );
+ ULONG nEnd = pMvStt->GetIndex() + nMvLen - 1;
+ MoveFromUndoNds( *pDoc, pMvStt->GetIndex(), 0, aInsPos, &nEnd, 0 );
+
+ // Indizies wieder zerstoren, Inhalt ist aus dem UndoNodes-Array
+ // entfernt worden.
+ DELETEZ( pMvStt );
+ nMvLen = 0;
+
+ if( pRedlSaveData )
+ {
+ SwUndo::SetSaveData( *pDoc, *pRedlSaveData );
+ delete pRedlSaveData, pRedlSaveData = 0;
+ }
+ }
+}
+
+// START
+SwUndoStart::SwUndoStart( SwUndoId nInitId )
+ : SwUndo( UNDO_START ), nUserId( nInitId ), nEndOffset( 0 )
+{
+}
+
+void SwUndoStart::Undo( SwUndoIter& rUndoIter )
+{
+ if( !( --rUndoIter.nEndCnt ) && rUndoIter.bWeiter &&
+ ( rUndoIter.GetId() ? ( rUndoIter.GetId() == nUserId ||
+ ( UNDO_END == rUndoIter.GetId() && UNDO_START == GetId() )) : TRUE ))
+ rUndoIter.bWeiter = FALSE;
+}
+
+void SwUndoStart::Redo( SwUndoIter& rUndoIter )
+{
+ rUndoIter.bWeiter = TRUE;
+ ++rUndoIter.nEndCnt;
+}
+
+void SwUndoStart::Repeat( SwUndoIter& rUndoIter )
+{
+ rUndoIter.bWeiter = FALSE;
+}
+
+String SwUndoStart::GetComment() const
+{
+ String sResult;
+
+ switch (nUserId)
+ {
+ case UNDO_START:
+ case UNDO_END:
+ sResult = String("??", RTL_TEXTENCODING_ASCII_US);
+
+ break;
+
+ default:
+ sResult = String(SW_RES(UNDO_BASE + nUserId));
+ sResult = GetRewriter().Apply(sResult);
+ }
+
+ return sResult;
+}
+
+SwRewriter SwUndoStart::GetRewriter() const
+{
+ return mRewriter;
+}
+
+SwUndoId SwUndoStart::GetEffectiveId() const
+{
+ return GetUserId();
+}
+
+void SwUndoStart::SetRewriter(const SwRewriter & rRewriter)
+{
+ mRewriter = rRewriter;
+}
+
+// END
+SwUndoEnd::SwUndoEnd( SwUndoId nInitId )
+ : SwUndo( UNDO_END ), nUserId( nInitId ), nSttOffset( 0 )
+{
+}
+
+void SwUndoEnd::Undo( SwUndoIter& rUndoIter )
+{
+ if( rUndoIter.GetId() == GetId() || !rUndoIter.GetId() )
+ rUndoIter.bWeiter = TRUE;
+ if( rUndoIter.bWeiter )
+ ++rUndoIter.nEndCnt;
+}
+
+void SwUndoEnd::Redo( SwUndoIter& rUndoIter )
+{
+ if( !( --rUndoIter.nEndCnt ) && rUndoIter.bWeiter &&
+ ( rUndoIter.GetId() ? ( rUndoIter.GetId() == nUserId ||
+ ( UNDO_END == rUndoIter.GetId() && UNDO_START == GetId() )) : TRUE ))
+ rUndoIter.bWeiter = FALSE;
+}
+
+void SwUndoEnd::Repeat( SwUndoIter& rUndoIter )
+{
+ rUndoIter.bWeiter = FALSE;
+}
+
+String SwUndoEnd::GetComment() const
+{
+ String sResult;
+
+ switch (nUserId)
+ {
+ case UNDO_START:
+ case UNDO_END:
+ sResult = String("??", RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ default:
+ sResult = SW_RES(UNDO_BASE + nUserId);
+ sResult = GetRewriter().Apply(sResult);
+ }
+
+ return sResult;
+}
+
+void SwUndoEnd::SetRewriter(const SwRewriter & rRewriter)
+{
+ mRewriter = rRewriter;
+}
+
+SwUndoId SwUndoEnd::GetEffectiveId() const
+{
+ return GetUserId();
+}
+
+SwRewriter SwUndoEnd::GetRewriter() const
+{
+ return mRewriter;
+}
+
+/* */
+ // sicher und setze die RedlineDaten
+
+SwRedlineSaveData::SwRedlineSaveData( SwComparePosition eCmpPos,
+ const SwPosition& rSttPos,
+ const SwPosition& rEndPos,
+ SwRedline& rRedl,
+ BOOL bCopyNext )
+ : SwUndRng( rRedl ),
+ SwRedlineData( rRedl.GetRedlineData(), bCopyNext )
+{
+ OSL_ENSURE( POS_OUTSIDE == eCmpPos ||
+ !rRedl.GetContentIdx(), "Redline mit Content" );
+
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE: // Pos1 ueberlappt Pos2 am Anfang
+ nEndNode = rEndPos.nNode.GetIndex();
+ nEndCntnt = rEndPos.nContent.GetIndex();
+ break;
+ case POS_OVERLAP_BEHIND: // Pos1 ueberlappt Pos2 am Ende
+ nSttNode = rSttPos.nNode.GetIndex();
+ nSttCntnt = rSttPos.nContent.GetIndex();
+ break;
+
+ case POS_INSIDE: // Pos1 liegt vollstaendig in Pos2
+ nSttNode = rSttPos.nNode.GetIndex();
+ nSttCntnt = rSttPos.nContent.GetIndex();
+ nEndNode = rEndPos.nNode.GetIndex();
+ nEndCntnt = rEndPos.nContent.GetIndex();
+ break;
+
+ case POS_OUTSIDE: // Pos2 liegt vollstaendig in Pos1
+ if( rRedl.GetContentIdx() )
+ {
+ // dann den Bereich ins UndoArray verschieben und merken
+ SaveSection( rRedl.GetDoc(), *rRedl.GetContentIdx() );
+ rRedl.SetContentIdx( 0 );
+ }
+ break;
+
+ case POS_EQUAL: // Pos1 ist genauso gross wie Pos2
+ break;
+
+ default:
+ OSL_ENSURE( !this, "keine gueltigen Daten!" );
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ nRedlineCount = rSttPos.nNode.GetNode().GetDoc()->GetRedlineTbl().Count();
+#endif
+}
+
+SwRedlineSaveData::~SwRedlineSaveData()
+{
+}
+
+void SwRedlineSaveData::RedlineToDoc( SwPaM& rPam )
+{
+ SwDoc& rDoc = *rPam.GetDoc();
+ SwRedline* pRedl = new SwRedline( *this, rPam );
+
+ if( GetMvSttIdx() )
+ {
+ SwNodeIndex aIdx( rDoc.GetNodes() );
+ RestoreSection( &rDoc, &aIdx, SwNormalStartNode );
+ if( GetHistory() )
+ GetHistory()->Rollback( &rDoc );
+ pRedl->SetContentIdx( &aIdx );
+ }
+ SetPaM( *pRedl );
+ // erstmal die "alten" entfernen, damit im Append keine unerwarteten
+ // Dinge passieren, wie z.B. eine Delete in eigenen Insert. Dann wird
+ // naehmlich das gerade restaurierte wieder geloescht - nicht das gewollte
+ rDoc.DeleteRedline( *pRedl, false, USHRT_MAX );
+
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES));
+ //#i92154# let UI know about a new redline with comment
+ if (rDoc.GetDocShell() && (pRedl->GetComment() != String(::rtl::OUString::createFromAscii(""))) )
+ rDoc.GetDocShell()->Broadcast(SwRedlineHint(pRedl,SWREDLINE_INSERTED));
+ //
+#if OSL_DEBUG_LEVEL > 0
+ bool const bSuccess =
+#endif
+ rDoc.AppendRedline( pRedl, true );
+ OSL_ENSURE(bSuccess,
+ "SwRedlineSaveData::RedlineToDoc: insert redline failed");
+ rDoc.SetRedlineMode_intern( eOld );
+}
+
+BOOL SwUndo::FillSaveData( const SwPaM& rRange, SwRedlineSaveDatas& rSData,
+ BOOL bDelRange, BOOL bCopyNext )
+{
+ if( rSData.Count() )
+ rSData.DeleteAndDestroy( 0, rSData.Count() );
+
+ SwRedlineSaveData* pNewData;
+ const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
+ const SwRedlineTbl& rTbl = rRange.GetDoc()->GetRedlineTbl();
+ USHORT n = 0;
+ rRange.GetDoc()->GetRedline( *pStt, &n );
+ for( ; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
+
+ SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
+ if( POS_BEFORE != eCmpPos && POS_BEHIND != eCmpPos &&
+ POS_COLLIDE_END != eCmpPos && POS_COLLIDE_START != eCmpPos )
+ {
+ pNewData = new SwRedlineSaveData( eCmpPos, *pStt, *pEnd,
+ *pRedl, bCopyNext );
+ rSData.Insert( pNewData, rSData.Count() );
+ }
+ }
+ if( rSData.Count() && bDelRange )
+ rRange.GetDoc()->DeleteRedline( rRange, false, USHRT_MAX );
+ return 0 != rSData.Count();
+}
+
+BOOL SwUndo::FillSaveDataForFmt( const SwPaM& rRange, SwRedlineSaveDatas& rSData )
+{
+ if( rSData.Count() )
+ rSData.DeleteAndDestroy( 0, rSData.Count() );
+
+ SwRedlineSaveData* pNewData;
+ const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
+ const SwRedlineTbl& rTbl = rRange.GetDoc()->GetRedlineTbl();
+ USHORT n = 0;
+ rRange.GetDoc()->GetRedline( *pStt, &n );
+ for( ; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( nsRedlineType_t::REDLINE_FORMAT == pRedl->GetType() )
+ {
+ const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
+
+ SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
+ if( POS_BEFORE != eCmpPos && POS_BEHIND != eCmpPos &&
+ POS_COLLIDE_END != eCmpPos && POS_COLLIDE_START != eCmpPos )
+ {
+ pNewData = new SwRedlineSaveData( eCmpPos, *pStt, *pEnd,
+ *pRedl, TRUE );
+ rSData.Insert( pNewData, rSData.Count() );
+ }
+
+
+ }
+ }
+ return 0 != rSData.Count();
+}
+
+void SwUndo::SetSaveData( SwDoc& rDoc, const SwRedlineSaveDatas& rSData )
+{
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+ SwPaM aPam( rDoc.GetNodes().GetEndOfContent() );
+
+ for( USHORT n = rSData.Count(); n; )
+ rSData[ --n ]->RedlineToDoc( aPam );
+
+ // check redline count against count saved in RedlineSaveData object
+ DBG_ASSERT( (rSData.Count() == 0) ||
+ (rSData[0]->nRedlineCount == rDoc.GetRedlineTbl().Count()),
+ "redline count not restored properly" );
+
+ rDoc.SetRedlineMode_intern( eOld );
+}
+
+BOOL SwUndo::HasHiddenRedlines( const SwRedlineSaveDatas& rSData )
+{
+ for( USHORT n = rSData.Count(); n; )
+ if( rSData[ --n ]->GetMvSttIdx() )
+ return TRUE;
+ return FALSE;
+}
+
+BOOL SwUndo::CanRedlineGroup( SwRedlineSaveDatas& rCurr,
+ const SwRedlineSaveDatas& rCheck, BOOL bCurrIsEnd )
+{
+ BOOL bRet = FALSE;
+ USHORT n;
+
+ if( rCurr.Count() == rCheck.Count() )
+ {
+ bRet = TRUE;
+ for( n = 0; n < rCurr.Count(); ++n )
+ {
+ const SwRedlineSaveData& rSet = *rCurr[ n ];
+ const SwRedlineSaveData& rGet = *rCheck[ n ];
+ if( rSet.nSttNode != rGet.nSttNode ||
+ rSet.GetMvSttIdx() || rGet.GetMvSttIdx() ||
+ ( bCurrIsEnd ? rSet.nSttCntnt != rGet.nEndCntnt
+ : rSet.nEndCntnt != rGet.nSttCntnt ) ||
+ !rGet.CanCombine( rSet ) )
+ {
+ bRet = FALSE;
+ break;
+ }
+ }
+
+ if( bRet )
+ for( n = 0; n < rCurr.Count(); ++n )
+ {
+ SwRedlineSaveData& rSet = *rCurr[ n ];
+ const SwRedlineSaveData& rGet = *rCheck[ n ];
+ if( bCurrIsEnd )
+ rSet.nSttCntnt = rGet.nSttCntnt;
+ else
+ rSet.nEndCntnt = rGet.nEndCntnt;
+ }
+ }
+ return bRet;
+}
+
+// #111827#
+String ShortenString(const String & rStr, xub_StrLen nLength, const String & rFillStr)
+{
+ OSL_ENSURE( nLength - rFillStr.Len() >= 2, "improper arguments");
+
+ String aResult;
+
+ if (rStr.Len() <= nLength)
+ aResult = rStr;
+ else
+ {
+ long nTmpLength = nLength - rFillStr.Len();
+ if ( nTmpLength < 2 )
+ nTmpLength = 2;
+
+ nLength = static_cast<xub_StrLen>(nTmpLength);
+
+ const xub_StrLen nFrontLen = nLength - nLength / 2;
+ const xub_StrLen nBackLen = nLength - nFrontLen;
+
+ aResult += rStr.Copy(0, nFrontLen);
+ aResult += rFillStr;
+ aResult += rStr.Copy(rStr.Len() - nBackLen, nBackLen);
+ }
+
+ return aResult;
+}
+
+static bool lcl_IsSpecialCharacter(sal_Unicode nChar)
+{
+ switch (nChar)
+ {
+ case CH_TXTATR_BREAKWORD:
+ case CH_TXTATR_INWORD:
+ case CH_TXTATR_TAB:
+ case CH_TXTATR_NEWLINE:
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static String lcl_DenotedPortion(String rStr, xub_StrLen nStart,
+ xub_StrLen nEnd)
+{
+ String aResult;
+
+ if (nEnd - nStart > 0)
+ {
+ sal_Unicode cLast = rStr.GetChar(nEnd - 1);
+ if (lcl_IsSpecialCharacter(cLast))
+ {
+ switch(cLast)
+ {
+ case CH_TXTATR_TAB:
+ aResult += String(SW_RES(STR_UNDO_TABS));
+
+ break;
+ case CH_TXTATR_NEWLINE:
+ aResult += String(SW_RES(STR_UNDO_NLS));
+
+ break;
+
+ case CH_TXTATR_INWORD:
+ case CH_TXTATR_BREAKWORD:
+ aResult += UNDO_ARG2;
+
+ break;
+
+ }
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1,
+ String::CreateFromInt32(nEnd - nStart));
+ aResult = aRewriter.Apply(aResult);
+ }
+ else
+ {
+ aResult = String(SW_RES(STR_START_QUOTE));
+ aResult += rStr.Copy(nStart, nEnd - nStart);
+ aResult += String(SW_RES(STR_END_QUOTE));
+ }
+ }
+
+ return aResult;
+}
+
+String DenoteSpecialCharacters(const String & rStr)
+{
+ String aResult;
+
+ if (rStr.Len() > 0)
+ {
+ bool bStart = false;
+ xub_StrLen nStart = 0;
+ sal_Unicode cLast = 0;
+
+ for (xub_StrLen i = 0; i < rStr.Len(); i++)
+ {
+ if (lcl_IsSpecialCharacter(rStr.GetChar(i)))
+ {
+ if (cLast != rStr.GetChar(i))
+ bStart = true;
+
+ }
+ else
+ {
+ if (lcl_IsSpecialCharacter(cLast))
+ bStart = true;
+ }
+
+ if (bStart)
+ {
+ aResult += lcl_DenotedPortion(rStr, nStart, i);
+
+ nStart = i;
+ bStart = false;
+ }
+
+ cLast = rStr.GetChar(i);
+ }
+
+ aResult += lcl_DenotedPortion(rStr, nStart, rStr.Len());
+ }
+ else
+ aResult = UNDO_ARG2;
+
+ return aResult;
+}
+
+bool IsDestroyFrameAnchoredAtChar(SwPosition const & rAnchorPos,
+ SwPosition const & rStart, SwPosition const & rEnd,
+ DelCntntType const nDelCntntType)
+{
+
+ // Here we identified the objects to destroy:
+ // - anchored between start and end of the selection
+ // - anchored in start of the selection with "CheckNoContent"
+ // - anchored in start of sel. and the selection start at pos 0
+ return (rAnchorPos.nNode < rEnd.nNode)
+ && ( (nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType)
+ || (rStart.nNode < rAnchorPos.nNode)
+ || !rStart.nContent.GetIndex()
+ );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undobj1.cxx b/sw/source/core/undo/undobj1.cxx
new file mode 100644
index 000000000000..7e8f6d7331ae
--- /dev/null
+++ b/sw/source/core/undo/undobj1.cxx
@@ -0,0 +1,706 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <svl/itemiter.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcntnt.hxx>
+#include <txtflcnt.hxx>
+#include <frmfmt.hxx>
+#include <flyfrm.hxx>
+#include <undobj.hxx>
+#include <rolbck.hxx> // fuer die Attribut History
+#include <doc.hxx>
+#include <docary.hxx>
+#include <rootfrm.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+// OD 26.06.2003 #108784#
+#include <dcontact.hxx>
+#include <ndole.hxx>
+
+// Inline Methode vom UndoIter
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+//---------------------------------------------------------------------
+
+SwUndoFlyBase::SwUndoFlyBase( SwFrmFmt* pFormat, SwUndoId nUndoId )
+ : SwUndo( nUndoId ), pFrmFmt( pFormat )
+{
+}
+
+SwUndoFlyBase::~SwUndoFlyBase()
+{
+ if( bDelFmt ) // loeschen waehrend eines Undo's ??
+ delete pFrmFmt;
+}
+
+void SwUndoFlyBase::InsFly( SwUndoIter& rUndoIter, BOOL bShowSelFrm )
+{
+ SwDoc* pDoc = &rUndoIter.GetDoc();
+
+ // ins Array wieder eintragen
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ rFlyFmts.Insert( pFrmFmt, rFlyFmts.Count() );
+
+ // OD 26.06.2003 #108784# - insert 'master' drawing object into drawing page
+ if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ SwDrawContact* pDrawContact =
+ static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
+ if ( pDrawContact )
+ {
+ pDrawContact->InsertMasterIntoDrawPage();
+ // --> OD 2005-01-31 #i40845# - follow-up of #i35635#
+ // move object to visible layer
+ pDrawContact->MoveObjToVisibleLayer( pDrawContact->GetMaster() );
+ // <--
+ }
+ }
+
+ SwFmtAnchor aAnchor( (RndStdIds)nRndId );
+
+ if (FLY_AT_PAGE == nRndId)
+ {
+ aAnchor.SetPageNum( (USHORT)nNdPgPos );
+ }
+ else
+ {
+ SwPosition aNewPos( *rUndoIter.pAktPam->GetPoint() );
+ aNewPos.nNode = nNdPgPos;
+ if ((FLY_AS_CHAR == nRndId) || (FLY_AT_CHAR == nRndId))
+ {
+ aNewPos.nContent.Assign( aNewPos.nNode.GetNode().GetCntntNode(),
+ nCntPos );
+ }
+ aAnchor.SetAnchor( &aNewPos );
+ }
+
+ pFrmFmt->SetFmtAttr( aAnchor ); // Anker neu setzen
+
+ if( RES_DRAWFRMFMT != pFrmFmt->Which() )
+ {
+ // Content holen und -Attribut neu setzen
+ SwNodeIndex aIdx( pDoc->GetNodes() );
+ RestoreSection( pDoc, &aIdx, SwFlyStartNode );
+ pFrmFmt->SetFmtAttr( SwFmtCntnt( aIdx.GetNode().GetStartNode() ));
+ }
+
+ //JP 18.12.98: Bug 60505 - InCntntAttribut erst setzen, wenn der Inhalt
+ // vorhanden ist! Sonst wuerde das Layout den Fly vorher
+ // formatieren, aber keine Inhalt finden; so geschene bei
+ // Grafiken aus dem Internet
+ if (FLY_AS_CHAR == nRndId)
+ {
+ // es muss mindestens das Attribut im TextNode stehen
+ SwCntntNode* pCNd = aAnchor.GetCntntAnchor()->nNode.GetNode().GetCntntNode();
+ OSL_ENSURE( pCNd->IsTxtNode(), "no Text Node at position." );
+ SwFmtFlyCnt aFmt( pFrmFmt );
+ static_cast<SwTxtNode*>(pCNd)->InsertItem( aFmt, nCntPos, nCntPos );
+ }
+
+ pFrmFmt->MakeFrms();
+
+ if( bShowSelFrm )
+ rUndoIter.pSelFmt = pFrmFmt;
+
+ if( GetHistory() )
+ GetHistory()->Rollback( pDoc );
+
+ switch( nRndId )
+ {
+ case FLY_AS_CHAR:
+ case FLY_AT_CHAR:
+ {
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
+ nCntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
+ }
+ break;
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ {
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
+ }
+ break;
+ case FLY_AT_PAGE:
+ break;
+ }
+ bDelFmt = FALSE;
+}
+
+void SwUndoFlyBase::DelFly( SwDoc* pDoc )
+{
+ bDelFmt = TRUE; // im DTOR das Format loeschen
+ pFrmFmt->DelFrms(); // Frms vernichten.
+
+ // alle Uno-Objecte sollten sich jetzt abmelden
+ {
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFrmFmt );
+ pFrmFmt->Modify( &aMsgHint, &aMsgHint );
+ }
+
+ if ( RES_DRAWFRMFMT != pFrmFmt->Which() )
+ {
+ // gibt es ueberhaupt Inhalt, dann sicher diesen
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), "Fly ohne Inhalt" );
+
+ SaveSection( pDoc, *rCntnt.GetCntntIdx() );
+ ((SwFmtCntnt&)rCntnt).SetNewCntntIdx( (const SwNodeIndex*)0 );
+ }
+ // OD 02.07.2003 #108784# - remove 'master' drawing object from drawing page
+ else if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ SwDrawContact* pDrawContact =
+ static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
+ if ( pDrawContact )
+ {
+ pDrawContact->RemoveMasterFromDrawPage();
+ }
+ }
+
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ const SwPosition* pPos = rAnchor.GetCntntAnchor();
+ // die Positionen im Nodes-Array haben sich verschoben
+ nRndId = static_cast<USHORT>(rAnchor.GetAnchorId());
+ if (FLY_AS_CHAR == nRndId)
+ {
+ nNdPgPos = pPos->nNode.GetIndex();
+ nCntPos = pPos->nContent.GetIndex();
+ SwTxtNode *pTxtNd = pDoc->GetNodes()[ pPos->nNode ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "Kein Textnode gefunden" );
+ SwTxtFlyCnt* const pAttr = static_cast<SwTxtFlyCnt*>(
+ pTxtNd->GetTxtAttrForCharAt( nCntPos, RES_TXTATR_FLYCNT ) );
+ // Attribut steht noch im TextNode, loeschen
+ if( pAttr && pAttr->GetFlyCnt().GetFrmFmt() == pFrmFmt )
+ {
+ // Pointer auf 0, nicht loeschen
+ ((SwFmtFlyCnt&)pAttr->GetFlyCnt()).SetFlyFmt();
+ SwIndex aIdx( pPos->nContent );
+ pTxtNd->EraseText( aIdx, 1 );
+ }
+ }
+ else if (FLY_AT_CHAR == nRndId)
+ {
+ nNdPgPos = pPos->nNode.GetIndex();
+ nCntPos = pPos->nContent.GetIndex();
+ }
+ else if ((FLY_AT_PARA == nRndId) || (FLY_AT_FLY == nRndId))
+ {
+ nNdPgPos = pPos->nNode.GetIndex();
+ }
+ else
+ {
+ nNdPgPos = rAnchor.GetPageNum();
+ }
+
+ pFrmFmt->ResetFmtAttr( RES_ANCHOR ); // Anchor loeschen
+
+
+ // aus dem Array austragen
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFrmFmt ));
+}
+
+// ----- Undo-InsertFly ------
+
+SwUndoInsLayFmt::SwUndoInsLayFmt( SwFrmFmt* pFormat, ULONG nNodeIdx, xub_StrLen nCntIdx )
+ : SwUndoFlyBase( pFormat, RES_DRAWFRMFMT == pFormat->Which() ?
+ UNDO_INSDRAWFMT : UNDO_INSLAYFMT ),
+ mnCrsrSaveIndexPara( nNodeIdx ), mnCrsrSaveIndexPos( nCntIdx )
+{
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ nRndId = static_cast<USHORT>(rAnchor.GetAnchorId());
+ bDelFmt = FALSE;
+ switch( nRndId )
+ {
+ case FLY_AT_PAGE:
+ nNdPgPos = rAnchor.GetPageNum();
+ break;
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
+ break;
+ case FLY_AS_CHAR:
+ case FLY_AT_CHAR:
+ {
+ const SwPosition* pPos = rAnchor.GetCntntAnchor();
+ nCntPos = pPos->nContent.GetIndex();
+ nNdPgPos = pPos->nNode.GetIndex();
+ }
+ break;
+ default:
+ OSL_ENSURE( FALSE, "Was denn fuer ein FlyFrame?" );
+ }
+}
+
+SwUndoInsLayFmt::~SwUndoInsLayFmt()
+{
+}
+
+void SwUndoInsLayFmt::Undo( SwUndoIter& rUndoIter )
+{
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() ) // kein Inhalt
+ {
+ bool bRemoveIdx = true;
+ if( mnCrsrSaveIndexPara > 0 )
+ {
+ SwTxtNode *pNode = rUndoIter.GetDoc().GetNodes()[mnCrsrSaveIndexPara]->GetTxtNode();
+ if( pNode )
+ {
+ SwNodeIndex aIdx( rUndoIter.GetDoc().GetNodes(), rCntnt.GetCntntIdx()->GetIndex() );
+ SwNodeIndex aEndIdx( rUndoIter.GetDoc().GetNodes(), aIdx.GetNode().EndOfSectionIndex() );
+ SwIndex aIndex( pNode, mnCrsrSaveIndexPos );
+ SwPosition aPos( *pNode, aIndex );
+ rUndoIter.GetDoc().CorrAbs( aIdx, aEndIdx, aPos, TRUE );
+ bRemoveIdx = false;
+ }
+ }
+ if( bRemoveIdx )
+ RemoveIdxFromSection( rUndoIter.GetDoc(),
+ rCntnt.GetCntntIdx()->GetIndex() );
+ }
+ DelFly( &rUndoIter.GetDoc() );
+}
+
+void SwUndoInsLayFmt::Redo( SwUndoIter& rUndoIter )
+{
+ rUndoIter.pLastUndoObj = 0;
+ InsFly( rUndoIter );
+}
+
+void SwUndoInsLayFmt::Repeat( SwUndoIter& rUndoIter )
+{
+ if( UNDO_INSLAYFMT == rUndoIter.GetLastUndoId() &&
+ pFrmFmt == ((SwUndoInsLayFmt*)rUndoIter.pLastUndoObj)->pFrmFmt )
+ return;
+
+ SwDoc* pDoc = &rUndoIter.GetDoc();
+ // erfrage und setze den Anker neu
+ SwFmtAnchor aAnchor( pFrmFmt->GetAnchor() );
+ if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == aAnchor.GetAnchorId()))
+ {
+ SwPosition aPos( *rUndoIter.pAktPam->GetPoint() );
+ if (FLY_AT_PARA == aAnchor.GetAnchorId())
+ {
+ aPos.nContent.Assign( 0, 0 );
+ }
+ aAnchor.SetAnchor( &aPos );
+ }
+ else if( FLY_AT_FLY == aAnchor.GetAnchorId() )
+ {
+ const SwStartNode* pSttNd = rUndoIter.pAktPam->GetNode()->FindFlyStartNode();
+ if( pSttNd )
+ {
+ SwPosition aPos( *pSttNd );
+ aAnchor.SetAnchor( &aPos );
+ }
+ else
+ {
+ rUndoIter.pLastUndoObj = this;
+ return ;
+ }
+ }
+ else if (FLY_AT_PAGE == aAnchor.GetAnchorId())
+ {
+ aAnchor.SetPageNum( pDoc->GetRootFrm()->GetCurrPage(
+ rUndoIter.pAktPam ));
+ }
+ else {
+ OSL_ENSURE( FALSE, "was fuer ein Anker ist es denn nun?" );
+ }
+
+ SwFrmFmt* pFlyFmt = pDoc->CopyLayoutFmt( *pFrmFmt, aAnchor, true, true );
+ rUndoIter.pSelFmt = pFlyFmt;
+
+ rUndoIter.pLastUndoObj = this;
+}
+
+// #111827#
+String SwUndoInsLayFmt::GetComment() const
+{
+ String aResult;
+
+ if (! pComment)
+ {
+ /*
+ If frame format is present and has an SdrObject use the undo
+ comment of the SdrObject. Otherwise use the default comment.
+ */
+
+ bool bDone = false;
+ if (pFrmFmt)
+ {
+ const SdrObject * pSdrObj = pFrmFmt->FindSdrObject();
+ if ( pSdrObj )
+ {
+ aResult = SdrUndoNewObj::GetComment( *pSdrObj );
+ bDone = true;
+ }
+ }
+
+ if (! bDone)
+ aResult = SwUndo::GetComment();
+ }
+ else
+ aResult = *pComment;
+
+ return aResult;
+}
+
+// ----- Undo-DeleteFly ------
+
+SwUndoDelLayFmt::SwUndoDelLayFmt( SwFrmFmt* pFormat )
+ : SwUndoFlyBase( pFormat, UNDO_DELLAYFMT ), bShowSelFrm( TRUE )
+{
+ SwDoc* pDoc = pFormat->GetDoc();
+ DelFly( pDoc );
+
+ SwNodeIndex* pIdx = GetMvSttIdx();
+ SwNode* pNd;
+ if( 1 == GetMvNodeCnt() && pIdx &&
+ ( pNd = (*pDoc->GetUndoNds())[ *pIdx ] )->IsNoTxtNode() )
+ {
+ // dann setze eine andere Undo-ID; Grafik oder OLE
+ if( pNd->IsGrfNode() )
+ SetId( UNDO_DELGRF );
+ else if( pNd->IsOLENode() )
+ {
+ SetId( UNDO_DELETE );
+
+ }
+ }
+}
+
+SwRewriter SwUndoDelLayFmt::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ SwDoc * pDoc = pFrmFmt->GetDoc();
+
+ if (pDoc)
+ {
+ SwNodeIndex* pIdx = GetMvSttIdx();
+ if( 1 == GetMvNodeCnt() && pIdx)
+ {
+ SwNode * pNd = (*pDoc->GetUndoNds())[ *pIdx ];
+
+ if ( pNd->IsNoTxtNode() && pNd->IsOLENode())
+ {
+ SwOLENode * pOLENd = pNd->GetOLENode();
+
+ aRewriter.AddRule(UNDO_ARG1, pOLENd->GetDescription());
+ }
+ }
+ }
+
+ return aRewriter;
+}
+
+void SwUndoDelLayFmt::Undo( SwUndoIter& rUndoIter )
+{
+ InsFly( rUndoIter, bShowSelFrm );
+}
+
+void SwUndoDelLayFmt::Redo( SwUndoIter& rUndoIter )
+{
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() ) // kein Inhalt
+ RemoveIdxFromSection( rUndoIter.GetDoc(),
+ rCntnt.GetCntntIdx()->GetIndex() );
+
+ DelFly( &rUndoIter.GetDoc() );
+}
+
+void SwUndoDelLayFmt::Redo()
+{
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() ) // kein Inhalt
+ RemoveIdxFromSection( *pFrmFmt->GetDoc(),
+ rCntnt.GetCntntIdx()->GetIndex() );
+
+ DelFly( pFrmFmt->GetDoc() );
+}
+
+/* */
+
+SwUndoSetFlyFmt::SwUndoSetFlyFmt( SwFrmFmt& rFlyFmt, SwFrmFmt& rNewFrmFmt )
+ : SwUndo( UNDO_SETFLYFRMFMT ), SwClient( &rFlyFmt ), pFrmFmt( &rFlyFmt ),
+ pOldFmt( (SwFrmFmt*)rFlyFmt.DerivedFrom() ), pNewFmt( &rNewFrmFmt ),
+ pItemSet( new SfxItemSet( *rFlyFmt.GetAttrSet().GetPool(),
+ rFlyFmt.GetAttrSet().GetRanges() )),
+ nOldNode( 0 ), nNewNode( 0 ),
+ nOldCntnt( 0 ), nNewCntnt( 0 ),
+ nOldAnchorTyp( 0 ), nNewAnchorTyp( 0 ), bAnchorChgd( FALSE )
+{
+}
+
+SwRewriter SwUndoSetFlyFmt::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ if (pNewFmt)
+ aRewriter.AddRule(UNDO_ARG1, pNewFmt->GetName());
+
+ return aRewriter;
+}
+
+
+SwUndoSetFlyFmt::~SwUndoSetFlyFmt()
+{
+ delete pItemSet;
+}
+
+void SwUndoSetFlyFmt::GetAnchor( SwFmtAnchor& rAnchor,
+ ULONG nNode, xub_StrLen nCntnt )
+{
+ RndStdIds nAnchorTyp = rAnchor.GetAnchorId();
+ if (FLY_AT_PAGE != nAnchorTyp)
+ {
+ SwNode* pNd = pFrmFmt->GetDoc()->GetNodes()[ nNode ];
+
+ if( FLY_AT_FLY == nAnchorTyp
+ ? ( !pNd->IsStartNode() || SwFlyStartNode !=
+ ((SwStartNode*)pNd)->GetStartNodeType() )
+ : !pNd->IsTxtNode() )
+ {
+ pNd = 0; // invalid position
+ }
+ else
+ {
+ SwPosition aPos( *pNd );
+ if ((FLY_AS_CHAR == nAnchorTyp) ||
+ (FLY_AT_CHAR == nAnchorTyp))
+ {
+ if ( nCntnt > static_cast<SwTxtNode*>(pNd)->GetTxt().Len() )
+ {
+ pNd = 0; // invalid position
+ }
+ else
+ {
+ aPos.nContent.Assign(static_cast<SwTxtNode*>(pNd), nCntnt);
+ }
+ }
+ if ( pNd )
+ {
+ rAnchor.SetAnchor( &aPos );
+ }
+ }
+
+ if( !pNd )
+ {
+ // ungueltige Position - setze auf 1. Seite
+ rAnchor.SetType( FLY_AT_PAGE );
+ rAnchor.SetPageNum( 1 );
+ }
+ }
+ else
+ rAnchor.SetPageNum( nCntnt );
+}
+
+void SwUndoSetFlyFmt::Undo( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+
+ // ist das neue Format noch vorhanden ??
+ if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmtPtr)pOldFmt ) )
+ {
+ if( bAnchorChgd )
+ pFrmFmt->DelFrms();
+
+ if( pFrmFmt->DerivedFrom() != pOldFmt )
+ pFrmFmt->SetDerivedFrom( pOldFmt );
+
+ SfxItemIter aIter( *pItemSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( pItem )
+ {
+ if( IsInvalidItem( pItem ))
+ pFrmFmt->ResetFmtAttr( pItemSet->GetWhichByPos(
+ aIter.GetCurPos() ));
+ else
+ pFrmFmt->SetFmtAttr( *pItem );
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+
+ if( bAnchorChgd )
+ {
+ const SwFmtAnchor& rOldAnch = pFrmFmt->GetAnchor();
+ if (FLY_AS_CHAR == rOldAnch.GetAnchorId())
+ {
+ // Bei InCntnt's wird es spannend: Das TxtAttribut muss
+ // vernichtet werden. Leider reisst dies neben den Frms
+ // auch noch das Format mit in sein Grab. Um dass zu
+ // unterbinden loesen wir vorher die Verbindung zwischen
+ // Attribut und Format.
+ const SwPosition *pPos = rOldAnch.GetCntntAnchor();
+ SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * pHnt = pTxtNode->GetTxtAttrForCharAt(
+ nIdx, RES_TXTATR_FLYCNT );
+ OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ OSL_ENSURE( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFrmFmt,
+ "Wrong TxtFlyCnt-Hint." );
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
+
+ // Die Verbindung ist geloest, jetzt muss noch das Attribut
+ // vernichtet werden.
+ pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
+ }
+
+ // Anker umsetzen
+ SwFmtAnchor aNewAnchor( (RndStdIds) nOldAnchorTyp );
+ GetAnchor( aNewAnchor, nOldNode, nOldCntnt );
+ pFrmFmt->SetFmtAttr( aNewAnchor );
+
+ if (FLY_AS_CHAR == aNewAnchor.GetAnchorId())
+ {
+ SwPosition* pPos = (SwPosition*)aNewAnchor.GetCntntAnchor();
+ SwFmtFlyCnt aFmt( pFrmFmt );
+ pPos->nNode.GetNode().GetTxtNode()->InsertItem( aFmt,
+ nOldCntnt, 0 );
+ }
+
+ pFrmFmt->MakeFrms();
+ }
+ rIter.pSelFmt = pFrmFmt;
+ }
+}
+
+void SwUndoSetFlyFmt::Redo( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+
+ // ist das neue Format noch vorhanden ??
+ if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmtPtr)pNewFmt ) )
+ {
+
+ if( bAnchorChgd )
+ {
+ SwFmtAnchor aNewAnchor( (RndStdIds) nNewAnchorTyp );
+ GetAnchor( aNewAnchor, nNewNode, nNewCntnt );
+ SfxItemSet aSet( rDoc.GetAttrPool(), aFrmFmtSetRange );
+ aSet.Put( aNewAnchor );
+ rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, &aSet );
+ }
+ else
+ rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, 0 );
+
+ rIter.pSelFmt = pFrmFmt;
+ }
+}
+
+void SwUndoSetFlyFmt::PutAttr( USHORT nWhich, const SfxPoolItem* pItem )
+{
+ if( pItem && pItem != GetDfltAttr( nWhich ) )
+ {
+ // Sonderbehandlung fuer den Anchor
+ if( RES_ANCHOR == nWhich )
+ {
+ // nur den 1. Ankerwechsel vermerken
+ OSL_ENSURE( !bAnchorChgd, "mehrfacher Ankerwechsel nicht erlaubt!" );
+
+ bAnchorChgd = TRUE;
+
+ const SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem;
+ switch( nOldAnchorTyp = static_cast<USHORT>(pAnchor->GetAnchorId()) )
+ {
+ case FLY_AS_CHAR:
+ case FLY_AT_CHAR:
+ nOldCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex();
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ nOldNode = pAnchor->GetCntntAnchor()->nNode.GetIndex();
+ break;
+
+ default:
+ nOldCntnt = pAnchor->GetPageNum();
+ }
+
+ pAnchor = (SwFmtAnchor*)&pFrmFmt->GetAnchor();
+ switch( nNewAnchorTyp = static_cast<USHORT>(pAnchor->GetAnchorId()) )
+ {
+ case FLY_AS_CHAR:
+ case FLY_AT_CHAR:
+ nNewCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex();
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ nNewNode = pAnchor->GetCntntAnchor()->nNode.GetIndex();
+ break;
+
+ default:
+ nNewCntnt = pAnchor->GetPageNum();
+ }
+ }
+ else
+ pItemSet->Put( *pItem );
+ }
+ else
+ pItemSet->InvalidateItem( nWhich );
+}
+
+void SwUndoSetFlyFmt::Modify( SfxPoolItem* pOld, SfxPoolItem* )
+{
+ if( pOld )
+ {
+ USHORT nWhich = pOld->Which();
+
+ if( nWhich < POOLATTR_END )
+ PutAttr( nWhich, pOld );
+ else if( RES_ATTRSET_CHG == nWhich )
+ {
+ SfxItemIter aIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( pItem )
+ {
+ PutAttr( pItem->Which(), pItem );
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undoflystrattr.cxx b/sw/source/core/undo/undoflystrattr.cxx
new file mode 100644
index 000000000000..072115ec6798
--- /dev/null
+++ b/sw/source/core/undo/undoflystrattr.cxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <undoflystrattr.hxx>
+#include <frmfmt.hxx>
+
+SwUndoFlyStrAttr::SwUndoFlyStrAttr( SwFlyFrmFmt& rFlyFrmFmt,
+ const SwUndoId eUndoId,
+ const String& sOldStr,
+ const String& sNewStr )
+ : SwUndo( eUndoId ),
+ mrFlyFrmFmt( rFlyFrmFmt ),
+ msOldStr( sOldStr ),
+ msNewStr( sNewStr )
+{
+ OSL_ENSURE( eUndoId == UNDO_FLYFRMFMT_TITLE ||
+ eUndoId == UNDO_FLYFRMFMT_DESCRIPTION,
+ "<SwUndoFlyStrAttr::SwUndoFlyStrAttr(..)> - unexpected undo id --> Undo will not work" );
+}
+
+SwUndoFlyStrAttr::~SwUndoFlyStrAttr()
+{
+}
+
+void SwUndoFlyStrAttr::Undo( SwUndoIter& )
+{
+ switch ( GetId() )
+ {
+ case UNDO_FLYFRMFMT_TITLE:
+ {
+ mrFlyFrmFmt.SetObjTitle( msOldStr, true );
+ }
+ break;
+ case UNDO_FLYFRMFMT_DESCRIPTION:
+ {
+ mrFlyFrmFmt.SetObjDescription( msOldStr, true );
+ }
+ break;
+ default:
+ {
+ }
+ }
+}
+
+void SwUndoFlyStrAttr::Redo( SwUndoIter& )
+{
+ switch ( GetId() )
+ {
+ case UNDO_FLYFRMFMT_TITLE:
+ {
+ mrFlyFrmFmt.SetObjTitle( msNewStr, true );
+ }
+ break;
+ case UNDO_FLYFRMFMT_DESCRIPTION:
+ {
+ mrFlyFrmFmt.SetObjDescription( msNewStr, true );
+ }
+ break;
+ default:
+ {
+ }
+ }
+}
+
+void SwUndoFlyStrAttr::Repeat( SwUndoIter& )
+{
+ // no repeat
+}
+
+SwRewriter SwUndoFlyStrAttr::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ aResult.AddRule( UNDO_ARG1, mrFlyFrmFmt.GetName() );
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undraw.cxx b/sw/source/core/undo/undraw.cxx
new file mode 100644
index 000000000000..a571e8101fff
--- /dev/null
+++ b/sw/source/core/undo/undraw.cxx
@@ -0,0 +1,644 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <rtl/string.h>
+#include <rtl/memory.h>
+#include <hintids.hxx>
+
+#include <svx/svdogrp.hxx>
+#include <svx/svdundo.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdmark.hxx>
+#include <fmtanchr.hxx>
+#include <fmtflcnt.hxx>
+#include <txtflcnt.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <frame.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <dcontact.hxx>
+#include <dview.hxx>
+#include <rootfrm.hxx>
+#include <viewsh.hxx>
+
+
+struct SwUndoGroupObjImpl
+{
+ SwDrawFrmFmt* pFmt;
+ SdrObject* pObj;
+ ULONG nNodeIdx;
+
+ // OD 2004-04-15 #i26791# - keeping the anchor and the relative position
+ // of drawing objects no longer needed
+};
+
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+// Draw-Objecte
+
+IMPL_LINK( SwDoc, AddDrawUndo, SdrUndoAction *, pUndo )
+{
+#if OSL_DEBUG_LEVEL > 1
+ USHORT nId = pUndo->GetId();
+ (void)nId;
+ String sComment( pUndo->GetComment() );
+#endif
+
+ if( DoesUndo() && !IsNoDrawUndoObj() )
+ {
+ ClearRedo();
+ const SdrMarkList* pMarkList = 0;
+ ViewShell* pSh = GetRootFrm() ? GetRootFrm()->GetCurrShell() : 0;
+ if( pSh && pSh->HasDrawView() )
+ pMarkList = &pSh->GetDrawView()->GetMarkedObjectList();
+
+ AppendUndo( new SwSdrUndo( pUndo, pMarkList ) );
+ }
+ else
+ delete pUndo;
+ return 0;
+}
+
+SwSdrUndo::SwSdrUndo( SdrUndoAction* pUndo, const SdrMarkList* pMrkLst )
+ : SwUndo( UNDO_DRAWUNDO ), pSdrUndo( pUndo )
+{
+ if( pMrkLst && pMrkLst->GetMarkCount() )
+ pMarkList = new SdrMarkList( *pMrkLst );
+ else
+ pMarkList = 0;
+}
+
+SwSdrUndo::~SwSdrUndo()
+{
+ delete pSdrUndo;
+ delete pMarkList;
+}
+
+void SwSdrUndo::Undo( SwUndoIter& rUndoIter )
+{
+ pSdrUndo->Undo();
+ rUndoIter.pMarkList = pMarkList;
+}
+
+void SwSdrUndo::Redo( SwUndoIter& rUndoIter )
+{
+ pSdrUndo->Redo();
+ rUndoIter.pMarkList = pMarkList;
+}
+
+String SwSdrUndo::GetComment() const
+{
+ return pSdrUndo->GetComment();
+}
+
+//--------------------------------------------
+
+void lcl_SendRemoveToUno( SwFmt& rFmt )
+{
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, &rFmt );
+ rFmt.Modify( &aMsgHint, &aMsgHint );
+}
+
+void lcl_SaveAnchor( SwFrmFmt* pFmt, ULONG& rNodePos )
+{
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == rAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == rAnchor.GetAnchorId()))
+ {
+ rNodePos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
+ xub_StrLen nCntntPos = 0;
+
+ if (FLY_AS_CHAR == rAnchor.GetAnchorId())
+ {
+ nCntntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
+
+ // TextAttribut zerstoeren
+ SwTxtNode *pTxtNd = pFmt->GetDoc()->GetNodes()[ rNodePos ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "Kein Textnode gefunden" );
+ SwTxtFlyCnt* pAttr = static_cast<SwTxtFlyCnt*>(
+ pTxtNd->GetTxtAttrForCharAt( nCntntPos, RES_TXTATR_FLYCNT ));
+ // Attribut steht noch im TextNode, loeschen
+ if( pAttr && pAttr->GetFlyCnt().GetFrmFmt() == pFmt )
+ {
+ // Pointer auf 0, nicht loeschen
+ ((SwFmtFlyCnt&)pAttr->GetFlyCnt()).SetFlyFmt();
+ SwIndex aIdx( pTxtNd, nCntntPos );
+ pTxtNd->EraseText( aIdx, 1 );
+ }
+ }
+ else if (FLY_AT_CHAR == rAnchor.GetAnchorId())
+ {
+ nCntntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
+ }
+
+ pFmt->SetFmtAttr( SwFmtAnchor( rAnchor.GetAnchorId(), nCntntPos ) );
+ }
+}
+
+void lcl_RestoreAnchor( SwFrmFmt* pFmt, ULONG& rNodePos )
+{
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == rAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == rAnchor.GetAnchorId()))
+ {
+ xub_StrLen nCntntPos = rAnchor.GetPageNum();
+ SwNodes& rNds = pFmt->GetDoc()->GetNodes();
+
+ SwNodeIndex aIdx( rNds, rNodePos );
+ SwPosition aPos( aIdx );
+
+ SwFmtAnchor aTmp( rAnchor.GetAnchorId() );
+ if ((FLY_AS_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()))
+ {
+ aPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), nCntntPos );
+ }
+ aTmp.SetAnchor( &aPos );
+ pFmt->SetFmtAttr( aTmp );
+
+ if (FLY_AS_CHAR == rAnchor.GetAnchorId())
+ {
+ SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "no Text Node" );
+ SwFmtFlyCnt aFmt( pFmt );
+ pTxtNd->InsertItem( aFmt, nCntntPos, nCntntPos );
+ }
+ }
+}
+
+SwUndoDrawGroup::SwUndoDrawGroup( USHORT nCnt )
+ : SwUndo( UNDO_DRAWGROUP ), nSize( nCnt + 1 ), bDelFmt( TRUE )
+{
+ pObjArr = new SwUndoGroupObjImpl[ nSize ];
+}
+
+SwUndoDrawGroup::~SwUndoDrawGroup()
+{
+ if( bDelFmt )
+ {
+ SwUndoGroupObjImpl* pTmp = pObjArr + 1;
+ for( USHORT n = 1; n < nSize; ++n, ++pTmp )
+ delete pTmp->pFmt;
+ }
+ else
+ delete pObjArr->pFmt; // das GroupObject-Format
+
+ delete [] pObjArr;
+}
+
+void SwUndoDrawGroup::Undo( SwUndoIter& )
+{
+ bDelFmt = FALSE;
+
+ // das Group-Object sichern
+ SwDrawFrmFmt* pFmt = pObjArr->pFmt;
+ SwDrawContact* pDrawContact = (SwDrawContact*)pFmt->FindContactObj();
+ SdrObject* pObj = pDrawContact->GetMaster();
+ pObjArr->pObj = pObj;
+
+ //loescht sich selbst!
+ pDrawContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ ::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
+
+ // alle Uno-Objecte sollten sich jetzt abmelden
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ // aus dem Array austragen
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+
+ for( USHORT n = 1; n < nSize; ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+
+ ::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
+ rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
+
+ pObj = rSave.pObj;
+
+ SwDrawContact *pContact = new SwDrawContact( rSave.pFmt, pObj );
+ pContact->ConnectToLayout();
+ // --> OD 2005-03-22 #i45718# - follow-up of #i35635#
+ // move object to visible layer
+ pContact->MoveObjToVisibleLayer( pObj );
+ // <--
+ // --> OD 2005-05-10 #i45952# - notify that position attributes
+ // are already set
+ OSL_ENSURE( rSave.pFmt->ISA(SwDrawFrmFmt),
+ "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
+ if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
+ }
+ // <--
+ }
+}
+
+void SwUndoDrawGroup::Redo( SwUndoIter& )
+{
+ bDelFmt = TRUE;
+
+ // aus dem Array austragen
+ SwDoc* pDoc = pObjArr->pFmt->GetDoc();
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ SdrObject* pObj;
+
+ for( USHORT n = 1; n < nSize; ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+
+ pObj = rSave.pObj;
+
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+ //loescht sich selbst!
+ pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ ::lcl_SaveAnchor( rSave.pFmt, rSave.nNodeIdx );
+
+ // alle Uno-Objecte sollten sich jetzt abmelden
+ ::lcl_SendRemoveToUno( *rSave.pFmt );
+
+ rFlyFmts.Remove( rFlyFmts.GetPos( rSave.pFmt ));
+ }
+
+ // das Group-Object wieder einfuegen
+ ::lcl_RestoreAnchor( pObjArr->pFmt, pObjArr->nNodeIdx );
+ rFlyFmts.Insert( pObjArr->pFmt, rFlyFmts.Count() );
+
+ SwDrawContact *pContact = new SwDrawContact( pObjArr->pFmt, pObjArr->pObj );
+ // OD 2004-04-15 #i26791# - correction: connect object to layout
+ pContact->ConnectToLayout();
+ // --> OD 2005-03-22 #i45718# - follow-up of #i35635#
+ // move object to visible layer
+ pContact->MoveObjToVisibleLayer( pObjArr->pObj );
+ // <--
+ // --> OD 2005-05-10 #i45952# - notify that position attributes
+ // are already set
+ OSL_ENSURE( pObjArr->pFmt->ISA(SwDrawFrmFmt),
+ "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
+ if ( pObjArr->pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(pObjArr->pFmt)->PosAttrSet();
+ }
+ // <--
+}
+
+void SwUndoDrawGroup::AddObj( USHORT nPos, SwDrawFrmFmt* pFmt, SdrObject* pObj )
+{
+ SwUndoGroupObjImpl& rSave = *( pObjArr + nPos + 1 );
+ rSave.pObj = pObj;
+ rSave.pFmt = pFmt;
+ ::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
+
+ // alle Uno-Objecte sollten sich jetzt abmelden
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ // aus dem Array austragen
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pFmt->GetDoc()->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+}
+
+void SwUndoDrawGroup::SetGroupFmt( SwDrawFrmFmt* pFmt )
+{
+ pObjArr->pObj = 0;
+ pObjArr->pFmt = pFmt;
+}
+
+
+// ------------------------------
+
+SwUndoDrawUnGroup::SwUndoDrawUnGroup( SdrObjGroup* pObj )
+ : SwUndo( UNDO_DRAWUNGROUP ), bDelFmt( FALSE )
+{
+ nSize = (USHORT)pObj->GetSubList()->GetObjCount() + 1;
+ pObjArr = new SwUndoGroupObjImpl[ nSize ];
+
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+ SwDrawFrmFmt* pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
+
+ pObjArr->pObj = pObj;
+ pObjArr->pFmt = pFmt;
+
+ //loescht sich selbst!
+ pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ ::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
+
+ // alle Uno-Objecte sollten sich jetzt abmelden
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ // aus dem Array austragen
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pFmt->GetDoc()->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+}
+
+SwUndoDrawUnGroup::~SwUndoDrawUnGroup()
+{
+ if( bDelFmt )
+ {
+ SwUndoGroupObjImpl* pTmp = pObjArr + 1;
+ for( USHORT n = 1; n < nSize; ++n, ++pTmp )
+ delete pTmp->pFmt;
+ }
+ else
+ delete pObjArr->pFmt; // das GroupObject-Format
+
+ delete [] pObjArr;
+}
+
+void SwUndoDrawUnGroup::Undo( SwUndoIter& rIter )
+{
+ bDelFmt = TRUE;
+
+ // aus dem Array austragen
+ SwDoc* pDoc = &rIter.GetDoc();
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+
+ for( USHORT n = 1; n < nSize; ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+
+ // --> OD 2006-11-01 #130889# - taken over by <SwUndoDrawUnGroupConnectToLayout>
+// SwDrawContact* pContact = (SwDrawContact*)rSave.pFmt->FindContactObj();
+
+// rSave.pObj = pContact->GetMaster();
+
+// //loescht sich selbst!
+// pContact->Changed( *rSave.pObj, SDRUSERCALL_DELETE,
+// rSave.pObj->GetLastBoundRect() );
+// rSave.pObj->SetUserCall( 0 );
+ // <--
+
+ ::lcl_SaveAnchor( rSave.pFmt, rSave.nNodeIdx );
+
+ // alle Uno-Objecte sollten sich jetzt abmelden
+ ::lcl_SendRemoveToUno( *rSave.pFmt );
+
+ rFlyFmts.Remove( rFlyFmts.GetPos( rSave.pFmt ));
+ }
+
+ // das Group-Object wieder einfuegen
+ ::lcl_RestoreAnchor( pObjArr->pFmt, pObjArr->nNodeIdx );
+ rFlyFmts.Insert( pObjArr->pFmt, rFlyFmts.Count() );
+
+ SwDrawContact *pContact = new SwDrawContact( pObjArr->pFmt, pObjArr->pObj );
+ pContact->ConnectToLayout();
+ // --> OD 2005-03-22 #i45718# - follow-up of #i35635#
+ // move object to visible layer
+ pContact->MoveObjToVisibleLayer( pObjArr->pObj );
+ // <--
+ // --> OD 2005-05-10 #i45952# - notify that position attributes
+ // are already set
+ OSL_ENSURE( pObjArr->pFmt->ISA(SwDrawFrmFmt),
+ "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
+ if ( pObjArr->pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(pObjArr->pFmt)->PosAttrSet();
+ }
+ // <--
+}
+
+void SwUndoDrawUnGroup::Redo( SwUndoIter& )
+{
+ bDelFmt = FALSE;
+
+ // das Group-Object sichern
+ SwDrawFrmFmt* pFmt = pObjArr->pFmt;
+ SwDrawContact* pContact = (SwDrawContact*)pFmt->FindContactObj();
+
+ //loescht sich selbst!
+ pContact->Changed( *pObjArr->pObj, SDRUSERCALL_DELETE,
+ pObjArr->pObj->GetLastBoundRect() );
+ pObjArr->pObj->SetUserCall( 0 );
+
+ ::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
+
+ // alle Uno-Objecte sollten sich jetzt abmelden
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ // aus dem Array austragen
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+
+ for( USHORT n = 1; n < nSize; ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+
+ ::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
+ rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
+
+ // --> OD 2006-11-01 #130889# - taken over by <SwUndoDrawUnGroupConnectToLayout>
+// SdrObject* pObj = rSave.pObj;
+
+// SwDrawContact *pContact = new SwDrawContact( rSave.pFmt, rSave.pObj );
+// pContact->ConnectToLayout();
+// // --> OD 2005-03-22 #i45718# - follow-up of #i35635#
+// // move object to visible layer
+// pContact->MoveObjToVisibleLayer( rSave.pObj );
+// // <--
+ // <--
+ // --> OD 2005-05-10 #i45952# - notify that position attributes
+ // are already set
+ OSL_ENSURE( rSave.pFmt->ISA(SwDrawFrmFmt),
+ "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
+ if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
+ }
+ // <--
+ }
+}
+
+void SwUndoDrawUnGroup::AddObj( USHORT nPos, SwDrawFrmFmt* pFmt )
+{
+ SwUndoGroupObjImpl& rSave = *( pObjArr + nPos + 1 );
+ rSave.pFmt = pFmt;
+ rSave.pObj = 0;
+}
+
+//-------------------------------------
+// --> OD 2006-11-01 #130889#
+SwUndoDrawUnGroupConnectToLayout::SwUndoDrawUnGroupConnectToLayout()
+ : SwUndo( UNDO_DRAWUNGROUP )
+{
+}
+
+SwUndoDrawUnGroupConnectToLayout::~SwUndoDrawUnGroupConnectToLayout()
+{
+}
+
+void SwUndoDrawUnGroupConnectToLayout::Undo( SwUndoIter& )
+{
+ for ( std::vector< SdrObject >::size_type i = 0;
+ i < aDrawFmtsAndObjs.size(); ++i )
+ {
+ SdrObject* pObj( aDrawFmtsAndObjs[i].second );
+ SwDrawContact* pDrawContact( dynamic_cast<SwDrawContact*>(pObj->GetUserCall()) );
+ OSL_ENSURE( pDrawContact,
+ "<SwUndoDrawUnGroupConnectToLayout::Undo(..)> -- missing SwDrawContact instance" );
+ if ( pDrawContact )
+ {
+ // deletion of instance <pDrawContact> and thus disconnection from
+ // the Writer layout.
+ pDrawContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+ }
+ }
+}
+
+void SwUndoDrawUnGroupConnectToLayout::Redo( SwUndoIter& )
+{
+ for ( std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >::size_type i = 0;
+ i < aDrawFmtsAndObjs.size(); ++i )
+ {
+ SwDrawFrmFmt* pFmt( aDrawFmtsAndObjs[i].first );
+ SdrObject* pObj( aDrawFmtsAndObjs[i].second );
+ SwDrawContact *pContact = new SwDrawContact( pFmt, pObj );
+ pContact->ConnectToLayout();
+ pContact->MoveObjToVisibleLayer( pObj );
+ }
+}
+
+void SwUndoDrawUnGroupConnectToLayout::AddFmtAndObj( SwDrawFrmFmt* pDrawFrmFmt,
+ SdrObject* pDrawObject )
+{
+ aDrawFmtsAndObjs.push_back(
+ std::pair< SwDrawFrmFmt*, SdrObject* >( pDrawFrmFmt, pDrawObject ) );
+}
+// <--
+
+//-------------------------------------
+
+SwUndoDrawDelete::SwUndoDrawDelete( USHORT nCnt )
+ : SwUndo( UNDO_DRAWDELETE ), nSize( nCnt ), bDelFmt( TRUE )
+{
+ pObjArr = new SwUndoGroupObjImpl[ nSize ];
+ pMarkLst = new SdrMarkList();
+}
+
+SwUndoDrawDelete::~SwUndoDrawDelete()
+{
+ if( bDelFmt )
+ {
+ SwUndoGroupObjImpl* pTmp = pObjArr;
+ for( USHORT n = 0; n < pMarkLst->GetMarkCount(); ++n, ++pTmp )
+ delete pTmp->pFmt;
+ }
+ delete [] pObjArr;
+ delete pMarkLst;
+}
+
+void SwUndoDrawDelete::Undo( SwUndoIter &rIter )
+{
+ bDelFmt = FALSE;
+ SwSpzFrmFmts& rFlyFmts = *rIter.GetDoc().GetSpzFrmFmts();
+ for( USHORT n = 0; n < pMarkLst->GetMarkCount(); ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+ ::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
+ rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
+ SdrObject *pObj = rSave.pObj;
+ SwDrawContact *pContact = new SwDrawContact( rSave.pFmt, pObj );
+ pContact->_Changed( *pObj, SDRUSERCALL_INSERTED, NULL );
+ // --> OD 2005-03-22 #i45718# - follow-up of #i35635#
+ // move object to visible layer
+ pContact->MoveObjToVisibleLayer( pObj );
+ // <--
+ // --> OD 2005-05-10 #i45952# - notify that position attributes
+ // are already set
+ OSL_ENSURE( rSave.pFmt->ISA(SwDrawFrmFmt),
+ "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
+ if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
+ }
+ // <--
+ }
+ rIter.pMarkList = pMarkLst;
+}
+
+void SwUndoDrawDelete::Redo( SwUndoIter &rIter )
+{
+ bDelFmt = TRUE;
+ SwSpzFrmFmts& rFlyFmts = *rIter.GetDoc().GetSpzFrmFmts();
+ for( USHORT n = 0; n < pMarkLst->GetMarkCount(); ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+ SdrObject *pObj = rSave.pObj;
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+ SwDrawFrmFmt *pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
+ //loescht sich selbst!
+ pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ // alle Uno-Objecte sollten sich jetzt abmelden
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+ ::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
+ }
+}
+
+void SwUndoDrawDelete::AddObj( USHORT , SwDrawFrmFmt* pFmt,
+ const SdrMark& rMark )
+{
+ SwUndoGroupObjImpl& rSave = *( pObjArr + pMarkLst->GetMarkCount() );
+ rSave.pObj = rMark.GetMarkedSdrObj();
+ rSave.pFmt = pFmt;
+ ::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
+
+ // alle Uno-Objecte sollten sich jetzt abmelden
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ // aus dem Array austragen
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+
+ pMarkLst->InsertEntry( rMark );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unfmco.cxx b/sw/source/core/undo/unfmco.cxx
new file mode 100644
index 000000000000..555a207dfa1b
--- /dev/null
+++ b/sw/source/core/undo/unfmco.cxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include "doc.hxx"
+#include "swundo.hxx" // fuer die UndoIds
+#include "pam.hxx"
+#include "ndtxt.hxx"
+
+#include "undobj.hxx"
+#include "rolbck.hxx"
+
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+//--------------------------------------------------
+
+
+// --> OD 2008-04-15 #refactorlists#
+SwUndoFmtColl::SwUndoFmtColl( const SwPaM& rRange,
+ SwFmtColl* pColl,
+ const bool bReset,
+ const bool bResetListAttrs )
+ : SwUndo( UNDO_SETFMTCOLL ),
+ SwUndRng( rRange ),
+ pHistory( new SwHistory ),
+ pFmtColl( pColl ),
+ mbReset( bReset ),
+ mbResetListAttrs( bResetListAttrs )
+// <--
+{
+ // --> FME 2004-08-06 #i31191#
+ if ( pColl )
+ aFmtName = pColl->GetName();
+ // <--
+}
+
+
+SwUndoFmtColl::~SwUndoFmtColl()
+{
+ delete pHistory;
+}
+
+
+void SwUndoFmtColl::Undo( SwUndoIter& rUndoIter )
+{
+ // die alten Werte wieder zurueck
+ pHistory->TmpRollback( &rUndoIter.GetDoc(), 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+
+ // setze noch den Cursor auf den Undo-Bereich
+ SetPaM( rUndoIter );
+}
+
+
+void SwUndoFmtColl::Redo( SwUndoIter& rUndoIter )
+{
+ // setze Attribut in dem Bereich:
+ SetPaM( rUndoIter );
+ rUndoIter.pLastUndoObj = 0;
+
+ Repeat( rUndoIter ); // Collection setzen
+
+ rUndoIter.pLastUndoObj = 0;
+}
+
+
+void SwUndoFmtColl::Repeat( SwUndoIter& rUndoIter )
+{
+ if( UNDO_SETFMTCOLL == rUndoIter.GetLastUndoId() &&
+ pFmtColl == ((SwUndoFmtColl*)rUndoIter.pLastUndoObj)->pFmtColl )
+ return;
+
+ // es kann nur eine TextFmtColl auf einen Bereich angewendet werden,
+ // also erfrage auch nur in dem Array
+ USHORT nPos = rUndoIter.GetDoc().GetTxtFmtColls()->GetPos(
+ (SwTxtFmtColl*)pFmtColl );
+ // ist das Format ueberhaupt noch vorhanden?
+ if( USHRT_MAX != nPos )
+ {
+ // --> OD 2008-04-15 #refactorlists#
+ rUndoIter.GetDoc().SetTxtFmtColl( *rUndoIter.pAktPam,
+ (SwTxtFmtColl*)pFmtColl,
+ mbReset,
+ mbResetListAttrs );
+ // <--
+ }
+
+ rUndoIter.pLastUndoObj = this;
+}
+
+SwRewriter SwUndoFmtColl::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ // --> FME 2004-08-06 #i31191# Use stored format name instead of
+ // pFmtColl->GetName(), because pFmtColl does not have to be available
+ // anymore.
+ aResult.AddRule(UNDO_ARG1, aFmtName );
+ // <--
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unins.cxx b/sw/source/core/undo/unins.cxx
new file mode 100644
index 000000000000..644ea3291eb6
--- /dev/null
+++ b/sw/source/core/undo/unins.cxx
@@ -0,0 +1,1102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <unotools/charclass.hxx>
+#include <sot/storage.hxx>
+#include <editeng/keepitem.hxx>
+#include <svx/svdobj.hxx>
+
+#include <docsh.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <rolbck.hxx>
+#include <ndgrf.hxx>
+#include <ndole.hxx>
+#include <grfatr.hxx>
+#include <cntfrm.hxx>
+#include <flyfrm.hxx>
+#include <fesh.hxx>
+#include <swtable.hxx>
+#include <redline.hxx>
+#include <docary.hxx>
+#include <acorrect.hxx>
+#include <dcontact.hxx>
+
+#include <comcore.hrc> // #111827#
+#include <undo.hrc>
+
+using namespace ::com::sun::star;
+
+
+class _UnReplaceData : private SwUndoSaveCntnt
+{
+ String m_sOld, m_sIns;
+ ULONG m_nSttNd, m_nEndNd, m_nOffset;
+ xub_StrLen m_nSttCnt, m_nEndCnt, m_nSetPos, m_nSelEnd;
+ BOOL m_bSplitNext : 1;
+ BOOL m_bRegExp : 1;
+ // metadata references for paragraph and following para (if m_bSplitNext)
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
+
+public:
+ _UnReplaceData( const SwPaM& rPam, const String& rIns, BOOL bRegExp );
+ ~_UnReplaceData();
+
+ void Undo( SwUndoIter& rIter );
+ void Redo( SwUndoIter& rIter );
+ void SetEnd( const SwPaM& rPam );
+
+ const String & GetOld() const { return m_sOld; }
+ const String & GetIns() const { return m_sIns; }
+};
+
+
+SV_IMPL_PTRARR( _UnReplaceDatas, _UnReplaceData* )
+
+//------------------------------------------------------------------
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+// zwei Zugriffs-Funktionen
+inline SwPosition* IterPt( SwUndoIter& rUIter )
+{ return rUIter.pAktPam->GetPoint(); }
+inline SwPosition* IterMk( SwUndoIter& rUIter )
+{ return rUIter.pAktPam->GetMark(); }
+
+//------------------------------------------------------------
+
+// INSERT
+
+String * SwUndoInsert::GetTxtFromDoc() const
+{
+ String * pResult = NULL;
+
+ SwNodeIndex aNd( pDoc->GetNodes(), nNode);
+ SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();
+ SwPaM aPaM( *pCNd, nCntnt );
+
+ aPaM.SetMark();
+
+ if( pCNd->IsTxtNode() )
+ {
+ pResult = new String( ((SwTxtNode*)pCNd)->GetTxt().Copy(nCntnt-nLen,
+ nLen ) );
+
+ }
+
+ return pResult;
+}
+
+void SwUndoInsert::Init(const SwNodeIndex & rNd)
+{
+ // Redline beachten
+ pDoc = rNd.GetNode().GetDoc();
+ if( pDoc->IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT,
+ pDoc->GetRedlineAuthor() );
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ }
+
+ pUndoTxt = GetTxtFromDoc();
+
+ bCacheComment = false;
+}
+
+// #111827#
+SwUndoInsert::SwUndoInsert( const SwNodeIndex& rNd, xub_StrLen nCnt,
+ xub_StrLen nL,
+ const IDocumentContentOperations::InsertFlags nInsertFlags,
+ BOOL bWDelim )
+ : SwUndo(UNDO_TYPING), pPos( 0 ), pTxt( 0 ), pRedlData( 0 ),
+ nNode( rNd.GetIndex() ), nCntnt(nCnt), nLen(nL),
+ bIsWordDelim( bWDelim ), bIsAppend( FALSE )
+ , m_nInsertFlags(nInsertFlags)
+{
+ Init(rNd);
+}
+
+// #111827#
+SwUndoInsert::SwUndoInsert( const SwNodeIndex& rNd )
+ : SwUndo(UNDO_SPLITNODE), pPos( 0 ), pTxt( 0 ),
+ pRedlData( 0 ), nNode( rNd.GetIndex() ), nCntnt(0), nLen(1),
+ bIsWordDelim( FALSE ), bIsAppend( TRUE )
+ , m_nInsertFlags(IDocumentContentOperations::INS_EMPTYEXPAND)
+{
+ Init(rNd);
+}
+
+// stelle fest, ob das naechste Insert mit dem aktuellen zusammengefasst
+// werden kann. Wenn ja, dann aender die Laenge und die InsPos.
+// Dann wird von SwDoc::Insert kein neues Object in die Undoliste gestellt.
+
+BOOL SwUndoInsert::CanGrouping( sal_Unicode cIns )
+{
+ if( !bIsAppend && bIsWordDelim ==
+ !GetAppCharClass().isLetterNumeric( String( cIns )) )
+ {
+ nLen++;
+ nCntnt++;
+
+ if (pUndoTxt)
+ pUndoTxt->Insert(cIns);
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL SwUndoInsert::CanGrouping( const SwPosition& rPos )
+{
+ BOOL bRet = FALSE;
+ if( nNode == rPos.nNode.GetIndex() &&
+ nCntnt == rPos.nContent.GetIndex() )
+ {
+ // Redline beachten
+ SwDoc& rDoc = *rPos.nNode.GetNode().GetDoc();
+ if( ( ~nsRedlineMode_t::REDLINE_SHOW_MASK & rDoc.GetRedlineMode() ) ==
+ ( ~nsRedlineMode_t::REDLINE_SHOW_MASK & GetRedlineMode() ) )
+ {
+ bRet = TRUE;
+
+ // dann war oder ist noch Redline an:
+ // pruefe, ob an der InsPosition ein anderer Redline
+ // rumsteht. Wenn der gleiche nur einmalig vorhanden ist,
+ // kann zusammen gefasst werden.
+ const SwRedlineTbl& rTbl = rDoc.GetRedlineTbl();
+ if( rTbl.Count() )
+ {
+ SwRedlineData aRData( nsRedlineType_t::REDLINE_INSERT, rDoc.GetRedlineAuthor() );
+ const SwIndexReg* pIReg = rPos.nContent.GetIdxReg();
+ SwIndex* pIdx;
+ for( USHORT i = 0; i < rTbl.Count(); ++i )
+ {
+ SwRedline* pRedl = rTbl[ i ];
+ if( pIReg == (pIdx = &pRedl->End()->nContent)->GetIdxReg() &&
+ nCntnt == pIdx->GetIndex() )
+ {
+ if( !pRedl->HasMark() || !pRedlData ||
+ *pRedl != *pRedlData || *pRedl != aRData )
+ {
+ bRet = FALSE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+SwUndoInsert::~SwUndoInsert()
+{
+ if( pPos ) // loesche noch den Bereich aus dem UndoNodes Array
+ {
+ // Insert speichert den Inhalt in der IconSection
+ SwNodes& rUNds = pPos->nNode.GetNode().GetNodes();
+ if( pPos->nContent.GetIndex() ) // nicht den gesamten Node loeschen
+ {
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "kein TextNode, aus dem geloescht werden soll" );
+ pTxtNd->EraseText( pPos->nContent );
+ pPos->nNode++;
+ }
+ pPos->nContent.Assign( 0, 0 );
+ rUNds.Delete( pPos->nNode, rUNds.GetEndOfExtras().GetIndex() -
+ pPos->nNode.GetIndex() );
+ delete pPos;
+ }
+ else if( pTxt ) // der eingefuegte Text
+ delete pTxt;
+ delete pRedlData;
+}
+
+
+
+void SwUndoInsert::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc* pTmpDoc = &rUndoIter.GetDoc();
+
+ if( bIsAppend )
+ {
+ SwPaM* pPam = rUndoIter.pAktPam;
+ pPam->GetPoint()->nNode = nNode;
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), 0 );
+ pPam->SetMark();
+ pPam->Move( fnMoveBackward );
+ pPam->Exchange();
+ pTmpDoc->DeleteRedline( *pPam, true, USHRT_MAX );
+ }
+ pPam->DeleteMark();
+ pTmpDoc->DelFullPara( *pPam );
+ pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), 0 );
+ }
+ else
+ {
+ ULONG nNd = nNode;
+ xub_StrLen nCnt = nCntnt;
+ if( nLen )
+ {
+ SwNodeIndex aNd( pTmpDoc->GetNodes(), nNode);
+ SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();
+ SwPaM aPaM( *pCNd, nCntnt );
+
+ aPaM.SetMark();
+
+ SwTxtNode * const pTxtNode( pCNd->GetTxtNode() );
+ if ( pTxtNode )
+ {
+ aPaM.GetPoint()->nContent -= nLen;
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ pTmpDoc->DeleteRedline( aPaM, true, USHRT_MAX );
+ RemoveIdxFromRange( aPaM, FALSE );
+ pTxt = new String( pTxtNode->GetTxt().Copy(nCntnt-nLen, nLen) );
+ pTxtNode->EraseText( aPaM.GetPoint()->nContent, nLen );
+ }
+ else // ansonsten Grafik/OLE/Text/...
+ {
+ aPaM.Move(fnMoveBackward);
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ pTmpDoc->DeleteRedline( aPaM, true, USHRT_MAX );
+ RemoveIdxFromRange( aPaM, FALSE );
+ }
+
+ nNd = aPaM.GetPoint()->nNode.GetIndex();
+ nCnt = aPaM.GetPoint()->nContent.GetIndex();
+
+ if( !pTxt )
+ {
+ pPos = new SwPosition( *aPaM.GetPoint() );
+ MoveToUndoNds( aPaM, &pPos->nNode, &pPos->nContent );
+ }
+ nNode = aPaM.GetPoint()->nNode.GetIndex();
+ nCntnt = aPaM.GetPoint()->nContent.GetIndex();
+ }
+
+ // setze noch den Cursor auf den Undo-Bereich
+ rUndoIter.pAktPam->DeleteMark();
+
+ IterPt(rUndoIter)->nNode = nNd;
+ IterPt(rUndoIter)->nContent.Assign( pTmpDoc->GetNodes()[
+ IterPt(rUndoIter)->nNode ]->GetCntntNode(), nCnt );
+ // SPoint und GetMark auf der gleichen Position
+ }
+
+ DELETEZ(pUndoTxt);
+}
+
+
+void SwUndoInsert::Redo( SwUndoIter& rUndoIter )
+{
+ // setze noch den Cursor auf den Redo-Bereich
+ SwPaM* pPam = rUndoIter.pAktPam;
+ SwDoc* pTmpDoc = pPam->GetDoc();
+ pPam->DeleteMark();
+
+ if( bIsAppend )
+ {
+ pPam->GetPoint()->nNode = nNode - 1;
+ pTmpDoc->AppendTxtNode( *pPam->GetPoint() );
+
+ pPam->SetMark();
+ pPam->Move( fnMoveBackward );
+ pPam->Exchange();
+
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ RedlineMode_t eOld = pTmpDoc->GetRedlineMode();
+ pTmpDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+ pTmpDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true);
+ pTmpDoc->SetRedlineMode_intern( eOld );
+ }
+ else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ pTmpDoc->GetRedlineTbl().Count() )
+ pTmpDoc->SplitRedline( *pPam );
+
+ pPam->DeleteMark();
+ }
+ else
+ {
+ pPam->GetPoint()->nNode = nNode;
+ SwCntntNode* pCNd = pTmpDoc->GetNodes()[ pPam->GetPoint()->nNode ]->GetCntntNode();
+ pPam->GetPoint()->nContent.Assign( pCNd, nCntnt );
+
+ if( nLen )
+ {
+ BOOL bMvBkwrd = MovePtBackward( *pPam );
+
+ if( pTxt )
+ {
+ SwTxtNode *const pTxtNode = pCNd->GetTxtNode();
+ OSL_ENSURE( pTxtNode, "where is my textnode ?" );
+ pTxtNode->InsertText( *pTxt, pPam->GetMark()->nContent,
+ m_nInsertFlags );
+ DELETEZ( pTxt );
+ }
+ else
+ {
+ // Inhalt wieder einfuegen. (erst pPos abmelden !!)
+ ULONG nMvNd = pPos->nNode.GetIndex();
+ xub_StrLen nMvCnt = pPos->nContent.GetIndex();
+ DELETEZ( pPos );
+ MoveFromUndoNds( *pTmpDoc, nMvNd, nMvCnt, *pPam->GetMark() );
+ }
+ nNode = pPam->GetMark()->nNode.GetIndex();
+ nCntnt = pPam->GetMark()->nContent.GetIndex();
+
+ MovePtForward( *pPam, bMvBkwrd );
+ rUndoIter.pAktPam->Exchange();
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ RedlineMode_t eOld = pTmpDoc->GetRedlineMode();
+ pTmpDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+ pTmpDoc->AppendRedline( new SwRedline( *pRedlData,
+ *rUndoIter.pAktPam ), true);
+ pTmpDoc->SetRedlineMode_intern( eOld );
+ }
+ else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ pTmpDoc->GetRedlineTbl().Count() )
+ pTmpDoc->SplitRedline( *rUndoIter.pAktPam );
+ }
+ }
+
+ pUndoTxt = GetTxtFromDoc();
+}
+
+
+void SwUndoInsert::Repeat( SwUndoIter& rUndoIter )
+{
+ rUndoIter.pLastUndoObj = this;
+ if( !nLen )
+ return;
+
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SwNodeIndex aNd( rDoc.GetNodes(), nNode );
+ SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();;
+
+ if( !bIsAppend && 1 == nLen ) // >1 dann immer nur Text, ansonsten Grafik/OLE/Text/...
+ {
+ SwPaM aPaM( *pCNd, nCntnt );
+ aPaM.SetMark();
+ aPaM.Move(fnMoveBackward);
+ pCNd = aPaM.GetCntntNode();
+ }
+
+// Was passiert mit dem evt. selektierten Bereich ???
+
+ switch( pCNd->GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ if( bIsAppend )
+ rDoc.AppendTxtNode( *rUndoIter.pAktPam->GetPoint() );
+ else
+ {
+ String aTxt( ((SwTxtNode*)pCNd)->GetTxt() );
+ BOOL bGroupUndo = rDoc.DoesGroupUndo();
+ rDoc.DoGroupUndo( FALSE );
+ rDoc.InsertString( *rUndoIter.pAktPam,
+ aTxt.Copy( nCntnt - nLen, nLen ) );
+ rDoc.DoGroupUndo( bGroupUndo );
+ }
+ break;
+ case ND_GRFNODE:
+ {
+ SwGrfNode* pGrfNd = (SwGrfNode*)pCNd;
+ String sFile, sFilter;
+ if( pGrfNd->IsGrfLink() )
+ pGrfNd->GetFileFilterNms( &sFile, &sFilter );
+
+ rDoc.Insert( *rUndoIter.pAktPam, sFile, sFilter,
+ &pGrfNd->GetGrf(),
+ 0/* Grafik-Collection*/, NULL, NULL );
+ }
+ break;
+
+ case ND_OLENODE:
+ {
+ // StarView bietet noch nicht die Moeglichkeit ein StarOBJ zu kopieren
+ SvStorageRef aRef = new SvStorage( aEmptyStr );
+ SwOLEObj& rSwOLE = (SwOLEObj&)((SwOLENode*)pCNd)->GetOLEObj();
+
+ // temporary storage until object is inserted
+ // TODO/MBA: seems that here a physical copy is done - not as in drawing layer! Testing!
+ // TODO/LATER: Copying through the container would copy the replacement image as well
+ comphelper::EmbeddedObjectContainer aCnt;
+ ::rtl::OUString aName = aCnt.CreateUniqueObjectName();
+ if ( aCnt.StoreEmbeddedObject( rSwOLE.GetOleRef(), aName, sal_True ) )
+ {
+ uno::Reference < embed::XEmbeddedObject > aNew = aCnt.GetEmbeddedObject( aName );
+ rDoc.Insert( *rUndoIter.pAktPam, svt::EmbeddedObjectRef( aNew, ((SwOLENode*)pCNd)->GetAspect() ), NULL, NULL, NULL );
+ }
+
+ break;
+ }
+ }
+}
+
+// #111827#
+SwRewriter SwUndoInsert::GetRewriter() const
+{
+ SwRewriter aResult;
+ String * pStr = NULL;
+ bool bDone = false;
+
+ if (pTxt)
+ pStr = pTxt;
+ else if (pUndoTxt)
+ pStr = pUndoTxt;
+
+ if (pStr)
+ {
+ String aString = ShortenString(DenoteSpecialCharacters(*pStr),
+ nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+
+ aResult.AddRule(UNDO_ARG1, aString);
+
+ bDone = true;
+ }
+
+ if ( ! bDone )
+ {
+ aResult.AddRule(UNDO_ARG1, String("??", RTL_TEXTENCODING_ASCII_US));
+ }
+
+ return aResult;
+}
+
+
+/* */
+
+SwUndoReplace::SwUndoReplace()
+ : SwUndo( UNDO_REPLACE ), nAktPos( USHRT_MAX )
+{
+}
+
+SwUndoReplace::~SwUndoReplace()
+{
+}
+
+void SwUndoReplace::Undo( SwUndoIter& rUndoIter )
+{
+ // war dieses nicht die letze Undo-Aktion, dann setze den
+ // Count neu
+ if( rUndoIter.pLastUndoObj != this )
+ {
+ nAktPos = aArr.Count();
+ rUndoIter.pLastUndoObj = this;
+ bOldIterFlag = rUndoIter.bWeiter;
+ rUndoIter.bWeiter = TRUE;
+ }
+
+ aArr[ --nAktPos ]->Undo( rUndoIter );
+
+ if( !nAktPos ) // alten Status wieder zurueck
+ rUndoIter.bWeiter = bOldIterFlag;
+}
+
+
+void SwUndoReplace::Redo( SwUndoIter& rUndoIter )
+{
+ // war dieses nicht die letze Undo-Aktion, dann setze den
+ // Count neu
+ if( rUndoIter.pLastUndoObj != this )
+ {
+ OSL_ENSURE( !nAktPos, "Redo ohne vorheriges Undo??" );
+ rUndoIter.pLastUndoObj = this;
+ bOldIterFlag = rUndoIter.bWeiter;
+ rUndoIter.bWeiter = TRUE;
+ }
+
+ aArr[ nAktPos ]->Redo( rUndoIter );
+
+ if( ++nAktPos >= aArr.Count() ) // alten Status wieder zurueck
+ {
+ nAktPos = USHRT_MAX;
+ rUndoIter.bWeiter = bOldIterFlag;
+ }
+}
+
+// #111827#
+SwRewriter SwUndoReplace::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ if (aArr.Count() > 1)
+ {
+ aResult.AddRule(UNDO_ARG1, String::CreateFromInt32(aArr.Count()));
+ aResult.AddRule(UNDO_ARG2, String(SW_RES(STR_OCCURRENCES_OF)));
+
+ String aTmpStr;
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ aTmpStr += ShortenString(aArr[0]->GetOld(), nUndoStringLength,
+ SW_RES(STR_LDOTS));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+ aResult.AddRule(UNDO_ARG3, aTmpStr);
+ }
+ else if (aArr.Count() == 1)
+ {
+ {
+ String aTmpStr;
+
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ // #i33488 #
+ aTmpStr += ShortenString(aArr[0]->GetOld(), nUndoStringLength,
+ SW_RES(STR_LDOTS));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+ aResult.AddRule(UNDO_ARG1, aTmpStr);
+ }
+
+ aResult.AddRule(UNDO_ARG2, String(SW_RES(STR_YIELDS)));
+
+ {
+ String aTmpStr;
+
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ // #i33488 #
+ aTmpStr += ShortenString(aArr[0]->GetIns(), nUndoStringLength,
+ SW_RES(STR_LDOTS));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+ aResult.AddRule(UNDO_ARG3, aTmpStr);
+ }
+ }
+
+ return aResult;
+}
+
+void SwUndoReplace::AddEntry( const SwPaM& rPam, const String& rInsert,
+ BOOL bRegExp )
+{
+ _UnReplaceData* pNew = new _UnReplaceData( rPam, rInsert, bRegExp );
+ aArr.C40_INSERT(_UnReplaceData, pNew, aArr.Count() );
+}
+
+void SwUndoReplace::SetEntryEnd( const SwPaM& rPam )
+{
+ _UnReplaceData* pEntry = aArr[ aArr.Count()-1 ];
+ pEntry->SetEnd( rPam );
+}
+
+_UnReplaceData::_UnReplaceData( const SwPaM& rPam, const String& rIns,
+ BOOL bRgExp )
+ : m_sIns( rIns ), m_nOffset( 0 )
+{
+ m_bRegExp = bRgExp;
+
+ const SwPosition * pStt( rPam.Start() );
+ const SwPosition * pEnd( rPam.End() );
+
+ m_nSttNd = m_nEndNd = pStt->nNode.GetIndex();
+ m_nSttCnt = pStt->nContent.GetIndex();
+ m_nSelEnd = m_nEndCnt = pEnd->nContent.GetIndex();
+
+ m_bSplitNext = m_nSttNd != pEnd->nNode.GetIndex();
+
+ SwTxtNode* pNd = pStt->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pNd, "wo ist der TextNode" );
+
+ pHistory = new SwHistory;
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+
+ m_nSetPos = pHistory->Count();
+
+ ULONG nNewPos = pStt->nNode.GetIndex();
+ m_nOffset = m_nSttNd - nNewPos;
+
+ if ( pNd->GetpSwpHints() )
+ {
+ pHistory->CopyAttr( pNd->GetpSwpHints(), nNewPos, 0,
+ pNd->GetTxt().Len(), true );
+ }
+
+ if ( m_bSplitNext )
+ {
+ if( pNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNewPos );
+ pHistory->Add( pNd->GetTxtColl(), nNewPos, ND_TEXTNODE );
+
+ SwTxtNode* pNext = pEnd->nNode.GetNode().GetTxtNode();
+ ULONG nTmp = pNext->GetIndex();
+ pHistory->CopyAttr( pNext->GetpSwpHints(), nTmp, 0,
+ pNext->GetTxt().Len(), true );
+ if( pNext->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pNext->GetpSwAttrSet(), nTmp );
+ pHistory->Add( pNext->GetTxtColl(),nTmp, ND_TEXTNODE );
+ // METADATA: store
+ m_pMetadataUndoStart = pNd ->CreateUndo();
+ m_pMetadataUndoEnd = pNext->CreateUndo();
+ }
+
+ if( !pHistory->Count() )
+ delete pHistory, pHistory = 0;
+
+ xub_StrLen nECnt = m_bSplitNext ? pNd->GetTxt().Len()
+ : pEnd->nContent.GetIndex();
+ m_sOld = pNd->GetTxt().Copy( m_nSttCnt, nECnt - m_nSttCnt );
+}
+
+_UnReplaceData::~_UnReplaceData()
+{
+}
+
+void _UnReplaceData::Undo( SwUndoIter& rIter )
+{
+ SwDoc* pDoc = &rIter.GetDoc();
+ SwPaM& rPam = *rIter.pAktPam;
+ rPam.DeleteMark();
+
+ SwTxtNode* pNd = pDoc->GetNodes()[ m_nSttNd - m_nOffset ]->GetTxtNode();
+ OSL_ENSURE( pNd, "Wo ist der TextNode geblieben?" );
+
+ SwAutoCorrExceptWord* pACEWord = pDoc->GetAutoCorrExceptWord();
+ if( pACEWord )
+ {
+ if( 1 == m_sIns.Len() && 1 == m_sOld.Len() )
+ {
+ SwPosition aPos( *pNd ); aPos.nContent.Assign( pNd, m_nSttCnt );
+ pACEWord->CheckChar( aPos, m_sOld.GetChar( 0 ) );
+ }
+ pDoc->SetAutoCorrExceptWord( 0 );
+ }
+
+ SwIndex aIdx( pNd, m_nSttCnt );
+ if( m_nSttNd == m_nEndNd )
+ {
+ pNd->EraseText( aIdx, m_sIns.Len() );
+ }
+ else
+ {
+ rPam.GetPoint()->nNode = *pNd;
+ rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt );
+ rPam.SetMark();
+ rPam.GetPoint()->nNode = m_nEndNd - m_nOffset;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), m_nEndCnt );
+
+ pDoc->DeleteAndJoin( rPam );
+ rPam.DeleteMark();
+ pNd = rPam.GetNode()->GetTxtNode();
+ OSL_ENSURE( pNd, "Wo ist der TextNode geblieben?" );
+ aIdx.Assign( pNd, m_nSttCnt );
+ }
+
+ if( m_bSplitNext )
+ {
+ SwPosition aPos( *pNd, aIdx );
+ pDoc->SplitNode( aPos, false );
+ pNd->RestoreMetadata(m_pMetadataUndoEnd);
+ pNd = pDoc->GetNodes()[ m_nSttNd - m_nOffset ]->GetTxtNode();
+ aIdx.Assign( pNd, m_nSttCnt );
+ // METADATA: restore
+ pNd->RestoreMetadata(m_pMetadataUndoStart);
+ }
+
+ if( m_sOld.Len() )
+ {
+ pNd->InsertText( m_sOld, aIdx );
+ }
+
+ if( pHistory )
+ {
+ if( pNd->GetpSwpHints() )
+ pNd->ClearSwpHintsArr( true );
+
+ pHistory->TmpRollback( pDoc, m_nSetPos, false );
+ if ( m_nSetPos ) // there were footnotes/FlyFrames
+ {
+ // gibts ausser diesen noch andere ?
+ if( m_nSetPos < pHistory->Count() )
+ {
+ // dann sicher die Attribute anderen Attribute
+ SwHistory aHstr;
+ aHstr.Move( 0, pHistory, m_nSetPos );
+ pHistory->Rollback( pDoc );
+ pHistory->Move( 0, &aHstr );
+ }
+ else
+ {
+ pHistory->Rollback( pDoc );
+ DELETEZ( pHistory );
+ }
+ }
+ }
+
+ rPam.GetPoint()->nNode = m_nSttNd;
+ rPam.GetPoint()->nContent = aIdx;
+}
+
+void _UnReplaceData::Redo( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+ BOOL bUndo = rDoc.DoesUndo();
+ rDoc.DoUndo( FALSE );
+
+ SwPaM& rPam = *rIter.pAktPam;
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = m_nSttNd;
+
+ SwTxtNode* pNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pNd, "Wo ist der TextNode geblieben?" );
+ rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt );
+ rPam.SetMark();
+ if( m_bSplitNext )
+ {
+ rPam.GetPoint()->nNode = m_nSttNd + 1;
+ pNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
+ }
+ rPam.GetPoint()->nContent.Assign( pNd, m_nSelEnd );
+
+ if( pHistory )
+ {
+ SwHistory* pSave = pHistory;
+ SwHistory aHst;
+ pHistory = &aHst;
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+ m_nSetPos = pHistory->Count();
+
+ pHistory = pSave;
+ pHistory->Move( 0, &aHst );
+ }
+ else
+ {
+ pHistory = new SwHistory;
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+ m_nSetPos = pHistory->Count();
+ if( !m_nSetPos )
+ delete pHistory, pHistory = 0;
+ }
+
+ rDoc.ReplaceRange( rPam, m_sIns, m_bRegExp );
+ rPam.DeleteMark();
+ rDoc.DoUndo( bUndo );
+}
+
+void _UnReplaceData::SetEnd( const SwPaM& rPam )
+{
+ if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
+ {
+ // es wurden mehrere Absaetze eingefuegt
+ const SwPosition* pEnd = rPam.End();
+ m_nEndNd = m_nOffset + pEnd->nNode.GetIndex();
+ m_nEndCnt = pEnd->nContent.GetIndex();
+ }
+}
+
+/* */
+
+
+SwUndoReRead::SwUndoReRead( const SwPaM& rPam, const SwGrfNode& rGrfNd )
+ : SwUndo( UNDO_REREAD ), nPos( rPam.GetPoint()->nNode.GetIndex() )
+{
+ SaveGraphicData( rGrfNd );
+}
+
+
+SwUndoReRead::~SwUndoReRead()
+{
+ delete pGrf;
+ delete pNm;
+ delete pFltr;
+}
+
+
+void SwUndoReRead::SetAndSave( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+ SwGrfNode* pGrfNd = rDoc.GetNodes()[ nPos ]->GetGrfNode();
+
+ if( !pGrfNd )
+ return ;
+
+ // die alten Werte zwischen speichern
+ Graphic* pOldGrf = pGrf;
+ String* pOldNm = pNm;
+ String* pOldFltr = pFltr;
+ USHORT nOldMirr = nMirr;
+
+ SaveGraphicData( *pGrfNd );
+ if( pOldNm )
+ {
+ pGrfNd->ReRead( *pOldNm, pFltr ? *pFltr : aEmptyStr, 0, 0, TRUE );
+ delete pOldNm;
+ delete pOldFltr;
+ }
+ else
+ {
+ pGrfNd->ReRead( aEmptyStr, aEmptyStr, pOldGrf, 0, TRUE );
+ delete pOldGrf;
+ }
+
+ if( RES_MIRROR_GRAPH_DONT != nOldMirr )
+ pGrfNd->SetAttr( SwMirrorGrf() );
+
+ rIter.pSelFmt = pGrfNd->GetFlyFmt();
+}
+
+
+void SwUndoReRead::Undo( SwUndoIter& rIter )
+{
+ SetAndSave( rIter );
+}
+
+
+void SwUndoReRead::Redo( SwUndoIter& rIter )
+{
+ SetAndSave( rIter );
+}
+
+
+void SwUndoReRead::SaveGraphicData( const SwGrfNode& rGrfNd )
+{
+ if( rGrfNd.IsGrfLink() )
+ {
+ pNm = new String;
+ pFltr = new String;
+ rGrfNd.GetFileFilterNms( pNm, pFltr );
+ pGrf = 0;
+ }
+ else
+ {
+ ((SwGrfNode&)rGrfNd).SwapIn( TRUE );
+ pGrf = new Graphic( rGrfNd.GetGrf() );
+ pNm = pFltr = 0;
+ }
+ nMirr = rGrfNd.GetSwAttrSet().GetMirrorGrf().GetValue();
+}
+
+/* */
+
+SwUndoInsertLabel::SwUndoInsertLabel( const SwLabelType eTyp,
+ const String &rTxt,
+ const String& rSeparator,
+ const String& rNumberSeparator,
+ const BOOL bBef,
+ const USHORT nInitId,
+ const String& rCharacterStyle,
+ const BOOL bCpyBorder )
+ : SwUndo( UNDO_INSERTLABEL ),
+ sText( rTxt ),
+ sSeparator( rSeparator ),
+ sNumberSeparator( rNumberSeparator ),//#i61007# order of captions
+ sCharacterStyle( rCharacterStyle ),
+ nFldId( nInitId ),
+ eType( eTyp ),
+ nLayerId( 0 ),
+ bBefore( bBef ),
+ bCpyBrd( bCpyBorder )
+{
+ bUndoKeep = FALSE;
+ OBJECT.pUndoFly = 0;
+ OBJECT.pUndoAttr = 0;
+}
+
+SwUndoInsertLabel::~SwUndoInsertLabel()
+{
+ if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
+ {
+ delete OBJECT.pUndoFly;
+ delete OBJECT.pUndoAttr;
+ }
+ else
+ delete NODE.pUndoInsNd;
+}
+
+void SwUndoInsertLabel::Undo( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+
+ if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
+ {
+ OSL_ENSURE( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer nicht initialisiert" );
+ SwFrmFmt* pFmt;
+ SdrObject *pSdrObj = 0;
+ if( OBJECT.pUndoAttr &&
+ 0 != (pFmt = (SwFrmFmt*)OBJECT.pUndoAttr->GetFmt( rDoc )) &&
+ ( LTYPE_DRAW != eType ||
+ 0 != (pSdrObj = pFmt->FindSdrObject()) ) )
+ {
+ OBJECT.pUndoAttr->Undo( rIter );
+ OBJECT.pUndoFly->Undo( rIter );
+ if( LTYPE_DRAW == eType )
+ {
+ pSdrObj->SetLayer( nLayerId );
+ }
+ }
+ }
+ else if( NODE.nNode )
+ {
+ if ( eType == LTYPE_TABLE && bUndoKeep )
+ {
+ SwTableNode *pNd = rDoc.GetNodes()[
+ rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode();
+ if ( pNd )
+ pNd->GetTable().GetFrmFmt()->ResetFmtAttr( RES_KEEP );
+ }
+ SwPaM aPam( *rIter.pAktPam->GetPoint() );
+ aPam.GetPoint()->nNode = NODE.nNode;
+ aPam.SetMark();
+ aPam.GetPoint()->nNode = NODE.nNode + 1;
+ NODE.pUndoInsNd = new SwUndoDelete( aPam, TRUE );
+ }
+}
+
+
+void SwUndoInsertLabel::Redo( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+
+ if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
+ {
+ OSL_ENSURE( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer nicht initialisiert" );
+ SwFrmFmt* pFmt;
+ SdrObject *pSdrObj = 0;
+ if( OBJECT.pUndoAttr &&
+ 0 != (pFmt = (SwFrmFmt*)OBJECT.pUndoAttr->GetFmt( rDoc )) &&
+ ( LTYPE_DRAW != eType ||
+ 0 != (pSdrObj = pFmt->FindSdrObject()) ) )
+ {
+ OBJECT.pUndoFly->Redo( rIter );
+ OBJECT.pUndoAttr->Redo( rIter );
+ if( LTYPE_DRAW == eType )
+ {
+ pSdrObj->SetLayer( nLayerId );
+ if( pSdrObj->GetLayer() == rDoc.GetHellId() )
+ pSdrObj->SetLayer( rDoc.GetHeavenId() );
+ // OD 02.07.2003 #108784#
+ else if( pSdrObj->GetLayer() == rDoc.GetInvisibleHellId() )
+ pSdrObj->SetLayer( rDoc.GetInvisibleHeavenId() );
+ }
+ }
+ }
+ else if( NODE.pUndoInsNd )
+ {
+ if ( eType == LTYPE_TABLE && bUndoKeep )
+ {
+ SwTableNode *pNd = rDoc.GetNodes()[
+ rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode();
+ if ( pNd )
+ pNd->GetTable().GetFrmFmt()->SetFmtAttr( SvxFmtKeepItem(TRUE, RES_KEEP) );
+ }
+ NODE.pUndoInsNd->Undo( rIter );
+ delete NODE.pUndoInsNd, NODE.pUndoInsNd = 0;
+ }
+}
+
+void SwUndoInsertLabel::Repeat( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+ const SwPosition& rPos = *rIter.pAktPam->GetPoint();
+
+ ULONG nIdx = 0;
+
+ SwCntntNode* pCNd = rPos.nNode.GetNode().GetCntntNode();
+ if( pCNd )
+ switch( eType )
+ {
+ case LTYPE_TABLE:
+ {
+ const SwTableNode* pTNd = pCNd->FindTableNode();
+ if( pTNd )
+ nIdx = pTNd->GetIndex();
+ }
+ break;
+
+ case LTYPE_FLY:
+ case LTYPE_OBJECT:
+ {
+ SwFlyFrm* pFly;
+ SwCntntFrm *pCnt = pCNd->GetFrm();
+ if( pCnt && 0 != ( pFly = pCnt->FindFlyFrm() ) )
+ nIdx = pFly->GetFmt()->GetCntnt().GetCntntIdx()->GetIndex();
+ }
+ break;
+ case LTYPE_DRAW:
+ break;
+ }
+
+ if( nIdx )
+ {
+ rDoc.InsertLabel( eType, sText, sSeparator, sNumberSeparator, bBefore,
+ nFldId, nIdx, sCharacterStyle, bCpyBrd );
+ }
+}
+
+// #111827#
+SwRewriter SwUndoInsertLabel::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ String aTmpStr;
+
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ aTmpStr += ShortenString(sText, nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ return aRewriter;
+}
+
+void SwUndoInsertLabel::SetFlys( SwFrmFmt& rOldFly, SfxItemSet& rChgSet,
+ SwFrmFmt& rNewFly )
+{
+ if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
+ {
+ SwUndoFmtAttrHelper aTmp( rOldFly, false );
+ rOldFly.SetFmtAttr( rChgSet );
+ if ( aTmp.GetUndo() )
+ {
+ OBJECT.pUndoAttr = aTmp.ReleaseUndo();
+ }
+ OBJECT.pUndoFly = new SwUndoInsLayFmt( &rNewFly,0,0 );
+ }
+}
+
+void SwUndoInsertLabel::SetDrawObj( BYTE nLId )
+{
+ if( LTYPE_DRAW == eType )
+ {
+ nLayerId = nLId;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unmove.cxx b/sw/source/core/undo/unmove.cxx
new file mode 100644
index 000000000000..ccb48192518b
--- /dev/null
+++ b/sw/source/core/undo/unmove.cxx
@@ -0,0 +1,358 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <doc.hxx>
+#include <pam.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <rolbck.hxx>
+
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+// MOVE
+
+SwUndoMove::SwUndoMove( const SwPaM& rRange, const SwPosition& rMvPos )
+ : SwUndo( UNDO_MOVE ), SwUndRng( rRange ),
+ nMvDestNode( rMvPos.nNode.GetIndex() ),
+ nMvDestCntnt( rMvPos.nContent.GetIndex() ),
+ bMoveRedlines( false )
+{
+ bMoveRange = bJoinNext = bJoinPrev = FALSE;
+
+ // StartNode vorm loeschen von Fussnoten besorgen!
+ SwDoc* pDoc = rRange.GetDoc();
+ SwTxtNode* pTxtNd = pDoc->GetNodes()[ nSttNode ]->GetTxtNode();
+ SwTxtNode* pEndTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode();
+
+ pHistory = new SwHistory;
+
+ if( pTxtNd )
+ {
+ pHistory->Add( pTxtNd->GetTxtColl(), nSttNode, ND_TEXTNODE );
+ if ( pTxtNd->GetpSwpHints() )
+ {
+ pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode,
+ 0, pTxtNd->GetTxt().Len(), false );
+ }
+ if( pTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode );
+ }
+ if( pEndTxtNd && pEndTxtNd != pTxtNd )
+ {
+ pHistory->Add( pEndTxtNd->GetTxtColl(), nEndNode, ND_TEXTNODE );
+ if ( pEndTxtNd->GetpSwpHints() )
+ {
+ pHistory->CopyAttr( pEndTxtNd->GetpSwpHints(), nEndNode,
+ 0, pEndTxtNd->GetTxt().Len(), false );
+ }
+ if( pEndTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pEndTxtNd->GetpSwAttrSet(), nEndNode );
+ }
+
+ if( 0 != (pTxtNd = rRange.GetDoc()->GetNodes()[ rMvPos.nNode ]->GetTxtNode() ))
+ {
+ pHistory->Add( pTxtNd->GetTxtColl(), nMvDestNode, ND_TEXTNODE );
+ if ( pTxtNd->GetpSwpHints() )
+ {
+ pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nMvDestNode,
+ 0, pTxtNd->GetTxt().Len(), false );
+ }
+ if( pTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nMvDestNode );
+ }
+
+
+ nFtnStt = pHistory->Count();
+ DelFtn( rRange );
+
+ if( pHistory && !pHistory->Count() )
+ DELETEZ( pHistory );
+}
+
+
+SwUndoMove::SwUndoMove( SwDoc* pDoc, const SwNodeRange& rRg,
+ const SwNodeIndex& rMvPos )
+ : SwUndo( UNDO_MOVE ),
+ nMvDestNode( rMvPos.GetIndex() ),
+ bMoveRedlines( false )
+{
+ bMoveRange = TRUE;
+ bJoinNext = bJoinPrev = FALSE;
+
+ nSttCntnt = nEndCntnt = nMvDestCntnt = STRING_MAXLEN;
+
+ nSttNode = rRg.aStart.GetIndex();
+ nEndNode = rRg.aEnd.GetIndex();
+
+// DelFtn( rRange );
+
+ // wird aus dem CntntBereich in den Sonderbereich verschoben ?
+ ULONG nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
+ if( nMvDestNode < nCntntStt && rRg.aStart.GetIndex() > nCntntStt )
+ {
+ // loesche alle Fussnoten. Diese sind dort nicht erwuenscht.
+ SwPosition aPtPos( rRg.aEnd );
+ SwCntntNode* pCNd = rRg.aEnd.GetNode().GetCntntNode();
+ if( pCNd )
+ aPtPos.nContent.Assign( pCNd, pCNd->Len() );
+ SwPosition aMkPos( rRg.aStart );
+ if( 0 != ( pCNd = aMkPos.nNode.GetNode().GetCntntNode() ))
+ aMkPos.nContent.Assign( pCNd, 0 );
+
+ DelCntntIndex( aMkPos, aPtPos, nsDelCntntType::DELCNT_FTN );
+
+ if( pHistory && !pHistory->Count() )
+ DELETEZ( pHistory );
+ }
+
+ nFtnStt = 0;
+}
+
+
+
+void SwUndoMove::SetDestRange( const SwPaM& rRange,
+ const SwPosition& rInsPos,
+ BOOL bJoin, BOOL bCorrPam )
+{
+ const SwPosition *pStt = rRange.Start(),
+ *pEnd = rRange.GetPoint() == pStt
+ ? rRange.GetMark()
+ : rRange.GetPoint();
+
+ nDestSttNode = pStt->nNode.GetIndex();
+ nDestSttCntnt = pStt->nContent.GetIndex();
+ nDestEndNode = pEnd->nNode.GetIndex();
+ nDestEndCntnt = pEnd->nContent.GetIndex();
+
+ nInsPosNode = rInsPos.nNode.GetIndex();
+ nInsPosCntnt = rInsPos.nContent.GetIndex();
+
+ if( bCorrPam )
+ {
+ nDestSttNode--;
+ nDestEndNode--;
+ }
+
+ bJoinNext = nDestSttNode != nDestEndNode &&
+ pStt->nNode.GetNode().GetTxtNode() &&
+ pEnd->nNode.GetNode().GetTxtNode();
+ bJoinPrev = bJoin;
+}
+
+
+void SwUndoMove::SetDestRange( const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd,
+ const SwNodeIndex& rInsPos )
+{
+ nDestSttNode = rStt.GetIndex();
+ nDestEndNode = rEnd.GetIndex();
+ if( nDestSttNode > nDestEndNode )
+ {
+ nDestSttNode = nDestEndNode;
+ nDestEndNode = rStt.GetIndex();
+ }
+ nInsPosNode = rInsPos.GetIndex();
+
+ nDestSttCntnt = nDestEndCntnt = nInsPosCntnt = STRING_MAXLEN;
+}
+
+
+void SwUndoMove::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc* pDoc = &rUndoIter.GetDoc();
+ BOOL bUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+
+ // Block, damit aus diesem gesprungen werden kann
+ do {
+ // erzeuge aus den Werten die Insert-Position und den Bereich
+ SwNodeIndex aIdx( pDoc->GetNodes(), nDestSttNode );
+
+ if( bMoveRange )
+ {
+ // nur ein Move mit SwRange
+ SwNodeRange aRg( aIdx, aIdx );
+ aRg.aEnd = nDestEndNode;
+ aIdx = nInsPosNode;
+ bool bSuccess = pDoc->MoveNodeRange( aRg, aIdx,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ if (!bSuccess)
+ break;
+ }
+ else
+ {
+ SwPaM aPam( aIdx.GetNode(), nDestSttCntnt,
+ *pDoc->GetNodes()[ nDestEndNode ], nDestEndCntnt );
+
+ // #i17764# if redlines are to be moved, we may not remove them before
+ // pDoc->Move gets a chance to handle them
+ if( ! bMoveRedlines )
+ RemoveIdxFromRange( aPam, FALSE );
+
+ SwPosition aPos( *pDoc->GetNodes()[ nInsPosNode] );
+ SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
+ aPos.nContent.Assign( pCNd, nInsPosCntnt );
+
+ if( pCNd->HasSwAttrSet() )
+ pCNd->ResetAllAttr();
+
+ if( pCNd->IsTxtNode() && ((SwTxtNode*)pCNd)->GetpSwpHints() )
+ ((SwTxtNode*)pCNd)->ClearSwpHintsArr( false );
+
+ // an der InsertPos erstmal alle Attribute entfernen,
+ const bool bSuccess = pDoc->MoveRange( aPam, aPos, (bMoveRedlines)
+ ? IDocumentContentOperations::DOC_MOVEREDLINES
+ : IDocumentContentOperations::DOC_MOVEDEFAULT );
+ if (!bSuccess)
+ break;
+
+ aPam.Exchange();
+ aPam.DeleteMark();
+// pDoc->ResetAttr( aPam, FALSE );
+ if( aPam.GetNode()->IsCntntNode() )
+ aPam.GetNode()->GetCntntNode()->ResetAllAttr();
+ // der Pam wird jetzt aufgegeben.
+ }
+
+ SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode();
+ if( bJoinNext )
+ {
+ {
+ RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
+ SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
+ }
+ // sind keine Pams mehr im naechsten TextNode
+ pTxtNd->JoinNext();
+ }
+
+ if( bJoinPrev && pTxtNd->CanJoinPrev( &aIdx ) )
+ {
+ // ?? sind keine Pams mehr im naechsten TextNode ??
+ pTxtNd = aIdx.GetNode().GetTxtNode();
+ {
+ RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
+ SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
+ }
+ pTxtNd->JoinNext();
+ }
+
+ } while( FALSE );
+
+ if( pHistory )
+ {
+ if( nFtnStt != pHistory->Count() )
+ pHistory->Rollback( pDoc, nFtnStt );
+ pHistory->TmpRollback( pDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+
+ pDoc->DoUndo( bUndo );
+
+ // setze noch den Cursor auf den Undo-Bereich
+ if( !bMoveRange )
+ SetPaM( rUndoIter );
+}
+
+
+void SwUndoMove::Redo( SwUndoIter& rUndoIter )
+{
+ SwPaM* pPam = rUndoIter.pAktPam;
+ SwDoc& rDoc = *pPam->GetDoc();
+
+ SwNodes& rNds = rDoc.GetNodes();
+ SwNodeIndex aIdx( rNds, nMvDestNode );
+
+ if( bMoveRange )
+ {
+ // nur ein Move mit SwRange
+ SwNodeRange aRg( rNds, nSttNode, rNds, nEndNode );
+ rDoc.MoveNodeRange( aRg, aIdx, (bMoveRedlines)
+ ? IDocumentContentOperations::DOC_MOVEREDLINES
+ : IDocumentContentOperations::DOC_MOVEDEFAULT );
+ }
+ else
+ {
+ SwPaM aPam( *pPam->GetPoint() );
+ SetPaM( aPam );
+ SwPosition aMvPos( aIdx, SwIndex( aIdx.GetNode().GetCntntNode(),
+ nMvDestCntnt ));
+
+ DelFtn( aPam );
+ RemoveIdxFromRange( aPam, FALSE );
+
+ aIdx = aPam.Start()->nNode;
+ BOOL bJoinTxt = aIdx.GetNode().IsTxtNode();
+
+ aIdx--;
+ rDoc.MoveRange( aPam, aMvPos,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+
+ if( nSttNode != nEndNode && bJoinTxt )
+ {
+ aIdx++;
+ SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
+ if( pTxtNd && pTxtNd->CanJoinNext() )
+ {
+ {
+ RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
+ SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
+ }
+ pTxtNd->JoinNext();
+ }
+ }
+ *pPam->GetPoint() = *aPam.GetPoint();
+ pPam->SetMark();
+ *pPam->GetMark() = *aPam.GetMark();
+ }
+}
+
+
+void SwUndoMove::DelFtn( const SwPaM& rRange )
+{
+ // wird aus dem CntntBereich in den Sonderbereich verschoben ?
+ SwDoc* pDoc = rRange.GetDoc();
+ ULONG nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
+ if( nMvDestNode < nCntntStt &&
+ rRange.GetPoint()->nNode.GetIndex() >= nCntntStt )
+ {
+ // loesche alle Fussnoten. Diese sind dort nicht erwuenscht.
+ DelCntntIndex( *rRange.GetMark(), *rRange.GetPoint(),
+ nsDelCntntType::DELCNT_FTN );
+
+ if( pHistory && !pHistory->Count() )
+ delete pHistory, pHistory = 0;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unnum.cxx b/sw/source/core/undo/unnum.cxx
new file mode 100644
index 000000000000..6da4a95b1ba7
--- /dev/null
+++ b/sw/source/core/undo/unnum.cxx
@@ -0,0 +1,468 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/lrspitem.hxx>
+#include <doc.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <rolbck.hxx>
+
+
+SV_DECL_PTRARR_DEL( _SfxPoolItems, SfxPoolItem*, 16, 16 )
+SV_IMPL_PTRARR( _SfxPoolItems, SfxPoolItem* );
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+SwUndoInsNum::SwUndoInsNum( const SwNumRule& rOldRule,
+ const SwNumRule& rNewRule,
+ SwUndoId nUndoId )
+ : SwUndo( nUndoId ),
+ aNumRule( rNewRule ), pHistory( 0 ), nSttSet( ULONG_MAX ),
+ pOldNumRule( new SwNumRule( rOldRule )), nLRSavePos( 0 )
+{
+}
+
+SwUndoInsNum::SwUndoInsNum( const SwPaM& rPam, const SwNumRule& rRule )
+ : SwUndo( UNDO_INSNUM ), SwUndRng( rPam ),
+ aNumRule( rRule ), pHistory( 0 ),
+ nSttSet( ULONG_MAX ), pOldNumRule( 0 ), nLRSavePos( 0 )
+{
+}
+
+SwUndoInsNum::SwUndoInsNum( const SwPosition& rPos, const SwNumRule& rRule,
+ const String& rReplaceRule )
+ : SwUndo( UNDO_INSNUM ),
+ aNumRule( rRule ), pHistory( 0 ),
+ nSttSet( ULONG_MAX ), pOldNumRule( 0 ),
+ sReplaceRule( rReplaceRule ), nLRSavePos( 0 )
+{
+ // keine Selektion !!
+ nEndNode = 0, nEndCntnt = USHRT_MAX;
+ nSttNode = rPos.nNode.GetIndex();
+ nSttCntnt = rPos.nContent.GetIndex();
+}
+
+SwUndoInsNum::~SwUndoInsNum()
+{
+ delete pHistory;
+ delete pOldNumRule;
+}
+
+SwRewriter SwUndoInsNum::GetRewriter() const
+{
+ SwRewriter aResult;
+ if( UNDO_INSFMTATTR == GetId() )
+ aResult.AddRule(UNDO_ARG1, aNumRule.GetName());
+ return aResult;
+}
+
+void SwUndoInsNum::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ if( nSttNode )
+ SetPaM( rUndoIter );
+
+ BOOL bUndo = rDoc.DoesUndo();
+ rDoc.DoUndo( FALSE );
+
+ if( pOldNumRule )
+ rDoc.ChgNumRuleFmts( *pOldNumRule );
+
+ if( pHistory )
+ {
+ SwTxtNode* pNd;
+ if( ULONG_MAX != nSttSet &&
+ 0 != ( pNd = rDoc.GetNodes()[ nSttSet ]->GetTxtNode() ))
+ pNd->SetListRestart( TRUE );
+ else
+ pNd = 0;
+
+
+ if( nLRSavePos )
+ {
+ // sofort Updaten, damit eventuell "alte" LRSpaces wieder
+ // gueltig werden.
+ // !!! Dafuer suche aber erstmal den richtigen NumRule - Namen!
+ if( !pNd && nSttNode )
+ pNd = rDoc.GetNodes()[ nSttNode ]->GetTxtNode();
+
+ // This code seems to be superfluous because the methods
+ // don't have any known side effects.
+ // ToDo: iasue i83806 should be used to remove this code
+ const SwNumRule* pNdRule;
+ if( pNd )
+ pNdRule = pNd->GetNumRule();
+ else
+ pNdRule = rDoc.FindNumRulePtr( aNumRule.GetName() );
+ // End of ToDo for issue i83806
+
+ pHistory->TmpRollback( &rDoc, nLRSavePos );
+
+ }
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+
+ if( nSttNode )
+ SetPaM( rUndoIter );
+ rDoc.DoUndo( bUndo );
+}
+
+
+void SwUndoInsNum::Redo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ if( pOldNumRule )
+ rDoc.ChgNumRuleFmts( aNumRule );
+ else if( pHistory )
+ {
+ SetPaM( rUndoIter );
+ if( sReplaceRule.Len() )
+ rDoc.ReplaceNumRule( *rUndoIter.pAktPam->GetPoint(),
+ sReplaceRule, aNumRule.GetName() );
+ else
+ {
+ // --> OD 2005-02-25 #i42921# - adapt to changed signature
+ // --> OD 2008-03-18 #refactorlists#
+ rDoc.SetNumRule( *rUndoIter.pAktPam, aNumRule, false );
+ // <--
+ }
+ }
+}
+
+void SwUndoInsNum::SetLRSpaceEndPos()
+{
+ if( pHistory )
+ nLRSavePos = pHistory->Count();
+}
+
+void SwUndoInsNum::Repeat( SwUndoIter& rUndoIter )
+{
+ if( nSttNode )
+ {
+ if( !sReplaceRule.Len() )
+ {
+ // --> OD 2005-02-25 #i42921# - adapt to changed signature
+ // --> OD 2008-03-18 #refactorlists#
+ rUndoIter.GetDoc().SetNumRule( *rUndoIter.pAktPam, aNumRule, false );
+ // <--
+ }
+ }
+ else
+ rUndoIter.GetDoc().ChgNumRuleFmts( aNumRule );
+}
+
+SwHistory* SwUndoInsNum::GetHistory()
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+ return pHistory;
+}
+
+void SwUndoInsNum::SaveOldNumRule( const SwNumRule& rOld )
+{
+ if( !pOldNumRule )
+ pOldNumRule = new SwNumRule( rOld );
+}
+
+/* */
+
+
+SwUndoDelNum::SwUndoDelNum( const SwPaM& rPam )
+ : SwUndo( UNDO_DELNUM ), SwUndRng( rPam ),
+ aNodeIdx( BYTE( nEndNode - nSttNode > 255 ? 255 : nEndNode - nSttNode )),
+ aLevels( BYTE( nEndNode - nSttNode > 255 ? 255 : nEndNode - nSttNode ))
+{
+ pHistory = new SwHistory;
+}
+
+
+SwUndoDelNum::~SwUndoDelNum()
+{
+ delete pHistory;
+}
+
+
+void SwUndoDelNum::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SetPaM( rUndoIter );
+
+ BOOL bUndo = rDoc.DoesUndo();
+ rDoc.DoUndo( FALSE );
+
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+
+ for( USHORT n = 0; n < aNodeIdx.Count(); ++n )
+ {
+ SwTxtNode* pNd = rDoc.GetNodes()[ aNodeIdx[ n ] ]->GetTxtNode();
+ OSL_ENSURE( pNd, "wo ist der TextNode geblieben?" );
+ pNd->SetAttrListLevel(aLevels[ n ] );
+
+ if( pNd->GetCondFmtColl() )
+ pNd->ChkCondColl();
+ }
+
+ SetPaM( rUndoIter );
+ rDoc.DoUndo( bUndo );
+}
+
+
+void SwUndoDelNum::Redo( SwUndoIter& rUndoIter )
+{
+ SetPaM( rUndoIter );
+ rUndoIter.GetDoc().DelNumRules( *rUndoIter.pAktPam );
+}
+
+
+void SwUndoDelNum::Repeat( SwUndoIter& rUndoIter )
+{
+ SetPaM( rUndoIter );
+ rUndoIter.GetDoc().DelNumRules( *rUndoIter.pAktPam );
+}
+
+void SwUndoDelNum::AddNode( const SwTxtNode& rNd, BOOL )
+{
+ if( rNd.GetNumRule() )
+ {
+ USHORT nIns = aNodeIdx.Count();
+ aNodeIdx.Insert( rNd.GetIndex(), nIns );
+
+ aLevels.Insert( static_cast<BYTE>(rNd.GetActualListLevel()), nIns );
+ }
+}
+
+
+/* */
+
+
+SwUndoMoveNum::SwUndoMoveNum( const SwPaM& rPam, long nOff, BOOL bIsOutlMv )
+ : SwUndo( bIsOutlMv ? UNDO_OUTLINE_UD : UNDO_MOVENUM ),
+ SwUndRng( rPam ),
+ nNewStt( 0 ), nOffset( nOff )
+{
+ // nOffset: nach unten => 1
+ // nach oben => -1
+}
+
+
+void SwUndoMoveNum::Undo( SwUndoIter& rUndoIter )
+{
+ ULONG nTmpStt = nSttNode, nTmpEnd = nEndNode;
+
+ if( nEndNode || USHRT_MAX != nEndCntnt ) // Bereich ?
+ {
+ if( nNewStt < nSttNode ) // nach vorne verschoben
+ nEndNode = nEndNode - ( nSttNode - nNewStt );
+ else
+ nEndNode = nEndNode + ( nNewStt - nSttNode );
+ }
+ nSttNode = nNewStt;
+
+//JP 22.06.95: wird wollen die Bookmarks/Verzeichnisse behalten, oder?
+// SetPaM( rUndoIter );
+// RemoveIdxFromRange( *rUndoIter.pAktPam, TRUE );
+
+ SetPaM( rUndoIter );
+ rUndoIter.GetDoc().MoveParagraph( *rUndoIter.pAktPam, -nOffset,
+ UNDO_OUTLINE_UD == GetId() );
+ nSttNode = nTmpStt;
+ nEndNode = nTmpEnd;
+}
+
+
+void SwUndoMoveNum::Redo( SwUndoIter& rUndoIter )
+{
+//JP 22.06.95: wird wollen die Bookmarks/Verzeichnisse behalten, oder?
+// SetPaM( rUndoIter );
+// RemoveIdxFromRange( *rUndoIter.pAktPam, TRUE );
+
+ SetPaM( rUndoIter );
+ rUndoIter.GetDoc().MoveParagraph( *rUndoIter.pAktPam, nOffset,
+ UNDO_OUTLINE_UD == GetId() );
+}
+
+
+void SwUndoMoveNum::Repeat( SwUndoIter& rUndoIter )
+{
+ if( UNDO_OUTLINE_UD == GetId() )
+ rUndoIter.GetDoc().MoveOutlinePara( *rUndoIter.pAktPam,
+ 0 < nOffset ? 1 : -1 );
+ else
+ rUndoIter.GetDoc().MoveParagraph( *rUndoIter.pAktPam, nOffset, FALSE );
+}
+
+/* */
+
+
+SwUndoNumUpDown::SwUndoNumUpDown( const SwPaM& rPam, short nOff )
+ : SwUndo( nOff > 0 ? UNDO_NUMUP : UNDO_NUMDOWN ), SwUndRng( rPam ),
+ nOffset( nOff )
+{
+ // nOffset: Down => 1
+ // Up => -1
+}
+
+
+void SwUndoNumUpDown::Undo( SwUndoIter& rUndoIter )
+{
+ SetPaM( rUndoIter );
+ rUndoIter.GetDoc().NumUpDown( *rUndoIter.pAktPam, 1 != nOffset );
+}
+
+
+void SwUndoNumUpDown::Redo( SwUndoIter& rUndoIter )
+{
+ SetPaM( rUndoIter );
+ rUndoIter.GetDoc().NumUpDown( *rUndoIter.pAktPam, 1 == nOffset );
+}
+
+
+void SwUndoNumUpDown::Repeat( SwUndoIter& rUndoIter )
+{
+ rUndoIter.GetDoc().NumUpDown( *rUndoIter.pAktPam, 1 == nOffset );
+}
+
+/* */
+
+// #115901#
+SwUndoNumOrNoNum::SwUndoNumOrNoNum( const SwNodeIndex& rIdx, BOOL bOldNum,
+ BOOL bNewNum)
+ : SwUndo( UNDO_NUMORNONUM ), nIdx( rIdx.GetIndex() ), mbNewNum(bNewNum),
+ mbOldNum(bOldNum)
+{
+}
+
+// #115901#, #i40034#
+void SwUndoNumOrNoNum::Undo( SwUndoIter& rUndoIter )
+{
+ SwNodeIndex aIdx( rUndoIter.GetDoc().GetNodes(), nIdx );
+ SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
+
+ if (NULL != pTxtNd)
+ {
+ pTxtNd->SetCountedInList(mbOldNum);
+ }
+}
+
+// #115901#, #i40034#
+void SwUndoNumOrNoNum::Redo( SwUndoIter& rUndoIter )
+{
+ SwNodeIndex aIdx( rUndoIter.GetDoc().GetNodes(), nIdx );
+ SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
+
+ if (NULL != pTxtNd)
+ {
+ pTxtNd->SetCountedInList(mbNewNum);
+ }
+}
+
+// #115901#
+void SwUndoNumOrNoNum::Repeat( SwUndoIter& rUndoIter )
+{
+
+ if (mbOldNum && ! mbNewNum)
+ rUndoIter.GetDoc().NumOrNoNum( rUndoIter.pAktPam->GetPoint()->nNode,
+ FALSE);
+ else if ( ! mbOldNum && mbNewNum )
+ rUndoIter.GetDoc().NumOrNoNum( rUndoIter.pAktPam->GetPoint()->nNode,
+ TRUE);
+}
+
+/* */
+
+SwUndoNumRuleStart::SwUndoNumRuleStart( const SwPosition& rPos, BOOL bFlg )
+ : SwUndo( UNDO_SETNUMRULESTART ),
+ nIdx( rPos.nNode.GetIndex() ), nOldStt( USHRT_MAX ),
+ nNewStt( USHRT_MAX ), bSetSttValue( FALSE ), bFlag( bFlg )
+{
+}
+
+SwUndoNumRuleStart::SwUndoNumRuleStart( const SwPosition& rPos, USHORT nStt )
+ : SwUndo( UNDO_SETNUMRULESTART ),
+ nIdx( rPos.nNode.GetIndex() ),
+ nOldStt( USHRT_MAX ), nNewStt( nStt ), bSetSttValue( TRUE )
+{
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if ( pTxtNd )
+ {
+ // --> OD 2008-02-28 #refactorlists#
+ if ( pTxtNd->HasAttrListRestartValue() )
+ {
+ nOldStt = static_cast<USHORT>(pTxtNd->GetAttrListRestartValue());
+ }
+ else
+ {
+ nOldStt = USHRT_MAX; // indicating, that the list restart value is not set
+ }
+ // <--
+ }
+}
+
+
+void SwUndoNumRuleStart::Undo( SwUndoIter& rUndoIter )
+{
+ SwPosition aPos( *rUndoIter.GetDoc().GetNodes()[ nIdx ] );
+ if( bSetSttValue )
+ rUndoIter.GetDoc().SetNodeNumStart( aPos, nOldStt );
+ else
+ rUndoIter.GetDoc().SetNumRuleStart( aPos, !bFlag );
+}
+
+
+void SwUndoNumRuleStart::Redo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ SwPosition aPos( *rDoc.GetNodes()[ nIdx ] );
+ if( bSetSttValue )
+ rDoc.SetNodeNumStart( aPos, nNewStt );
+ else
+ rDoc.SetNumRuleStart( aPos, bFlag );
+}
+
+
+void SwUndoNumRuleStart::Repeat( SwUndoIter& rUndoIter )
+{
+ if( bSetSttValue )
+ rUndoIter.GetDoc().SetNodeNumStart( *rUndoIter.pAktPam->GetPoint(), nNewStt );
+ else
+ rUndoIter.GetDoc().SetNumRuleStart( *rUndoIter.pAktPam->GetPoint(), bFlag );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unoutl.cxx b/sw/source/core/undo/unoutl.cxx
new file mode 100644
index 000000000000..cfdea00be125
--- /dev/null
+++ b/sw/source/core/undo/unoutl.cxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include "doc.hxx"
+#include "swundo.hxx" // fuer die UndoIds
+#include "pam.hxx"
+#include "ndtxt.hxx"
+
+#include "undobj.hxx"
+
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+SwUndoOutlineLeftRight::SwUndoOutlineLeftRight( const SwPaM& rPam,
+ short nOff )
+ : SwUndo( UNDO_OUTLINE_LR ), SwUndRng( rPam ), nOffset( nOff )
+{
+}
+
+
+void SwUndoOutlineLeftRight::Undo( SwUndoIter& rUndoIter )
+{
+ SetPaM( rUndoIter );
+ rUndoIter.GetDoc().OutlineUpDown( *rUndoIter.pAktPam, -nOffset );
+}
+
+
+void SwUndoOutlineLeftRight::Redo( SwUndoIter& rUndoIter )
+{
+ SetPaM( rUndoIter );
+ rUndoIter.GetDoc().OutlineUpDown( *rUndoIter.pAktPam, nOffset );
+}
+
+
+void SwUndoOutlineLeftRight::Repeat( SwUndoIter& rUndoIter )
+{
+ rUndoIter.GetDoc().OutlineUpDown( *rUndoIter.pAktPam, nOffset );
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unovwr.cxx b/sw/source/core/undo/unovwr.cxx
new file mode 100644
index 000000000000..a9608aaf4365
--- /dev/null
+++ b/sw/source/core/undo/unovwr.cxx
@@ -0,0 +1,514 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <unotools/charclass.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <comphelper/processfactory.hxx>
+#include <doc.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <rolbck.hxx>
+#include <acorrect.hxx>
+#include <docary.hxx>
+
+#include <tools/resid.hxx>
+#include <comcore.hrc> // #111827#
+#include <undo.hrc>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::uno;
+
+//------------------------------------------------------------------
+
+// zwei Zugriffs-Funktionen
+inline SwPosition* IterPt( SwUndoIter& rUIter )
+{ return rUIter.pAktPam->GetPoint(); }
+inline SwPosition* IterMk( SwUndoIter& rUIter )
+{ return rUIter.pAktPam->GetMark(); }
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+//------------------------------------------------------------
+
+
+// OVERWRITE
+
+
+SwUndoOverwrite::SwUndoOverwrite( SwDoc* pDoc, SwPosition& rPos,
+ sal_Unicode cIns )
+ : SwUndo(UNDO_OVERWRITE),
+ pRedlSaveData( 0 ), bGroup( FALSE )
+{
+ if( !pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() )
+ {
+ SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(),
+ rPos.nNode, rPos.nContent.GetIndex()+1 );
+ pRedlSaveData = new SwRedlineSaveDatas;
+ if( !FillSaveData( aPam, *pRedlSaveData, FALSE ))
+ delete pRedlSaveData, pRedlSaveData = 0;
+ }
+
+ nSttNode = rPos.nNode.GetIndex();
+ nSttCntnt = rPos.nContent.GetIndex();
+
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "Overwrite nicht im TextNode?" );
+
+ bInsChar = TRUE;
+ xub_StrLen nTxtNdLen = pTxtNd->GetTxt().Len();
+ if( nSttCntnt < nTxtNdLen ) // kein reines Einfuegen ?
+ {
+ aDelStr.Insert( pTxtNd->GetTxt().GetChar( nSttCntnt ) );
+ if( !pHistory )
+ pHistory = new SwHistory;
+ SwRegHistory aRHst( *pTxtNd, pHistory );
+ pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode, 0,
+ nTxtNdLen, false );
+ rPos.nContent++;
+ bInsChar = FALSE;
+ }
+
+ BOOL bOldExpFlg = pTxtNd->IsIgnoreDontExpand();
+ pTxtNd->SetIgnoreDontExpand( TRUE );
+
+ pTxtNd->InsertText( cIns, rPos.nContent,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ aInsStr.Insert( cIns );
+
+ if( !bInsChar )
+ {
+ const SwIndex aTmpIndex( rPos.nContent, -2 );
+ pTxtNd->EraseText( aTmpIndex, 1 );
+ }
+ pTxtNd->SetIgnoreDontExpand( bOldExpFlg );
+
+ bCacheComment = false;
+}
+
+SwUndoOverwrite::~SwUndoOverwrite()
+{
+ delete pRedlSaveData;
+}
+
+BOOL SwUndoOverwrite::CanGrouping( SwDoc* pDoc, SwPosition& rPos,
+ sal_Unicode cIns )
+{
+/// ?? was ist mit nur eingefuegten Charaktern ???
+
+ // es kann nur das Loeschen von einzelnen char's zusammengefasst werden
+ if( rPos.nNode != nSttNode || !aInsStr.Len() ||
+ ( !bGroup && aInsStr.Len() != 1 ))
+ return FALSE;
+
+ // ist der Node ueberhaupt ein TextNode?
+ SwTxtNode * pDelTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if( !pDelTxtNd ||
+ ( pDelTxtNd->GetTxt().Len() != rPos.nContent.GetIndex() &&
+ rPos.nContent.GetIndex() != ( nSttCntnt + aInsStr.Len() )))
+ return FALSE;
+
+ CharClass& rCC = GetAppCharClass();
+
+ // befrage das einzufuegende Charakter
+ if (( CH_TXTATR_BREAKWORD == cIns || CH_TXTATR_INWORD == cIns ) ||
+ rCC.isLetterNumeric( String( cIns ), 0 ) !=
+ rCC.isLetterNumeric( aInsStr, aInsStr.Len()-1 ) )
+ return FALSE;
+
+ {
+ SwRedlineSaveDatas* pTmpSav = new SwRedlineSaveDatas;
+ SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(),
+ rPos.nNode, rPos.nContent.GetIndex()+1 );
+
+ if( !FillSaveData( aPam, *pTmpSav, FALSE ))
+ delete pTmpSav, pTmpSav = 0;
+
+ BOOL bOk = ( !pRedlSaveData && !pTmpSav ) ||
+ ( pRedlSaveData && pTmpSav &&
+ SwUndo::CanRedlineGroup( *pRedlSaveData, *pTmpSav,
+ nSttCntnt > rPos.nContent.GetIndex() ));
+ delete pTmpSav;
+ if( !bOk )
+ return FALSE;
+
+ pDoc->DeleteRedline( aPam, false, USHRT_MAX );
+ }
+
+ // Ok, die beiden 'Overwrites' koennen zusammen gefasst werden, also
+ // 'verschiebe' das enstprechende Zeichen
+ if( !bInsChar )
+ {
+ if( rPos.nContent.GetIndex() < pDelTxtNd->GetTxt().Len() )
+ {
+ aDelStr.Insert( pDelTxtNd->GetTxt().GetChar(rPos.nContent.GetIndex()) );
+ rPos.nContent++;
+ }
+ else
+ bInsChar = TRUE;
+ }
+
+ BOOL bOldExpFlg = pDelTxtNd->IsIgnoreDontExpand();
+ pDelTxtNd->SetIgnoreDontExpand( TRUE );
+
+ pDelTxtNd->InsertText( cIns, rPos.nContent,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ aInsStr.Insert( cIns );
+
+ if( !bInsChar )
+ {
+ const SwIndex aTmpIndex( rPos.nContent, -2 );
+ pDelTxtNd->EraseText( aTmpIndex, 1 );
+ }
+ pDelTxtNd->SetIgnoreDontExpand( bOldExpFlg );
+
+ bGroup = TRUE;
+ return TRUE;
+}
+
+
+
+
+
+void SwUndoOverwrite::Undo( SwUndoIter& rUndoIter )
+{
+ SwPaM* pAktPam = rUndoIter.pAktPam;
+ SwDoc* pDoc = pAktPam->GetDoc();
+ pAktPam->DeleteMark();
+ pAktPam->GetPoint()->nNode = nSttNode;
+ SwTxtNode* pTxtNd = pAktPam->GetNode()->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "Overwrite nicht im TextNode?" );
+ SwIndex& rIdx = pAktPam->GetPoint()->nContent;
+ rIdx.Assign( pTxtNd, nSttCntnt );
+
+ SwAutoCorrExceptWord* pACEWord = pDoc->GetAutoCorrExceptWord();
+ if( pACEWord )
+ {
+ if( 1 == aInsStr.Len() && 1 == aDelStr.Len() )
+ pACEWord->CheckChar( *pAktPam->GetPoint(), aDelStr.GetChar( 0 ) );
+ pDoc->SetAutoCorrExceptWord( 0 );
+ }
+
+ // wurde nicht nur ueberschieben sondern auch geinsertet, so loesche
+ // den Ueberhang
+ if( aInsStr.Len() > aDelStr.Len() )
+ {
+ rIdx += aDelStr.Len();
+ pTxtNd->EraseText( rIdx, aInsStr.Len() - aDelStr.Len() );
+ rIdx = nSttCntnt;
+ }
+
+ if( aDelStr.Len() )
+ {
+ String aTmpStr( '1' );
+ sal_Unicode* pTmpStr = aTmpStr.GetBufferAccess();
+
+ BOOL bOldExpFlg = pTxtNd->IsIgnoreDontExpand();
+ pTxtNd->SetIgnoreDontExpand( TRUE );
+
+ rIdx++;
+ for( xub_StrLen n = 0; n < aDelStr.Len(); n++ )
+ {
+ // einzeln, damit die Attribute stehen bleiben !!!
+ *pTmpStr = aDelStr.GetChar( n );
+ pTxtNd->InsertText( aTmpStr, rIdx /*???, SETATTR_NOTXTATRCHR*/ );
+ rIdx -= 2;
+ pTxtNd->EraseText( rIdx, 1 );
+ rIdx += 2;
+ }
+ pTxtNd->SetIgnoreDontExpand( bOldExpFlg );
+ rIdx--;
+ }
+ if( pHistory )
+ {
+ if( pTxtNd->GetpSwpHints() )
+ pTxtNd->ClearSwpHintsArr( false );
+ pHistory->TmpRollback( pDoc, 0, false );
+ }
+
+ if( pAktPam->GetMark()->nContent.GetIndex() != nSttCntnt )
+ {
+ pAktPam->SetMark();
+ pAktPam->GetMark()->nContent = nSttCntnt;
+ }
+
+ if( pRedlSaveData )
+ SetSaveData( *pDoc, *pRedlSaveData );
+}
+
+void SwUndoOverwrite::Repeat( SwUndoIter& rUndoIter )
+{
+ rUndoIter.pLastUndoObj = this;
+ SwPaM* pAktPam = rUndoIter.pAktPam;
+ if( !aInsStr.Len() || pAktPam->HasMark() )
+ return;
+
+ SwDoc& rDoc = *pAktPam->GetDoc();
+
+ BOOL bGroupUndo = rDoc.DoesGroupUndo();
+ rDoc.DoGroupUndo( FALSE );
+ rDoc.Overwrite( *pAktPam, aInsStr.GetChar( 0 ));
+ rDoc.DoGroupUndo( bGroupUndo );
+ for( xub_StrLen n = 1; n < aInsStr.Len(); ++n )
+ rDoc.Overwrite( *pAktPam, aInsStr.GetChar( n ) );
+}
+
+
+
+void SwUndoOverwrite::Redo( SwUndoIter& rUndoIter )
+{
+ SwPaM* pAktPam = rUndoIter.pAktPam;
+ SwDoc* pDoc = pAktPam->GetDoc();
+ pAktPam->DeleteMark();
+ pAktPam->GetPoint()->nNode = nSttNode;
+ SwTxtNode* pTxtNd = pAktPam->GetNode()->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "Overwrite nicht im TextNode?" );
+ SwIndex& rIdx = pAktPam->GetPoint()->nContent;
+
+ if( pRedlSaveData )
+ {
+ rIdx.Assign( pTxtNd, nSttCntnt );
+ pAktPam->SetMark();
+ pAktPam->GetMark()->nContent += aInsStr.Len();
+ pDoc->DeleteRedline( *pAktPam, false, USHRT_MAX );
+ pAktPam->DeleteMark();
+ }
+ rIdx.Assign( pTxtNd, aDelStr.Len() ? nSttCntnt+1 : nSttCntnt );
+
+ BOOL bOldExpFlg = pTxtNd->IsIgnoreDontExpand();
+ pTxtNd->SetIgnoreDontExpand( TRUE );
+
+ for( xub_StrLen n = 0; n < aInsStr.Len(); n++ )
+ {
+ // einzeln, damit die Attribute stehen bleiben !!!
+ pTxtNd->InsertText( aInsStr.GetChar( n ), rIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ if( n < aDelStr.Len() )
+ {
+ rIdx -= 2;
+ pTxtNd->EraseText( rIdx, 1 );
+ rIdx += n+1 < aDelStr.Len() ? 2 : 1;
+ }
+ }
+ pTxtNd->SetIgnoreDontExpand( bOldExpFlg );
+
+ // alte Anfangs-Position vom UndoNodes-Array zurueckholen
+ if( pHistory )
+ pHistory->SetTmpEnd( pHistory->Count() );
+ if( pAktPam->GetMark()->nContent.GetIndex() != nSttCntnt )
+ {
+ pAktPam->SetMark();
+ pAktPam->GetMark()->nContent = nSttCntnt;
+ }
+}
+
+SwRewriter SwUndoOverwrite::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ String aString;
+
+ aString += String(SW_RES(STR_START_QUOTE));
+ aString += ShortenString(aInsStr, nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+ aString += String(SW_RES(STR_END_QUOTE));
+
+ aResult.AddRule(UNDO_ARG1, aString);
+
+ return aResult;
+}
+
+//------------------------------------------------------------
+
+struct _UndoTransliterate_Data
+{
+ String sText;
+ SwHistory* pHistory;
+ Sequence< sal_Int32 >* pOffsets;
+ ULONG nNdIdx;
+ xub_StrLen nStart, nLen;
+
+ _UndoTransliterate_Data( ULONG nNd, xub_StrLen nStt, xub_StrLen nStrLen, const String& rTxt )
+ : sText( rTxt ), pHistory( 0 ), pOffsets( 0 ),
+ nNdIdx( nNd ), nStart( nStt ), nLen( nStrLen )
+ {}
+ ~_UndoTransliterate_Data() { delete pOffsets; delete pHistory; }
+
+ void SetChangeAtNode( SwDoc& rDoc );
+};
+
+SwUndoTransliterate::SwUndoTransliterate(
+ const SwPaM& rPam,
+ const utl::TransliterationWrapper& rTrans )
+ : SwUndo( UNDO_TRANSLITERATE ), SwUndRng( rPam ), nType( rTrans.getType() )
+{
+}
+
+SwUndoTransliterate::~SwUndoTransliterate()
+{
+ for (size_t i = 0; i < aChanges.size(); ++i)
+ delete aChanges[i];
+}
+
+void SwUndoTransliterate::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ BOOL bUndo = rDoc.DoesUndo();
+ rDoc.DoUndo( FALSE );
+
+ // since the changes were added to the vector from the end of the string/node towards
+ // the start, we need to revert them from the start towards the end now to keep the
+ // offset information of the undo data in sync with the changing text.
+ // Thus we need to iterate from the end of the vector to the start
+ for (sal_Int32 i = aChanges.size() - 1; i >= 0; --i)
+ aChanges[i]->SetChangeAtNode( rDoc );
+
+ rDoc.DoUndo( bUndo );
+ SetPaM( rUndoIter, TRUE );
+}
+
+void SwUndoTransliterate::Redo( SwUndoIter& rUndoIter )
+{
+/* ??? */ rUndoIter.SetUpdateAttr( TRUE );
+
+ SetPaM( *rUndoIter.pAktPam );
+ Repeat( rUndoIter );
+}
+
+void SwUndoTransliterate::Repeat( SwUndoIter& rUndoIter )
+{
+ SwPaM& rPam = *rUndoIter.pAktPam;
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ utl::TransliterationWrapper aTrans( ::comphelper::getProcessServiceFactory(), nType );
+ rDoc.TransliterateText( rPam, aTrans );
+
+ rUndoIter.pLastUndoObj = this;
+}
+
+void SwUndoTransliterate::AddChanges( SwTxtNode& rTNd,
+ xub_StrLen nStart, xub_StrLen nLen,
+ uno::Sequence <sal_Int32>& rOffsets )
+{
+ long nOffsLen = rOffsets.getLength();
+ _UndoTransliterate_Data* pNew = new _UndoTransliterate_Data(
+ rTNd.GetIndex(), nStart, (xub_StrLen)nOffsLen,
+ rTNd.GetTxt().Copy( nStart, nLen ));
+
+ aChanges.push_back( pNew );
+
+ const sal_Int32* pOffsets = rOffsets.getConstArray();
+ // where did we need less memory ?
+ const sal_Int32* p = pOffsets;
+ for( long n = 0; n < nOffsLen; ++n, ++p )
+ if( *p != ( nStart + n ))
+ {
+ // create the Offset array
+ pNew->pOffsets = new Sequence <sal_Int32> ( nLen );
+ sal_Int32* pIdx = pNew->pOffsets->getArray();
+ p = pOffsets;
+ long nMyOff, nNewVal = nStart;
+ for( n = 0, nMyOff = nStart; n < nOffsLen; ++p, ++n, ++nMyOff )
+ {
+ if( *p < nMyOff )
+ {
+ // something is deleted
+ nMyOff = *p;
+ *(pIdx-1) = nNewVal++;
+ }
+ else if( *p > nMyOff )
+ {
+ for( ; *p > nMyOff; ++nMyOff )
+ *pIdx++ = nNewVal;
+ --nMyOff;
+ --n;
+ --p;
+ }
+ else
+ *pIdx++ = nNewVal++;
+ }
+
+ // and then we need to save the attributes/bookmarks
+ // but this data must moved every time to the last in the chain!
+ for (size_t i = 0; i + 1 < aChanges.size(); ++i) // check all changes but not the current one
+ {
+ _UndoTransliterate_Data* pD = aChanges[i];
+ if( pD->nNdIdx == pNew->nNdIdx && pD->pHistory )
+ {
+ // same node and have a history?
+ pNew->pHistory = pD->pHistory;
+ pD->pHistory = 0;
+ break; // more can't exist
+ }
+ }
+
+ if( !pNew->pHistory )
+ {
+ pNew->pHistory = new SwHistory;
+ SwRegHistory aRHst( rTNd, pNew->pHistory );
+ pNew->pHistory->CopyAttr( rTNd.GetpSwpHints(),
+ pNew->nNdIdx, 0, rTNd.GetTxt().Len(), false );
+ }
+ break;
+ }
+}
+
+void _UndoTransliterate_Data::SetChangeAtNode( SwDoc& rDoc )
+{
+ SwTxtNode* pTNd = rDoc.GetNodes()[ nNdIdx ]->GetTxtNode();
+ if( pTNd )
+ {
+ Sequence <sal_Int32> aOffsets( pOffsets ? pOffsets->getLength() : nLen );
+ if( pOffsets )
+ aOffsets = *pOffsets;
+ else
+ {
+ sal_Int32* p = aOffsets.getArray();
+ for( xub_StrLen n = 0; n < nLen; ++n, ++p )
+ *p = n + nStart;
+ }
+ pTNd->ReplaceTextOnly( nStart, nLen, sText, aOffsets );
+
+ if( pHistory )
+ {
+ if( pTNd->GetpSwpHints() )
+ pTNd->ClearSwpHintsArr( false );
+ pHistory->TmpRollback( &rDoc, 0, false );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
new file mode 100644
index 000000000000..ffb72815590e
--- /dev/null
+++ b/sw/source/core/undo/unredln.cxx
@@ -0,0 +1,545 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <unotools/charclass.hxx>
+#include <doc.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <rolbck.hxx>
+#include <redline.hxx>
+#include <docary.hxx>
+#include <sortopt.hxx>
+
+extern void lcl_JoinText( SwPaM& rPam, BOOL bJoinPrev );
+extern void lcl_GetJoinFlags( SwPaM& rPam, BOOL& rJoinTxt, BOOL& rJoinPrev );
+
+//------------------------------------------------------------------
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+
+SwUndoRedline::SwUndoRedline( SwUndoId nUsrId, const SwPaM& rRange )
+ : SwUndo( UNDO_REDLINE ), SwUndRng( rRange ),
+ pRedlData( 0 ), pRedlSaveData( 0 ), nUserId( nUsrId ),
+ bHiddenRedlines( FALSE )
+{
+ // Redline beachten
+ SwDoc& rDoc = *rRange.GetDoc();
+ if( rDoc.IsRedlineOn() )
+ {
+ switch( nUserId )
+ {
+ case UNDO_DELETE:
+ case UNDO_REPLACE:
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_DELETE, rDoc.GetRedlineAuthor() );
+ break;
+ default:
+ ;
+ }
+ SetRedlineMode( rDoc.GetRedlineMode() );
+ }
+
+ ULONG nEndExtra = rDoc.GetNodes().GetEndOfExtras().GetIndex();
+
+ pRedlSaveData = new SwRedlineSaveDatas;
+ if( !FillSaveData( rRange, *pRedlSaveData, FALSE,
+ UNDO_REJECT_REDLINE != nUserId ))
+ delete pRedlSaveData, pRedlSaveData = 0;
+ else
+ {
+ bHiddenRedlines = HasHiddenRedlines( *pRedlSaveData );
+ if( bHiddenRedlines ) // dann muessen die NodeIndizies
+ { // vom SwUndRng korrigiert werden
+ nEndExtra -= rDoc.GetNodes().GetEndOfExtras().GetIndex();
+ nSttNode -= nEndExtra;
+ nEndNode -= nEndExtra;
+ }
+ }
+}
+
+SwUndoRedline::~SwUndoRedline()
+{
+ delete pRedlData;
+ delete pRedlSaveData;
+}
+
+void SwUndoRedline::Undo( SwUndoIter& rIter )
+{
+ SwDoc* pDoc = &rIter.GetDoc();
+ SetPaM( *rIter.pAktPam );
+
+// RedlineMode setzen?
+ _Undo( rIter );
+
+ if( pRedlSaveData )
+ {
+ ULONG nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex();
+ SetSaveData( *pDoc, *pRedlSaveData );
+ if( bHiddenRedlines )
+ {
+ pRedlSaveData->DeleteAndDestroy( 0, pRedlSaveData->Count() );
+
+ nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex() - nEndExtra;
+ nSttNode += nEndExtra;
+ nEndNode += nEndExtra;
+ }
+ SetPaM( *rIter.pAktPam, TRUE );
+ }
+}
+
+
+void SwUndoRedline::Redo( SwUndoIter& rIter )
+{
+ SwDoc* pDoc = &rIter.GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+
+ SetPaM( *rIter.pAktPam );
+ if( pRedlSaveData && bHiddenRedlines )
+ {
+ ULONG nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex();
+ FillSaveData( *rIter.pAktPam, *pRedlSaveData, FALSE,
+ UNDO_REJECT_REDLINE != nUserId );
+
+ nEndExtra -= pDoc->GetNodes().GetEndOfExtras().GetIndex();
+ nSttNode -= nEndExtra;
+ nEndNode -= nEndExtra;
+ }
+ _Redo( rIter );
+
+ SetPaM( *rIter.pAktPam, TRUE );
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+// default ist leer
+void SwUndoRedline::_Undo( SwUndoIter& )
+{
+}
+
+// default ist Redlines entfernen
+void SwUndoRedline::_Redo( SwUndoIter& rIter )
+{
+ rIter.GetDoc().DeleteRedline( *rIter.pAktPam, true, USHRT_MAX );
+}
+
+
+/* */
+
+SwUndoRedlineDelete::SwUndoRedlineDelete( const SwPaM& rRange, SwUndoId nUsrId )
+ : SwUndoRedline( nUsrId = (nUsrId ? nUsrId : UNDO_DELETE), rRange ),
+ bCanGroup( FALSE ), bIsDelim( FALSE ), bIsBackspace( FALSE )
+{
+ const SwTxtNode* pTNd;
+ if( UNDO_DELETE == nUserId &&
+ nSttNode == nEndNode && nSttCntnt + 1 == nEndCntnt &&
+ 0 != (pTNd = rRange.GetNode()->GetTxtNode()) )
+ {
+ sal_Unicode cCh = pTNd->GetTxt().GetChar( nSttCntnt );
+ if( CH_TXTATR_BREAKWORD != cCh && CH_TXTATR_INWORD != cCh )
+ {
+ bCanGroup = TRUE;
+ bIsDelim = !GetAppCharClass().isLetterNumeric( pTNd->GetTxt(),
+ nSttCntnt );
+ bIsBackspace = nSttCntnt == rRange.GetPoint()->nContent.GetIndex();
+ }
+ }
+
+ bCacheComment = false;
+}
+
+void SwUndoRedlineDelete::_Undo( SwUndoIter& rIter )
+{
+ rIter.GetDoc().DeleteRedline( *rIter.pAktPam, true, USHRT_MAX );
+}
+
+void SwUndoRedlineDelete::_Redo( SwUndoIter& rIter )
+{
+ if( *rIter.pAktPam->GetPoint() != *rIter.pAktPam->GetMark() )
+ rIter.GetDoc().AppendRedline( new SwRedline( *pRedlData, *rIter.pAktPam ), FALSE );
+}
+
+BOOL SwUndoRedlineDelete::CanGrouping( const SwUndoRedlineDelete& rNext )
+{
+ BOOL bRet = FALSE;
+ if( UNDO_DELETE == nUserId && nUserId == rNext.nUserId &&
+ bCanGroup == rNext.bCanGroup &&
+ bIsDelim == rNext.bIsDelim &&
+ bIsBackspace == rNext.bIsBackspace &&
+ nSttNode == nEndNode &&
+ rNext.nSttNode == nSttNode &&
+ rNext.nEndNode == nEndNode )
+ {
+ int bIsEnd = 0;
+ if( rNext.nSttCntnt == nEndCntnt )
+ bIsEnd = 1;
+ else if( rNext.nEndCntnt == nSttCntnt )
+ bIsEnd = -1;
+
+ if( bIsEnd &&
+ (( !pRedlSaveData && !rNext.pRedlSaveData ) ||
+ ( pRedlSaveData && rNext.pRedlSaveData &&
+ SwUndo::CanRedlineGroup( *pRedlSaveData,
+ *rNext.pRedlSaveData, 1 != bIsEnd )
+ )))
+ {
+ if( 1 == bIsEnd )
+ nEndCntnt = rNext.nEndCntnt;
+ else
+ nSttCntnt = rNext.nSttCntnt;
+ bRet = TRUE;
+ }
+ }
+ return bRet;
+}
+
+/* */
+
+SwUndoRedlineSort::SwUndoRedlineSort( const SwPaM& rRange,
+ const SwSortOptions& rOpt )
+ : SwUndoRedline( UNDO_SORT_TXT, rRange ),
+ pOpt( new SwSortOptions( rOpt ) ),
+ nSaveEndNode( nEndNode ), nOffset( 0 ), nSaveEndCntnt( nEndCntnt )
+{
+}
+
+SwUndoRedlineSort::~SwUndoRedlineSort()
+{
+ delete pOpt;
+}
+
+void SwUndoRedlineSort::_Undo( SwUndoIter& rIter )
+{
+ // im rIter.pAktPam ist der sortiete Bereich,
+ // im aSaveRange steht der kopierte, sprich der originale.
+ SwDoc& rDoc = rIter.GetDoc();
+
+ SwPosition* pStart = rIter.pAktPam->Start();
+ SwPosition* pEnd = rIter.pAktPam->End();
+
+ SwNodeIndex aPrevIdx( pStart->nNode, -1 );
+ ULONG nOffsetTemp = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex();
+
+ if( 0 == ( nsRedlineMode_t::REDLINE_SHOW_DELETE & rDoc.GetRedlineMode()) )
+ {
+ // die beiden Redline Objecte suchen und diese dann anzeigen lassen,
+ // damit die Nodes wieder uebereinstimmen!
+ // das Geloeschte ist versteckt, also suche das INSERT
+ // Redline Object. Dahinter steht das Geloeschte
+ USHORT nFnd = rDoc.GetRedlinePos(
+ *rDoc.GetNodes()[ nSttNode + 1 ],
+ nsRedlineType_t::REDLINE_INSERT );
+ OSL_ENSURE( USHRT_MAX != nFnd && nFnd+1 < rDoc.GetRedlineTbl().Count(),
+ "kein Insert Object gefunden" );
+ ++nFnd;
+ rDoc.GetRedlineTbl()[nFnd]->Show( 1 );
+ }
+
+ {
+ SwPaM aTmp( *rIter.pAktPam->GetMark() );
+ aTmp.GetMark()->nContent = 0;
+ aTmp.SetMark();
+ aTmp.GetPoint()->nNode = nSaveEndNode;
+ aTmp.GetPoint()->nContent.Assign( aTmp.GetCntntNode(), nSaveEndCntnt );
+ rDoc.DeleteRedline( aTmp, true, USHRT_MAX );
+ }
+
+ rDoc.DelFullPara( *rIter.pAktPam );
+
+ SwPaM* pPam = rIter.pAktPam;
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
+ SwCntntNode* pCNd = pPam->GetCntntNode();
+ pPam->GetPoint()->nContent.Assign(pCNd, 0 );
+ pPam->SetMark();
+
+ pPam->GetPoint()->nNode += nOffsetTemp;
+ pCNd = pPam->GetCntntNode();
+ pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+
+ SetValues( *pPam );
+
+ SetPaM( *rIter.pAktPam );
+}
+
+void SwUndoRedlineSort::_Redo( SwUndoIter& rIter )
+{
+ SwPaM& rPam = *rIter.pAktPam;
+
+ SwPaM* pPam = &rPam;
+ SwPosition* pStart = pPam->Start();
+ SwPosition* pEnd = pPam->End();
+
+ SwNodeIndex aPrevIdx( pStart->nNode, -1 );
+ ULONG nOffsetTemp = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex();
+ xub_StrLen nCntStt = pStart->nContent.GetIndex();
+
+ rIter.GetDoc().SortText( rPam, *pOpt );
+
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
+ SwCntntNode* pCNd = pPam->GetCntntNode();
+ xub_StrLen nLen = pCNd->Len();
+ if( nLen > nCntStt )
+ nLen = nCntStt;
+ pPam->GetPoint()->nContent.Assign(pCNd, nLen );
+ pPam->SetMark();
+
+ pPam->GetPoint()->nNode += nOffsetTemp;
+ pCNd = pPam->GetCntntNode();
+ pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+
+ SetValues( rPam );
+
+ SetPaM( rPam );
+ rPam.GetPoint()->nNode = nSaveEndNode;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), nSaveEndCntnt );
+}
+
+void SwUndoRedlineSort::Repeat( SwUndoIter& rIter )
+{
+ rIter.GetDoc().SortText( *rIter.pAktPam, *pOpt );
+}
+
+void SwUndoRedlineSort::SetSaveRange( const SwPaM& rRange )
+{
+ const SwPosition& rPos = *rRange.End();
+ nSaveEndNode = rPos.nNode.GetIndex();
+ nSaveEndCntnt = rPos.nContent.GetIndex();
+}
+
+void SwUndoRedlineSort::SetOffset( const SwNodeIndex& rIdx )
+{
+ nOffset = rIdx.GetIndex() - nSttNode;
+}
+
+/* */
+
+SwUndoAcceptRedline::SwUndoAcceptRedline( const SwPaM& rRange )
+ : SwUndoRedline( UNDO_ACCEPT_REDLINE, rRange )
+{
+}
+
+void SwUndoAcceptRedline::_Redo( SwUndoIter& rIter )
+{
+ rIter.GetDoc().AcceptRedline( *rIter.pAktPam, false );
+}
+
+void SwUndoAcceptRedline::Repeat( SwUndoIter& rIter )
+{
+ rIter.GetDoc().AcceptRedline( *rIter.pAktPam, true );
+}
+
+SwUndoRejectRedline::SwUndoRejectRedline( const SwPaM& rRange )
+ : SwUndoRedline( UNDO_REJECT_REDLINE, rRange )
+{
+}
+
+void SwUndoRejectRedline::_Redo( SwUndoIter& rIter )
+{
+ rIter.GetDoc().RejectRedline( *rIter.pAktPam, false );
+}
+
+void SwUndoRejectRedline::Repeat( SwUndoIter& rIter )
+{
+ rIter.GetDoc().RejectRedline( *rIter.pAktPam, true );
+}
+
+/* */
+
+SwUndoCompDoc::SwUndoCompDoc( const SwPaM& rRg, BOOL bIns )
+ : SwUndo( UNDO_COMPAREDOC ), SwUndRng( rRg ), pRedlData( 0 ),
+ pUnDel( 0 ), pUnDel2( 0 ), pRedlSaveData( 0 ), bInsert( bIns )
+{
+ SwDoc* pDoc = (SwDoc*)rRg.GetDoc();
+ if( pDoc->IsRedlineOn() )
+ {
+ RedlineType_t eTyp = bInsert ? nsRedlineType_t::REDLINE_INSERT : nsRedlineType_t::REDLINE_DELETE;
+ pRedlData = new SwRedlineData( eTyp, pDoc->GetRedlineAuthor() );
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ }
+}
+
+SwUndoCompDoc::SwUndoCompDoc( const SwRedline& rRedl )
+ : SwUndo( UNDO_COMPAREDOC ), SwUndRng( rRedl ), pRedlData( 0 ),
+ pUnDel( 0 ), pUnDel2( 0 ), pRedlSaveData( 0 ),
+ // fuers MergeDoc wird aber der jeweils umgekehrte Zweig benoetigt!
+ bInsert( nsRedlineType_t::REDLINE_DELETE == rRedl.GetType() )
+{
+ SwDoc* pDoc = (SwDoc*)rRedl.GetDoc();
+ if( pDoc->IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( rRedl.GetRedlineData() );
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ }
+
+ pRedlSaveData = new SwRedlineSaveDatas;
+ if( !FillSaveData( rRedl, *pRedlSaveData, FALSE, TRUE ))
+ delete pRedlSaveData, pRedlSaveData = 0;
+}
+
+SwUndoCompDoc::~SwUndoCompDoc()
+{
+ delete pRedlData;
+ delete pUnDel;
+ delete pUnDel2;
+ delete pRedlSaveData;
+}
+
+void SwUndoCompDoc::Undo( SwUndoIter& rIter )
+{
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+
+ SetPaM( *pPam );
+
+ if( !bInsert )
+ {
+ // die Redlines loeschen
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON));
+
+ pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
+
+ pDoc->SetRedlineMode_intern( eOld );
+
+ //per definition Point is end (in SwUndRng!)
+ SwCntntNode* pCSttNd = pPam->GetCntntNode( FALSE );
+ SwCntntNode* pCEndNd = pPam->GetCntntNode( TRUE );
+
+ // if start- and end-content is zero, then the doc-compare moves
+ // complete nodes into the current doc. And then the selection
+ // must be from end to start, so the delete join into the right
+ // direction.
+ if( !nSttCntnt && !nEndCntnt )
+ pPam->Exchange();
+
+ BOOL bJoinTxt, bJoinPrev;
+ ::lcl_GetJoinFlags( *pPam, bJoinTxt, bJoinPrev );
+
+ pUnDel = new SwUndoDelete( *pPam, FALSE );
+
+ if( bJoinTxt )
+ ::lcl_JoinText( *pPam, bJoinPrev );
+
+ if( pCSttNd && !pCEndNd)
+ {
+ // #112139# Do not step behind the end of content.
+ SwNode * pTmp = pPam->GetNode(TRUE);
+ if (pTmp)
+ {
+ SwNode * pEnd = pDoc->GetNodes().DocumentSectionEndNode(pTmp);
+
+ if (pTmp != pEnd)
+ {
+ pPam->SetMark();
+ pPam->GetPoint()->nNode++;
+ pPam->GetBound( TRUE ).nContent.Assign( 0, 0 );
+ pPam->GetBound( FALSE ).nContent.Assign( 0, 0 );
+ pUnDel2 = new SwUndoDelete( *pPam, TRUE );
+ }
+ }
+ }
+ pPam->DeleteMark();
+ }
+ else
+ {
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
+
+ if( pRedlSaveData )
+ SetSaveData( *pDoc, *pRedlSaveData );
+ }
+ SetPaM( rIter, TRUE );
+ }
+}
+
+void SwUndoCompDoc::Redo( SwUndoIter& rIter )
+{
+ // setze noch den Cursor auf den Redo-Bereich
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+
+ rIter.pLastUndoObj = 0;
+
+ if( bInsert )
+ {
+ SetPaM( *pPam );
+
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ SwRedline* pTmp = new SwRedline( *pRedlData, *pPam );
+ ((SwRedlineTbl&)pDoc->GetRedlineTbl()).Insert( pTmp );
+ pTmp->InvalidateRange();
+
+/*
+ SwRedlineMode eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( eOld & ~REDLINE_IGNORE );
+ pDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ));
+ pDoc->SetRedlineMode_intern( eOld );
+*/
+ }
+ else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ pDoc->GetRedlineTbl().Count() )
+ pDoc->SplitRedline( *pPam );
+ }
+ else
+ {
+// SwRedlineMode eOld = pDoc->GetRedlineMode();
+// pDoc->SetRedlineMode_intern( ( eOld & ~REDLINE_IGNORE) | REDLINE_ON );
+
+ if( pUnDel2 )
+ {
+ pUnDel2->Undo( rIter );
+ delete pUnDel2, pUnDel2 = 0;
+ }
+ pUnDel->Undo( rIter );
+ delete pUnDel, pUnDel = 0;
+
+ SetPaM( *pPam );
+
+ SwRedline* pTmp = new SwRedline( *pRedlData, *pPam );
+ ((SwRedlineTbl&)pDoc->GetRedlineTbl()).Insert( pTmp );
+ if (pTmp) // #i19649#
+ pTmp->InvalidateRange();
+
+// pDoc->SetRedlineMode_intern( eOld );
+ }
+
+ SetPaM( rIter, TRUE );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unsect.cxx b/sw/source/core/undo/unsect.cxx
new file mode 100644
index 000000000000..8d51db6b1aa9
--- /dev/null
+++ b/sw/source/core/undo/unsect.cxx
@@ -0,0 +1,501 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <sfx2/linkmgr.hxx>
+#include <fmtcntnt.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <section.hxx>
+#include <rolbck.hxx>
+#include <redline.hxx>
+#include <doctxm.hxx>
+#include <ftnidx.hxx>
+#include <editsh.hxx>
+/// OD 04.10.2002 #102894#
+/// class Calc needed for calculation of the hidden condition of a section.
+#include <calc.hxx>
+
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+SfxItemSet* lcl_GetAttrSet( const SwSection& rSect )
+{
+ // Attribute des Formate sichern (Spalten, Farbe, ... )
+ // Cntnt- und Protect- Items interessieren nicht (stehen schon in der
+ // Section), muessen also entfernen werden
+ SfxItemSet* pAttr = 0;
+ if( rSect.GetFmt() )
+ {
+ USHORT nCnt = 1;
+ if( rSect.IsProtect() )
+ ++nCnt;
+
+ if( nCnt < rSect.GetFmt()->GetAttrSet().Count() )
+ {
+ pAttr = new SfxItemSet( rSect.GetFmt()->GetAttrSet() );
+ pAttr->ClearItem( RES_PROTECT );
+ pAttr->ClearItem( RES_CNTNT );
+ if( !pAttr->Count() )
+ delete pAttr, pAttr = 0;
+ }
+ }
+ return pAttr;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+SwUndoInsSection::SwUndoInsSection(
+ SwPaM const& rPam, SwSectionData const& rNewData,
+ SfxItemSet const*const pSet, SwTOXBase const*const pTOXBase)
+ : SwUndo( UNDO_INSSECTION ), SwUndRng( rPam )
+ , m_pSectionData(new SwSectionData(rNewData))
+ , m_pTOXBase( (pTOXBase) ? new SwTOXBase(*pTOXBase) : 0 )
+ , m_pAttrSet( (pSet && pSet->Count()) ? new SfxItemSet( *pSet ) : 0 )
+ , m_pHistory(0)
+ , m_pRedlData(0)
+ , m_nSectionNodePos(0)
+ , m_bSplitAtStart(false)
+ , m_bSplitAtEnd(false)
+ , m_bUpdateFtn(false)
+{
+ SwDoc& rDoc = *(SwDoc*)rPam.GetDoc();
+ if( rDoc.IsRedlineOn() )
+ {
+ m_pRedlData.reset(new SwRedlineData( nsRedlineType_t::REDLINE_INSERT,
+ rDoc.GetRedlineAuthor() ));
+ SetRedlineMode( rDoc.GetRedlineMode() );
+ }
+
+
+ if( !rPam.HasMark() )
+ {
+ const SwCntntNode* pCNd = rPam.GetPoint()->nNode.GetNode().GetCntntNode();
+ if( pCNd && pCNd->HasSwAttrSet() && (
+ !rPam.GetPoint()->nContent.GetIndex() ||
+ rPam.GetPoint()->nContent.GetIndex() == pCNd->Len() ))
+ {
+ SfxItemSet aBrkSet( rDoc.GetAttrPool(), aBreakSetRange );
+ aBrkSet.Put( *pCNd->GetpSwAttrSet() );
+ if( aBrkSet.Count() )
+ {
+ m_pHistory.reset( new SwHistory );
+ m_pHistory->CopyFmtAttr( aBrkSet, pCNd->GetIndex() );
+ }
+ }
+ }
+}
+
+SwUndoInsSection::~SwUndoInsSection()
+{
+}
+
+void SwUndoInsSection::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ RemoveIdxFromSection( rDoc, m_nSectionNodePos );
+
+ SwSectionNode *const pNd =
+ rDoc.GetNodes()[ m_nSectionNodePos ]->GetSectionNode();
+ OSL_ENSURE( pNd, "wo ist mein SectionNode?" );
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ rDoc.DeleteRedline( *pNd, true, USHRT_MAX );
+
+ // lag keine Selektion vor ??
+ SwNodeIndex aIdx( *pNd );
+ if( ( !nEndNode && STRING_MAXLEN == nEndCntnt ) ||
+ ( nSttNode == nEndNode && nSttCntnt == nEndCntnt ))
+ // loesche einfach alle Nodes
+ rDoc.GetNodes().Delete( aIdx, pNd->EndOfSectionIndex() -
+ aIdx.GetIndex() );
+ else
+ // einfach das Format loeschen, der Rest erfolgt automatisch
+ rDoc.DelSectionFmt( pNd->GetSection().GetFmt() );
+
+ // muessen wir noch zusammenfassen ?
+ if (m_bSplitAtStart)
+ {
+ Join( rDoc, nSttNode );
+ }
+
+ if (m_bSplitAtEnd)
+ {
+ Join( rDoc, nEndNode );
+ }
+
+ if (m_pHistory.get())
+ {
+ m_pHistory->TmpRollback( &rDoc, 0, false );
+ }
+
+ if (m_bUpdateFtn)
+ {
+ rDoc.GetFtnIdxs().UpdateFtn( aIdx );
+ }
+
+ SetPaM( rUndoIter );
+}
+
+
+void SwUndoInsSection::Redo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SetPaM( rUndoIter );
+
+ const SwTOXBaseSection* pUpdateTOX = 0;
+ if (m_pTOXBase.get())
+ {
+ pUpdateTOX = rDoc.InsertTableOf( *rUndoIter.pAktPam->GetPoint(),
+ *m_pTOXBase, m_pAttrSet.get(), true);
+ }
+ else
+ {
+ rDoc.InsertSwSection(*rUndoIter.pAktPam,
+ *m_pSectionData, 0, m_pAttrSet.get(), true);
+ }
+
+ if (m_pHistory.get())
+ {
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+ }
+
+ SwSectionNode *const pSectNd =
+ rDoc.GetNodes()[ m_nSectionNodePos ]->GetSectionNode();
+ if (m_pRedlData.get() &&
+ IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode()))
+ {
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+
+ SwPaM aPam( *pSectNd->EndOfSectionNode(), *pSectNd, 1 );
+ rDoc.AppendRedline( new SwRedline( *m_pRedlData, aPam ), true);
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ rDoc.GetRedlineTbl().Count() )
+ {
+ SwPaM aPam( *pSectNd->EndOfSectionNode(), *pSectNd, 1 );
+ rDoc.SplitRedline( aPam );
+ }
+
+ if( pUpdateTOX )
+ {
+ // Formatierung anstossen
+ SwEditShell* pESh = rDoc.GetEditShell();
+ if( pESh )
+ pESh->CalcLayout();
+
+ // Seitennummern eintragen
+ ((SwTOXBaseSection*)pUpdateTOX)->UpdatePageNum();
+ }
+}
+
+
+void SwUndoInsSection::Repeat( SwUndoIter& rUndoIter )
+{
+ if (m_pTOXBase.get())
+ {
+ rUndoIter.GetDoc().InsertTableOf( *rUndoIter.pAktPam->GetPoint(),
+ *m_pTOXBase, m_pAttrSet.get(), true);
+ }
+ else
+ {
+ rUndoIter.GetDoc().InsertSwSection( *rUndoIter.pAktPam,
+ *m_pSectionData, 0, m_pAttrSet.get());
+ }
+}
+
+
+void SwUndoInsSection::Join( SwDoc& rDoc, ULONG nNode )
+{
+ SwNodeIndex aIdx( rDoc.GetNodes(), nNode );
+ SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "wo ist mein TextNode?" );
+
+ {
+ RemoveIdxRel( nNode + 1, SwPosition( aIdx,
+ SwIndex( pTxtNd, pTxtNd->GetTxt().Len() )));
+ }
+ pTxtNd->JoinNext();
+
+ if (m_pHistory.get())
+ {
+ SwIndex aCntIdx( pTxtNd, 0 );
+ pTxtNd->RstAttr( aCntIdx, pTxtNd->Len(), 0, 0, true );
+ }
+}
+
+
+void
+SwUndoInsSection::SaveSplitNode(SwTxtNode *const pTxtNd, bool const bAtStart)
+{
+ if( pTxtNd->GetpSwpHints() )
+ {
+ if (!m_pHistory.get())
+ {
+ m_pHistory.reset( new SwHistory );
+ }
+ m_pHistory->CopyAttr( pTxtNd->GetpSwpHints(), pTxtNd->GetIndex(), 0,
+ pTxtNd->GetTxt().Len(), false );
+ }
+
+ if (bAtStart)
+ {
+ m_bSplitAtStart = true;
+ }
+ else
+ {
+ m_bSplitAtEnd = true;
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+class SwUndoDelSection
+ : public SwUndo
+{
+private:
+ ::std::auto_ptr<SwSectionData> const m_pSectionData; /// section not TOX
+ ::std::auto_ptr<SwTOXBase> const m_pTOXBase; /// set iff section is TOX
+ ::std::auto_ptr<SfxItemSet> const m_pAttrSet;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > const m_pMetadataUndo;
+ ULONG const m_nStartNode;
+ ULONG const m_nEndNode;
+
+public:
+ SwUndoDelSection(
+ SwSectionFmt const&, SwSection const&, SwNodeIndex const*const);
+ virtual ~SwUndoDelSection();
+ virtual void Undo( SwUndoIter& );
+ virtual void Redo( SwUndoIter& );
+};
+
+SW_DLLPRIVATE SwUndo * MakeUndoDelSection(SwSectionFmt const& rFormat)
+{
+ return new SwUndoDelSection(rFormat, *rFormat.GetSection(),
+ rFormat.GetCntnt().GetCntntIdx());
+}
+
+SwUndoDelSection::SwUndoDelSection(
+ SwSectionFmt const& rSectionFmt, SwSection const& rSection,
+ SwNodeIndex const*const pIndex)
+ : SwUndo( UNDO_DELSECTION )
+ , m_pSectionData( new SwSectionData(rSection) )
+ , m_pTOXBase( rSection.ISA( SwTOXBaseSection )
+ ? new SwTOXBase(static_cast<SwTOXBaseSection const&>(rSection))
+ : 0 )
+ , m_pAttrSet( ::lcl_GetAttrSet(rSection) )
+ , m_pMetadataUndo( rSectionFmt.CreateUndo() )
+ , m_nStartNode( pIndex->GetIndex() )
+ , m_nEndNode( pIndex->GetNode().EndOfSectionIndex() )
+{
+}
+
+SwUndoDelSection::~SwUndoDelSection()
+{
+}
+
+void SwUndoDelSection::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ if (m_pTOXBase.get())
+ {
+ rDoc.InsertTableOf(m_nStartNode, m_nEndNode-2, *m_pTOXBase,
+ m_pAttrSet.get());
+ }
+ else
+ {
+ SwNodeIndex aStt( rDoc.GetNodes(), m_nStartNode );
+ SwNodeIndex aEnd( rDoc.GetNodes(), m_nEndNode-2 );
+ SwSectionFmt* pFmt = rDoc.MakeSectionFmt( 0 );
+ if (m_pAttrSet.get())
+ {
+ pFmt->SetFmtAttr( *m_pAttrSet );
+ }
+
+ /// OD 04.10.2002 #102894#
+ /// remember inserted section node for further calculations
+ SwSectionNode* pInsertedSectNd = rDoc.GetNodes().InsertTextSection(
+ aStt, *pFmt, *m_pSectionData, 0, & aEnd);
+
+ if( SFX_ITEM_SET == pFmt->GetItemState( RES_FTN_AT_TXTEND ) ||
+ SFX_ITEM_SET == pFmt->GetItemState( RES_END_AT_TXTEND ))
+ {
+ rDoc.GetFtnIdxs().UpdateFtn( aStt );
+ }
+
+ /// OD 04.10.2002 #102894#
+ /// consider that section is hidden by condition.
+ /// If section is hidden by condition,
+ /// recalculate condition and update hidden condition flag.
+ /// Recalculation is necessary, because fields, on which the hide
+ /// condition depends, can be changed - fields changes aren't undoable.
+ /// NOTE: setting hidden condition flag also creates/deletes corresponding
+ /// frames, if the hidden condition flag changes.
+ SwSection& aInsertedSect = pInsertedSectNd->GetSection();
+ if ( aInsertedSect.IsHidden() &&
+ aInsertedSect.GetCondition().Len() > 0 )
+ {
+ SwCalc aCalc( rDoc );
+ rDoc.FldsToCalc(aCalc, pInsertedSectNd->GetIndex(), USHRT_MAX);
+ bool bRecalcCondHidden =
+ aCalc.Calculate( aInsertedSect.GetCondition() ).GetBool() ? true : false;
+ aInsertedSect.SetCondHidden( bRecalcCondHidden );
+ }
+
+ pFmt->RestoreMetadata(m_pMetadataUndo);
+ }
+}
+
+void SwUndoDelSection::Redo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ SwSectionNode *const pNd =
+ rDoc.GetNodes()[ m_nStartNode ]->GetSectionNode();
+ OSL_ENSURE( pNd, "wo ist mein SectionNode?" );
+ // einfach das Format loeschen, der Rest erfolgt automatisch
+ rDoc.DelSectionFmt( pNd->GetSection().GetFmt() );
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+class SwUndoUpdateSection
+ : public SwUndo
+{
+private:
+ ::std::auto_ptr<SwSectionData> m_pSectionData;
+ ::std::auto_ptr<SfxItemSet> m_pAttrSet;
+ ULONG const m_nStartNode;
+ bool const m_bOnlyAttrChanged;
+
+public:
+ SwUndoUpdateSection(
+ SwSection const&, SwNodeIndex const*const, bool const bOnlyAttr);
+ virtual ~SwUndoUpdateSection();
+ virtual void Undo( SwUndoIter& );
+ virtual void Redo( SwUndoIter& );
+};
+
+SW_DLLPRIVATE SwUndo *
+MakeUndoUpdateSection(SwSectionFmt const& rFormat, bool const bOnlyAttr)
+{
+ return new SwUndoUpdateSection(*rFormat.GetSection(),
+ rFormat.GetCntnt().GetCntntIdx(), bOnlyAttr);
+}
+
+SwUndoUpdateSection::SwUndoUpdateSection(
+ SwSection const& rSection, SwNodeIndex const*const pIndex,
+ bool const bOnlyAttr)
+ : SwUndo( UNDO_CHGSECTION )
+ , m_pSectionData( new SwSectionData(rSection) )
+ , m_pAttrSet( ::lcl_GetAttrSet(rSection) )
+ , m_nStartNode( pIndex->GetIndex() )
+ , m_bOnlyAttrChanged( bOnlyAttr )
+{
+}
+
+SwUndoUpdateSection::~SwUndoUpdateSection()
+{
+}
+
+void SwUndoUpdateSection::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SwSectionNode *const pSectNd =
+ rDoc.GetNodes()[ m_nStartNode ]->GetSectionNode();
+ OSL_ENSURE( pSectNd, "wo ist mein SectionNode?" );
+
+ SwSection& rNdSect = pSectNd->GetSection();
+ SwFmt* pFmt = rNdSect.GetFmt();
+
+ SfxItemSet* pCur = ::lcl_GetAttrSet( rNdSect );
+ if (m_pAttrSet.get())
+ {
+ // das Content- und Protect-Item muss bestehen bleiben
+ const SfxPoolItem* pItem;
+ m_pAttrSet->Put( pFmt->GetFmtAttr( RES_CNTNT ));
+ if( SFX_ITEM_SET == pFmt->GetItemState( RES_PROTECT, TRUE, &pItem ))
+ {
+ m_pAttrSet->Put( *pItem );
+ }
+ pFmt->DelDiffs( *m_pAttrSet );
+ m_pAttrSet->ClearItem( RES_CNTNT );
+ pFmt->SetFmtAttr( *m_pAttrSet );
+ }
+ else
+ {
+ // dann muessen die alten entfernt werden
+ pFmt->ResetFmtAttr( RES_FRMATR_BEGIN, RES_BREAK );
+ pFmt->ResetFmtAttr( RES_HEADER, RES_OPAQUE );
+ pFmt->ResetFmtAttr( RES_SURROUND, RES_FRMATR_END-1 );
+ }
+ m_pAttrSet.reset(pCur);
+
+ if (!m_bOnlyAttrChanged)
+ {
+ const bool bUpdate =
+ (!rNdSect.IsLinkType() && m_pSectionData->IsLinkType())
+ || ( m_pSectionData->GetLinkFileName().Len()
+ && (m_pSectionData->GetLinkFileName() !=
+ rNdSect.GetLinkFileName()));
+
+ // swap stored section data with live section data
+ SwSectionData *const pOld( new SwSectionData(rNdSect) );
+ rNdSect.SetSectionData(*m_pSectionData);
+ m_pSectionData.reset(pOld);
+
+ if( bUpdate )
+ rNdSect.CreateLink( CREATE_UPDATE );
+ else if( CONTENT_SECTION == rNdSect.GetType() && rNdSect.IsConnected() )
+ {
+ rNdSect.Disconnect();
+ rDoc.GetLinkManager().Remove( &rNdSect.GetBaseLink() );
+ }
+ }
+}
+
+void SwUndoUpdateSection::Redo( SwUndoIter& rUndoIter )
+{
+ Undo( rUndoIter );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unsort.cxx b/sw/source/core/undo/unsort.cxx
new file mode 100644
index 000000000000..03aebaa89458
--- /dev/null
+++ b/sw/source/core/undo/unsort.cxx
@@ -0,0 +1,302 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <doc.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <sortopt.hxx>
+#include <docsort.hxx>
+#include <redline.hxx>
+#include <node2lay.hxx>
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+/*--------------------------------------------------------------------
+ Beschreibung: Undo fuers Sorting
+ --------------------------------------------------------------------*/
+
+
+SV_IMPL_PTRARR(SwSortList, SwSortUndoElement*)
+SV_IMPL_PTRARR(SwUndoSortList, SwNodeIndex*)
+
+
+SwSortUndoElement::~SwSortUndoElement()
+{
+ // sind String Pointer gespeichert ??
+ if( 0xffffffff != SORT_TXT_TBL.TXT.nKenn )
+ {
+ delete SORT_TXT_TBL.TBL.pSource;
+ delete SORT_TXT_TBL.TBL.pTarget;
+ }
+}
+
+
+SwUndoSort::SwUndoSort(const SwPaM& rRg, const SwSortOptions& rOpt)
+ : SwUndo(UNDO_SORT_TXT), SwUndRng(rRg), pUndoTblAttr( 0 ),
+ pRedlData( 0 )
+{
+ pSortOpt = new SwSortOptions(rOpt);
+}
+
+
+SwUndoSort::SwUndoSort( ULONG nStt, ULONG nEnd, const SwTableNode& rTblNd,
+ const SwSortOptions& rOpt, BOOL bSaveTable )
+ : SwUndo(UNDO_SORT_TBL), pUndoTblAttr( 0 ), pRedlData( 0 )
+{
+ nSttNode = nStt;
+ nEndNode = nEnd;
+ nTblNd = rTblNd.GetIndex();
+
+ pSortOpt = new SwSortOptions(rOpt);
+ if( bSaveTable )
+ pUndoTblAttr = new SwUndoAttrTbl( rTblNd );
+}
+
+
+
+SwUndoSort::~SwUndoSort()
+{
+ delete pSortOpt;
+ delete pUndoTblAttr;
+ delete pRedlData;
+}
+
+
+
+void SwUndoSort::Undo( SwUndoIter& rIter)
+{
+ SwDoc& rDoc = rIter.GetDoc();
+ if(pSortOpt->bTable)
+ {
+ // Undo Tabelle
+ RemoveIdxFromSection( rDoc, nSttNode, &nEndNode );
+
+ if( pUndoTblAttr )
+ pUndoTblAttr->Undo( rIter );
+
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
+
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ SwNode2Layout aNode2Layout( *pTblNd );
+ // <--
+
+ pTblNd->DelFrms();
+ const SwTable& rTbl = pTblNd->GetTable();
+
+ SwMovedBoxes aMovedList;
+ for( USHORT i=0; i < aSortList.Count(); i++)
+ {
+ const SwTableBox* pSource = rTbl.GetTblBox(
+ *aSortList[i]->SORT_TXT_TBL.TBL.pSource );
+ const SwTableBox* pTarget = rTbl.GetTblBox(
+ *aSortList[i]->SORT_TXT_TBL.TBL.pTarget );
+
+ // zurueckverschieben
+ MoveCell(&rDoc, pTarget, pSource,
+ USHRT_MAX != aMovedList.GetPos(pSource) );
+
+ // schon Verschobenen in der Liste merken
+ aMovedList.Insert(pTarget, aMovedList.Count() );
+ }
+
+ // Restore table frames:
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ const ULONG nIdx = pTblNd->GetIndex();
+ aNode2Layout.RestoreUpperFrms( rDoc.GetNodes(), nIdx, nIdx + 1 );
+ // <--
+ }
+ else
+ {
+ // Undo Text
+ RemoveIdx( *rIter.pAktPam );
+
+ // fuer die sorted Positions einen Index anlegen.
+ // JP 25.11.97: Die IndexList muss aber nach SourcePosition
+ // aufsteigend sortiert aufgebaut werden
+ SwUndoSortList aIdxList( (BYTE)aSortList.Count() );
+ USHORT i;
+
+ for( i = 0; i < aSortList.Count(); ++i)
+ for( USHORT ii=0; ii < aSortList.Count(); ++ii )
+ if( aSortList[ii]->SORT_TXT_TBL.TXT.nSource == nSttNode + i )
+ {
+ SwNodeIndex* pIdx = new SwNodeIndex( rDoc.GetNodes(),
+ aSortList[ii]->SORT_TXT_TBL.TXT.nTarget );
+ aIdxList.C40_INSERT(SwNodeIndex, pIdx, i );
+ break;
+ }
+
+ for(i=0; i < aSortList.Count(); ++i)
+ {
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode + i );
+ SwNodeRange aRg( *aIdxList[i], 0, *aIdxList[i], 1 );
+ rDoc.MoveNodeRange(aRg, aIdx,
+ IDocumentContentOperations::DOC_MOVEDEFAULT);
+ }
+ // Indixes loeschen
+ aIdxList.DeleteAndDestroy(0, aIdxList.Count());
+ SetPaM( rIter, TRUE );
+ }
+}
+
+
+void SwUndoSort::Redo( SwUndoIter& rIter)
+{
+ SwDoc& rDoc = rIter.GetDoc();
+
+ if(pSortOpt->bTable)
+ {
+ // Redo bei Tabelle
+ RemoveIdxFromSection( rDoc, nSttNode, &nEndNode );
+
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
+
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ SwNode2Layout aNode2Layout( *pTblNd );
+ // <--
+
+ pTblNd->DelFrms();
+ const SwTable& rTbl = pTblNd->GetTable();
+
+ SwMovedBoxes aMovedList;
+ for(USHORT i=0; i < aSortList.Count(); ++i)
+ {
+ const SwTableBox* pSource = rTbl.GetTblBox(
+ (const String&) *aSortList[i]->SORT_TXT_TBL.TBL.pSource );
+ const SwTableBox* pTarget = rTbl.GetTblBox(
+ (const String&) *aSortList[i]->SORT_TXT_TBL.TBL.pTarget );
+
+ // zurueckverschieben
+ MoveCell(&rDoc, pSource, pTarget,
+ USHRT_MAX != aMovedList.GetPos( pTarget ) );
+ // schon Verschobenen in der Liste merken
+ aMovedList.Insert( pSource, aMovedList.Count() );
+ }
+
+ if( pUndoTblAttr )
+ pUndoTblAttr->Redo( rIter );
+
+ // Restore table frames:
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ const ULONG nIdx = pTblNd->GetIndex();
+ aNode2Layout.RestoreUpperFrms( rDoc.GetNodes(), nIdx, nIdx + 1 );
+ // <--
+ }
+ else
+ {
+ // Redo bei Text
+ RemoveIdx( *rIter.pAktPam );
+
+ SwUndoSortList aIdxList( (BYTE)aSortList.Count() );
+ USHORT i;
+
+ for( i = 0; i < aSortList.Count(); ++i)
+ { // aktuelle Pos ist die Ausgangslage
+ SwNodeIndex* pIdx = new SwNodeIndex( rDoc.GetNodes(),
+ aSortList[i]->SORT_TXT_TBL.TXT.nSource);
+ aIdxList.C40_INSERT( SwNodeIndex, pIdx, i );
+ }
+
+ for(i=0; i < aSortList.Count(); ++i)
+ {
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode + i);
+ SwNodeRange aRg( *aIdxList[i], 0, *aIdxList[i], 1 );
+ rDoc.MoveNodeRange(aRg, aIdx,
+ IDocumentContentOperations::DOC_MOVEDEFAULT);
+ }
+ // Indixes loeschen
+ aIdxList.DeleteAndDestroy(0, aIdxList.Count());
+ SetPaM( rIter, TRUE );
+ const SwTxtNode* pTNd = rIter.pAktPam->GetNode()->GetTxtNode();
+ if( pTNd )
+ rIter.pAktPam->GetPoint()->nContent = pTNd->GetTxt().Len();
+ }
+}
+
+
+void SwUndoSort::Repeat(SwUndoIter& rIter)
+{
+ if(!pSortOpt->bTable)
+ {
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc& rDoc = *pPam->GetDoc();
+
+ if( !rDoc.IsIdxInTbl( pPam->Start()->nNode ) )
+ rDoc.SortText(*pPam, *pSortOpt);
+ }
+ // Tabelle ist nicht Repeat-Faehig
+ rIter.pLastUndoObj = this;
+}
+
+
+void SwUndoSort::RemoveIdx( SwPaM& rPam )
+{
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = nSttNode;
+
+ SwCntntNode* pCNd = rPam.GetCntntNode();
+ xub_StrLen nLen = pCNd->Len();
+ if( nLen >= nSttCntnt )
+ nLen = nSttCntnt;
+ rPam.GetPoint()->nContent.Assign(pCNd, nLen );
+ rPam.SetMark();
+
+ rPam.GetPoint()->nNode = nEndNode;
+ pCNd = rPam.GetCntntNode();
+ nLen = pCNd->Len();
+ if( nLen >= nEndCntnt )
+ nLen = nEndCntnt;
+ rPam.GetPoint()->nContent.Assign(pCNd, nLen );
+ RemoveIdxFromRange( rPam, TRUE );
+}
+
+
+void SwUndoSort::Insert( const String& rOrgPos, const String& rNewPos)
+{
+ SwSortUndoElement* pEle = new SwSortUndoElement(rOrgPos, rNewPos);
+ aSortList.C40_INSERT( SwSortUndoElement, pEle, aSortList.Count() );
+}
+
+
+void SwUndoSort::Insert( ULONG nOrgPos, ULONG nNewPos)
+{
+ SwSortUndoElement* pEle = new SwSortUndoElement(nOrgPos, nNewPos);
+ aSortList.C40_INSERT( SwSortUndoElement, pEle, aSortList.Count() );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unspnd.cxx b/sw/source/core/undo/unspnd.cxx
new file mode 100644
index 000000000000..875da9c9bca7
--- /dev/null
+++ b/sw/source/core/undo/unspnd.cxx
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "doc.hxx"
+#include "pam.hxx"
+#include "swtable.hxx"
+#include "ndtxt.hxx"
+#include "swundo.hxx" // fuer die UndoIds
+#include <editeng/brkitem.hxx>
+#include <fmtpdsc.hxx>
+#include <frmfmt.hxx>
+#include "undobj.hxx"
+#include "rolbck.hxx"
+#include "redline.hxx"
+#include "docary.hxx"
+
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+
+
+//------------------------------------------------------------------
+
+// SPLITNODE
+
+
+SwUndoSplitNode::SwUndoSplitNode( SwDoc* pDoc, const SwPosition& rPos,
+ BOOL bChkTable )
+ : SwUndo( UNDO_SPLITNODE ), pHistory( 0 ), pRedlData( 0 ), nNode( rPos.nNode.GetIndex() ),
+ nCntnt( rPos.nContent.GetIndex() ),
+ bTblFlag( FALSE ), bChkTblStt( bChkTable )
+{
+ SwTxtNode* pTxtNd = pDoc->GetNodes()[ rPos.nNode ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "nur beim TextNode rufen!" );
+ if( pTxtNd->GetpSwpHints() )
+ {
+ pHistory = new SwHistory;
+ pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nNode, 0,
+ pTxtNd->GetTxt().Len(), false );
+ if( !pHistory->Count() )
+ DELETEZ( pHistory );
+ }
+ // Redline beachten
+ if( pDoc->IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, pDoc->GetRedlineAuthor() );
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ }
+}
+
+
+
+
+SwUndoSplitNode::~SwUndoSplitNode()
+{
+ delete pHistory;
+ delete pRedlData;
+}
+
+
+
+void SwUndoSplitNode::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc* pDoc = &rUndoIter.GetDoc();
+ SwPaM& rPam = *rUndoIter.pAktPam;
+ rPam.DeleteMark();
+ if( bTblFlag )
+ {
+ // dann wurde direkt vor der akt. Tabelle ein TextNode eingefuegt.
+ SwNodeIndex& rIdx = rPam.GetPoint()->nNode;
+ rIdx = nNode;
+ SwTxtNode* pTNd;
+ SwNode* pCurrNd = pDoc->GetNodes()[ nNode + 1 ];
+ SwTableNode* pTblNd = pCurrNd->FindTableNode();
+ if( pCurrNd->IsCntntNode() && pTblNd &&
+ 0 != ( pTNd = pDoc->GetNodes()[ pTblNd->GetIndex()-1 ]->GetTxtNode() ))
+ {
+ // verschiebe die BreakAttribute noch
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+ const SfxItemSet* pNdSet = pTNd->GetpSwAttrSet();
+ if( pNdSet )
+ {
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pNdSet->GetItemState( RES_PAGEDESC, FALSE,
+ &pItem ) )
+ pTableFmt->SetFmtAttr( *pItem );
+
+ if( SFX_ITEM_SET == pNdSet->GetItemState( RES_BREAK, FALSE,
+ &pItem ) )
+ pTableFmt->SetFmtAttr( *pItem );
+ }
+
+ // dann loesche den wieder
+ SwNodeIndex aDelNd( *pTblNd, -1 );
+ rPam.GetPoint()->nContent.Assign( (SwCntntNode*)pCurrNd, 0 );
+ RemoveIdxRel( aDelNd.GetIndex(), *rPam.GetPoint() );
+ pDoc->GetNodes().Delete( aDelNd );
+ }
+ }
+ else
+ {
+ SwTxtNode * pTNd = pDoc->GetNodes()[ nNode ]->GetTxtNode();
+ if( pTNd )
+ {
+ rPam.GetPoint()->nNode = *pTNd;
+ rPam.GetPoint()->nContent.Assign( pTNd, pTNd->GetTxt().Len() );
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ rPam.SetMark();
+ rPam.GetMark()->nNode++;
+ rPam.GetMark()->nContent.Assign( rPam.GetMark()->
+ nNode.GetNode().GetCntntNode(), 0 );
+ pDoc->DeleteRedline( rPam, true, USHRT_MAX );
+ rPam.DeleteMark();
+ }
+
+ RemoveIdxRel( nNode+1, *rPam.GetPoint() );
+
+ pTNd->JoinNext();
+ if( pHistory )
+ {
+ rPam.GetPoint()->nContent = 0;
+ rPam.SetMark();
+ rPam.GetPoint()->nContent = pTNd->GetTxt().Len();
+
+ pDoc->RstTxtAttrs( rPam, TRUE );
+ pHistory->TmpRollback( pDoc, 0, false );
+ }
+ }
+ }
+
+ // setze noch den Cursor auf den Undo-Bereich
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = nNode;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), nCntnt );
+}
+
+
+void SwUndoSplitNode::Repeat( SwUndoIter& rUndoIter )
+{
+ if( UNDO_SPLITNODE == rUndoIter.GetLastUndoId() )
+ return;
+ rUndoIter.GetDoc().SplitNode( *rUndoIter.pAktPam->GetPoint(), bChkTblStt );
+ rUndoIter.pLastUndoObj = this;
+}
+
+
+void SwUndoSplitNode::Redo( SwUndoIter& rUndoIter )
+{
+ SwPaM& rPam = *rUndoIter.pAktPam;
+ ULONG nOldNode = rPam.GetPoint()->nNode.GetIndex();
+ rPam.GetPoint()->nNode = nNode;
+ SwTxtNode * pTNd = rPam.GetNode()->GetTxtNode();
+ if( pTNd ) // sollte eigentlich immer ein TextNode sein !!
+ {
+ rPam.GetPoint()->nContent.Assign( pTNd, nCntnt );
+
+ SwDoc* pDoc = rPam.GetDoc();
+ pDoc->SplitNode( *rPam.GetPoint(), bChkTblStt );
+
+ if( pHistory )
+ pHistory->SetTmpEnd( pHistory->Count() );
+
+ if( ( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) ||
+ ( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ pDoc->GetRedlineTbl().Count() ))
+ {
+ rPam.SetMark();
+ if( rPam.Move( fnMoveBackward ))
+ {
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+ pDoc->AppendRedline( new SwRedline( *pRedlData, rPam ), true);
+ pDoc->SetRedlineMode_intern( eOld );
+ }
+ else
+ pDoc->SplitRedline( rPam );
+ rPam.Exchange();
+ }
+ rPam.DeleteMark();
+ }
+ }
+ else
+ rPam.GetPoint()->nNode = nOldNode;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
new file mode 100644
index 000000000000..735c8c734039
--- /dev/null
+++ b/sw/source/core/undo/untbl.cxx
@@ -0,0 +1,3256 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/brkitem.hxx>
+#include <fmtornt.hxx>
+#include <fmtpdsc.hxx>
+#include <doc.hxx>
+#include <editsh.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <pam.hxx>
+#include <cntfrm.hxx>
+#include <tblsel.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <undobj.hxx>
+#include <rolbck.hxx>
+#include <ddefld.hxx>
+#include <tabcol.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <swcache.hxx>
+#include <tblafmt.hxx>
+#include <poolfmt.hxx>
+#include <mvsave.hxx>
+#include <cellatr.hxx>
+#include <swtblfmt.hxx>
+#include <swddetbl.hxx>
+#include <redline.hxx>
+#include <node2lay.hxx>
+#include <tblrwcl.hxx>
+#include <fmtanchr.hxx>
+#include <comcore.hrc>
+#include <unochart.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#define CHECK_TABLE(t) (t).CheckConsistency();
+#else
+#define CHECK_TABLE(t)
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+ void lcl_DebugRedline( const SwDoc* pDoc );
+ #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc );
+#else
+ #define _DEBUG_REDLINE( pDoc )
+#endif
+
+inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
+extern void ClearFEShellTabCols();
+
+typedef SfxItemSet* SfxItemSetPtr;
+SV_DECL_PTRARR_DEL( SfxItemSets, SfxItemSetPtr, 10, 5 )
+
+typedef SwUndoSaveSection* SwUndoSaveSectionPtr;
+SV_DECL_PTRARR_DEL( SwUndoSaveSections, SwUndoSaveSectionPtr, 0, 10 )
+
+typedef SwUndoMove* SwUndoMovePtr;
+SV_DECL_PTRARR_DEL( SwUndoMoves, SwUndoMovePtr, 0, 10 )
+
+struct SwTblToTxtSave;
+typedef SwTblToTxtSave* SwTblToTxtSavePtr;
+SV_DECL_PTRARR_DEL( SwTblToTxtSaves, SwTblToTxtSavePtr, 0, 10 )
+
+struct _UndoTblCpyTbl_Entry
+{
+ ULONG nBoxIdx, nOffset;
+ SfxItemSet* pBoxNumAttr;
+ SwUndo* pUndo;
+
+ // Was the last paragraph of the new and the first paragraph of the old content joined?
+ bool bJoin; // For redlining only
+
+ _UndoTblCpyTbl_Entry( const SwTableBox& rBox );
+ ~_UndoTblCpyTbl_Entry();
+};
+typedef _UndoTblCpyTbl_Entry* _UndoTblCpyTbl_EntryPtr;
+SV_DECL_PTRARR_DEL( _UndoTblCpyTbl_Entries, _UndoTblCpyTbl_EntryPtr, 0, 10 )
+
+class _SaveBox;
+class _SaveLine;
+
+class _SaveTable
+{
+ friend class _SaveBox;
+ friend class _SaveLine;
+ SfxItemSet aTblSet;
+ _SaveLine* pLine;
+ const SwTable* pSwTable;
+ SfxItemSets aSets;
+ SwFrmFmts aFrmFmts;
+ USHORT nLineCount;
+ BOOL bModifyBox : 1;
+ BOOL bSaveFormula : 1;
+ BOOL bNewModel : 1;
+
+public:
+ _SaveTable( const SwTable& rTbl, USHORT nLnCnt = USHRT_MAX,
+ BOOL bSaveFml = TRUE );
+ ~_SaveTable();
+
+ USHORT AddFmt( SwFrmFmt* pFmt, bool bIsLine );
+ void NewFrmFmt( const SwClient* pLnBx, BOOL bIsLine, USHORT nFmtPos,
+ SwFrmFmt* pOldFmt );
+
+ void RestoreAttr( SwTable& rTbl, BOOL bModifyBox = FALSE );
+ void SaveCntntAttrs( SwDoc* pDoc );
+ void CreateNew( SwTable& rTbl, BOOL bCreateFrms = TRUE,
+ BOOL bRestoreChart = TRUE );
+ BOOL IsNewModel() const { return bNewModel; }
+};
+
+class _SaveLine
+{
+ friend class _SaveTable;
+ friend class _SaveBox;
+
+ _SaveLine* pNext;
+ _SaveBox* pBox;
+ USHORT nItemSet;
+
+public:
+
+ _SaveLine( _SaveLine* pPrev, const SwTableLine& rLine, _SaveTable& rSTbl );
+ ~_SaveLine();
+
+ void RestoreAttr( SwTableLine& rLine, _SaveTable& rSTbl );
+ void SaveCntntAttrs( SwDoc* pDoc );
+
+ void CreateNew( SwTable& rTbl, SwTableBox& rParent, _SaveTable& rSTbl );
+};
+
+class _SaveBox
+{
+ friend class _SaveLine;
+
+ _SaveBox* pNext;
+ ULONG nSttNode;
+ long nRowSpan;
+ USHORT nItemSet;
+ union
+ {
+ SfxItemSets* pCntntAttrs;
+ _SaveLine* pLine;
+ } Ptrs;
+
+public:
+ _SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl );
+ ~_SaveBox();
+
+ void RestoreAttr( SwTableBox& rBox, _SaveTable& rSTbl );
+ void SaveCntntAttrs( SwDoc* pDoc );
+
+ void CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl );
+};
+
+void InsertSort( SvUShorts& rArr, USHORT nIdx, USHORT* pInsPos = 0 );
+void InsertSort( SvULongs& rArr, ULONG nIdx, USHORT* pInsPos = 0 );
+
+#if OSL_DEBUG_LEVEL > 1
+#include "shellio.hxx"
+void CheckTable( const SwTable& );
+#define CHECKTABLE(t) CheckTable( t );
+#else
+#define CHECKTABLE(t)
+#endif
+
+/* #130880: Crash in undo of table to text when the table has (freshly) merged cells
+The order of cell content nodes in the nodes array is not given by the recursive table structure.
+The algorithmn must not rely on this even it holds for a fresh loaded table in odt file format.
+So we need to remember not only the start node position but the end node position as well.
+*/
+
+struct SwTblToTxtSave
+{
+ ULONG m_nSttNd;
+ ULONG m_nEndNd;
+ xub_StrLen m_nCntnt;
+ SwHistory* m_pHstry;
+ // metadata references for first and last paragraph in cell
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
+
+ SwTblToTxtSave( SwDoc& rDoc, ULONG nNd, ULONG nEndIdx, xub_StrLen nCntnt );
+ ~SwTblToTxtSave() { delete m_pHstry; }
+};
+
+SV_IMPL_PTRARR( SfxItemSets, SfxItemSetPtr )
+SV_IMPL_PTRARR( SwUndoSaveSections, SwUndoSaveSectionPtr )
+SV_IMPL_PTRARR( SwUndoMoves, SwUndoMovePtr )
+SV_IMPL_PTRARR( SwTblToTxtSaves, SwTblToTxtSavePtr )
+SV_IMPL_PTRARR( _UndoTblCpyTbl_Entries, _UndoTblCpyTbl_EntryPtr )
+
+USHORT __FAR_DATA aSave_BoxCntntSet[] = {
+ RES_CHRATR_COLOR, RES_CHRATR_CROSSEDOUT,
+ RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
+ RES_CHRATR_POSTURE, RES_CHRATR_POSTURE,
+ RES_CHRATR_SHADOWED, RES_CHRATR_WEIGHT,
+ RES_PARATR_ADJUST, RES_PARATR_ADJUST,
+ 0 };
+
+
+
+SwUndoInsTbl::SwUndoInsTbl( const SwPosition& rPos, USHORT nCl, USHORT nRw,
+ USHORT nAdj, const SwInsertTableOptions& rInsTblOpts,
+ const SwTableAutoFmt* pTAFmt,
+ const SvUShorts* pColArr,
+ const String & rName)
+ : SwUndo( UNDO_INSTABLE ),
+ aInsTblOpts( rInsTblOpts ), pDDEFldType( 0 ), pColWidth( 0 ), pRedlData( 0 ), pAutoFmt( 0 ),
+ nSttNode( rPos.nNode.GetIndex() ), nRows( nRw ), nCols( nCl ), nAdjust( nAdj )
+{
+ if( pColArr )
+ {
+ pColWidth = new SvUShorts( 0, 1 );
+ pColWidth->Insert( pColArr, 0 );
+ }
+ if( pTAFmt )
+ pAutoFmt = new SwTableAutoFmt( *pTAFmt );
+
+ // Redline beachten
+ SwDoc& rDoc = *rPos.nNode.GetNode().GetDoc();
+ if( rDoc.IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, rDoc.GetRedlineAuthor() );
+ SetRedlineMode( rDoc.GetRedlineMode() );
+ }
+
+ sTblNm = rName;
+}
+
+
+SwUndoInsTbl::~SwUndoInsTbl()
+{
+ delete pDDEFldType;
+ delete pColWidth;
+ delete pRedlData;
+ delete pAutoFmt;
+}
+
+void SwUndoInsTbl::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
+
+ SwTableNode* pTblNd = aIdx.GetNode().GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+ pTblNd->DelFrms();
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ rDoc.DeleteRedline( *pTblNd, true, USHRT_MAX );
+ RemoveIdxFromSection( rDoc, nSttNode );
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ SwCntntNode* pNextNd = rDoc.GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode();
+ if( pNextNd )
+ {
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+ const SfxPoolItem *pItem;
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
+ FALSE, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
+ FALSE, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+ }
+
+
+ sTblNm = pTblNd->GetTable().GetFrmFmt()->GetName();
+ if( pTblNd->GetTable().IsA( TYPE( SwDDETable )) )
+ pDDEFldType = (SwDDEFieldType*)((SwDDETable&)pTblNd->GetTable()).
+ GetDDEFldType()->Copy();
+
+ rDoc.GetNodes().Delete( aIdx, pTblNd->EndOfSectionIndex() -
+ aIdx.GetIndex() + 1 );
+
+ rUndoIter.pAktPam->DeleteMark();
+ rUndoIter.pAktPam->GetPoint()->nNode = aIdx;
+ rUndoIter.pAktPam->GetPoint()->nContent.Assign(
+ rUndoIter.pAktPam->GetCntntNode(), 0 );
+}
+
+
+void SwUndoInsTbl::Redo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ SwPosition aPos( *rUndoIter.pAktPam->GetPoint() );
+ aPos.nNode = nSttNode;
+ const SwTable* pTbl = rDoc.InsertTable( aInsTblOpts, aPos, nRows, nCols,
+ nAdjust,
+ pAutoFmt, pColWidth );
+ ((SwFrmFmt*)pTbl->GetFrmFmt())->SetName( sTblNm );
+ SwTableNode* pTblNode = (SwTableNode*)rDoc.GetNodes()[nSttNode]->GetTableNode();
+
+ if( pDDEFldType )
+ {
+ SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType(
+ *pDDEFldType);
+ SwDDETable* pDDETbl = new SwDDETable( pTblNode->GetTable(), pNewType );
+ pTblNode->SetNewTable( pDDETbl ); // setze die DDE-Tabelle
+ delete pDDEFldType, pDDEFldType = 0;
+ }
+
+ if( (pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) ||
+ ( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ rDoc.GetRedlineTbl().Count() ))
+ {
+ SwPaM aPam( *pTblNode->EndOfSectionNode(), *pTblNode, 1 );
+ SwCntntNode* pCNd = aPam.GetCntntNode( FALSE );
+ if( pCNd )
+ aPam.GetMark()->nContent.Assign( pCNd, 0 );
+
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+
+ rDoc.AppendRedline( new SwRedline( *pRedlData, aPam ), true);
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else
+ rDoc.SplitRedline( aPam );
+ }
+}
+
+
+void SwUndoInsTbl::Repeat( SwUndoIter& rUndoIter )
+{
+ rUndoIter.GetDoc().InsertTable( aInsTblOpts, *rUndoIter.pAktPam->GetPoint(),
+ nRows, nCols, nAdjust,
+ pAutoFmt, pColWidth );
+}
+
+SwRewriter SwUndoInsTbl::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, SW_RES(STR_START_QUOTE));
+ aRewriter.AddRule(UNDO_ARG2, sTblNm);
+ aRewriter.AddRule(UNDO_ARG3, SW_RES(STR_END_QUOTE));
+
+ return aRewriter;
+}
+
+// -----------------------------------------------------
+
+SwTblToTxtSave::SwTblToTxtSave( SwDoc& rDoc, ULONG nNd, ULONG nEndIdx, xub_StrLen nCnt )
+ : m_nSttNd( nNd ), m_nEndNd( nEndIdx), m_nCntnt( nCnt ), m_pHstry( 0 )
+{
+ // Attributierung des gejointen Node merken.
+ SwTxtNode* pNd = rDoc.GetNodes()[ nNd ]->GetTxtNode();
+ if( pNd )
+ {
+ m_pHstry = new SwHistory;
+
+ m_pHstry->Add( pNd->GetTxtColl(), nNd, ND_TEXTNODE );
+ if ( pNd->GetpSwpHints() )
+ {
+ m_pHstry->CopyAttr( pNd->GetpSwpHints(), nNd, 0,
+ pNd->GetTxt().Len(), false );
+ }
+ if( pNd->HasSwAttrSet() )
+ m_pHstry->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNd );
+
+ if( !m_pHstry->Count() )
+ delete m_pHstry, m_pHstry = 0;
+
+ // METADATA: store
+ m_pMetadataUndoStart = pNd->CreateUndo();
+ }
+
+ // we also need to store the metadata reference of the _last_ paragraph
+ // we subtract 1 to account for the removed cell start/end node pair
+ // (after SectionUp, the end of the range points to the node after the cell)
+ if ( nEndIdx - 1 > nNd )
+ {
+ SwTxtNode* pLastNode( rDoc.GetNodes()[ nEndIdx - 1 ]->GetTxtNode() );
+ if( pLastNode )
+ {
+ // METADATA: store
+ m_pMetadataUndoEnd = pLastNode->CreateUndo();
+ }
+ }
+}
+
+SwUndoTblToTxt::SwUndoTblToTxt( const SwTable& rTbl, sal_Unicode cCh )
+ : SwUndo( UNDO_TABLETOTEXT ),
+ sTblNm( rTbl.GetFrmFmt()->GetName() ), pDDEFldType( 0 ), pHistory( 0 ),
+ nSttNd( 0 ), nEndNd( 0 ),
+ nAdjust( static_cast<USHORT>(rTbl.GetFrmFmt()->GetHoriOrient().GetHoriOrient()) ),
+ cTrenner( cCh ), nHdlnRpt( rTbl.GetRowsToRepeat() )
+{
+ pTblSave = new _SaveTable( rTbl );
+ pBoxSaves = new SwTblToTxtSaves( (BYTE)rTbl.GetTabSortBoxes().Count() );
+
+ if( rTbl.IsA( TYPE( SwDDETable ) ) )
+ pDDEFldType = (SwDDEFieldType*)((SwDDETable&)rTbl).GetDDEFldType()->Copy();
+
+ bCheckNumFmt = rTbl.GetFrmFmt()->GetDoc()->IsInsTblFormatNum();
+
+ pHistory = new SwHistory;
+ const SwTableNode* pTblNd = rTbl.GetTableNode();
+ ULONG nTblStt = pTblNd->GetIndex(), nTblEnd = pTblNd->EndOfSectionIndex();
+
+ const SwSpzFrmFmts& rFrmFmtTbl = *pTblNd->GetDoc()->GetSpzFrmFmts();
+ for( USHORT n = 0; n < rFrmFmtTbl.Count(); ++n )
+ {
+ SwFrmFmt* pFmt = rFrmFmtTbl[ n ];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
+ (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
+ nTblStt <= pAPos->nNode.GetIndex() &&
+ pAPos->nNode.GetIndex() < nTblEnd )
+ {
+ pHistory->Add( *pFmt );
+ }
+ }
+
+ if( !pHistory->Count() )
+ delete pHistory, pHistory = 0;
+}
+
+
+SwUndoTblToTxt::~SwUndoTblToTxt()
+{
+ delete pDDEFldType;
+ delete pTblSave;
+ delete pBoxSaves;
+ delete pHistory;
+}
+
+
+
+void SwUndoTblToTxt::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SwPaM* pPam = rUndoIter.pAktPam;
+
+ SwNodeIndex aFrmIdx( rDoc.GetNodes(), nSttNd );
+ SwNodeIndex aEndIdx( rDoc.GetNodes(), nEndNd );
+
+ pPam->GetPoint()->nNode = aFrmIdx;
+ pPam->SetMark();
+ pPam->GetPoint()->nNode = aEndIdx;
+ rDoc.DelNumRules( *pPam );
+ pPam->DeleteMark();
+
+ // dann sammel mal alle Uppers ein
+ SwNode2Layout aNode2Layout( aFrmIdx.GetNode() );
+
+ // erzeuge die TabelleNode Structur
+ SwTableNode* pTblNd = rDoc.GetNodes().UndoTableToText( nSttNd, nEndNd, *pBoxSaves );
+ pTblNd->GetTable().SetTableModel( pTblSave->IsNewModel() );
+ SwTableFmt* pTableFmt = rDoc.MakeTblFrmFmt( sTblNm, rDoc.GetDfltFrmFmt() );
+ pTableFmt->Add( &pTblNd->GetTable() ); // das Frame-Format setzen
+ pTblNd->GetTable().SetRowsToRepeat( nHdlnRpt );
+
+ // erzeuge die alte Tabellen Struktur
+ pTblSave->CreateNew( pTblNd->GetTable() );
+
+ if( pDDEFldType )
+ {
+ SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType(
+ *pDDEFldType);
+ SwDDETable* pDDETbl = new SwDDETable( pTblNd->GetTable(), pNewType );
+ pTblNd->SetNewTable( pDDETbl, FALSE ); // setze die DDE-Tabelle
+ delete pDDEFldType, pDDEFldType = 0;
+ }
+
+ if( bCheckNumFmt )
+ {
+ SwTableSortBoxes& rBxs = pTblNd->GetTable().GetTabSortBoxes();
+ for( USHORT nBoxes = rBxs.Count(); nBoxes; )
+ rDoc.ChkBoxNumFmt( *rBxs[ --nBoxes ], FALSE );
+ }
+
+ if( pHistory )
+ {
+ USHORT nTmpEnd = pHistory->GetTmpEnd();
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( nTmpEnd );
+ }
+
+ aNode2Layout.RestoreUpperFrms( rDoc.GetNodes(),
+ pTblNd->GetIndex(), pTblNd->GetIndex()+1 );
+
+ // will man eine TabellenSelektion ??
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
+ pPam->SetMark();
+ pPam->GetPoint()->nNode = *pPam->GetNode()->StartOfSectionNode();
+ pPam->Move( fnMoveForward, fnGoCntnt );
+ pPam->Exchange();
+ pPam->Move( fnMoveBackward, fnGoCntnt );
+
+ ClearFEShellTabCols();
+}
+
+ // steht im untbl.cxx und darf nur vom Undoobject gerufen werden
+SwTableNode* SwNodes::UndoTableToText( ULONG nSttNd, ULONG nEndNd,
+ const SwTblToTxtSaves& rSavedData )
+{
+ SwNodeIndex aSttIdx( *this, nSttNd );
+ SwNodeIndex aEndIdx( *this, nEndNd+1 );
+
+ SwTableNode * pTblNd = new SwTableNode( aSttIdx );
+ SwEndNode* pEndNd = new SwEndNode( aEndIdx, *pTblNd );
+
+ aEndIdx = *pEndNd;
+
+ /* Set pTblNd as start of section for all nodes in [nSttNd, nEndNd].
+ Delete all Frames attached to the nodes in that range. */
+ SwNode* pNd;
+ {
+ ULONG n, nTmpEnd = aEndIdx.GetIndex();
+ for( n = pTblNd->GetIndex() + 1; n < nTmpEnd; ++n )
+ {
+ if( ( pNd = (*this)[ n ] )->IsCntntNode() )
+ ((SwCntntNode*)pNd)->DelFrms();
+ pNd->pStartOfSection = pTblNd;
+ }
+ }
+
+ // dann die Tabellen Struktur teilweise aufbauen. Erstmal eine Line
+ // in der alle Boxen stehen! Die korrekte Struktur kommt dann aus der
+ // SaveStruct
+ SwTableBoxFmt* pBoxFmt = GetDoc()->MakeTableBoxFmt();
+ SwTableLineFmt* pLineFmt = GetDoc()->MakeTableLineFmt();
+ SwTableLine* pLine = new SwTableLine( pLineFmt, rSavedData.Count(), 0 );
+ pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pLine, 0 );
+
+ SvULongs aBkmkArr( 0, 4 );
+ for( USHORT n = rSavedData.Count(); n; )
+ {
+ SwTblToTxtSave* pSave = rSavedData[ --n ];
+ // if the start node was merged with last from prev. cell,
+ // subtract 1 from index to get the merged paragraph, and split that
+ aSttIdx = pSave->m_nSttNd - ( ( USHRT_MAX != pSave->m_nCntnt ) ? 1 : 0);
+ SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
+
+ if( USHRT_MAX != pSave->m_nCntnt )
+ {
+ // an der ContentPosition splitten, das vorherige Zeichen
+ // loeschen (ist der Trenner!)
+ OSL_ENSURE( pTxtNd, "Wo ist der TextNode geblieben?" );
+ SwIndex aCntPos( pTxtNd, pSave->m_nCntnt - 1 );
+
+ pTxtNd->EraseText( aCntPos, 1 );
+ SwCntntNode* pNewNd = pTxtNd->SplitCntntNode(
+ SwPosition( aSttIdx, aCntPos ));
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( aBkmkArr, *pNewNd, pSave->m_nCntnt,
+ pSave->m_nCntnt + 1 );
+ }
+ else
+ {
+ if( aBkmkArr.Count() )
+ aBkmkArr.Remove( 0, aBkmkArr.Count() );
+ if( pTxtNd )
+ _SaveCntntIdx( GetDoc(), aSttIdx.GetIndex(),
+ pTxtNd->GetTxt().Len(), aBkmkArr );
+ }
+
+ if( pTxtNd )
+ {
+ // METADATA: restore
+ pTxtNd->GetTxtNode()->RestoreMetadata(pSave->m_pMetadataUndoStart);
+ if( pTxtNd->HasSwAttrSet() )
+ pTxtNd->ResetAllAttr();
+
+ if( pTxtNd->GetpSwpHints() )
+ pTxtNd->ClearSwpHintsArr( false );
+ }
+
+ if( pSave->m_pHstry )
+ {
+ USHORT nTmpEnd = pSave->m_pHstry->GetTmpEnd();
+ pSave->m_pHstry->TmpRollback( GetDoc(), 0 );
+ pSave->m_pHstry->SetTmpEnd( nTmpEnd );
+ }
+
+ // METADATA: restore
+ // end points to node after cell
+ if ( pSave->m_nEndNd - 1 > pSave->m_nSttNd )
+ {
+ SwTxtNode* pLastNode = (*this)[ pSave->m_nEndNd - 1 ]->GetTxtNode();
+ if (pLastNode)
+ {
+ pLastNode->RestoreMetadata(pSave->m_pMetadataUndoEnd);
+ }
+ }
+
+ aEndIdx = pSave->m_nEndNd;
+ SwStartNode* pSttNd = new SwStartNode( aSttIdx, ND_STARTNODE,
+ SwTableBoxStartNode );
+ pSttNd->pStartOfSection = pTblNd;
+ new SwEndNode( aEndIdx, *pSttNd );
+
+ for( ULONG i = aSttIdx.GetIndex(); i < aEndIdx.GetIndex()-1; ++i )
+ {
+ pNd = (*this)[ i ];
+ pNd->pStartOfSection = pSttNd;
+ if( pNd->IsStartNode() )
+ i = pNd->EndOfSectionIndex();
+ }
+
+ SwTableBox* pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
+ pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, 0 );
+ }
+ return pTblNd;
+}
+
+
+void SwUndoTblToTxt::Redo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SwPaM* pPam = rUndoIter.pAktPam;
+
+
+ pPam->GetPoint()->nNode = nSttNd;
+ pPam->GetPoint()->nContent.Assign( 0, 0 );
+ SwNodeIndex aSaveIdx( pPam->GetPoint()->nNode, -1 );
+
+ pPam->SetMark(); // alle Indizies abmelden
+ pPam->DeleteMark();
+
+ SwTableNode* pTblNd = pPam->GetNode()->GetTableNode();
+ OSL_ENSURE( pTblNd, "keinen TableNode gefunden" );
+
+ if( pTblNd->GetTable().IsA( TYPE( SwDDETable )) )
+ pDDEFldType = (SwDDEFieldType*)((SwDDETable&)pTblNd->GetTable()).
+ GetDDEFldType()->Copy();
+
+ rDoc.TableToText( pTblNd, cTrenner );
+
+ aSaveIdx++;
+ SwCntntNode* pCNd = aSaveIdx.GetNode().GetCntntNode();
+ if( !pCNd && 0 == ( pCNd = rDoc.GetNodes().GoNext( &aSaveIdx ) ) &&
+ 0 == ( pCNd = rDoc.GetNodes().GoPrevious( &aSaveIdx )) )
+ {
+ OSL_ENSURE( FALSE, "wo steht denn nun der TextNode" );
+ }
+
+ pPam->GetPoint()->nNode = aSaveIdx;
+ pPam->GetPoint()->nContent.Assign( pCNd, 0 );
+
+ pPam->SetMark(); // alle Indizies abmelden
+ pPam->DeleteMark();
+}
+
+
+void SwUndoTblToTxt::Repeat( SwUndoIter& rUndoIter )
+{
+ SwTableNode* pTblNd = rUndoIter.pAktPam->GetNode()->FindTableNode();
+ if( pTblNd )
+ {
+ // bewege den Cursor aus der Tabelle
+ SwPaM* pPam = rUndoIter.pAktPam;
+ pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
+ pPam->Move( fnMoveForward, fnGoCntnt );
+ pPam->SetMark();
+ pPam->DeleteMark();
+
+ rUndoIter.GetDoc().TableToText( pTblNd, cTrenner );
+ }
+}
+
+void SwUndoTblToTxt::SetRange( const SwNodeRange& rRg )
+{
+ nSttNd = rRg.aStart.GetIndex();
+ nEndNd = rRg.aEnd.GetIndex();
+}
+
+void SwUndoTblToTxt::AddBoxPos( SwDoc& rDoc, ULONG nNdIdx, ULONG nEndIdx, xub_StrLen nCntntIdx )
+{
+ SwTblToTxtSave* pNew = new SwTblToTxtSave( rDoc, nNdIdx, nEndIdx, nCntntIdx );
+ pBoxSaves->Insert( pNew, pBoxSaves->Count() );
+}
+
+// -----------------------------------------------------
+
+SwUndoTxtToTbl::SwUndoTxtToTbl( const SwPaM& rRg,
+ const SwInsertTableOptions& rInsTblOpts,
+ sal_Unicode cCh, USHORT nAdj,
+ const SwTableAutoFmt* pAFmt )
+ : SwUndo( UNDO_TEXTTOTABLE ), SwUndRng( rRg ), aInsTblOpts( rInsTblOpts ),
+ pDelBoxes( 0 ), pAutoFmt( 0 ),
+ pHistory( 0 ), cTrenner( cCh ), nAdjust( nAdj )
+{
+ if( pAFmt )
+ pAutoFmt = new SwTableAutoFmt( *pAFmt );
+
+ const SwPosition* pEnd = rRg.End();
+ SwNodes& rNds = rRg.GetDoc()->GetNodes();
+ bSplitEnd = pEnd->nContent.GetIndex() && ( pEnd->nContent.GetIndex()
+ != pEnd->nNode.GetNode().GetCntntNode()->Len() ||
+ pEnd->nNode.GetIndex() >= rNds.GetEndOfContent().GetIndex()-1 );
+}
+
+SwUndoTxtToTbl::~SwUndoTxtToTbl()
+{
+ delete pDelBoxes;
+ delete pAutoFmt;
+}
+
+void SwUndoTxtToTbl::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ ULONG nTblNd = nSttNode;
+ if( nSttCntnt )
+ ++nTblNd; // Node wurde vorher gesplittet
+ SwNodeIndex aIdx( rDoc.GetNodes(), nTblNd );
+ SwTableNode* pTNd = rDoc.GetNodes()[ aIdx ]->GetTableNode();
+ OSL_ENSURE( pTNd, "keinen Tabellen-Node gefunden" );
+
+ RemoveIdxFromSection( rDoc, nTblNd );
+
+ sTblNm = pTNd->GetTable().GetFrmFmt()->GetName();
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+
+ if( pDelBoxes )
+ {
+ SwTable& rTbl = pTNd->GetTable();
+ for( USHORT n = pDelBoxes->Count(); n; )
+ {
+ SwTableBox* pBox = rTbl.GetTblBox( (*pDelBoxes)[ --n ] );
+ if( pBox )
+ ::_DeleteBox( rTbl, pBox, 0, FALSE, FALSE );
+ else {
+ OSL_ENSURE( !this, "Wo ist die Box geblieben?" );
+ }
+ }
+ }
+
+ SwNodeIndex aEndIdx( *pTNd->EndOfSectionNode() );
+ rDoc.TableToText( pTNd, 0x0b == cTrenner ? 0x09 : cTrenner );
+
+ // am Start wieder zusammenfuegen ?
+ SwPosition* pPos = rUndoIter.pAktPam->GetPoint();
+ if( nSttCntnt )
+ {
+ pPos->nNode = nTblNd;
+ pPos->nContent.Assign( rDoc.GetNodes()[ pPos->nNode ]->GetCntntNode(), 0 );
+ if( rUndoIter.pAktPam->Move( fnMoveBackward, fnGoCntnt))
+ {
+ SwNodeIndex& rIdx = rUndoIter.pAktPam->GetPoint()->nNode;
+
+ // dann die Crsr/etc. nochmal relativ verschieben
+ RemoveIdxRel( rIdx.GetIndex()+1, *pPos );
+
+ rIdx.GetNode().GetCntntNode()->JoinNext();
+ }
+ }
+
+ // am Ende wieder zusammenfuegen ?
+ if( bSplitEnd )
+ {
+ SwNodeIndex& rIdx = pPos->nNode;
+ rIdx = nEndNode;
+ SwTxtNode* pTxtNd = rIdx.GetNode().GetTxtNode();
+ if( pTxtNd && pTxtNd->CanJoinNext() )
+ {
+ rUndoIter.pAktPam->GetMark()->nContent.Assign( 0, 0 );
+ rUndoIter.pAktPam->GetPoint()->nContent.Assign( 0, 0 );
+
+ // dann die Crsr/etc. nochmal relativ verschieben
+ pPos->nContent.Assign( pTxtNd, pTxtNd->GetTxt().Len() );
+ RemoveIdxRel( nEndNode + 1, *pPos );
+
+ pTxtNd->JoinNext();
+ }
+ }
+
+ SetPaM( rUndoIter ); // manipulierten Bereich selectieren
+}
+
+
+void SwUndoTxtToTbl::Redo( SwUndoIter& rUndoIter )
+{
+ SetPaM( rUndoIter );
+ RemoveIdxFromRange( *rUndoIter.pAktPam, FALSE );
+ SetPaM( rUndoIter );
+
+ const SwTable* pTable = rUndoIter.GetDoc().TextToTable(
+ aInsTblOpts, *rUndoIter.pAktPam, cTrenner,
+ nAdjust, pAutoFmt );
+ ((SwFrmFmt*)pTable->GetFrmFmt())->SetName( sTblNm );
+}
+
+
+void SwUndoTxtToTbl::Repeat( SwUndoIter& rUndoIter )
+{
+ // keine TABLE IN TABLE
+ if( !rUndoIter.pAktPam->GetNode()->FindTableNode() )
+ rUndoIter.GetDoc().TextToTable( aInsTblOpts, *rUndoIter.pAktPam,
+ cTrenner, nAdjust,
+ pAutoFmt );
+}
+
+void SwUndoTxtToTbl::AddFillBox( const SwTableBox& rBox )
+{
+ if( !pDelBoxes )
+ pDelBoxes = new SvULongs;
+ pDelBoxes->Insert( rBox.GetSttIdx(), pDelBoxes->Count() );
+}
+
+SwHistory& SwUndoTxtToTbl::GetHistory()
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+ return *pHistory;
+}
+
+// -----------------------------------------------------
+
+SwUndoTblHeadline::SwUndoTblHeadline( const SwTable& rTbl, USHORT nOldHdl,
+ USHORT nNewHdl )
+ : SwUndo( UNDO_TABLEHEADLINE ),
+ nOldHeadline( nOldHdl ),
+ nNewHeadline( nNewHdl )
+{
+ OSL_ENSURE( rTbl.GetTabSortBoxes().Count(), "Tabelle ohne Inhalt" );
+ const SwStartNode *pSttNd = rTbl.GetTabSortBoxes()[ 0 ]->GetSttNd();
+ OSL_ENSURE( pSttNd, "Box ohne Inhalt" );
+
+ nTblNd = pSttNd->StartOfSectionIndex();
+}
+
+
+void SwUndoTblHeadline::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
+ OSL_ENSURE( pTNd, "keinen Tabellen-Node gefunden" );
+
+ rDoc.SetRowsToRepeat( pTNd->GetTable(), nOldHeadline );
+}
+
+
+void SwUndoTblHeadline::Redo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
+ OSL_ENSURE( pTNd, "keinen Tabellen-Node gefunden" );
+
+ rDoc.SetRowsToRepeat( pTNd->GetTable(), nNewHeadline );
+}
+
+
+void SwUndoTblHeadline::Repeat( SwUndoIter& rUndoIter )
+{
+ SwTableNode* pTblNd = rUndoIter.pAktPam->GetNode()->FindTableNode();
+ if( pTblNd )
+ rUndoIter.GetDoc().SetRowsToRepeat( pTblNd->GetTable(), nNewHeadline );
+}
+
+
+/* */
+
+
+
+_SaveTable::_SaveTable( const SwTable& rTbl, USHORT nLnCnt, BOOL bSaveFml )
+ : aTblSet( *rTbl.GetFrmFmt()->GetAttrSet().GetPool(), aTableSetRange ),
+ pSwTable( &rTbl ), nLineCount( nLnCnt ), bSaveFormula( bSaveFml )
+{
+ bModifyBox = FALSE;
+ bNewModel = rTbl.IsNewModel();
+ aTblSet.Put( rTbl.GetFrmFmt()->GetAttrSet() );
+ pLine = new _SaveLine( 0, *rTbl.GetTabLines()[ 0 ], *this );
+
+ _SaveLine* pLn = pLine;
+ if( USHRT_MAX == nLnCnt )
+ nLnCnt = rTbl.GetTabLines().Count();
+ for( USHORT n = 1; n < nLnCnt; ++n )
+ pLn = new _SaveLine( pLn, *rTbl.GetTabLines()[ n ], *this );
+
+ aFrmFmts.Remove( 0, aFrmFmts.Count() );
+ pSwTable = 0;
+}
+
+
+_SaveTable::~_SaveTable()
+{
+ delete pLine;
+}
+
+
+USHORT _SaveTable::AddFmt( SwFrmFmt* pFmt, bool bIsLine )
+{
+ USHORT nRet = aFrmFmts.GetPos( pFmt );
+ if( USHRT_MAX == nRet )
+ {
+ // Kopie vom ItemSet anlegen
+ SfxItemSet* pSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
+ bIsLine ? aTableLineSetRange : aTableBoxSetRange );
+ pSet->Put( pFmt->GetAttrSet() );
+ //JP 20.04.98: Bug 49502 - wenn eine Formel gesetzt ist, nie den
+ // Value mit sichern. Der muss gegebenfalls neu
+ // errechnet werden!
+ //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_BOXATR_FORMULA, TRUE, &pItem ))
+ {
+ pSet->ClearItem( RES_BOXATR_VALUE );
+ if( pSwTable && bSaveFormula )
+ {
+ SwTableFmlUpdate aMsgHnt( pSwTable );
+ aMsgHnt.eFlags = TBL_BOXNAME;
+ ((SwTblBoxFormula*)pItem)->ChgDefinedIn( pFmt );
+ ((SwTblBoxFormula*)pItem)->ChangeState( &aMsgHnt );
+ ((SwTblBoxFormula*)pItem)->ChgDefinedIn( 0 );
+ }
+ }
+ aSets.Insert( pSet, (nRet = aSets.Count() ) );
+ aFrmFmts.Insert( pFmt, nRet );
+ }
+ return nRet;
+}
+
+
+void _SaveTable::RestoreAttr( SwTable& rTbl, BOOL bMdfyBox )
+{
+ USHORT n;
+
+ bModifyBox = bMdfyBox;
+
+ // zuerst die Attribute des TabellenFrmFormates zurueck holen
+ SwFrmFmt* pFmt = rTbl.GetFrmFmt();
+ SfxItemSet& rFmtSet = (SfxItemSet&)pFmt->GetAttrSet();
+ rFmtSet.ClearItem();
+ rFmtSet.Put( aTblSet );
+
+ if( pFmt->IsInCache() )
+ {
+ SwFrm::GetCache().Delete( pFmt );
+ pFmt->SetInCache( FALSE );
+ }
+
+ // zur Sicherheit alle Tableframes invalidieren
+ SwClientIter aIter( *pFmt );
+ for( SwClient* pLast = aIter.First( TYPE( SwFrm ) ); pLast; pLast = aIter.Next() )
+ if( ((SwTabFrm*)pLast)->GetTable() == &rTbl )
+ {
+ ((SwTabFrm*)pLast)->InvalidateAll();
+ ((SwTabFrm*)pLast)->SetCompletePaint();
+ }
+
+ // FrmFmts mit Defaults (0) fuellen
+ pFmt = 0;
+ for( n = aSets.Count(); n; --n )
+ aFrmFmts.Insert( pFmt, aFrmFmts.Count() );
+
+ USHORT nLnCnt = nLineCount;
+ if( USHRT_MAX == nLnCnt )
+ nLnCnt = rTbl.GetTabLines().Count();
+
+ _SaveLine* pLn = pLine;
+ for( n = 0; n < nLnCnt; ++n, pLn = pLn->pNext )
+ {
+ if( !pLn )
+ {
+ OSL_ENSURE( !this, "Anzahl der Lines hat sich veraendert" );
+ break;
+ }
+
+ pLn->RestoreAttr( *rTbl.GetTabLines()[ n ], *this );
+ }
+
+ aFrmFmts.Remove( 0, aFrmFmts.Count() );
+ bModifyBox = FALSE;
+}
+
+
+void _SaveTable::SaveCntntAttrs( SwDoc* pDoc )
+{
+ pLine->SaveCntntAttrs( pDoc );
+}
+
+
+void _SaveTable::CreateNew( SwTable& rTbl, BOOL bCreateFrms,
+ BOOL bRestoreChart )
+{
+ USHORT n;
+
+ _FndBox aTmpBox( 0, 0 );
+ //if( bRestoreChart )
+ // // ? TL_CHART2: notification or locking of controller required ?
+ aTmpBox.DelFrms( rTbl );
+
+ // zuerst die Attribute des TabellenFrmFormates zurueck holen
+ SwFrmFmt* pFmt = rTbl.GetFrmFmt();
+ SfxItemSet& rFmtSet = (SfxItemSet&)pFmt->GetAttrSet();
+ rFmtSet.ClearItem();
+ rFmtSet.Put( aTblSet );
+
+ if( pFmt->IsInCache() )
+ {
+ SwFrm::GetCache().Delete( pFmt );
+ pFmt->SetInCache( FALSE );
+ }
+
+ // SwTableBox muss ein Format haben!!
+ SwTableBox aParent( (SwTableBoxFmt*)pFmt, rTbl.GetTabLines().Count(), 0 );
+
+ // FrmFmts mit Defaults (0) fuellen
+ pFmt = 0;
+ for( n = aSets.Count(); n; --n )
+ aFrmFmts.Insert( pFmt, aFrmFmts.Count() );
+
+ pLine->CreateNew( rTbl, aParent, *this );
+ aFrmFmts.Remove( 0, aFrmFmts.Count() );
+
+ // die neuen Lines eintragen, die alten loeschen
+ USHORT nOldLines = nLineCount;
+ if( USHRT_MAX == nLineCount )
+ nOldLines = rTbl.GetTabLines().Count();
+
+ SwDoc *pDoc = rTbl.GetFrmFmt()->GetDoc();
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ for( n = 0; n < aParent.GetTabLines().Count(); ++n )
+ {
+ SwTableLine* pLn = aParent.GetTabLines()[ n ];
+ pLn->SetUpper( 0 );
+ if( n < nOldLines )
+ {
+ SwTableLine* pOld = rTbl.GetTabLines()[ n ];
+
+ // TL_CHART2: notify chart about boxes to be removed
+ const SwTableBoxes &rBoxes = pOld->GetTabBoxes();
+ USHORT nBoxes = rBoxes.Count();
+ for (USHORT k = 0; k < nBoxes; ++k)
+ {
+ SwTableBox *pBox = rBoxes[k];
+ if (pPCD)
+ pPCD->DeleteBox( &rTbl, *pBox );
+ }
+
+ rTbl.GetTabLines().C40_REPLACE( SwTableLine, pLn, n );
+ delete pOld;
+ }
+ else
+ rTbl.GetTabLines().C40_INSERT( SwTableLine, pLn, n );
+ }
+
+ if( n < nOldLines )
+ {
+ // remove remaining lines...
+
+ for (USHORT k1 = 0; k1 < nOldLines - n; ++k1)
+ {
+ const SwTableBoxes &rBoxes = rTbl.GetTabLines()[n + k1]->GetTabBoxes();
+ USHORT nBoxes = rBoxes.Count();
+ for (USHORT k2 = 0; k2 < nBoxes; ++k2)
+ {
+ SwTableBox *pBox = rBoxes[k2];
+ // TL_CHART2: notify chart about boxes to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &rTbl, *pBox );
+ }
+ }
+
+ rTbl.GetTabLines().DeleteAndDestroy( n, nOldLines - n );
+ }
+
+ aParent.GetTabLines().Remove( 0, n );
+
+ if( bCreateFrms )
+ aTmpBox.MakeFrms( rTbl );
+ if( bRestoreChart )
+ {
+ // TL_CHART2: need to inform chart of probably changed cell names
+ pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
+ }
+}
+
+
+void _SaveTable::NewFrmFmt( const SwClient* pLnBx, BOOL bIsLine,
+ USHORT nFmtPos, SwFrmFmt* pOldFmt )
+{
+ SwDoc* pDoc = pOldFmt->GetDoc();
+
+ SwFrmFmt* pFmt = aFrmFmts[ nFmtPos ];
+ if( !pFmt )
+ {
+ if( bIsLine )
+ pFmt = pDoc->MakeTableLineFmt();
+ else
+ pFmt = pDoc->MakeTableBoxFmt();
+ pFmt->SetFmtAttr( *aSets[ nFmtPos ] );
+ aFrmFmts.Replace( pFmt, nFmtPos );
+ }
+
+ //Erstmal die Frms ummelden.
+ SwClientIter aIter( *pOldFmt );
+ for( SwClient* pLast = aIter.First( TYPE( SwFrm ) ); pLast; pLast = aIter.Next() )
+ {
+ if( bIsLine ? pLnBx == ((SwRowFrm*)pLast)->GetTabLine()
+ : pLnBx == ((SwCellFrm*)pLast)->GetTabBox() )
+ {
+ pFmt->Add( pLast );
+ ((SwFrm*)pLast)->InvalidateAll();
+ ((SwFrm*)pLast)->ReinitializeFrmSizeAttrFlags();
+ if ( !bIsLine )
+ {
+ ((SwCellFrm*)pLast)->SetDerivedVert( FALSE );
+ ((SwCellFrm*)pLast)->CheckDirChange();
+ }
+ }
+ }
+
+ //Jetzt noch mich selbst ummelden.
+ pFmt->Add( (SwClient*)pLnBx );
+
+ if( bModifyBox && !bIsLine )
+ {
+ const SfxPoolItem& rOld = pOldFmt->GetFmtAttr( RES_BOXATR_FORMAT ),
+ & rNew = pFmt->GetFmtAttr( RES_BOXATR_FORMAT );
+ if( rOld != rNew )
+ pFmt->Modify( (SfxPoolItem*)&rOld, (SfxPoolItem*)&rNew );
+ }
+
+ if( !pOldFmt->GetDepends() )
+ delete pOldFmt;
+
+}
+
+
+_SaveLine::_SaveLine( _SaveLine* pPrev, const SwTableLine& rLine, _SaveTable& rSTbl )
+ : pNext( 0 )
+{
+ if( pPrev )
+ pPrev->pNext = this;
+
+ nItemSet = rSTbl.AddFmt( rLine.GetFrmFmt(), true );
+
+ pBox = new _SaveBox( 0, *rLine.GetTabBoxes()[ 0 ], rSTbl );
+ _SaveBox* pBx = pBox;
+ for( USHORT n = 1; n < rLine.GetTabBoxes().Count(); ++n )
+ pBx = new _SaveBox( pBx, *rLine.GetTabBoxes()[ n ], rSTbl );
+}
+
+
+_SaveLine::~_SaveLine()
+{
+ delete pBox;
+ delete pNext;
+}
+
+
+void _SaveLine::RestoreAttr( SwTableLine& rLine, _SaveTable& rSTbl )
+{
+ rSTbl.NewFrmFmt( &rLine, TRUE, nItemSet, rLine.GetFrmFmt() );
+
+ _SaveBox* pBx = pBox;
+ for( USHORT n = 0; n < rLine.GetTabBoxes().Count(); ++n, pBx = pBx->pNext )
+ {
+ if( !pBx )
+ {
+ OSL_ENSURE( !this, "Anzahl der Boxen hat sich veraendert" );
+ break;
+ }
+ pBx->RestoreAttr( *rLine.GetTabBoxes()[ n ], rSTbl );
+ }
+}
+
+
+void _SaveLine::SaveCntntAttrs( SwDoc* pDoc )
+{
+ pBox->SaveCntntAttrs( pDoc );
+ if( pNext )
+ pNext->SaveCntntAttrs( pDoc );
+}
+
+
+void _SaveLine::CreateNew( SwTable& rTbl, SwTableBox& rParent, _SaveTable& rSTbl )
+{
+ SwTableLineFmt* pFmt = (SwTableLineFmt*)rSTbl.aFrmFmts[ nItemSet ];
+ if( !pFmt )
+ {
+ SwDoc* pDoc = rTbl.GetFrmFmt()->GetDoc();
+ pFmt = pDoc->MakeTableLineFmt();
+ pFmt->SetFmtAttr( *rSTbl.aSets[ nItemSet ] );
+ rSTbl.aFrmFmts.Replace( pFmt, nItemSet );
+ }
+ SwTableLine* pNew = new SwTableLine( pFmt, 1, &rParent );
+
+ rParent.GetTabLines().C40_INSERT( SwTableLine, pNew, rParent.GetTabLines().Count() );
+
+ // HB, #127868# robustness: in some cases - which I
+ // cannot reproduce nor see from the code - pNew seems
+ // to be set to NULL in C40_INSERT.
+ OSL_ENSURE(pNew, "Table line just created set to NULL in C40_INSERT");
+
+ if (pNew)
+ {
+ pBox->CreateNew( rTbl, *pNew, rSTbl );
+ }
+
+ if( pNext )
+ pNext->CreateNew( rTbl, rParent, rSTbl );
+}
+
+
+_SaveBox::_SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl )
+ : pNext( 0 ), nSttNode( ULONG_MAX ), nRowSpan(0)
+{
+ Ptrs.pLine = 0;
+
+ if( pPrev )
+ pPrev->pNext = this;
+
+ nItemSet = rSTbl.AddFmt( rBox.GetFrmFmt(), false );
+
+ if( rBox.GetSttNd() )
+ {
+ nSttNode = rBox.GetSttIdx();
+ nRowSpan = rBox.getRowSpan();
+ }
+ else
+ {
+ Ptrs.pLine = new _SaveLine( 0, *rBox.GetTabLines()[ 0 ], rSTbl );
+
+ _SaveLine* pLn = Ptrs.pLine;
+ for( USHORT n = 1; n < rBox.GetTabLines().Count(); ++n )
+ pLn = new _SaveLine( pLn, *rBox.GetTabLines()[ n ], rSTbl );
+ }
+}
+
+
+_SaveBox::~_SaveBox()
+{
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ delete Ptrs.pLine;
+ else
+ delete Ptrs.pCntntAttrs;
+ delete pNext;
+}
+
+
+void _SaveBox::RestoreAttr( SwTableBox& rBox, _SaveTable& rSTbl )
+{
+ rSTbl.NewFrmFmt( &rBox, FALSE, nItemSet, rBox.GetFrmFmt() );
+
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ {
+ if( !rBox.GetTabLines().Count() )
+ {
+ OSL_ENSURE( !this, "Anzahl der Lines hat sich veraendert" );
+ }
+ else
+ {
+ _SaveLine* pLn = Ptrs.pLine;
+ for( USHORT n = 0; n < rBox.GetTabLines().Count(); ++n, pLn = pLn->pNext )
+ {
+ if( !pLn )
+ {
+ OSL_ENSURE( !this, "Anzahl der Lines hat sich veraendert" );
+ break;
+ }
+
+ pLn->RestoreAttr( *rBox.GetTabLines()[ n ], rSTbl );
+ }
+ }
+ }
+ else if( rBox.GetSttNd() && rBox.GetSttIdx() == nSttNode )
+ {
+ if( Ptrs.pCntntAttrs )
+ {
+ SwNodes& rNds = rBox.GetFrmFmt()->GetDoc()->GetNodes();
+ USHORT nSet = 0;
+ ULONG nEnd = rBox.GetSttNd()->EndOfSectionIndex();
+ for( ULONG n = nSttNode + 1; n < nEnd; ++n )
+ {
+ SwCntntNode* pCNd = rNds[ n ]->GetCntntNode();
+ if( pCNd )
+ {
+ SfxItemSet* pSet = (*Ptrs.pCntntAttrs)[ nSet++ ];
+ if( pSet )
+ {
+ USHORT *pRstAttr = aSave_BoxCntntSet;
+ while( *pRstAttr )
+ {
+ pCNd->ResetAttr( *pRstAttr, *(pRstAttr+1) );
+ pRstAttr += 2;
+ }
+ pCNd->SetAttr( *pSet );
+ }
+ else
+ pCNd->ResetAllAttr();
+ }
+ }
+ }
+ }
+ else
+ {
+ OSL_ENSURE( !this, "Box nicht mehr am gleichen Node" );
+ }
+}
+
+
+void _SaveBox::SaveCntntAttrs( SwDoc* pDoc )
+{
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ {
+ // weiter in der Line
+ Ptrs.pLine->SaveCntntAttrs( pDoc );
+ }
+ else
+ {
+ ULONG nEnd = pDoc->GetNodes()[ nSttNode ]->EndOfSectionIndex();
+ Ptrs.pCntntAttrs = new SfxItemSets( (BYTE)(nEnd - nSttNode - 1 ), 5 );
+ for( ULONG n = nSttNode + 1; n < nEnd; ++n )
+ {
+ SwCntntNode* pCNd = pDoc->GetNodes()[ n ]->GetCntntNode();
+ if( pCNd )
+ {
+ SfxItemSet* pSet = 0;
+ if( pCNd->HasSwAttrSet() )
+ {
+ pSet = new SfxItemSet( pDoc->GetAttrPool(),
+ aSave_BoxCntntSet );
+ pSet->Put( *pCNd->GetpSwAttrSet() );
+ }
+
+ Ptrs.pCntntAttrs->Insert( pSet, Ptrs.pCntntAttrs->Count() );
+ }
+ }
+ }
+ if( pNext )
+ pNext->SaveCntntAttrs( pDoc );
+}
+
+
+void _SaveBox::CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl )
+{
+ SwTableBoxFmt* pFmt = (SwTableBoxFmt*)rSTbl.aFrmFmts[ nItemSet ];
+ if( !pFmt )
+ {
+ SwDoc* pDoc = rTbl.GetFrmFmt()->GetDoc();
+ pFmt = pDoc->MakeTableBoxFmt();
+ pFmt->SetFmtAttr( *rSTbl.aSets[ nItemSet ] );
+ rSTbl.aFrmFmts.Replace( pFmt, nItemSet );
+ }
+
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ {
+ SwTableBox* pNew = new SwTableBox( pFmt, 1, &rParent );
+ rParent.GetTabBoxes().C40_INSERT( SwTableBox, pNew, rParent.GetTabBoxes().Count() );
+
+ Ptrs.pLine->CreateNew( rTbl, *pNew, rSTbl );
+ }
+ else
+ {
+ // Box zum StartNode in der alten Tabelle suchen
+ SwTableBox* pBox = rTbl.GetTblBox( nSttNode );
+ OSL_ENSURE( pBox, "Wo ist meine TabellenBox geblieben?" );
+
+ SwFrmFmt* pOld = pBox->GetFrmFmt();
+ pFmt->Add( pBox );
+ if( !pOld->GetDepends() )
+ delete pOld;
+
+ pBox->setRowSpan( nRowSpan );
+
+ SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
+ pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) );
+
+ pBox->SetUpper( &rParent );
+ pTBoxes = &rParent.GetTabBoxes();
+ pTBoxes->C40_INSERT( SwTableBox, pBox, pTBoxes->Count() );
+ }
+
+ if( pNext )
+ pNext->CreateNew( rTbl, rParent, rSTbl );
+}
+
+
+/* */
+
+// UndoObject fuer Attribut Aenderung an der Tabelle
+
+
+SwUndoAttrTbl::SwUndoAttrTbl( const SwTableNode& rTblNd, BOOL bClearTabCols )
+ : SwUndo( UNDO_TABLE_ATTR ),
+ nSttNode( rTblNd.GetIndex() )
+{
+ bClearTabCol = bClearTabCols;
+ pSaveTbl = new _SaveTable( rTblNd.GetTable() );
+}
+
+
+SwUndoAttrTbl::~SwUndoAttrTbl()
+{
+ delete pSaveTbl;
+}
+
+
+
+void SwUndoAttrTbl::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ if (pTblNd)
+ {
+ _SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() );
+ pSaveTbl->RestoreAttr( pTblNd->GetTable() );
+ delete pSaveTbl;
+ pSaveTbl = pOrig;
+ }
+
+ if( bClearTabCol )
+ ClearFEShellTabCols();
+}
+
+
+void SwUndoAttrTbl::Redo( SwUndoIter& rUndoIter )
+{
+ Undo( rUndoIter );
+}
+
+
+/* */
+
+// UndoObject fuer AutoFormat an der Tabelle
+
+
+SwUndoTblAutoFmt::SwUndoTblAutoFmt( const SwTableNode& rTblNd,
+ const SwTableAutoFmt& rAFmt )
+ : SwUndo( UNDO_TABLE_AUTOFMT ),
+ nSttNode( rTblNd.GetIndex() ), pUndos( 0 ),
+ bSaveCntntAttr( FALSE )
+{
+ pSaveTbl = new _SaveTable( rTblNd.GetTable() );
+
+ if( rAFmt.IsFont() || rAFmt.IsJustify() )
+ {
+ // dann auch noch ueber die ContentNodes der EndBoxen und
+ // und alle Absatz-Attribute zusammen sammeln
+ pSaveTbl->SaveCntntAttrs( (SwDoc*)rTblNd.GetDoc() );
+ bSaveCntntAttr = TRUE;
+ }
+}
+
+
+SwUndoTblAutoFmt::~SwUndoTblAutoFmt()
+{
+ delete pUndos;
+ delete pSaveTbl;
+}
+
+void SwUndoTblAutoFmt::SaveBoxCntnt( const SwTableBox& rBox )
+{
+ SwUndoTblNumFmt* p = new SwUndoTblNumFmt( rBox );
+ if( !pUndos )
+ pUndos = new SwUndos( 8, 8 );
+ pUndos->Insert( p, pUndos->Count() );
+}
+
+
+void SwUndoTblAutoFmt::UndoRedo( BOOL bUndo, SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ _SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() );
+ // dann auch noch ueber die ContentNodes der EndBoxen und
+ // und alle Absatz-Attribute zusammen sammeln
+ if( bSaveCntntAttr )
+ pOrig->SaveCntntAttrs( &rDoc );
+
+ if( pUndos && bUndo )
+ for( USHORT n = pUndos->Count(); n; )
+ pUndos->GetObject( --n )->Undo( rUndoIter );
+
+ pSaveTbl->RestoreAttr( pTblNd->GetTable(), !bUndo );
+ delete pSaveTbl;
+ pSaveTbl = pOrig;
+}
+
+void SwUndoTblAutoFmt::Undo( SwUndoIter& rUndoIter )
+{
+ UndoRedo( TRUE, rUndoIter );
+}
+
+
+void SwUndoTblAutoFmt::Redo( SwUndoIter& rUndoIter )
+{
+ UndoRedo( FALSE, rUndoIter );
+}
+
+
+/* */
+
+
+SwUndoTblNdsChg::SwUndoTblNdsChg( SwUndoId nAction,
+ const SwSelBoxes& rBoxes,
+ const SwTableNode& rTblNd,
+ long nMn, long nMx,
+ USHORT nCnt, BOOL bFlg, BOOL bSmHght )
+ : SwUndo( nAction ),
+ aBoxes( rBoxes.Count() < 255 ? (BYTE)rBoxes.Count() : 255, 10 ),
+ nMin( nMn ), nMax( nMx ),
+ nSttNode( rTblNd.GetIndex() ), nCurrBox( 0 ),
+ nCount( nCnt ), nRelDiff( 0 ), nAbsDiff( 0 ),
+ nSetColType( USHRT_MAX ),
+ bFlag( bFlg ),
+ bSameHeight( bSmHght )
+{
+ Ptrs.pNewSttNds = 0;
+
+ const SwTable& rTbl = rTblNd.GetTable();
+ pSaveTbl = new _SaveTable( rTbl );
+
+ // und die Selektion merken
+ for( USHORT n = 0; n < rBoxes.Count(); ++n )
+ aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
+}
+
+
+SwUndoTblNdsChg::SwUndoTblNdsChg( SwUndoId nAction,
+ const SwSelBoxes& rBoxes,
+ const SwTableNode& rTblNd )
+ : SwUndo( nAction ),
+ aBoxes( rBoxes.Count() < 255 ? (BYTE)rBoxes.Count() : 255, 10 ),
+ nMin( 0 ), nMax( 0 ),
+ nSttNode( rTblNd.GetIndex() ), nCurrBox( 0 ),
+ nCount( 0 ), nRelDiff( 0 ), nAbsDiff( 0 ),
+ nSetColType( USHRT_MAX ),
+ bFlag( FALSE ),
+ bSameHeight( FALSE )
+{
+ Ptrs.pNewSttNds = 0;
+
+ const SwTable& rTbl = rTblNd.GetTable();
+ pSaveTbl = new _SaveTable( rTbl );
+
+ // und die Selektion merken
+ for( USHORT n = 0; n < rBoxes.Count(); ++n )
+ aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
+}
+
+void SwUndoTblNdsChg::ReNewBoxes( const SwSelBoxes& rBoxes )
+{
+ if( rBoxes.Count() != aBoxes.Count() )
+ {
+ aBoxes.Remove( 0, aBoxes.Count() );
+ for( USHORT n = 0; n < rBoxes.Count(); ++n )
+ aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
+ }
+}
+
+SwUndoTblNdsChg::~SwUndoTblNdsChg()
+{
+ delete pSaveTbl;
+
+ if( IsDelBox() )
+ delete Ptrs.pDelSects;
+ else
+ delete Ptrs.pNewSttNds;
+}
+
+void SwUndoTblNdsChg::SaveNewBoxes( const SwTableNode& rTblNd,
+ const SwTableSortBoxes& rOld )
+{
+ const SwTable& rTbl = rTblNd.GetTable();
+ const SwTableSortBoxes& rTblBoxes = rTbl.GetTabSortBoxes();
+ USHORT n;
+ USHORT i;
+
+ OSL_ENSURE( ! IsDelBox(), "falsche Action" );
+ Ptrs.pNewSttNds = new SvULongs( (BYTE)(rTblBoxes.Count() - rOld.Count()), 5 );
+
+ for( n = 0, i = 0; n < rOld.Count(); ++i )
+ {
+ if( rOld[ n ] == rTblBoxes[ i ] )
+ ++n;
+ else
+ // neue Box: sortiert einfuegen!!
+ InsertSort( *Ptrs.pNewSttNds, rTblBoxes[ i ]->GetSttIdx() );
+ }
+
+ for( ; i < rTblBoxes.Count(); ++i )
+ // neue Box: sortiert einfuegen!!
+ InsertSort( *Ptrs.pNewSttNds, rTblBoxes[ i ]->GetSttIdx() );
+}
+
+
+SwTableLine* lcl_FindTableLine( const SwTable& rTable,
+ const SwTableBox& rBox )
+{
+ SwTableLine* pRet = NULL;
+ // i63949: For nested cells we have to take nLineNo - 1, too, not 0!
+ const SwTableLines &rTableLines = ( rBox.GetUpper()->GetUpper() != NULL ) ?
+ rBox.GetUpper()->GetUpper()->GetTabLines()
+ : rTable.GetTabLines();
+ const SwTableLine* pLine = rBox.GetUpper();
+ USHORT nLineNo = rTableLines.C40_GETPOS( SwTableLine, pLine );
+ pRet = rTableLines[nLineNo - 1];
+
+ return pRet;
+}
+
+const SwTableLines& lcl_FindParentLines( const SwTable& rTable,
+ const SwTableBox& rBox )
+{
+ const SwTableLines& rRet =
+ ( rBox.GetUpper()->GetUpper() != NULL ) ?
+ rBox.GetUpper()->GetUpper()->GetTabLines() :
+ rTable.GetTabLines();
+
+ return rRet;
+}
+
+
+void SwUndoTblNdsChg::SaveNewBoxes( const SwTableNode& rTblNd,
+ const SwTableSortBoxes& rOld,
+ const SwSelBoxes& rBoxes,
+ const SvULongs& rNodeCnts )
+{
+ const SwTable& rTbl = rTblNd.GetTable();
+ const SwTableSortBoxes& rTblBoxes = rTbl.GetTabSortBoxes();
+
+ OSL_ENSURE( ! IsDelBox(), "falsche Action" );
+ Ptrs.pNewSttNds = new SvULongs( (BYTE)(rTblBoxes.Count() - rOld.Count()), 5 );
+
+ OSL_ENSURE( rTbl.IsNewModel() || rOld.Count() + nCount * rBoxes.Count() == rTblBoxes.Count(),
+ "unexpected boxes" );
+ OSL_ENSURE( rOld.Count() <= rTblBoxes.Count(), "more unexpected boxes" );
+ for( USHORT n = 0, i = 0; i < rTblBoxes.Count(); ++i )
+ {
+ if( ( n < rOld.Count() ) &&
+ ( rOld[ n ] == rTblBoxes[ i ] ) )
+ {
+ // box already known? Then nothing to be done.
+ ++n;
+ }
+ else
+ {
+ // new box found: insert (obey sort order)
+ USHORT nInsPos;
+ const SwTableBox* pBox = rTblBoxes[ i ];
+ InsertSort( *Ptrs.pNewSttNds, pBox->GetSttIdx(), &nInsPos );
+
+ // find the source box. It must be one in rBoxes.
+ // We found the right one if it's in the same column as pBox.
+ // No, if more than one selected cell in the same column has been splitted,
+ // we have to look for the nearest one (i65201)!
+ const SwTableBox* pSourceBox = NULL;
+ const SwTableBox* pCheckBox = NULL;
+ const SwTableLine* pBoxLine = pBox->GetUpper();
+ USHORT nLineDiff = lcl_FindParentLines(rTbl,*pBox).C40_GETPOS(SwTableLine,pBoxLine);
+ USHORT nLineNo = 0;
+ for( USHORT j = 0; j < rBoxes.Count(); ++j )
+ {
+ pCheckBox = rBoxes[j];
+ if( pCheckBox->GetUpper()->GetUpper() == pBox->GetUpper()->GetUpper() )
+ {
+ const SwTableLine* pCheckLine = pCheckBox->GetUpper();
+ USHORT nCheckLine = lcl_FindParentLines( rTbl, *pCheckBox ).
+ C40_GETPOS( SwTableLine, pCheckLine );
+ if( ( !pSourceBox || nCheckLine > nLineNo ) && nCheckLine < nLineDiff )
+ {
+ nLineNo = nCheckLine;
+ pSourceBox = pCheckBox;
+ }
+ }
+ }
+
+ // find the line number difference
+ // (to help determine bNodesMoved flag below)
+ nLineDiff = nLineDiff - nLineNo;
+ OSL_ENSURE( pSourceBox, "Splitted source box not found!" );
+ // find out how many nodes the source box used to have
+ // (to help determine bNodesMoved flag below)
+ USHORT nNdsPos = 0;
+ while( rBoxes[ nNdsPos ] != pSourceBox )
+ ++nNdsPos;
+ ULONG nNodes = rNodeCnts[ nNdsPos ];
+
+ // When a new table cell is created, it either gets a new
+ // node, or it gets node(s) from elsewhere. The undo must
+ // know, of course, and thus we must determine here just
+ // where pBox's nodes are from:
+ // If 1) the source box has lost nodes, and
+ // 2) we're in the node range that got nodes
+ // then pBox received nodes from elsewhere.
+ // If bNodesMoved is set for pBox the undo must move the
+ // boxes back, otherwise it must delete them.
+ // The bNodesMoved flag is stored in a seperate array
+ // which mirrors Ptrs.pNewSttNds, i.e. Ptrs.pNewSttNds[i]
+ // and aMvBoxes[i] belong together.
+ BOOL bNodesMoved =
+ ( nNodes != ( pSourceBox->GetSttNd()->EndOfSectionIndex() -
+ pSourceBox->GetSttIdx() ) )
+ && ( nNodes - 1 > nLineDiff );
+ aMvBoxes.Insert( bNodesMoved, nInsPos );
+ }
+ }
+}
+
+
+void SwUndoTblNdsChg::SaveSection( SwStartNode* pSttNd )
+{
+ OSL_ENSURE( IsDelBox(), "falsche Action" );
+ if( !Ptrs.pDelSects )
+ Ptrs.pDelSects = new SwUndoSaveSections( 10, 5 );
+
+ SwTableNode* pTblNd = pSttNd->FindTableNode();
+ SwUndoSaveSection* pSave = new SwUndoSaveSection;
+ pSave->SaveSection( pSttNd->GetDoc(), SwNodeIndex( *pSttNd ));
+
+ Ptrs.pDelSects->Insert( pSave, Ptrs.pDelSects->Count() );
+ nSttNode = pTblNd->GetIndex();
+}
+
+
+void SwUndoTblNdsChg::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
+
+ SwTableNode* pTblNd = rDoc.GetNodes()[ aIdx ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+
+ CHECK_TABLE( pTblNd->GetTable() )
+
+ _FndBox aTmpBox( 0, 0 );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+ SwChartDataProvider *pPCD = rDoc.GetChartDataProvider();
+ std::vector< SwTableBox* > aDelBoxes;
+ if( IsDelBox() )
+ {
+ // Trick: die fehlenden Boxen in irgendeine Line einfuegen, beim
+ // CreateNew werden sie korrekt verbunden.
+ SwTableBox* pCpyBox = pTblNd->GetTable().GetTabSortBoxes()[0];
+ SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes();
+
+ // die Sections wieder herstellen
+ for( USHORT n = Ptrs.pDelSects->Count(); n; )
+ {
+ SwUndoSaveSection* pSave = (*Ptrs.pDelSects)[ --n ];
+ pSave->RestoreSection( &rDoc, &aIdx, SwTableBoxStartNode );
+ if( pSave->GetHistory() )
+ pSave->GetHistory()->Rollback( &rDoc );
+ SwTableBox* pBox = new SwTableBox( (SwTableBoxFmt*)pCpyBox->GetFrmFmt(), aIdx,
+ pCpyBox->GetUpper() );
+ rLnBoxes.C40_INSERT( SwTableBox, pBox, rLnBoxes.Count() );
+ }
+ Ptrs.pDelSects->DeleteAndDestroy( 0, Ptrs.pDelSects->Count() );
+ }
+ else if( aMvBoxes.Count() )
+ {
+ // dann muessen Nodes verschoben und nicht geloescht werden!
+ // Dafuer brauchen wir aber ein temp Array
+ SvULongs aTmp( 0, 5);
+ aTmp.Insert( Ptrs.pNewSttNds, 0 );
+
+ // von hinten anfangen
+ for( USHORT n = aTmp.Count(); n; )
+ {
+ // Box aus der Tabellen-Struktur entfernen
+ ULONG nIdx = aTmp[ --n ];
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx );
+ OSL_ENSURE( pBox, "Wo ist meine TabellenBox geblieben?" );
+
+ // TL_CHART2: notify chart about box to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
+
+ if( aMvBoxes[ n ] )
+ {
+ SwNodeRange aRg( *pBox->GetSttNd(), 1,
+ *pBox->GetSttNd()->EndOfSectionNode() );
+
+ SwTableLine* pLine = lcl_FindTableLine( pTblNd->GetTable(), *pBox );
+ SwNodeIndex aInsPos( *(pLine->GetTabBoxes()[0]->GetSttNd()), 2 );
+
+ // alle StartNode Indizies anpassen
+ USHORT i = n;
+ ULONG nSttIdx = aInsPos.GetIndex() - 2,
+ nNdCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
+ while( i && aTmp[ --i ] > nSttIdx )
+ aTmp[ i ] += nNdCnt;
+
+ // erst die Box loeschen
+ delete pBox;
+ // dann die Nodes verschieben,
+ rDoc.GetNodes()._MoveNodes( aRg, rDoc.GetNodes(), aInsPos, FALSE );
+ }
+ else
+ rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+ aDelBoxes.insert( aDelBoxes.end(), pBox );
+ }
+ }
+ else
+ {
+ // Remove nodes from nodes array (backwards!)
+ for( USHORT n = Ptrs.pNewSttNds->Count(); n; )
+ {
+ ULONG nIdx = (*Ptrs.pNewSttNds)[ --n ];
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx );
+ OSL_ENSURE( pBox, "Where's my table box?" );
+ // TL_CHART2: notify chart about box to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
+ aDelBoxes.insert( aDelBoxes.end(), pBox );
+ rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+ }
+ }
+ // Remove boxes from table structure
+ for( USHORT n = 0; n < aDelBoxes.size(); ++n )
+ {
+ SwTableBox* pCurrBox = aDelBoxes[n];
+ SwTableBoxes* pTBoxes = &pCurrBox->GetUpper()->GetTabBoxes();
+ pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pCurrBox ) );
+ delete pCurrBox;
+ }
+
+ pSaveTbl->CreateNew( pTblNd->GetTable(), TRUE, FALSE );
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
+
+ if( IsDelBox() )
+ nSttNode = pTblNd->GetIndex();
+ ClearFEShellTabCols();
+ CHECK_TABLE( pTblNd->GetTable() )
+}
+
+
+void SwUndoTblNdsChg::Redo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+ CHECK_TABLE( pTblNd->GetTable() )
+
+ SwSelBoxes aSelBoxes;
+ for( USHORT n = 0; n < aBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( aBoxes[ n ] );
+ aSelBoxes.Insert( pBox );
+ }
+
+ // SelBoxes erzeugen und InsertCell/-Row/SplitTbl aufrufen
+ switch( GetId() )
+ {
+ case UNDO_TABLE_INSCOL:
+ if( USHRT_MAX == nSetColType )
+ rDoc.InsertCol( aSelBoxes, nCount, bFlag );
+ else
+ {
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nCurrBox );
+ rDoc.SetColRowWidthHeight( *pBox, nSetColType, nAbsDiff,
+ nRelDiff );
+ }
+ break;
+
+ case UNDO_TABLE_INSROW:
+ if( USHRT_MAX == nSetColType )
+ rDoc.InsertRow( aSelBoxes, nCount, bFlag );
+ else
+ {
+ SwTable& rTbl = pTblNd->GetTable();
+ SwTableBox* pBox = rTbl.GetTblBox( nCurrBox );
+ TblChgMode eOldMode = rTbl.GetTblChgMode();
+ rTbl.SetTblChgMode( (TblChgMode)nCount );
+ rDoc.SetColRowWidthHeight( *pBox, nSetColType, nAbsDiff, nRelDiff );
+ rTbl.SetTblChgMode( eOldMode );
+ }
+ break;
+
+ case UNDO_TABLE_SPLIT:
+ rDoc.SplitTbl( aSelBoxes, bFlag, nCount, bSameHeight );
+ break;
+ case UNDO_TABLE_DELBOX:
+ case UNDO_ROW_DELETE:
+ case UNDO_COL_DELETE:
+ if( USHRT_MAX == nSetColType )
+ {
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+ SwTable &rTable = pTblNd->GetTable();
+ if( nMax > nMin && rTable.IsNewModel() )
+ rTable.PrepareDeleteCol( nMin, nMax );
+ rTable.DeleteSel( &rDoc, aSelBoxes, 0, this, TRUE, TRUE );
+ }
+ else
+ {
+ SwTable& rTbl = pTblNd->GetTable();
+
+ SwTableFmlUpdate aMsgHnt( &rTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+
+ SwTableBox* pBox = rTbl.GetTblBox( nCurrBox );
+ TblChgMode eOldMode = rTbl.GetTblChgMode();
+ rTbl.SetTblChgMode( (TblChgMode)nCount );
+
+ rDoc.DoUndo( TRUE ); // wir brauchen die SaveSections!
+ SwUndoTblNdsChg* pUndo = 0;
+
+ switch( nSetColType & 0xff )
+ {
+ case nsTblChgWidthHeightType::WH_COL_LEFT:
+ case nsTblChgWidthHeightType::WH_COL_RIGHT:
+ case nsTblChgWidthHeightType::WH_CELL_LEFT:
+ case nsTblChgWidthHeightType::WH_CELL_RIGHT:
+ rTbl.SetColWidth( *pBox, nSetColType, nAbsDiff,
+ nRelDiff, (SwUndo**)&pUndo );
+ break;
+ case nsTblChgWidthHeightType::WH_ROW_TOP:
+ case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
+ case nsTblChgWidthHeightType::WH_CELL_TOP:
+ case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
+ rTbl.SetRowHeight( *pBox, nSetColType, nAbsDiff,
+ nRelDiff, (SwUndo**)&pUndo );
+ break;
+ }
+
+ if( pUndo )
+ {
+ Ptrs.pDelSects->Insert( pUndo->Ptrs.pDelSects, 0 );
+ pUndo->Ptrs.pDelSects->Remove( 0, pUndo->Ptrs.pDelSects->Count() );
+
+ delete pUndo;
+ }
+ rDoc.DoUndo( FALSE );
+
+ rTbl.SetTblChgMode( eOldMode );
+ }
+ nSttNode = pTblNd->GetIndex();
+ break;
+ default:
+ ;
+ }
+ ClearFEShellTabCols();
+ CHECK_TABLE( pTblNd->GetTable() )
+}
+
+
+/* */
+
+
+SwUndoTblMerge::SwUndoTblMerge( const SwPaM& rTblSel )
+ : SwUndo( UNDO_TABLE_MERGE ), SwUndRng( rTblSel ), pHistory( 0 )
+{
+ const SwTableNode* pTblNd = rTblSel.GetNode()->FindTableNode();
+ OSL_ENSURE( pTblNd, "Wo ist TabllenNode" );
+ pSaveTbl = new _SaveTable( pTblNd->GetTable() );
+ pMoves = new SwUndoMoves;
+ nTblNode = pTblNd->GetIndex();
+}
+
+
+SwUndoTblMerge::~SwUndoTblMerge()
+{
+ delete pSaveTbl;
+ delete pMoves;
+ delete pHistory;
+}
+
+
+void SwUndoTblMerge::Undo( SwUndoIter& rUndoIter )
+{
+ SwDoc& rDoc = rUndoIter.GetDoc();
+ SwNodeIndex aIdx( rDoc.GetNodes(), nTblNode );
+
+ SwTableNode* pTblNd = rDoc.GetNodes()[ aIdx ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+
+ _FndBox aTmpBox( 0, 0 );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+
+ // 1. die geloeschten Boxen wiederherstellen:
+
+ // Trick: die fehlenden Boxen in irgendeine Line einfuegen, beim
+ // CreateNew werden sie korrekt verbunden.
+ SwTableBox *pBox, *pCpyBox = pTblNd->GetTable().GetTabSortBoxes()[0];
+ SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes();
+
+CHECKTABLE(pTblNd->GetTable())
+
+ SwSelBoxes aSelBoxes;
+ SwTxtFmtColl* pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_STANDARD );
+ USHORT n;
+
+ for( n = 0; n < aBoxes.Count(); ++n )
+ {
+ aIdx = aBoxes[ n ];
+ SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection( aIdx,
+ SwTableBoxStartNode, pColl );
+ pBox = new SwTableBox( (SwTableBoxFmt*)pCpyBox->GetFrmFmt(), *pSttNd,
+ pCpyBox->GetUpper() );
+ rLnBoxes.C40_INSERT( SwTableBox, pBox, rLnBoxes.Count() );
+
+ aSelBoxes.Insert( pBox );
+ }
+
+CHECKTABLE(pTblNd->GetTable())
+
+ SwChartDataProvider *pPCD = rDoc.GetChartDataProvider();
+ // 2. die eingefuegten Boxen loeschen
+ // die Nodes loeschen (von Hinten!!)
+ for( n = aNewSttNds.Count(); n; )
+ {
+ // Box aus der Tabellen-Struktur entfernen
+ ULONG nIdx = aNewSttNds[ --n ];
+
+ if( !nIdx && n )
+ {
+ nIdx = aNewSttNds[ --n ];
+ pBox = pTblNd->GetTable().GetTblBox( nIdx );
+ OSL_ENSURE( pBox, "Wo ist meine TabellenBox geblieben?" );
+
+ if( !pSaveTbl->IsNewModel() )
+ rDoc.GetNodes().MakeTxtNode( SwNodeIndex(
+ *pBox->GetSttNd()->EndOfSectionNode() ), pColl );
+
+ // das war der Trenner, -> die verschobenen herstellen
+ for( USHORT i = pMoves->Count(); i; )
+ {
+ SwTxtNode* pTxtNd = 0;
+ USHORT nDelPos = 0;
+ SwUndoMove* pUndo = (*pMoves)[ --i ];
+ if( !pUndo->IsMoveRange() )
+ {
+ pTxtNd = rDoc.GetNodes()[ pUndo->GetDestSttNode() ]->GetTxtNode();
+ nDelPos = pUndo->GetDestSttCntnt() - 1;
+ }
+ pUndo->Undo( rUndoIter );
+ if( pUndo->IsMoveRange() )
+ {
+ // den ueberfluessigen Node loeschen
+ aIdx = pUndo->GetEndNode();
+ SwCntntNode *pCNd = aIdx.GetNode().GetCntntNode();
+ if( pCNd )
+ {
+ SwNodeIndex aTmp( aIdx, -1 );
+ SwCntntNode *pMove = aTmp.GetNode().GetCntntNode();
+ if( pMove )
+ pCNd->MoveTo( *pMove );
+ }
+ rDoc.GetNodes().Delete( aIdx, 1 );
+ }
+ else if( pTxtNd )
+ {
+ // evt. noch ueberflussige Attribute loeschen
+ SwIndex aTmpIdx( pTxtNd, nDelPos );
+ if( pTxtNd->GetpSwpHints() && pTxtNd->GetpSwpHints()->Count() )
+ pTxtNd->RstAttr( aTmpIdx, pTxtNd->GetTxt().Len() -
+ nDelPos + 1 );
+ // das Trennzeichen loeschen
+ pTxtNd->EraseText( aTmpIdx, 1 );
+ }
+ }
+ nIdx = pBox->GetSttIdx();
+ }
+ else
+ pBox = pTblNd->GetTable().GetTblBox( nIdx );
+
+ if( !pSaveTbl->IsNewModel() )
+ {
+ // TL_CHART2: notify chart about box to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
+
+ SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
+ pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) );
+
+
+ // Indizies aus dem Bereich loeschen
+ {
+ SwNodeIndex aTmpIdx( *pBox->GetSttNd() );
+ rDoc.CorrAbs( SwNodeIndex( aTmpIdx, 1 ),
+ SwNodeIndex( *aTmpIdx.GetNode().EndOfSectionNode() ),
+ SwPosition( aTmpIdx, SwIndex( 0, 0 )), TRUE );
+ }
+
+ delete pBox;
+ rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+ }
+ }
+CHECKTABLE(pTblNd->GetTable())
+
+
+ pSaveTbl->CreateNew( pTblNd->GetTable(), TRUE, FALSE );
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+// nTblNode = pTblNd->GetIndex();
+
+ SwPaM* pPam = rUndoIter.pAktPam;
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nSttNode;
+ pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), nSttCntnt );
+ pPam->SetMark();
+ pPam->DeleteMark();
+
+CHECKTABLE(pTblNd->GetTable())
+ ClearFEShellTabCols();
+}
+
+
+void SwUndoTblMerge::Redo( SwUndoIter& rUndoIter )
+{
+ SwPaM* pPam = rUndoIter.pAktPam;
+ SwDoc& rDoc = *pPam->GetDoc();
+
+ SetPaM( *pPam );
+ rDoc.MergeTbl( *pPam );
+}
+
+void SwUndoTblMerge::MoveBoxCntnt( SwDoc* pDoc, SwNodeRange& rRg, SwNodeIndex& rPos )
+{
+ SwNodeIndex aTmp( rRg.aStart, -1 ), aTmp2( rPos, -1 );
+ SwUndoMove* pUndo = new SwUndoMove( pDoc, rRg, rPos );
+ sal_Bool bDoesUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( sal_False );
+ pDoc->MoveNodeRange( rRg, rPos, (pSaveTbl->IsNewModel()) ?
+ IDocumentContentOperations::DOC_NO_DELFRMS :
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ if( bDoesUndo )
+ pDoc->DoUndo( sal_True );
+ aTmp++;
+ aTmp2++;
+ pUndo->SetDestRange( aTmp2, rPos, aTmp );
+
+ pMoves->Insert( pUndo, pMoves->Count() );
+}
+
+
+void SwUndoTblMerge::SetSelBoxes( const SwSelBoxes& rBoxes )
+{
+ // die Selektion merken
+ for( USHORT n = 0; n < rBoxes.Count(); ++n )
+ InsertSort( aBoxes, rBoxes[n]->GetSttIdx() );
+
+ // als Trennung fuers einfuegen neuer Boxen nach dem Verschieben!
+ aNewSttNds.Insert( (ULONG)0, aNewSttNds.Count() );
+
+ // The new table model does not delete overlapped cells (by row span),
+ // so the rBoxes array might be empty even some cells have been merged.
+ if( rBoxes.Count() )
+ nTblNode = rBoxes[ 0 ]->GetSttNd()->FindTableNode()->GetIndex();
+}
+
+void SwUndoTblMerge::SaveCollection( const SwTableBox& rBox )
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ SwNodeIndex aIdx( *rBox.GetSttNd(), 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = aIdx.GetNodes().GoNext( &aIdx );
+
+ pHistory->Add( pCNd->GetFmtColl(), aIdx.GetIndex(), pCNd->GetNodeType());
+ if( pCNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pCNd->GetpSwAttrSet(), aIdx.GetIndex() );
+}
+
+/* */
+
+
+SwUndoTblNumFmt::SwUndoTblNumFmt( const SwTableBox& rBox,
+ const SfxItemSet* pNewSet )
+ : SwUndo( UNDO_TBLNUMFMT ),
+ pBoxSet( 0 ), pHistory( 0 ), nFmtIdx( NUMBERFORMAT_TEXT )
+{
+ bNewFmt = bNewFml = bNewValue = FALSE;
+ nNode = rBox.GetSttIdx();
+
+ nNdPos = rBox.IsValidNumTxtNd( 0 == pNewSet );
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+
+ if( ULONG_MAX != nNdPos )
+ {
+ SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
+
+ pHistory = new SwHistory;
+ SwRegHistory aRHst( *rBox.GetSttNd(), pHistory );
+ // always save all text atttibutes because of possibly overlapping
+ // areas of on/off
+ pHistory->CopyAttr( pTNd->GetpSwpHints(), nNdPos, 0,
+ pTNd->GetTxt().Len(), true );
+
+ if( pTNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pTNd->GetpSwAttrSet(), nNdPos );
+
+ aStr = pTNd->GetTxt();
+ if( pTNd->GetpSwpHints() )
+ pTNd->GetpSwpHints()->DeRegister();
+ }
+
+ pBoxSet = new SfxItemSet( pDoc->GetAttrPool(), aTableBoxSetRange );
+ pBoxSet->Put( rBox.GetFrmFmt()->GetAttrSet() );
+
+ if( pNewSet )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMAT,
+ FALSE, &pItem ))
+ {
+ bNewFmt = TRUE;
+ nNewFmtIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ }
+ if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMULA,
+ FALSE, &pItem ))
+ {
+ bNewFml = TRUE;
+ aNewFml = ((SwTblBoxFormula*)pItem)->GetFormula();
+ }
+ if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_VALUE,
+ FALSE, &pItem ))
+ {
+ bNewValue = TRUE;
+ fNewNum = ((SwTblBoxValue*)pItem)->GetValue();
+ }
+ }
+
+ // wird die History ueberhaupt benoetigt ??
+ if( pHistory && !pHistory->Count() )
+ DELETEZ( pHistory );
+}
+
+
+SwUndoTblNumFmt::~SwUndoTblNumFmt()
+{
+ delete pHistory;
+ delete pBoxSet;
+}
+
+void SwUndoTblNumFmt::Undo( SwUndoIter& rIter )
+{
+ OSL_ENSURE( pBoxSet, "Where's the stored item set?" );
+
+ SwDoc& rDoc = rIter.GetDoc();
+ SwStartNode* pSttNd = rDoc.GetNodes()[ nNode ]->
+ FindSttNodeByType( SwTableBoxStartNode );
+ OSL_ENSURE( pSttNd, "ohne StartNode kein TabellenBox" );
+ SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox(
+ pSttNd->GetIndex() );
+ OSL_ENSURE( pBox, "keine TabellenBox gefunden" );
+
+ SwTableBoxFmt* pFmt = rDoc.MakeTableBoxFmt();
+ pFmt->SetFmtAttr( *pBoxSet );
+ pBox->ChgFrmFmt( pFmt );
+
+ if( ULONG_MAX == nNdPos )
+ return;
+
+ SwTxtNode* pTxtNd = rDoc.GetNodes()[ nNdPos ]->GetTxtNode();
+ // wenn mehr als ein Node geloescht wurde, dann wurden auch
+ // alle "Node"-Attribute gespeichert
+ if( pTxtNd->HasSwAttrSet() )
+ pTxtNd->ResetAllAttr();
+
+ if( pTxtNd->GetpSwpHints() && aStr.Len() )
+ pTxtNd->ClearSwpHintsArr( true );
+
+ // ChgTextToNum(..) only acts when the strings are different. We
+ // need to do the same here.
+ if( pTxtNd->GetTxt() != aStr )
+ {
+ rDoc.DeleteRedline( *( pBox->GetSttNd() ), false, USHRT_MAX );
+
+ SwIndex aIdx( pTxtNd, 0 );
+ if( aStr.Len() )
+ {
+ pTxtNd->EraseText( aIdx );
+ pTxtNd->InsertText( aStr, aIdx,
+ IDocumentContentOperations::INS_NOHINTEXPAND );
+ }
+ }
+
+ if( pHistory )
+ {
+ USHORT nTmpEnd = pHistory->GetTmpEnd();
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( nTmpEnd );
+ }
+
+ SwPaM* pPam = rIter.pAktPam;
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nNode + 1;
+ pPam->GetPoint()->nContent.Assign( pTxtNd, 0 );
+}
+
+/** switch the RedlineMode on the given document, using
+ * SetRedlineMode_intern. This class set the mode in the constructor,
+ * and changes it back in the destructor, i.e. it uses the
+ * initialization-is-resource-acquisition idiom.
+ */
+class RedlineModeInternGuard
+{
+ SwDoc& mrDoc;
+ RedlineMode_t meOldRedlineMode;
+
+public:
+ RedlineModeInternGuard(
+ SwDoc& rDoc, /// change mode of this document
+ RedlineMode_t eNewRedlineMode, /// new redline mode
+ RedlineMode_t eRedlineModeMask = (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE /*change only bits set in this mask*/));
+
+ ~RedlineModeInternGuard();
+};
+
+RedlineModeInternGuard::RedlineModeInternGuard(
+ SwDoc& rDoc,
+ RedlineMode_t eNewRedlineMode,
+ RedlineMode_t eRedlineModeMask )
+ : mrDoc( rDoc ),
+ meOldRedlineMode( rDoc.GetRedlineMode() )
+{
+ mrDoc.SetRedlineMode_intern((RedlineMode_t)( ( meOldRedlineMode & ~eRedlineModeMask ) |
+ ( eNewRedlineMode & eRedlineModeMask ) ));
+}
+
+RedlineModeInternGuard::~RedlineModeInternGuard()
+{
+ mrDoc.SetRedlineMode_intern( meOldRedlineMode );
+}
+
+
+
+void SwUndoTblNumFmt::Redo( SwUndoIter& rIter )
+{
+ // konnte die Box veraendert werden ?
+ if( !pBoxSet )
+ return ;
+
+ SwDoc& rDoc = rIter.GetDoc();
+
+ SwPaM* pPam = rIter.pAktPam;
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nNode;
+
+ SwNode* pNd = rDoc.GetNodes()[ pPam->GetPoint()->nNode ];
+ SwStartNode* pSttNd = pNd->FindSttNodeByType( SwTableBoxStartNode );
+ OSL_ENSURE( pSttNd, "ohne StartNode kein TabellenBox" );
+ SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox(
+ pSttNd->GetIndex() );
+ OSL_ENSURE( pBox, "keine TabellenBox gefunden" );
+
+ SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt();
+ if( bNewFmt || bNewFml || bNewValue )
+ {
+ SfxItemSet aBoxSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->LockModify();
+
+ if( bNewFml )
+ aBoxSet.Put( SwTblBoxFormula( aNewFml ));
+ else
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
+ if( bNewFmt )
+ aBoxSet.Put( SwTblBoxNumFormat( nNewFmtIdx ));
+ else
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT );
+ if( bNewValue )
+ aBoxSet.Put( SwTblBoxValue( fNewNum ));
+ else
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE );
+ pBoxFmt->UnlockModify();
+
+ // dvo: When redlining is (was) enabled, setting the attribute
+ // will also change the cell content. To allow this, the
+ // REDLINE_IGNORE flag must be removed during Redo. #108450#
+ RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE );
+ pBoxFmt->SetFmtAttr( aBoxSet );
+ }
+ else if( NUMBERFORMAT_TEXT != nFmtIdx )
+ {
+ SfxItemSet aBoxSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+
+ aBoxSet.Put( SwTblBoxNumFormat( nFmtIdx ));
+ aBoxSet.Put( SwTblBoxValue( fNum ));
+
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->LockModify();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
+ pBoxFmt->UnlockModify();
+
+ // dvo: When redlining is (was) enabled, setting the attribute
+ // will also change the cell content. To allow this, the
+ // REDLINE_IGNORE flag must be removed during Redo. #108450#
+ RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE );
+ pBoxFmt->SetFmtAttr( aBoxSet );
+ }
+ else
+ {
+ // es ist keine Zahl
+
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
+
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ }
+
+ if( bNewFml )
+ {
+ // egal was gesetzt wurde, ein Update der Tabelle macht sich immer gut
+ SwTableFmlUpdate aTblUpdate( &pSttNd->FindTableNode()->GetTable() );
+ rDoc.UpdateTblFlds( &aTblUpdate );
+ }
+
+ if( !pNd->IsCntntNode() )
+ pNd = rDoc.GetNodes().GoNext( &pPam->GetPoint()->nNode );
+ pPam->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
+}
+
+void SwUndoTblNumFmt::SetBox( const SwTableBox& rBox )
+{
+ nNode = rBox.GetSttIdx();
+}
+
+/* */
+
+_UndoTblCpyTbl_Entry::_UndoTblCpyTbl_Entry( const SwTableBox& rBox )
+ : nBoxIdx( rBox.GetSttIdx() ), nOffset( 0 ),
+ pBoxNumAttr( 0 ), pUndo( 0 ), bJoin( false )
+{
+}
+
+_UndoTblCpyTbl_Entry::~_UndoTblCpyTbl_Entry()
+{
+ delete pUndo;
+ delete pBoxNumAttr;
+}
+
+
+SwUndoTblCpyTbl::SwUndoTblCpyTbl()
+ : SwUndo( UNDO_TBLCPYTBL ), pInsRowUndo( 0 )
+{
+ pArr = new _UndoTblCpyTbl_Entries;
+}
+
+SwUndoTblCpyTbl::~SwUndoTblCpyTbl()
+{
+ delete pArr;
+ delete pInsRowUndo;
+}
+
+void SwUndoTblCpyTbl::Undo( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+ _DEBUG_REDLINE( &rDoc )
+
+ SwTableNode* pTblNd = 0;
+ for( USHORT n = pArr->Count(); n; )
+ {
+ _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ --n ];
+ ULONG nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
+ SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
+ if( !pTblNd )
+ pTblNd = pSNd->FindTableNode();
+
+ SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos );
+
+ SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
+ rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() );
+
+ // b62341295: Redline for copying tables
+ const SwNode *pEndNode = rBox.GetSttNd()->EndOfSectionNode();
+ SwPaM aPam( aInsIdx.GetNode(), *pEndNode );
+ SwUndoDelete* pUndo = 0;
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ bool bDeleteCompleteParagraph = false;
+ bool bShiftPam = false;
+ // There are a couple of different situations to consider during redlining
+ if( pEntry->pUndo )
+ {
+ SwUndoDelete *pUnDel = (SwUndoDelete*)pEntry->pUndo;
+ if( UNDO_REDLINE == pUnDel->GetId() )
+ {
+ // The old content was not empty or he has been merged with the new content
+ bDeleteCompleteParagraph = !pEntry->bJoin; // bJoin is set when merged
+ // Set aTmpIdx to the beginning fo the old content
+ SwNodeIndex aTmpIdx( *pEndNode, pUnDel->NodeDiff()-1 );
+ SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aPam.GetPoint()->nNode = *pTxt;
+ aPam.GetPoint()->nContent.Assign( pTxt, pUnDel->ContentStart() );
+ }
+ else
+ *aPam.GetPoint() = SwPosition( aTmpIdx );
+ }
+ else if( pUnDel->IsDelFullPara() )
+ {
+ // When the old content was an empty paragraph, but could not be joined
+ // with the new content (e.g. because of a section or table)
+ // We "save" the aPam.Point, we go one step backwards (because later on the
+ // empty paragraph will be inserted by the undo) and set the "ShiftPam-flag
+ // for step forward later on.
+ bDeleteCompleteParagraph = true;
+ bShiftPam = true;
+ SwNodeIndex aTmpIdx( *pEndNode, -1 );
+ SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aPam.GetPoint()->nNode = *pTxt;
+ aPam.GetPoint()->nContent.Assign( pTxt, 0 );
+ }
+ else
+ *aPam.GetPoint() = SwPosition( aTmpIdx );
+ }
+ }
+ rDoc.DeleteRedline( aPam, true, USHRT_MAX );
+
+ if( pEntry->pUndo )
+ {
+ pEntry->pUndo->Undo( rIter );
+ delete pEntry->pUndo;
+ }
+ if( bShiftPam )
+ {
+ // The aPam.Point is at the moment at the last position of the new content and has to be
+ // moved to the first postion of the old content for the SwUndoDelete operation
+ SwNodeIndex aTmpIdx( aPam.GetPoint()->nNode, 1 );
+ SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aPam.GetPoint()->nNode = *pTxt;
+ aPam.GetPoint()->nContent.Assign( pTxt, 0 );
+ }
+ else
+ *aPam.GetPoint() = SwPosition( aTmpIdx );
+ }
+ pUndo = new SwUndoDelete( aPam, bDeleteCompleteParagraph, TRUE );
+ }
+ else
+ {
+ pUndo = new SwUndoDelete( aPam, true );
+ if( pEntry->pUndo )
+ {
+ pEntry->pUndo->Undo( rIter );
+ delete pEntry->pUndo;
+ }
+ }
+ pEntry->pUndo = pUndo;
+
+ aInsIdx = rBox.GetSttIdx() + 1;
+ rDoc.GetNodes().Delete( aInsIdx, 1 );
+
+ SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() );
+ if( aTmpSet.Count() )
+ {
+ SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT );
+ }
+
+ if( pEntry->pBoxNumAttr )
+ {
+ rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr );
+ delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
+ }
+
+ if( aTmpSet.Count() )
+ {
+ pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pEntry->pBoxNumAttr->Put( aTmpSet );
+ }
+
+ pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
+ }
+
+ if( pInsRowUndo )
+ pInsRowUndo->Undo( rIter );
+ _DEBUG_REDLINE( &rDoc )
+}
+
+void SwUndoTblCpyTbl::Redo( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+ _DEBUG_REDLINE( &rDoc )
+
+ if( pInsRowUndo )
+ pInsRowUndo->Redo( rIter );
+
+ SwTableNode* pTblNd = 0;
+ for( USHORT n = 0; n < pArr->Count(); ++n )
+ {
+ _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ n ];
+ ULONG nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
+ SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
+ if( !pTblNd )
+ pTblNd = pSNd->FindTableNode();
+
+ SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos );
+
+ SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
+
+ // b62341295: Redline for copying tables - Start.
+ rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() );
+ SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode());
+ SwUndo* pUndo = IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ? 0 : new SwUndoDelete( aPam, TRUE );
+ if( pEntry->pUndo )
+ {
+ pEntry->pUndo->Undo( rIter );
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ // PrepareRedline has to be called with the beginning of the old content
+ // When new and old content has been joined, the rIter.pAktPam has been set
+ // by the Undo operation to this point.
+ // Otherwise aInsIdx has been moved during the Undo operation
+ if( pEntry->bJoin )
+ pUndo = PrepareRedline( &rDoc, rBox, *rIter.pAktPam->GetPoint(),
+ pEntry->bJoin, true );
+ else
+ {
+ SwPosition aTmpPos( aInsIdx );
+ pUndo = PrepareRedline( &rDoc, rBox, aTmpPos, pEntry->bJoin, true );
+ }
+ }
+ delete pEntry->pUndo;
+ }
+ pEntry->pUndo = pUndo;
+ // b62341295: Redline for copying tables - End.
+
+ aInsIdx = rBox.GetSttIdx() + 1;
+ rDoc.GetNodes().Delete( aInsIdx, 1 );
+
+ SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() );
+ if( aTmpSet.Count() )
+ {
+ SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT );
+ }
+ if( pEntry->pBoxNumAttr )
+ {
+ rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr );
+ delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
+ }
+
+ if( aTmpSet.Count() )
+ {
+ pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pEntry->pBoxNumAttr->Put( aTmpSet );
+ }
+
+ pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
+ }
+ _DEBUG_REDLINE( &rDoc )
+}
+
+void SwUndoTblCpyTbl::AddBoxBefore( const SwTableBox& rBox, BOOL bDelCntnt )
+{
+ if( pArr->Count() && !bDelCntnt )
+ return;
+
+ _UndoTblCpyTbl_Entry* pEntry = new _UndoTblCpyTbl_Entry( rBox );
+ pArr->Insert( pEntry, pArr->Count() );
+
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+ _DEBUG_REDLINE( pDoc )
+ if( bDelCntnt )
+ {
+ SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
+ pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
+ SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() );
+
+ if( !pDoc->IsRedlineOn() )
+ pEntry->pUndo = new SwUndoDelete( aPam, TRUE );
+ }
+
+ pEntry->pBoxNumAttr = new SfxItemSet( pDoc->GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pEntry->pBoxNumAttr->Put( rBox.GetFrmFmt()->GetAttrSet() );
+ if( !pEntry->pBoxNumAttr->Count() )
+ delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
+ _DEBUG_REDLINE( pDoc )
+}
+
+void SwUndoTblCpyTbl::AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex& rIdx, BOOL bDelCntnt )
+{
+ _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ pArr->Count() - 1 ];
+
+ // wurde der Inhalt geloescht, so loesche jetzt auch noch den temp.
+ // erzeugten Node
+ if( bDelCntnt )
+ {
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+ _DEBUG_REDLINE( pDoc )
+
+ if( pDoc->IsRedlineOn() )
+ {
+ SwPosition aTmpPos( rIdx );
+ pEntry->pUndo = PrepareRedline( pDoc, rBox, aTmpPos, pEntry->bJoin, false );
+ }
+ SwNodeIndex aDelIdx( *rBox.GetSttNd(), 1 );
+ rBox.GetFrmFmt()->GetDoc()->GetNodes().Delete( aDelIdx, 1 );
+ _DEBUG_REDLINE( pDoc )
+ }
+
+ pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
+}
+
+// PrepareRedline is called from AddBoxAfter() and from Redo() in slightly different situations.
+// bRedo is set by calling from Redo()
+// rJoin is false by calling from AddBoxAfter() and will be set if the old and new content has
+// been merged.
+// rJoin is true if Redo() is calling and the content has already been merged
+
+SwUndo* SwUndoTblCpyTbl::PrepareRedline( SwDoc* pDoc, const SwTableBox& rBox,
+ const SwPosition& rPos, bool& rJoin, bool bRedo )
+{
+ SwUndo *pUndo = 0;
+ // b62341295: Redline for copying tables
+ // What's to do?
+ // Mark the cell content before rIdx as insertion,
+ // mark the cell content behind rIdx as deletion
+ // merge text nodes at rIdx if possible
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)( ( eOld | nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) &
+ ~nsRedlineMode_t::REDLINE_IGNORE ));
+ SwPosition aInsertEnd( rPos );
+ SwTxtNode* pTxt;
+ if( !rJoin )
+ {
+ // If the content is not merged, the end of the insertion is at the end of the node
+ // _before_ the given position rPos
+ --aInsertEnd.nNode;
+ pTxt = aInsertEnd.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aInsertEnd.nContent.Assign( pTxt, pTxt->GetTxt().Len() );
+ if( !bRedo && rPos.nNode.GetNode().GetTxtNode() )
+ { // Try to merge, if not called by Redo()
+ rJoin = true;
+ pTxt->JoinNext();
+ }
+ }
+ else
+ aInsertEnd.nContent = SwIndex( 0 );
+ }
+ // For joined (merged) contents the start of deletionm and end of insertion are identical
+ // otherwise adjacent nodes.
+ SwPosition aDeleteStart( rJoin ? aInsertEnd : rPos );
+ if( !rJoin )
+ {
+ pTxt = aDeleteStart.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ aDeleteStart.nContent.Assign( pTxt, 0 );
+ }
+ SwPosition aCellEnd( SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode(), -1 ) );
+ pTxt = aCellEnd.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ aCellEnd.nContent.Assign( pTxt, pTxt->GetTxt().Len() );
+ if( aDeleteStart != aCellEnd )
+ { // If the old (deleted) part is not empty, here we are...
+ SwPaM aDeletePam( aDeleteStart, aCellEnd );
+ pUndo = new SwUndoRedlineDelete( aDeletePam, UNDO_DELETE );
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDeletePam ), true );
+ }
+ else if( !rJoin ) // If the old part is empty and joined, we are finished
+ { // if it is not joined, we have to delete this empty paragraph
+ aCellEnd = SwPosition(
+ SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode() ));
+ SwPaM aTmpPam( aDeleteStart, aCellEnd );
+ pUndo = new SwUndoDelete( aTmpPam, TRUE );
+ }
+ SwPosition aCellStart( SwNodeIndex( *rBox.GetSttNd(), 2 ) );
+ pTxt = aCellStart.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ aCellStart.nContent.Assign( pTxt, 0 );
+ if( aCellStart != aInsertEnd ) // An empty insertion will not been marked
+ {
+ SwPaM aTmpPam( aCellStart, aInsertEnd );
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aTmpPam ), true );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+ return pUndo;
+}
+
+
+BOOL SwUndoTblCpyTbl::InsertRow( SwTable& rTbl, const SwSelBoxes& rBoxes,
+ USHORT nCnt )
+{
+ SwTableNode* pTblNd = (SwTableNode*)rTbl.GetTabSortBoxes()[0]->
+ GetSttNd()->FindTableNode();
+
+ SwTableSortBoxes aTmpLst( 0, 5 );
+ pInsRowUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSROW, rBoxes, *pTblNd,
+ 0, 0, nCnt, TRUE, FALSE );
+ aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
+
+ BOOL bRet = rTbl.InsertRow( rTbl.GetFrmFmt()->GetDoc(), rBoxes, nCnt, TRUE );
+ if( bRet )
+ pInsRowUndo->SaveNewBoxes( *pTblNd, aTmpLst );
+ else
+ delete pInsRowUndo, pInsRowUndo = 0;
+ return bRet;
+}
+
+BOOL SwUndoTblCpyTbl::IsEmpty() const
+{
+ return !pInsRowUndo && !pArr->Count();
+}
+
+/* */
+
+SwUndoCpyTbl::SwUndoCpyTbl()
+ : SwUndo( UNDO_CPYTBL ), pDel( 0 ), nTblNode( 0 )
+{
+}
+
+SwUndoCpyTbl::~SwUndoCpyTbl()
+{
+ delete pDel;
+}
+
+void SwUndoCpyTbl::Undo( SwUndoIter& rIter )
+{
+ SwDoc& rDoc = rIter.GetDoc();
+ SwTableNode* pTNd = rDoc.GetNodes()[ nTblNode ]->GetTableNode();
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ SwCntntNode* pNextNd = rDoc.GetNodes()[ pTNd->EndOfSectionIndex()+1 ]->GetCntntNode();
+ if( pNextNd )
+ {
+ SwFrmFmt* pTableFmt = pTNd->GetTable().GetFrmFmt();
+ const SfxPoolItem *pItem;
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
+ FALSE, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
+ FALSE, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+ }
+
+ SwPaM aPam( *pTNd, *pTNd->EndOfSectionNode(), 0 , 1 );
+ pDel = new SwUndoDelete( aPam, TRUE );
+}
+
+void SwUndoCpyTbl::Redo( SwUndoIter& rIter )
+{
+ pDel->Undo( rIter );
+ delete pDel, pDel = 0;
+}
+
+
+/* */
+
+SwUndoSplitTbl::SwUndoSplitTbl( const SwTableNode& rTblNd,
+ SwSaveRowSpan* pRowSp, USHORT eMode, BOOL bNewSize )
+ : SwUndo( UNDO_SPLIT_TABLE ),
+ nTblNode( rTblNd.GetIndex() ), nOffset( 0 ), mpSaveRowSpan( pRowSp ), pSavTbl( 0 ),
+ pHistory( 0 ), nMode( eMode ), nFmlEnd( 0 ), bCalcNewSize( bNewSize )
+{
+ switch( nMode )
+ {
+ case HEADLINE_BOXATRCOLLCOPY:
+ pHistory = new SwHistory;
+ // kein break;
+ case HEADLINE_BORDERCOPY:
+ case HEADLINE_BOXATTRCOPY:
+ pSavTbl = new _SaveTable( rTblNd.GetTable(), 1, FALSE );
+ break;
+ }
+}
+
+SwUndoSplitTbl::~SwUndoSplitTbl()
+{
+ delete pSavTbl;
+ delete pHistory;
+ delete mpSaveRowSpan;
+}
+
+void SwUndoSplitTbl::Undo( SwUndoIter& rIter )
+{
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+
+ pPam->DeleteMark();
+ SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
+ rIdx = nTblNode + nOffset;
+
+ //Den implizit erzeugten Absatz wieder entfernen.
+ pDoc->GetNodes().Delete( rIdx, 1 );
+
+ rIdx = nTblNode + nOffset;
+ SwTableNode* pTblNd = rIdx.GetNode().GetTableNode();
+ SwTable& rTbl = pTblNd->GetTable();
+
+ SwTableFmlUpdate aMsgHnt( &rTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ pDoc->UpdateTblFlds( &aMsgHnt );
+
+ switch( nMode )
+ {
+ case HEADLINE_BOXATRCOLLCOPY:
+ if( pHistory )
+ pHistory->TmpRollback( pDoc, nFmlEnd );
+
+ // kein break
+ case HEADLINE_BOXATTRCOPY:
+ case HEADLINE_BORDERCOPY:
+ {
+ pSavTbl->CreateNew( rTbl, FALSE );
+ pSavTbl->RestoreAttr( rTbl );
+ }
+ break;
+
+ case HEADLINE_CNTNTCOPY:
+ // die erzeugte 1. Line muss wieder entfernt werden
+ {
+ SwSelBoxes aSelBoxes;
+ SwTableBox* pBox = rTbl.GetTblBox( nTblNode + nOffset + 1 );
+ rTbl.SelLineFromBox( pBox, aSelBoxes, TRUE );
+ _FndBox aTmpBox( 0, 0 );
+ aTmpBox.SetTableLines( aSelBoxes, rTbl );
+ aTmpBox.DelFrms( rTbl );
+ rTbl.DeleteSel( pDoc, aSelBoxes, 0, 0, FALSE, FALSE );
+ }
+ break;
+ }
+
+ pDoc->GetNodes().MergeTable( rIdx );
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( pDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+ if( mpSaveRowSpan )
+ {
+ pTblNd = rIdx.GetNode().FindTableNode();
+ if( pTblNd )
+ pTblNd->GetTable().RestoreRowSpan( *mpSaveRowSpan );
+ }
+ ClearFEShellTabCols();
+}
+
+void SwUndoSplitTbl::Redo( SwUndoIter& rIter )
+{
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nTblNode;
+ pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize );
+
+ ClearFEShellTabCols();
+}
+
+void SwUndoSplitTbl::Repeat( SwUndoIter& rIter )
+{
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+
+ pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize );
+ ClearFEShellTabCols();
+}
+
+void SwUndoSplitTbl::SaveFormula( SwHistory& rHistory )
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ nFmlEnd = rHistory.Count();
+ pHistory->Move( 0, &rHistory );
+}
+
+/* */
+
+SwUndoMergeTbl::SwUndoMergeTbl( const SwTableNode& rTblNd,
+ const SwTableNode& rDelTblNd,
+ BOOL bWithPrv, USHORT nMd )
+ : SwUndo( UNDO_MERGE_TABLE ), pSavTbl( 0 ),
+ pHistory( 0 ), nMode( nMd ), bWithPrev( bWithPrv )
+{
+ // Endnode der letzen Tabellenzelle merken, die auf der Position verbleibt
+ if( bWithPrev )
+ nTblNode = rDelTblNd.EndOfSectionIndex() - 1;
+ else
+ nTblNode = rTblNd.EndOfSectionIndex() - 1;
+
+ aName = rDelTblNd.GetTable().GetFrmFmt()->GetName();
+ pSavTbl = new _SaveTable( rDelTblNd.GetTable() );
+
+ pSavHdl = bWithPrev ? new _SaveTable( rTblNd.GetTable(), 1 ) : 0;
+}
+
+SwUndoMergeTbl::~SwUndoMergeTbl()
+{
+ delete pSavTbl;
+ delete pSavHdl;
+ delete pHistory;
+}
+
+void SwUndoMergeTbl::Undo( SwUndoIter& rIter )
+{
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+
+ pPam->DeleteMark();
+ SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
+ rIdx = nTblNode;
+
+ SwTableNode* pTblNd = rIdx.GetNode().FindTableNode();
+ SwTable* pTbl = &pTblNd->GetTable();
+
+ SwTableFmlUpdate aMsgHnt( pTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ pDoc->UpdateTblFlds( &aMsgHnt );
+
+ //Lines fuer das Layout-Update herausuchen.
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( *pTbl );
+ aFndBox.DelFrms( *pTbl );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+ SwTableNode* pNew = pDoc->GetNodes().SplitTable( rIdx, TRUE, FALSE );
+
+ //Layout updaten
+ aFndBox.MakeFrms( *pTbl );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+ if( bWithPrev )
+ {
+ // den Namen umsetzen
+ pNew->GetTable().GetFrmFmt()->SetName( pTbl->GetFrmFmt()->GetName() );
+ pSavHdl->RestoreAttr( pNew->GetTable() );
+ }
+ else
+ pTbl = &pNew->GetTable();
+ pTbl->GetFrmFmt()->SetName( aName );
+
+// pSavTbl->CreateNew( *pTbl, FALSE );
+ pSavTbl->RestoreAttr( *pTbl );
+
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( pDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+
+ // fuer die neue Tabelle die Frames anlegen
+ SwNodeIndex aTmpIdx( *pNew );
+ pNew->MakeFrms( &aTmpIdx );
+
+ // Cursor irgendwo in den Content stellen
+ SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &rIdx );
+ pPam->GetPoint()->nContent.Assign( pCNd, 0 );
+
+ ClearFEShellTabCols();
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ if (pPCD)
+ {
+ pDoc->UpdateCharts( pTbl->GetFrmFmt()->GetName() );
+ pDoc->UpdateCharts( pNew->GetTable().GetFrmFmt()->GetName() );
+ }
+}
+
+void SwUndoMergeTbl::Redo( SwUndoIter& rIter )
+{
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nTblNode;
+ if( bWithPrev )
+ pPam->GetPoint()->nNode = nTblNode + 3;
+ else
+ pPam->GetPoint()->nNode = nTblNode;
+
+ pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode );
+
+ ClearFEShellTabCols();
+}
+
+void SwUndoMergeTbl::Repeat( SwUndoIter& rIter )
+{
+ SwPaM* pPam = rIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+
+ pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode );
+ ClearFEShellTabCols();
+}
+
+void SwUndoMergeTbl::SaveFormula( SwHistory& rHistory )
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+ pHistory->Move( 0, &rHistory );
+}
+
+/* */
+
+
+void InsertSort( SvUShorts& rArr, USHORT nIdx, USHORT* pInsPos )
+{
+ USHORT nO = rArr.Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ if( *(rArr.GetData() + nM) == nIdx )
+ {
+ OSL_ENSURE( FALSE, "Index ist schon vorhanden, darf nie sein!" );
+ return;
+ }
+ if( *(rArr.GetData() + nM) < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ break;
+ else
+ nO = nM - 1;
+ }
+ }
+ rArr.Insert( nIdx, nU );
+ if( pInsPos )
+ *pInsPos = nU;
+}
+
+void InsertSort( SvULongs& rArr, ULONG nIdx, USHORT* pInsPos )
+{
+ USHORT nO = rArr.Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ if( *(rArr.GetData() + nM) == nIdx )
+ {
+ OSL_ENSURE( FALSE, "Index ist schon vorhanden, darf nie sein!" );
+ return;
+ }
+ if( *(rArr.GetData() + nM) < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ break;
+ else
+ nO = nM - 1;
+ }
+ }
+ rArr.Insert( nIdx, nU );
+ if( pInsPos )
+ *pInsPos = nU;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+
+void CheckTable( const SwTable& rTbl )
+{
+ const SwNodes& rNds = rTbl.GetFrmFmt()->GetDoc()->GetNodes();
+ const SwTableSortBoxes& rSrtArr = rTbl.GetTabSortBoxes();
+ for( USHORT n = 0; n < rSrtArr.Count(); ++n )
+ {
+ const SwTableBox* pBox = rSrtArr[ n ];
+ const SwNode* pNd = pBox->GetSttNd();
+ OSL_ENSURE( rNds[ pBox->GetSttIdx() ] == pNd, "Box mit falchem StartNode" );
+ }
+}
+#endif
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/untblk.cxx b/sw/source/core/undo/untblk.cxx
new file mode 100644
index 000000000000..7eb48657e99b
--- /dev/null
+++ b/sw/source/core/undo/untblk.cxx
@@ -0,0 +1,369 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <undobj.hxx>
+#include <rolbck.hxx>
+#include <redline.hxx>
+
+
+
+SwUndoInserts::SwUndoInserts( SwUndoId nUndoId, const SwPaM& rPam )
+ : SwUndo( nUndoId ), SwUndRng( rPam ),
+ pTxtFmtColl( 0 ), pLastNdColl(0), pFrmFmts( 0 ), pFlyUndos(0), pRedlData( 0 ),
+ bSttWasTxtNd( TRUE ), nNdDiff( 0 ), pPos( 0 ), nSetPos( 0 )
+{
+ pHistory = new SwHistory;
+ SwDoc* pDoc = (SwDoc*)rPam.GetDoc();
+
+ SwTxtNode* pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ {
+ pTxtFmtColl = pTxtNd->GetTxtColl();
+ pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode,
+ 0, pTxtNd->GetTxt().Len(), false );
+ if( pTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode );
+
+ if( !nSttCntnt ) // dann werden Flys mitgenommen !!
+ {
+ USHORT nArrLen = pDoc->GetSpzFrmFmts()->Count();
+ for( USHORT n = 0; n < nArrLen; ++n )
+ {
+ SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ const SwPosition* pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ (pAnchor->GetAnchorId() == FLY_AT_PARA) &&
+ nSttNode == pAPos->nNode.GetIndex() )
+ {
+ if( !pFrmFmts )
+ pFrmFmts = new SvPtrarr;
+ pFrmFmts->Insert( pFmt, pFrmFmts->Count() );
+ }
+ }
+ }
+ }
+ // Redline beachten
+ if( pDoc->IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, pDoc->GetRedlineAuthor() );
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ }
+}
+
+// setze den Destination-Bereich nach dem Einlesen.
+
+void SwUndoInserts::SetInsertRange( const SwPaM& rPam, BOOL bScanFlys,
+ BOOL bSttIsTxtNd )
+{
+ const SwPosition* pTmpPos = rPam.End();
+ nEndNode = pTmpPos->nNode.GetIndex();
+ nEndCntnt = pTmpPos->nContent.GetIndex();
+ if( rPam.HasMark() )
+ {
+ if( pTmpPos == rPam.GetPoint() )
+ pTmpPos = rPam.GetMark();
+ else
+ pTmpPos = rPam.GetPoint();
+
+ nSttNode = pTmpPos->nNode.GetIndex();
+ nSttCntnt = pTmpPos->nContent.GetIndex();
+
+ if( !bSttIsTxtNd ) // wird eine Tabellenselektion eingefuegt,
+ {
+ ++nSttNode; // dann stimmt der CopyPam nicht ganz
+ bSttWasTxtNd = FALSE;
+ }
+ }
+
+ if( bScanFlys && !nSttCntnt )
+ {
+ // dann alle neuen Flys zusammen sammeln !!
+ SwDoc* pDoc = (SwDoc*)rPam.GetDoc();
+ pFlyUndos = new SwUndos();
+ USHORT nFndPos, nArrLen = pDoc->GetSpzFrmFmts()->Count();
+ for( USHORT n = 0; n < nArrLen; ++n )
+ {
+ SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ (pAnchor->GetAnchorId() == FLY_AT_PARA) &&
+ nSttNode == pAPos->nNode.GetIndex() )
+ {
+ if( !pFrmFmts ||
+ USHRT_MAX == ( nFndPos = pFrmFmts->GetPos( pFmt ) ) )
+ {
+ SwUndoInsLayFmt* pFlyUndo = new SwUndoInsLayFmt( pFmt,0,0 );
+ pFlyUndos->Insert( pFlyUndo, pFlyUndos->Count() );
+ }
+ else
+ pFrmFmts->Remove( nFndPos );
+ }
+ }
+ delete pFrmFmts, pFrmFmts = 0;
+ if( !pFlyUndos->Count() )
+ delete pFlyUndos, pFlyUndos = 0;
+ }
+}
+
+
+SwUndoInserts::~SwUndoInserts()
+{
+ if( pPos ) // loesche noch den Bereich aus dem UndoNodes Array
+ {
+ // Insert speichert den Inhalt in der IconSection
+ SwNodes& rUNds = pPos->nNode.GetNodes();
+ if( pPos->nContent.GetIndex() ) // nicht den gesamten Node loeschen
+ {
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "kein TextNode, aus dem geloescht werden soll" );
+ if( pTxtNd ) // Robust
+ {
+ pTxtNd->EraseText( pPos->nContent );
+ }
+ pPos->nNode++;
+ }
+ pPos->nContent.Assign( 0, 0 );
+ rUNds.Delete( pPos->nNode, rUNds.GetEndOfExtras().GetIndex() -
+ pPos->nNode.GetIndex() );
+ delete pPos;
+ }
+ delete pFrmFmts;
+ delete pFlyUndos;
+ delete pRedlData;
+}
+
+
+void SwUndoInserts::Undo( SwUndoIter& rUndoIter )
+{
+ SwPaM * pPam = rUndoIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+ SetPaM( rUndoIter );
+ BOOL bUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( FALSE );
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
+
+ // sind an Point/Mark 2 unterschiedliche TextNodes, dann muss ein
+ // JoinNext ausgefuehrt werden.
+ BOOL bJoinNext = nSttNode != nEndNode &&
+ pPam->GetMark()->nNode.GetNode().GetTxtNode() &&
+ pPam->GetPoint()->nNode.GetNode().GetTxtNode();
+
+
+ // gibts ueberhaupt Inhalt ? (laden von Zeichenvorlagen hat kein Inhalt!)
+ if( nSttNode != nEndNode || nSttCntnt != nEndCntnt )
+ {
+ if( nSttNode != nEndNode )
+ {
+ SwTxtNode* pTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode();
+ if( pTxtNd && pTxtNd->GetTxt().Len() == nEndCntnt )
+ pLastNdColl = pTxtNd->GetTxtColl();
+ }
+
+ RemoveIdxFromRange( *pPam, FALSE );
+ SetPaM( rUndoIter );
+
+ // sind Fussnoten oder CntntFlyFrames im Text ??
+ nSetPos = pHistory->Count();
+ nNdDiff = pPam->GetMark()->nNode.GetIndex();
+ DelCntntIndex( *pPam->GetMark(), *pPam->GetPoint() );
+ nNdDiff -= pPam->GetMark()->nNode.GetIndex();
+
+ if( *pPam->GetPoint() != *pPam->GetMark() )
+ {
+ pPos = new SwPosition( *pPam->GetPoint() );
+ MoveToUndoNds( *pPam, &pPos->nNode, &pPos->nContent );
+
+ if( !bSttWasTxtNd )
+ pPam->Move( fnMoveBackward, fnGoCntnt );
+ }
+ }
+
+ if( pFlyUndos )
+ {
+ ULONG nTmp = pPam->GetPoint()->nNode.GetIndex();
+ for( USHORT n = pFlyUndos->Count(); n; )
+ (*pFlyUndos)[ --n ]->Undo( rUndoIter );
+ nNdDiff += nTmp - pPam->GetPoint()->nNode.GetIndex();
+ }
+
+ SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
+ SwTxtNode* pTxtNode = rIdx.GetNode().GetTxtNode();
+ if( pTxtNode )
+ {
+ if( !pTxtFmtColl ) // falls 0, dann war hier auch kein TextNode,
+ { // dann muss dieser geloescht werden,
+ SwNodeIndex aDelIdx( rIdx );
+ rIdx++;
+ SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
+ xub_StrLen nCnt = 0; if( pCNd ) nCnt = pCNd->Len();
+ pPam->GetPoint()->nContent.Assign( pCNd, nCnt );
+ pPam->SetMark();
+ pPam->DeleteMark();
+
+ RemoveIdxRel( aDelIdx.GetIndex(), *pPam->GetPoint() );
+
+ pDoc->GetNodes().Delete( aDelIdx, 1 );
+ }
+ else
+ {
+ if( bJoinNext && pTxtNode->CanJoinNext())
+ {
+ {
+ RemoveIdxRel( rIdx.GetIndex()+1, SwPosition( rIdx,
+ SwIndex( pTxtNode, pTxtNode->GetTxt().Len() )));
+ }
+ pTxtNode->JoinNext();
+ }
+ // reset all text attributes in the paragraph!
+ pTxtNode->RstAttr( SwIndex(pTxtNode, 0), pTxtNode->Len(),
+ 0, 0, true );
+
+ // setze alle Attribute im Node zurueck
+ pTxtNode->ResetAllAttr();
+
+ if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
+ pTxtFmtColl = (SwTxtFmtColl*)pTxtNode->ChgFmtColl( pTxtFmtColl );
+
+ pHistory->SetTmpEnd( nSetPos );
+ pHistory->TmpRollback( pDoc, 0, false );
+ }
+ }
+
+ pDoc->DoUndo( bUndo );
+ if( pPam != rUndoIter.pAktPam )
+ delete pPam;
+}
+
+void SwUndoInserts::Redo( SwUndoIter& rUndoIter )
+{
+ // setze noch den Cursor auf den Redo-Bereich
+ SwPaM* pPam = rUndoIter.pAktPam;
+ SwDoc* pDoc = pPam->GetDoc();
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nSttNode - nNdDiff;
+ SwCntntNode* pCNd = pPam->GetCntntNode();
+ pPam->GetPoint()->nContent.Assign( pCNd, nSttCntnt );
+
+ SwTxtFmtColl* pSavTxtFmtColl = pTxtFmtColl;
+ if( pTxtFmtColl && pCNd && pCNd->IsTxtNode() )
+ pSavTxtFmtColl = ((SwTxtNode*)pCNd)->GetTxtColl();
+
+ pHistory->SetTmpEnd( nSetPos );
+
+ // alte Anfangs-Position fuers Rollback zurueckholen
+ if( ( nSttNode != nEndNode || nSttCntnt != nEndCntnt ) && pPos )
+ {
+ BOOL bMvBkwrd = MovePtBackward( *pPam );
+
+ // Inhalt wieder einfuegen. (erst pPos abmelden !!)
+ ULONG nMvNd = pPos->nNode.GetIndex();
+ xub_StrLen nMvCnt = pPos->nContent.GetIndex();
+ DELETEZ( pPos );
+ MoveFromUndoNds( *pDoc, nMvNd, nMvCnt, *pPam->GetMark() );
+ if( bSttWasTxtNd )
+ MovePtForward( *pPam, bMvBkwrd );
+ pPam->Exchange();
+ }
+
+ if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
+ {
+ SwTxtNode* pTxtNd = pPam->GetMark()->nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ pTxtNd->ChgFmtColl( pTxtFmtColl );
+ }
+ pTxtFmtColl = pSavTxtFmtColl;
+
+ if( pLastNdColl && USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pLastNdColl ) &&
+ pPam->GetPoint()->nNode != pPam->GetMark()->nNode )
+ {
+ SwTxtNode* pTxtNd = pPam->GetPoint()->nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ pTxtNd->ChgFmtColl( pLastNdColl );
+ }
+
+ if( pFlyUndos )
+ for( USHORT n = pFlyUndos->Count(); n; )
+ (*pFlyUndos)[ --n ]->Redo( rUndoIter );
+
+ pHistory->Rollback( pDoc, nSetPos );
+
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)( eOld & ~nsRedlineMode_t::REDLINE_IGNORE ));
+ pDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true);
+ pDoc->SetRedlineMode_intern( eOld );
+ }
+ else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ pDoc->GetRedlineTbl().Count() )
+ pDoc->SplitRedline( *pPam );
+}
+
+void SwUndoInserts::Repeat( SwUndoIter& rUndoIter )
+{
+ if( GetId() == rUndoIter.GetLastUndoId() )
+ return;
+
+ SwPaM aPam( *rUndoIter.pAktPam->GetPoint() );
+ SetPaM( aPam );
+ aPam.GetDoc()->CopyRange( aPam, *rUndoIter.pAktPam->GetPoint(), false );
+
+ rUndoIter.pLastUndoObj = this;
+}
+
+
+/* */
+
+
+SwUndoInsDoc::SwUndoInsDoc( const SwPaM& rPam )
+ : SwUndoInserts( UNDO_INSDOKUMENT, rPam )
+{
+}
+
+SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM& rPam )
+ : SwUndoInserts( UNDO_COPY, rPam )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */