xref: /trunk/main/sw/source/core/doc/docbm.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #include <MarkManager.hxx>
33 #include <bookmrk.hxx>
34 #include <boost/bind.hpp>
35 #include <cntfrm.hxx>
36 #include <crossrefbookmark.hxx>
37 #include <dcontact.hxx>
38 #include <doc.hxx>
39 #include <docary.hxx>
40 #include <xmloff/odffields.hxx>
41 #include <editsh.hxx>
42 #include <errhdl.hxx>
43 #include <fmtanchr.hxx>
44 #include <frmfmt.hxx>
45 #include <functional>
46 #include <hintids.hxx>
47 #include <mvsave.hxx>
48 #include <ndtxt.hxx>
49 #include <node.hxx>
50 #include <pam.hxx>
51 #include <redline.hxx>
52 #include <rolbck.hxx>
53 #include <rtl/ustrbuf.hxx>
54 #include <rtl/ustring.hxx>
55 #include <sal/types.h>
56 #include <sortedobjs.hxx>
57 #include <sfx2/linkmgr.hxx>
58 #include <swserv.hxx>
59 #include <swundo.hxx>
60 #include <tools/pstm.hxx>
61 #include <unocrsr.hxx>
62 #include <viscrs.hxx>
63 #include <stdio.h>
64 
65 
66 using namespace ::std;
67 using namespace ::boost;
68 using namespace ::sw::mark;
69 
70 namespace
71 {
72     static bool lcl_GreaterThan( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
73     {
74         return pIdx ? ( rPos.nNode > rNdIdx || ( rPos.nNode == rNdIdx && rPos.nContent >= pIdx->GetIndex() )) : rPos.nNode >= rNdIdx;
75     }
76 
77     static bool lcl_Lower( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
78     {
79         return rPos.nNode < rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent < pIdx->GetIndex() );
80     }
81 
82     static bool lcl_MarkOrderingByStart(const IDocumentMarkAccess::pMark_t& rpFirst,
83         const IDocumentMarkAccess::pMark_t& rpSecond)
84     {
85         return rpFirst->GetMarkStart() < rpSecond->GetMarkStart();
86     }
87 
88     static bool lcl_MarkOrderingByEnd(const IDocumentMarkAccess::pMark_t& rpFirst,
89         const IDocumentMarkAccess::pMark_t& rpSecond)
90     {
91         return rpFirst->GetMarkEnd() < rpSecond->GetMarkEnd();
92     }
93 
94     static void lcl_InsertMarkSorted(IDocumentMarkAccess::container_t& io_vMarks,
95         const IDocumentMarkAccess::pMark_t& pMark)
96     {
97         io_vMarks.insert(
98             lower_bound(
99                 io_vMarks.begin(),
100                 io_vMarks.end(),
101                 pMark,
102                 &lcl_MarkOrderingByStart),
103             pMark);
104     }
105 
106     static inline auto_ptr<SwPosition> lcl_PositionFromCntntNode(SwCntntNode * const pCntntNode, const bool bAtEnd=false)
107     {
108         auto_ptr<SwPosition> pResult(new SwPosition(*pCntntNode));
109         pResult->nContent.Assign(pCntntNode, bAtEnd ? pCntntNode->Len() : 0);
110         return pResult;
111     }
112 
113     // return a position at the begin of rEnd, if it is a CntntNode
114     // else set it to the begin of the Node after rEnd, if there is one
115     // else set it to the end of the node before rStt
116     // else set it to the CntntNode of the Pos outside the Range
117     static inline auto_ptr<SwPosition> lcl_FindExpelPosition(const SwNodeIndex& rStt,
118         const SwNodeIndex& rEnd,
119         const SwPosition& rOtherPosition)
120     {
121         SwCntntNode * pNode = rEnd.GetNode().GetCntntNode();
122         SwNodeIndex aStt = SwNodeIndex(rStt);
123         SwNodeIndex aEnd = SwNodeIndex(rEnd);
124         bool bAtEnd = false;
125         if(!pNode)
126             pNode = rEnd.GetNodes().GoNext(&aEnd), bAtEnd = false;
127         if(!pNode)
128             pNode = rStt.GetNodes().GoPrevious(&aStt), bAtEnd = true;
129         if(pNode)
130             return lcl_PositionFromCntntNode(pNode, bAtEnd);
131         return auto_ptr<SwPosition>(new SwPosition(rOtherPosition));
132     };
133 
134     static IMark* lcl_getMarkAfter(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
135     {
136         IDocumentMarkAccess::const_iterator_t pMarkAfter = upper_bound(
137             rMarks.begin(),
138             rMarks.end(),
139             rPos,
140             bind(&IMark::StartsAfter, _2, _1)); // finds the first that is starting after
141         if(pMarkAfter == rMarks.end()) return NULL;
142         return pMarkAfter->get();
143     };
144 
145     static IMark* lcl_getMarkBefore(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
146     {
147         // candidates from which to choose the mark before
148         IDocumentMarkAccess::container_t vCandidates;
149         // no need to consider marks starting after rPos
150         IDocumentMarkAccess::const_iterator_t pCandidatesEnd = upper_bound(
151             rMarks.begin(),
152             rMarks.end(),
153             rPos,
154             bind(&IMark::StartsAfter, _2, _1));
155         vCandidates.reserve(pCandidatesEnd - rMarks.begin());
156         // only marks ending before are candidates
157         remove_copy_if(
158             rMarks.begin(),
159             pCandidatesEnd,
160             back_inserter(vCandidates),
161             bind(logical_not<bool>(), bind(&IMark::EndsBefore, _1, rPos)));
162         // no candidate left => we are in front of the first mark or there are none
163         if(!vCandidates.size()) return NULL;
164         // return the highest (last) candidate using mark end ordering
165         return max_element(vCandidates.begin(), vCandidates.end(), &lcl_MarkOrderingByEnd)->get();
166     }
167 
168     static bool lcl_FixCorrectedMark(bool bChangedPos, bool bChangedOPos, MarkBase* io_pMark)
169     {
170         if( (bChangedPos || bChangedOPos) && io_pMark->IsExpanded() &&
171             io_pMark->GetOtherMarkPos().nNode.GetNode().FindTableBoxStartNode() !=
172             io_pMark->GetMarkPos().nNode.GetNode().FindTableBoxStartNode() )
173         {
174             if(!bChangedOPos)
175                 io_pMark->SetMarkPos(io_pMark->GetOtherMarkPos());
176             io_pMark->ClearOtherMarkPos();
177             DdeBookmark * const pDdeBkmk = dynamic_cast< DdeBookmark*>(io_pMark);
178             if(pDdeBkmk && pDdeBkmk->IsServer())
179                 pDdeBkmk->SetRefObject(NULL);
180             return true;
181         }
182         return false;
183     }
184 
185     static IDocumentMarkAccess::iterator_t lcl_FindMark(
186         IDocumentMarkAccess::container_t& rMarks,
187         const IDocumentMarkAccess::pMark_t& rpMarkToFind)
188     {
189         IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
190             rMarks.begin(), rMarks.end(),
191             rpMarkToFind, &lcl_MarkOrderingByStart);
192         // since there are usually not too many marks on the same start
193         // position, we are not doing a bisect search for the upper bound
194         // but instead start to iterate from pMarkLow directly
195         while(ppCurrentMark != rMarks.end() && **ppCurrentMark == *rpMarkToFind)
196         {
197             if(ppCurrentMark->get() == rpMarkToFind.get())
198             {
199                 //OSL_TRACE("found mark named '%s'",
200                 //    ::rtl::OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
201                 return ppCurrentMark;
202             }
203             ++ppCurrentMark;
204         }
205         // reached a mark starting on a later start pos or the end of the
206         // vector => not found
207         return rMarks.end();
208     };
209 
210     static IDocumentMarkAccess::iterator_t lcl_FindMarkAtPos(
211         IDocumentMarkAccess::container_t& rMarks,
212         const SwPosition& rPos,
213         const IDocumentMarkAccess::MarkType eType)
214     {
215         for(IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
216                 rMarks.begin(), rMarks.end(),
217                 rPos,
218                 bind(&IMark::StartsBefore, _1, _2));
219             ppCurrentMark != rMarks.end();
220             ++ppCurrentMark)
221         {
222             // Once we reach a mark starting after the target pos
223             // we do not need to continue
224             if(ppCurrentMark->get()->StartsAfter(rPos))
225                 break;
226             if(IDocumentMarkAccess::GetType(**ppCurrentMark) == eType)
227             {
228                 //OSL_TRACE("found mark named '%s'",
229                 //    ::rtl::OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
230                 return ppCurrentMark;
231             }
232         }
233         // reached a mark starting on a later start pos or the end of the
234         // vector => not found
235         return rMarks.end();
236     };
237 
238     static IDocumentMarkAccess::const_iterator_t lcl_FindMarkByName(
239         const ::rtl::OUString& rName,
240         IDocumentMarkAccess::const_iterator_t ppMarksBegin,
241         IDocumentMarkAccess::const_iterator_t ppMarksEnd)
242     {
243         return find_if(
244             ppMarksBegin,
245             ppMarksEnd,
246             bind(&::rtl::OUString::equals, bind(&IMark::GetName, _1), rName));
247     }
248 
249 #if 0
250     static void lcl_DebugMarks(IDocumentMarkAccess::container_t vMarks)
251     {
252         OSL_TRACE("%d Marks", vMarks.size());
253         for(IDocumentMarkAccess::iterator_t ppMark = vMarks.begin();
254             ppMark != vMarks.end();
255             ppMark++)
256         {
257             IMark* pMark = ppMark->get();
258             ::rtl::OString sName = ::rtl::OUStringToOString(pMark->GetName(), RTL_TEXTENCODING_UTF8);
259             const SwPosition* const pStPos = &pMark->GetMarkStart();
260             const SwPosition* const pEndPos = &pMark->GetMarkEnd();
261             OSL_TRACE("%s %s %d,%d %d,%d",
262                 typeid(*pMark).name(),
263                 sName.getStr(),
264                 pStPos->nNode.GetIndex(),
265                 pStPos->nContent.GetIndex(),
266                 pEndPos->nNode.GetIndex(),
267                 pEndPos->nContent.GetIndex());
268         }
269     };
270 #endif
271 }
272 
273 IDocumentMarkAccess::MarkType IDocumentMarkAccess::GetType(const IMark& rBkmk)
274 {
275     const std::type_info* const pMarkTypeInfo = &typeid(rBkmk);
276     // not using dynamic_cast<> here for performance
277     if(*pMarkTypeInfo == typeid(UnoMark))
278         return UNO_BOOKMARK;
279     else if(*pMarkTypeInfo == typeid(DdeBookmark))
280         return DDE_BOOKMARK;
281     else if(*pMarkTypeInfo == typeid(Bookmark))
282         return BOOKMARK;
283     else if(*pMarkTypeInfo == typeid(CrossRefHeadingBookmark))
284         return CROSSREF_HEADING_BOOKMARK;
285     else if(*pMarkTypeInfo == typeid(CrossRefNumItemBookmark))
286         return CROSSREF_NUMITEM_BOOKMARK;
287     else if(*pMarkTypeInfo == typeid(TextFieldmark))
288         return TEXT_FIELDMARK;
289     else if(*pMarkTypeInfo == typeid(CheckboxFieldmark))
290         return CHECKBOX_FIELDMARK;
291     else if(*pMarkTypeInfo == typeid(NavigatorReminder))
292         return NAVIGATOR_REMINDER;
293     else
294     {
295         OSL_ENSURE(false,
296             "IDocumentMarkAccess::GetType(..)"
297             " - unknown MarkType. This needs to be fixed!");
298         return UNO_BOOKMARK;
299     }
300 }
301 
302 namespace sw { namespace mark
303 {
304     MarkManager::MarkManager(SwDoc& rDoc)
305         : m_pDoc(&rDoc)
306     { }
307 #if OSL_DEBUG_LEVEL > 1
308     void MarkManager::dumpFieldmarks( ) const
309     {
310         const_iterator_t pIt = m_vFieldmarks.begin();
311         for (; pIt != m_vFieldmarks.end( ); pIt++)
312         {
313             rtl::OUString str = (*pIt)->ToString();
314             OSL_TRACE("%s\n",
315                 ::rtl::OUStringToOString(str, RTL_TEXTENCODING_UTF8).getStr());
316         }
317     }
318 #endif
319     ::sw::mark::IMark* MarkManager::makeMark(const SwPaM& rPaM,
320         const ::rtl::OUString& rName,
321         const IDocumentMarkAccess::MarkType eType)
322     {
323 #if 0
324         {
325             ::rtl::OString sName = ::rtl::OUStringToOString(rName, RTL_TEXTENCODING_UTF8);
326             const SwPosition* const pPos1 = rPaM.GetPoint();
327             const SwPosition* pPos2 = pPos1;
328             if(rPaM.HasMark())
329                 pPos2 = rPaM.GetMark();
330             OSL_TRACE("%s %d,%d %d,%d",
331                 sName.getStr(),
332                 pPos1->nNode.GetIndex(),
333                 pPos1->nContent.GetIndex(),
334                 pPos2->nNode.GetIndex(),
335                 pPos2->nContent.GetIndex());
336         }
337 #endif
338         // see for example _SaveCntntIdx, Shells
339         OSL_PRECOND(m_vMarks.size() < USHRT_MAX,
340             "MarkManager::makeMark(..)"
341             " - more than USHRT_MAX marks are not supported correctly");
342         // There should only be one CrossRefBookmark per Textnode per Type
343         OSL_PRECOND(
344             (eType != CROSSREF_NUMITEM_BOOKMARK && eType != CROSSREF_HEADING_BOOKMARK)
345             || (lcl_FindMarkAtPos(m_vBookmarks, *rPaM.GetPoint(), eType) == m_vBookmarks.end()),
346             "MarkManager::makeMark(..)"
347             " - creating duplicate CrossRefBookmark");
348 
349         // create mark
350         pMark_t pMark;
351         switch(eType)
352         {
353             case IDocumentMarkAccess::TEXT_FIELDMARK:
354                 pMark = shared_ptr<IMark>(new TextFieldmark(rPaM));
355                 break;
356             case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
357                 pMark = shared_ptr<IMark>(new CheckboxFieldmark(rPaM));
358                 break;
359             case IDocumentMarkAccess::NAVIGATOR_REMINDER:
360                 pMark = shared_ptr<IMark>(new NavigatorReminder(rPaM));
361                 break;
362             case IDocumentMarkAccess::BOOKMARK:
363                 pMark = shared_ptr<IMark>(new Bookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
364                 break;
365             case IDocumentMarkAccess::DDE_BOOKMARK:
366                 pMark = shared_ptr<IMark>(new DdeBookmark(rPaM));
367                 break;
368             case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
369                 pMark = shared_ptr<IMark>(new CrossRefHeadingBookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
370                 break;
371             case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
372                 pMark = shared_ptr<IMark>(new CrossRefNumItemBookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
373                 break;
374             case IDocumentMarkAccess::UNO_BOOKMARK:
375                 pMark = shared_ptr<IMark>(new UnoMark(rPaM));
376                 break;
377         }
378         OSL_ENSURE(pMark.get(),
379             "MarkManager::makeMark(..)"
380             " - Mark was not created.");
381         MarkBase* pMarkBase = dynamic_cast<MarkBase*>(pMark.get());
382 
383         if(pMark->GetMarkPos() != pMark->GetMarkStart())
384             pMarkBase->Swap();
385 
386         // for performance reasons, we trust UnoMarks to have a (generated) unique name
387         if(eType != IDocumentMarkAccess::UNO_BOOKMARK)
388             pMarkBase->SetName(getUniqueMarkName(pMarkBase->GetName()));
389 
390         // register mark
391         lcl_InsertMarkSorted(m_vMarks, pMark);
392         switch(eType)
393         {
394             case IDocumentMarkAccess::BOOKMARK:
395             case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
396             case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
397             // if(dynamic_cast<IBookmark*>)
398                 lcl_InsertMarkSorted(m_vBookmarks, pMark);
399                 break;
400             case IDocumentMarkAccess::TEXT_FIELDMARK:
401             case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
402             // if(dynamic_cast<IFieldmark*>
403                 lcl_InsertMarkSorted(m_vFieldmarks, pMark);
404                 break;
405             case IDocumentMarkAccess::NAVIGATOR_REMINDER:
406             case IDocumentMarkAccess::DDE_BOOKMARK:
407             case IDocumentMarkAccess::UNO_BOOKMARK:
408             // no special array for these
409                 break;
410         }
411         pMarkBase->InitDoc(m_pDoc);
412 #if 0
413         OSL_TRACE("--- makeType ---");
414         OSL_TRACE("Marks");
415         lcl_DebugMarks(m_vMarks);
416         OSL_TRACE("Bookmarks");
417         lcl_DebugMarks(m_vBookmarks);
418         OSL_TRACE("Fieldmarks");
419         lcl_DebugMarks(m_vFieldmarks);
420 #endif
421         return pMark.get();
422     }
423 
424     ::sw::mark::IFieldmark* MarkManager::makeFieldBookmark( const SwPaM& rPaM,
425         const rtl::OUString& rName,
426         const rtl::OUString& rType )
427     {
428         sw::mark::IMark* pMark = makeMark( rPaM, rName,
429                 IDocumentMarkAccess::TEXT_FIELDMARK );
430         sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
431         pFieldMark->SetFieldname( rType );
432 
433         return pFieldMark;
434     }
435 
436     ::sw::mark::IFieldmark* MarkManager::makeNoTextFieldBookmark( const SwPaM& rPaM,
437         const rtl::OUString& rName,
438         const rtl::OUString& rType)
439     {
440         sw::mark::IMark* pMark = makeMark( rPaM, rName,
441                 IDocumentMarkAccess::CHECKBOX_FIELDMARK );
442         sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
443         pFieldMark->SetFieldname( rType );
444 
445         return pFieldMark;
446     }
447 
448     ::sw::mark::IMark* MarkManager::getMarkForTxtNode(const SwTxtNode& rTxtNode,
449         const IDocumentMarkAccess::MarkType eType)
450     {
451         SwPosition aPos(rTxtNode);
452         aPos.nContent.Assign(&(const_cast<SwTxtNode&>(rTxtNode)), 0);
453         const iterator_t ppExistingMark = lcl_FindMarkAtPos(m_vBookmarks, aPos, eType);
454         if(ppExistingMark != m_vBookmarks.end())
455             return ppExistingMark->get();
456         const SwPaM aPaM(aPos);
457         return makeMark(aPaM, ::rtl::OUString(), eType);
458     }
459 
460     void MarkManager::repositionMark( ::sw::mark::IMark* const io_pMark,
461         const SwPaM& rPaM)
462     {
463         OSL_PRECOND(io_pMark->GetMarkPos().GetDoc() == m_pDoc,
464             "<MarkManager::repositionMark(..)>"
465             " - Mark is not in my doc.");
466         MarkBase* const pMarkBase = dynamic_cast< MarkBase* >(io_pMark);
467         pMarkBase->SetMarkPos(*(rPaM.GetPoint()));
468         if(rPaM.HasMark())
469             pMarkBase->SetOtherMarkPos(*(rPaM.GetMark()));
470         else
471             pMarkBase->ClearOtherMarkPos();
472 
473         if(pMarkBase->GetMarkPos() != pMarkBase->GetMarkStart())
474             pMarkBase->Swap();
475 
476         sortMarks();
477     }
478 
479     bool MarkManager::renameMark(::sw::mark::IMark* io_pMark, const ::rtl::OUString& rNewName)
480     {
481         OSL_PRECOND(io_pMark->GetMarkPos().GetDoc() == m_pDoc,
482             "<MarkManager::repositionMark(..)>"
483             " - Mark is not in my doc.");
484         if(io_pMark->GetName() == rNewName)
485             return true;
486         if(findMark(rNewName) != getMarksEnd())
487             return false;
488         dynamic_cast< ::sw::mark::MarkBase* >(io_pMark)->SetName(rNewName);
489         return true;
490     }
491 
492     void MarkManager::correctMarksAbsolute(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset)
493     {
494         const SwNode* const pOldNode = &rOldNode.GetNode();
495         SwPosition aNewPos(rNewPos);
496         aNewPos.nContent += nOffset;
497         bool isSortingNeeded = false;
498         for(iterator_t ppMark = m_vMarks.begin();
499             ppMark != m_vMarks.end();
500             ppMark++)
501         {
502             // is on position ??
503             bool bChangedPos = false, bChangedOPos = false;
504             ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
505             if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
506             {
507                 pMark->SetMarkPos(aNewPos);
508                 bChangedPos = true;
509             }
510             if (pMark->IsExpanded() &&
511                 &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
512             {
513                 pMark->SetMarkPos(aNewPos);
514                 bChangedOPos= true;
515             }
516             // illegal selection? collapse the mark and restore sorting later
517             isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
518         }
519         // restore sorting if needed
520         if(isSortingNeeded)
521             sortMarks();
522 #if 0
523         OSL_TRACE("correctMarksAbsolute");
524         lcl_DebugMarks(m_vMarks);
525 #endif
526     }
527 
528     void MarkManager::correctMarksRelative(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset)
529     {
530         const SwNode* const pOldNode = &rOldNode.GetNode();
531         SwPosition aNewPos(rNewPos);
532         aNewPos.nContent += nOffset;
533         bool isSortingNeeded = false;
534         for(iterator_t ppMark = m_vMarks.begin();
535             ppMark != m_vMarks.end();
536             ppMark++)
537         {
538             // is on position ??
539             bool bChangedPos = false, bChangedOPos = false;
540             ::sw::mark::MarkBase* const pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
541             if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
542             {
543                 SwPosition aNewPosRel(aNewPos);
544                 aNewPosRel.nContent += pMark->GetMarkPos().nContent.GetIndex();
545                 pMark->SetMarkPos(aNewPosRel);
546                 bChangedPos = true;
547             }
548             if(pMark->IsExpanded() &&
549                 &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
550             {
551                 SwPosition aNewPosRel(aNewPos);
552                 aNewPosRel.nContent += pMark->GetOtherMarkPos().nContent.GetIndex();
553                 pMark->SetOtherMarkPos(aNewPosRel);
554                 bChangedOPos = true;
555             }
556             // illegal selection? collapse the mark and restore sorting later
557             isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
558         }
559         // restore sorting if needed
560         if(isSortingNeeded)
561             sortMarks();
562 #if 0
563         OSL_TRACE("correctMarksRelative");
564         lcl_DebugMarks(m_vMarks);
565 #endif
566     }
567 
568     void MarkManager::deleteMarks(
569             const SwNodeIndex& rStt,
570             const SwNodeIndex& rEnd,
571             ::std::vector<SaveBookmark>* pSaveBkmk,
572             const SwIndex* pSttIdx,
573             const SwIndex* pEndIdx )
574     {
575         vector<const_iterator_t> vMarksToDelete;
576         bool isSortingNeeded = false;
577         // copy all bookmarks in the move area to a vector storing all position data as offset
578         // reassignment is performed after the move
579         for(iterator_t ppMark = m_vMarks.begin();
580             ppMark != m_vMarks.end();
581             ppMark++)
582         {
583             // navigator marks should not be moved
584             // TODO: Check if this might make them invalid
585             if(IDocumentMarkAccess::GetType(**ppMark) == NAVIGATOR_REMINDER)
586                 continue;
587 
588             ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
589             // on position ??
590             bool isPosInRange = (lcl_GreaterThan(pMark->GetMarkPos(), rStt, pSttIdx) &&
591                 lcl_Lower(pMark->GetMarkPos(), rEnd, pEndIdx));
592             bool isOtherPosInRange = (pMark->IsExpanded() &&
593                 lcl_GreaterThan(pMark->GetOtherMarkPos(), rStt, pSttIdx) &&
594                 lcl_Lower(pMark->GetOtherMarkPos(), rEnd, pEndIdx));
595             // special case: completely in range, touching the end?
596             if(pEndIdx &&
597                     ((isOtherPosInRange
598                     && pMark->GetMarkPos().nNode == rEnd
599                     && pMark->GetMarkPos().nContent == *pEndIdx)
600                 || (isPosInRange
601                     && pMark->IsExpanded()
602                     && pMark->GetOtherMarkPos().nNode == rEnd
603                     && pMark->GetOtherMarkPos().nContent == *pEndIdx)))
604             {
605                 isPosInRange = true, isOtherPosInRange = true;
606             }
607 
608             if(isPosInRange && (isOtherPosInRange || !pMark->IsExpanded()))
609             {
610                 // completely in range
611 
612                 // --> OD 2009-08-07 #i92125#
613                 bool bKeepCrossRefBkmk( false );
614                 {
615                     if ( rStt == rEnd &&
616                          ( IDocumentMarkAccess::GetType(*pMark) ==
617                             IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK ||
618                            IDocumentMarkAccess::GetType(*pMark) ==
619                             IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK ) )
620                     {
621                         bKeepCrossRefBkmk = true;
622                     }
623                 }
624                 if ( !bKeepCrossRefBkmk )
625                 {
626                     if(pSaveBkmk)
627                         pSaveBkmk->push_back(SaveBookmark(true, true, *pMark, rStt, pSttIdx));
628                     vMarksToDelete.push_back(ppMark);
629                 }
630                 // <--
631             }
632             else if(isPosInRange ^ isOtherPosInRange)
633             {
634                 // the bookmark is partitially in the range
635                 // move position of that is in the range out of it
636                 auto_ptr<SwPosition> pNewPos;
637                 if(pEndIdx)
638                     pNewPos = auto_ptr<SwPosition>(new SwPosition(
639                         rEnd,
640                         *pEndIdx));
641                 else
642                     pNewPos = lcl_FindExpelPosition(
643                         rStt,
644                         rEnd,
645                         isPosInRange ? pMark->GetOtherMarkPos() : pMark->GetMarkPos());
646 
647                 // --> OD 2009-08-06 #i92125#
648                 // no move of position for cross-reference bookmarks,
649                 // if move occurs inside a certain node
650                 if ( ( IDocumentMarkAccess::GetType(*pMark) !=
651                                 IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK &&
652                        IDocumentMarkAccess::GetType(*pMark) !=
653                                 IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK ) ||
654                      pMark->GetMarkPos().nNode != pNewPos->nNode )
655                 {
656                     if(isPosInRange)
657                         pMark->SetMarkPos(*pNewPos);
658                     else
659                         pMark->SetOtherMarkPos(*pNewPos);
660 
661                     // illegal selection? collapse the mark and restore sorting later
662                     isSortingNeeded |= lcl_FixCorrectedMark(isPosInRange, isOtherPosInRange, pMark);
663                 }
664                 // <--
665             }
666         }
667 
668         // we just remembered the iterators to delete, so we do not need to search
669         // for the shared_ptr<> (the entry in m_vMarks) again
670         // reverse iteration, since erasing an entry invalidates iterators
671         // behind it (the iterators in vMarksToDelete are sorted)
672         for(vector<const_iterator_t>::reverse_iterator pppMark = vMarksToDelete.rbegin();
673             pppMark != vMarksToDelete.rend();
674             pppMark++)
675         {
676             deleteMark(*pppMark);
677         }
678         if(isSortingNeeded)
679             sortMarks();
680 #if 0
681         OSL_TRACE("deleteMarks");
682         lcl_DebugMarks(m_vMarks);
683 #endif
684     }
685 
686     void MarkManager::deleteMark(const const_iterator_t ppMark)
687     {
688         if(ppMark == m_vMarks.end()) return;
689 
690         switch(IDocumentMarkAccess::GetType(**ppMark))
691         {
692             case IDocumentMarkAccess::BOOKMARK:
693             case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
694             case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
695             // if(dynamic_cast<IBookmark*>)
696             {
697                 IDocumentMarkAccess::iterator_t ppBookmark = lcl_FindMark(m_vBookmarks, *ppMark);
698                 OSL_ENSURE(ppBookmark != m_vBookmarks.end(),
699                     "<MarkManager::deleteMark(..)>"
700                     " - Bookmark not found.");
701                 m_vBookmarks.erase(ppBookmark);
702                 break;
703             }
704             case IDocumentMarkAccess::TEXT_FIELDMARK:
705             case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
706             // if(dynamic_cast<IFieldmark*>
707             {
708                 IDocumentMarkAccess::iterator_t ppFieldmark = lcl_FindMark(m_vFieldmarks, *ppMark);
709                 OSL_ENSURE(ppFieldmark != m_vFieldmarks.end(),
710                     "<MarkManager::deleteMark(..)>"
711                     " - Bookmark not found.");
712                 m_vFieldmarks.erase(ppFieldmark);
713                 break;
714             }
715             case IDocumentMarkAccess::NAVIGATOR_REMINDER:
716             case IDocumentMarkAccess::DDE_BOOKMARK:
717             case IDocumentMarkAccess::UNO_BOOKMARK:
718             // no special array for these
719                 break;
720         }
721         DdeBookmark* const pDdeBookmark = dynamic_cast<DdeBookmark*>(ppMark->get());
722         if(pDdeBookmark)
723             pDdeBookmark->DeregisterFromDoc(m_pDoc);
724         m_vMarks.erase(m_vMarks.begin() + (ppMark - m_vMarks.begin())); // clumsy const-cast
725     }
726 
727     void MarkManager::deleteMark(const IMark* const pMark)
728     {
729         OSL_PRECOND(pMark->GetMarkPos().GetDoc() == m_pDoc,
730             "<MarkManager::repositionMark(..)>"
731             " - Mark is not in my doc.");
732         // finds the last Mark that is starting before pMark
733         // (pMarkLow < pMark)
734         iterator_t pMarkLow = lower_bound(
735             m_vMarks.begin(), m_vMarks.end(),
736             pMark->GetMarkStart(),
737             bind(&IMark::StartsBefore, _1, _2));
738         // finds the first Mark that pMark is starting before
739         // (pMark < pMarkHigh)
740         //iterator_t pMarkHigh = upper_bound(
741         //    pMarkLow, m_vMarks.end(),
742         //    pMark->GetMarkStart(),
743         //    bind(&IMark::StartsBefore, _2, _1));
744         // since it should be rare that pMark isnt found at all
745         // we skip the bisect search on the upper bound
746         iterator_t pMarkHigh = m_vMarks.end();
747         iterator_t pMarkFound = find_if(
748             pMarkLow, pMarkHigh,
749             bind(equal_to<const IMark*>(), bind(&shared_ptr<IMark>::get, _1), pMark));
750         if(pMarkFound != pMarkHigh)
751             deleteMark(pMarkFound);
752     }
753 
754     void MarkManager::clearAllMarks()
755     {
756         m_vFieldmarks.clear();
757         m_vBookmarks.clear();
758 #ifdef DEBUG
759         for(iterator_t pBkmk = m_vMarks.begin();
760             pBkmk != m_vMarks.end();
761             ++pBkmk)
762             OSL_ENSURE(pBkmk->unique(),
763                 "<MarkManager::clearAllMarks(..)>"
764                 " - a Bookmark is still in use.");
765 #endif
766         m_vMarks.clear();
767     }
768 
769     IDocumentMarkAccess::const_iterator_t MarkManager::findMark(const ::rtl::OUString& rName) const
770     {
771         return lcl_FindMarkByName(rName, m_vMarks.begin(), m_vMarks.end());
772     }
773 
774     IDocumentMarkAccess::const_iterator_t MarkManager::findBookmark(const ::rtl::OUString& rName) const
775     {
776         return lcl_FindMarkByName(rName, m_vBookmarks.begin(), m_vBookmarks.end());
777     }
778 
779     IDocumentMarkAccess::const_iterator_t MarkManager::getMarksBegin() const
780         { return m_vMarks.begin(); }
781 
782     IDocumentMarkAccess::const_iterator_t MarkManager::getMarksEnd() const
783         { return m_vMarks.end(); }
784 
785     sal_Int32 MarkManager::getMarksCount() const
786         { return m_vMarks.size(); }
787 
788     IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksBegin() const
789         { return m_vBookmarks.begin(); }
790 
791     IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksEnd() const
792         { return m_vBookmarks.end(); }
793 
794     sal_Int32 MarkManager::getBookmarksCount() const
795         { return m_vBookmarks.size(); }
796 
797     IFieldmark* MarkManager::getFieldmarkFor(const SwPosition& rPos) const
798     {
799         const_iterator_t pFieldmark = find_if(
800             m_vFieldmarks.begin(),
801             m_vFieldmarks.end( ),
802             bind(&IMark::IsCoveringPosition, _1, rPos));
803         if(pFieldmark == m_vFieldmarks.end()) return NULL;
804         return dynamic_cast<IFieldmark*>(pFieldmark->get());
805     }
806 
807     IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos) const
808         { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, rPos)); }
809 
810     IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const
811         { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos)); }
812 
813     ::rtl::OUString MarkManager::getUniqueMarkName(const ::rtl::OUString& rName) const
814     {
815         OSL_ENSURE(rName.getLength(),
816             "<MarkManager::getUniqueMarkName(..)>"
817             " - a name should be proposed");
818         if(findMark(rName) == getMarksEnd()) return rName;
819         ::rtl::OUStringBuffer sBuf;
820         ::rtl::OUString sTmp;
821         for(sal_Int32 nCnt = 1; nCnt < SAL_MAX_INT32; nCnt++)
822         {
823             sTmp = sBuf.append(rName).append(nCnt).makeStringAndClear();
824             if(findMark(sTmp) == getMarksEnd()) break;
825         }
826         return sTmp;
827     }
828 
829     void MarkManager::sortMarks()
830     {
831         sort(m_vMarks.begin(), m_vMarks.end(), &lcl_MarkOrderingByStart);
832         sort(m_vBookmarks.begin(), m_vBookmarks.end(), &lcl_MarkOrderingByStart);
833         sort(m_vFieldmarks.begin(), m_vFieldmarks.end(), &lcl_MarkOrderingByStart);
834     }
835 
836 }} // namespace ::sw::mark
837 
838 
839 // old implementation
840 
841 //SV_IMPL_OP_PTRARR_SORT(SwBookmarks, SwBookmarkPtr)
842 
843 #define PCURCRSR (_pCurrCrsr)
844 #define FOREACHPAM_START(pSttCrsr) \
845 	{\
846 		SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \
847 		do {
848 
849 #define FOREACHPAM_END() \
850 		} while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \
851 	}
852 #define PCURSH ((SwCrsrShell*)_pStartShell)
853 #define FOREACHSHELL_START( pEShell ) \
854     {\
855 		ViewShell *_pStartShell = pEShell; \
856 		do { \
857 			if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
858 			{
859 
860 #define FOREACHSHELL_END( pEShell ) \
861 			} \
862         } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \
863 	}
864 
865 namespace
866 {
867     // Aufbau vom Array: 2 longs,
868     //	1. Long enthaelt Type und Position im DocArray,
869     //	2. die ContentPosition
870     //
871     //	CntntType --
872     //			0x8000 = Bookmark Pos1
873     //			0x8001 = Bookmark Pos2
874     //			0x2000 = Absatzgebundener Rahmen
875     //			0x2001 = Auto-Absatzgebundener Rahmen, der umgehaengt werden soll
876     //			0x1000 = Redline Mark
877     //			0x1001 = Redline Point
878     //			0x0800 = Crsr aus der CrsrShell Mark
879     //			0x0801 = Crsr aus der CrsrShell Point
880     //			0x0400 = UnoCrsr Mark
881     //			0x0401 = UnoCrsr Point
882     //
883 
884     class _SwSaveTypeCountContent
885     {
886         union {
887             struct { sal_uInt16 nType, nCount; } TC;
888             sal_uLong nTypeCount;
889             } TYPECOUNT;
890         xub_StrLen nContent;
891 
892     public:
893         _SwSaveTypeCountContent() { TYPECOUNT.nTypeCount = 0; nContent = 0; }
894         _SwSaveTypeCountContent( sal_uInt16 nType )
895             {
896                 SetTypeAndCount( nType, 0 );
897                 nContent = 0;
898             }
899         _SwSaveTypeCountContent( const SvULongs& rArr, sal_uInt16& rPos )
900             {
901                 TYPECOUNT.nTypeCount = rArr[ rPos++ ];
902                 nContent = static_cast<xub_StrLen>(rArr[ rPos++ ]);
903             }
904         void Add( SvULongs& rArr )
905         {
906             rArr.Insert( TYPECOUNT.nTypeCount, rArr.Count() );
907             rArr.Insert( nContent, rArr.Count() );
908         }
909 
910         void SetType( sal_uInt16 n )		{ TYPECOUNT.TC.nType = n; }
911         sal_uInt16 GetType() const 			{ return TYPECOUNT.TC.nType; }
912         void IncType() 	 				{ ++TYPECOUNT.TC.nType; }
913         void DecType() 	 				{ --TYPECOUNT.TC.nType; }
914 
915         void SetCount( sal_uInt16 n ) 		{ TYPECOUNT.TC.nCount = n; }
916         sal_uInt16 GetCount() const 		{ return TYPECOUNT.TC.nCount; }
917         sal_uInt16 IncCount()  				{ return ++TYPECOUNT.TC.nCount; }
918         sal_uInt16 DecCount()  				{ return --TYPECOUNT.TC.nCount; }
919 
920         void SetTypeAndCount( sal_uInt16 nT, sal_uInt16 nC )
921             { TYPECOUNT.TC.nCount = nC; TYPECOUNT.TC.nType = nT; }
922 
923         void SetContent( xub_StrLen n )		{ nContent = n; }
924         xub_StrLen GetContent() const		{ return nContent; }
925     };
926 
927     // #i59534: If a paragraph will be splitted we have to restore some redline positions
928     // This help function checks a position compared with a node and an content index
929 
930     static const int BEFORE_NODE = 0;          // Position before the given node index
931     static const int BEFORE_SAME_NODE = 1;     // Same node index but content index before given content index
932     static const int SAME_POSITION = 2;        // Same node index and samecontent index
933     static const int BEHIND_SAME_NODE = 3;     // Same node index but content index behind given content index
934     static const int BEHIND_NODE = 4;          // Position behind the given node index
935 
936     static int lcl_RelativePosition( const SwPosition& rPos, sal_uLong nNode, xub_StrLen nCntnt )
937     {
938         sal_uLong nIndex = rPos.nNode.GetIndex();
939         int nReturn = BEFORE_NODE;
940         if( nIndex == nNode )
941         {
942             xub_StrLen nCntIdx = rPos.nContent.GetIndex();
943             if( nCntIdx < nCntnt )
944                 nReturn = BEFORE_SAME_NODE;
945             else if( nCntIdx == nCntnt )
946                 nReturn = SAME_POSITION;
947             else
948                 nReturn = BEHIND_SAME_NODE;
949         }
950         else if( nIndex > nNode )
951             nReturn = BEHIND_NODE;
952         return nReturn;
953     }
954 
955 
956     static inline int lcl_Greater( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
957     {
958         return rPos.nNode > rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent > pIdx->GetIndex() );
959     }
960 
961     static void lcl_ChkPaM( SvULongs& rSaveArr, sal_uLong nNode, xub_StrLen nCntnt,
962                     const SwPaM& rPam, _SwSaveTypeCountContent& rSave,
963                     sal_Bool bChkSelDirection )
964     {
965         // SelektionsRichtung beachten
966         bool bBound1IsStart = !bChkSelDirection ? sal_True :
967                             ( *rPam.GetPoint() < *rPam.GetMark()
968                                 ? rPam.GetPoint() == &rPam.GetBound()
969                                 : rPam.GetMark() == &rPam.GetBound());
970 
971         const SwPosition* pPos = &rPam.GetBound( sal_True );
972         if( pPos->nNode.GetIndex() == nNode &&
973             ( bBound1IsStart ? pPos->nContent.GetIndex() < nCntnt
974                                 : pPos->nContent.GetIndex() <= nCntnt ))
975         {
976             rSave.SetContent( pPos->nContent.GetIndex() );
977             rSave.Add( rSaveArr );
978         }
979 
980         pPos = &rPam.GetBound( sal_False );
981         if( pPos->nNode.GetIndex() == nNode &&
982             ( (bBound1IsStart && bChkSelDirection)
983                         ? pPos->nContent.GetIndex() <= nCntnt
984                         : pPos->nContent.GetIndex() < nCntnt ))
985         {
986             rSave.SetContent( pPos->nContent.GetIndex() );
987             rSave.IncType();
988             rSave.Add( rSaveArr );
989             rSave.DecType();
990         }
991     }
992 
993 }
994 
995 
996 // IDocumentMarkAccess for SwDoc
997 
998 IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess()
999     { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
1000 
1001 const IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess() const
1002     { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
1003 
1004 // SaveBookmark
1005 
1006 SaveBookmark::SaveBookmark(
1007     bool bSavePos,
1008     bool bSaveOtherPos,
1009     const IMark& rBkmk,
1010     const SwNodeIndex & rMvPos,
1011     const SwIndex* pIdx)
1012     : m_aName(rBkmk.GetName())
1013     , m_aShortName()
1014     , m_aCode()
1015     , m_bSavePos(bSavePos)
1016     , m_bSaveOtherPos(bSaveOtherPos)
1017     , m_eOrigBkmType(IDocumentMarkAccess::GetType(rBkmk))
1018 {
1019     const IBookmark* const pBookmark = dynamic_cast< const IBookmark* >(&rBkmk);
1020     if(pBookmark)
1021     {
1022         m_aShortName = pBookmark->GetShortName();
1023         m_aCode = pBookmark->GetKeyCode();
1024 
1025         ::sfx2::Metadatable const*const pMetadatable(
1026                 dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
1027         if (pMetadatable)
1028         {
1029             m_pMetadataUndo = pMetadatable->CreateUndo();
1030         }
1031     }
1032     m_nNode1 = rBkmk.GetMarkPos().nNode.GetIndex();
1033     m_nCntnt1 = rBkmk.GetMarkPos().nContent.GetIndex();
1034 
1035     if(m_bSavePos)
1036     {
1037         m_nNode1 -= rMvPos.GetIndex();
1038         if(pIdx && !m_nNode1)
1039             m_nCntnt1 -= pIdx->GetIndex();
1040     }
1041 
1042     if(rBkmk.IsExpanded())
1043     {
1044         m_nNode2 = rBkmk.GetOtherMarkPos().nNode.GetIndex();
1045         m_nCntnt2 = rBkmk.GetOtherMarkPos().nContent.GetIndex();
1046 
1047         if(m_bSaveOtherPos)
1048         {
1049             m_nNode2 -= rMvPos.GetIndex();
1050             if(pIdx && !m_nNode2)
1051                 m_nCntnt2 -= pIdx->GetIndex();
1052         }
1053     }
1054     else
1055         m_nNode2 = ULONG_MAX, m_nCntnt2 = STRING_NOTFOUND;
1056 }
1057 
1058 void SaveBookmark::SetInDoc(
1059     SwDoc* pDoc,
1060     const SwNodeIndex& rNewPos,
1061     const SwIndex* pIdx)
1062 {
1063     SwPaM aPam(rNewPos.GetNode());
1064     if(pIdx)
1065         aPam.GetPoint()->nContent = *pIdx;
1066 
1067     if(ULONG_MAX != m_nNode2)
1068     {
1069         aPam.SetMark();
1070 
1071         if(m_bSaveOtherPos)
1072         {
1073             aPam.GetMark()->nNode += m_nNode2;
1074             if(pIdx && !m_nNode2)
1075                 aPam.GetMark()->nContent += m_nCntnt2;
1076             else
1077                 aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
1078         }
1079         else
1080         {
1081             aPam.GetMark()->nNode = m_nNode2;
1082             aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
1083         }
1084     }
1085 
1086     if(m_bSavePos)
1087     {
1088         aPam.GetPoint()->nNode += m_nNode1;
1089 
1090         if(pIdx && !m_nNode1)
1091             aPam.GetPoint()->nContent += m_nCntnt1;
1092         else
1093             aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
1094     }
1095     else
1096     {
1097         aPam.GetPoint()->nNode = m_nNode1;
1098         aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
1099     }
1100 
1101     if(!aPam.HasMark()
1102         || CheckNodesRange(aPam.GetPoint()->nNode, aPam.GetMark()->nNode, sal_True))
1103     {
1104         ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pDoc->getIDocumentMarkAccess()->makeMark(aPam, m_aName, m_eOrigBkmType));
1105         if(pBookmark)
1106         {
1107             pBookmark->SetKeyCode(m_aCode);
1108             pBookmark->SetShortName(m_aShortName);
1109             if (m_pMetadataUndo)
1110             {
1111                 ::sfx2::Metadatable * const pMeta(
1112                     dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
1113                 OSL_ENSURE(pMeta, "metadata undo, but not metadatable?");
1114                 if (pMeta)
1115                 {
1116                     pMeta->RestoreMetadata(m_pMetadataUndo);
1117                 }
1118             }
1119         }
1120     }
1121 }
1122 
1123 // _DelBookmarks, _{Save,Restore}CntntIdx
1124 
1125 void _DelBookmarks(
1126     const SwNodeIndex& rStt,
1127     const SwNodeIndex& rEnd,
1128     ::std::vector<SaveBookmark> * pSaveBkmk,
1129     const SwIndex* pSttIdx,
1130     const SwIndex* pEndIdx)
1131 {
1132     // illegal range ??
1133     if(rStt.GetIndex() > rEnd.GetIndex()
1134         || (rStt == rEnd && (!pSttIdx || pSttIdx->GetIndex() >= pEndIdx->GetIndex())))
1135         return;
1136     SwDoc* const pDoc = rStt.GetNode().GetDoc();
1137 
1138     pDoc->getIDocumentMarkAccess()->deleteMarks(rStt, rEnd, pSaveBkmk, pSttIdx, pEndIdx);
1139 
1140     // kopiere alle Redlines, die im Move Bereich stehen in ein
1141     // Array, das alle Angaben auf die Position als Offset speichert.
1142     // Die neue Zuordung erfolgt nach dem Moven.
1143     SwRedlineTbl& rTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
1144     for(sal_uInt16 nCnt = 0; nCnt < rTbl.Count(); ++nCnt )
1145     {
1146         // liegt auf der Position ??
1147         SwRedline* pRedl = rTbl[ nCnt ];
1148 
1149         SwPosition *pRStt = &pRedl->GetBound(sal_True),
1150                    *pREnd = &pRedl->GetBound(sal_False);
1151         if( *pRStt > *pREnd )
1152         {
1153             SwPosition *pTmp = pRStt; pRStt = pREnd, pREnd = pTmp;
1154         }
1155 
1156         if( lcl_Greater( *pRStt, rStt, pSttIdx ) && lcl_Lower( *pRStt, rEnd, pEndIdx ))
1157         {
1158             pRStt->nNode = rEnd;
1159             if( pEndIdx )
1160                 pRStt->nContent = *pEndIdx;
1161             else
1162             {
1163                 sal_Bool bStt = sal_True;
1164                 SwCntntNode* pCNd = pRStt->nNode.GetNode().GetCntntNode();
1165                 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoNext( &pRStt->nNode )) )
1166                 {
1167                     bStt = sal_False;
1168                     pRStt->nNode = rStt;
1169                     if( 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pRStt->nNode )) )
1170                     {
1171                         pRStt->nNode = pREnd->nNode;
1172                         pCNd = pRStt->nNode.GetNode().GetCntntNode();
1173                     }
1174                 }
1175                 xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
1176                 pRStt->nContent.Assign( pCNd, nTmp );
1177             }
1178         }
1179         if( lcl_Greater( *pREnd, rStt, pSttIdx ) && lcl_Lower( *pREnd, rEnd, pEndIdx ))
1180         {
1181             pREnd->nNode = rStt;
1182             if( pSttIdx )
1183                 pREnd->nContent = *pSttIdx;
1184             else
1185             {
1186                 sal_Bool bStt = sal_False;
1187                 SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
1188                 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pREnd->nNode )) )
1189                 {
1190                     bStt = sal_True;
1191                     pREnd->nNode = rEnd;
1192                     if( 0 == ( pCNd = pDoc->GetNodes().GoNext( &pREnd->nNode )) )
1193                     {
1194                         pREnd->nNode = pRStt->nNode;
1195                         pCNd = pREnd->nNode.GetNode().GetCntntNode();
1196                     }
1197                 }
1198                 xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
1199                 pREnd->nContent.Assign( pCNd, nTmp );
1200             }
1201         }
1202     }
1203 }
1204 
1205 void _SaveCntntIdx(SwDoc* pDoc,
1206     sal_uLong nNode,
1207     xub_StrLen nCntnt,
1208     SvULongs& rSaveArr,
1209     sal_uInt8 nSaveFly)
1210 {
1211     // 1. Bookmarks
1212     _SwSaveTypeCountContent aSave;
1213     aSave.SetTypeAndCount( 0x8000, 0 );
1214 
1215     IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1216     const sal_Int32 nBkmks = pMarkAccess->getMarksCount();
1217     for(; aSave.GetCount() < nBkmks; aSave.IncCount())
1218     {
1219         bool bEqual = false;
1220         bool bLower = false;
1221         const ::sw::mark::IMark* pBkmk = (pMarkAccess->getMarksBegin() + aSave.GetCount())->get();
1222         if(pBkmk->GetMarkPos().nNode.GetIndex() == nNode
1223             && pBkmk->GetMarkPos().nContent.GetIndex() <= nCntnt)
1224         {
1225             if(pBkmk->GetMarkPos().nContent.GetIndex() < nCntnt)
1226             {
1227                 bLower = true; // a hint for the other position...
1228                 aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
1229                 aSave.Add(rSaveArr);
1230             }
1231             else // if a bookmark position is equal nCntnt, the other position
1232                 bEqual = true; // has to decide if it is added to the array
1233         }
1234 
1235         if(pBkmk->IsExpanded()
1236             && pBkmk->GetOtherMarkPos().nNode.GetIndex() == nNode
1237             && pBkmk->GetOtherMarkPos().nContent.GetIndex() <= nCntnt)
1238         {
1239             if(bLower || pBkmk->GetOtherMarkPos().nContent.GetIndex() < nCntnt)
1240             {
1241                 if(bEqual)
1242                 { // the other position is before, the (main) position is equal
1243                     aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
1244                     aSave.Add(rSaveArr);
1245                 }
1246                 aSave.SetContent(pBkmk->GetOtherMarkPos().nContent.GetIndex());
1247                 aSave.IncType();
1248                 aSave.Add(rSaveArr);
1249                 aSave.DecType();
1250             }
1251         }
1252     }
1253 
1254 	// 2. Redlines
1255 	aSave.SetTypeAndCount( 0x1000, 0 );
1256 	const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
1257 	for( ; aSave.GetCount() < rRedlTbl.Count(); aSave.IncCount() )
1258 	{
1259 		const SwRedline* pRdl = rRedlTbl[ aSave.GetCount() ];
1260         int nPointPos = lcl_RelativePosition( *pRdl->GetPoint(), nNode, nCntnt );
1261         int nMarkPos = pRdl->HasMark() ? lcl_RelativePosition( *pRdl->GetMark(), nNode, nCntnt ) :
1262                                           nPointPos;
1263         // #i59534: We have to store the positions inside the same node before the insert position
1264         // and the one at the insert position if the corresponding Point/Mark position is before
1265         // the insert position.
1266         if( nPointPos == BEFORE_SAME_NODE ||
1267             ( nPointPos == SAME_POSITION && nMarkPos < SAME_POSITION ) )
1268 		{
1269 			aSave.SetContent( pRdl->GetPoint()->nContent.GetIndex() );
1270 			aSave.IncType();
1271 			aSave.Add( rSaveArr );
1272 			aSave.DecType();
1273 		}
1274 		if( pRdl->HasMark() && ( nMarkPos == BEFORE_SAME_NODE ||
1275             ( nMarkPos == SAME_POSITION && nPointPos < SAME_POSITION ) ) )
1276         {
1277 			aSave.SetContent( pRdl->GetMark()->nContent.GetIndex() );
1278 			aSave.Add( rSaveArr );
1279 		}
1280 	}
1281 
1282 	// 4. Absatzgebundene Objekte
1283 	{
1284 		SwCntntNode *pNode = pDoc->GetNodes()[nNode]->GetCntntNode();
1285 		if( pNode )
1286 		{
1287 
1288 			SwFrm* pFrm = pNode->getLayoutFrm( pDoc->GetCurrentLayout() );
1289 #if OSL_DEBUG_LEVEL > 1
1290 			static sal_Bool bViaDoc = sal_False;
1291 			if( bViaDoc )
1292 				pFrm = NULL;
1293 #endif
1294 			if( pFrm ) // gibt es ein Layout? Dann ist etwas billiger...
1295 			{
1296 				if( pFrm->GetDrawObjs() )
1297 				{
1298                     const SwSortedObjs& rDObj = *pFrm->GetDrawObjs();
1299                     for( sal_uInt32 n = rDObj.Count(); n; )
1300 					{
1301                         SwAnchoredObject* pObj = rDObj[ --n ];
1302                         const SwFrmFmt& rFmt = pObj->GetFrmFmt();
1303                         const SwFmtAnchor& rAnchor = rFmt.GetAnchor();
1304                         SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
1305                         if ( pAPos &&
1306                              ( ( nSaveFly &&
1307                                  FLY_AT_PARA == rAnchor.GetAnchorId() ) ||
1308                                ( FLY_AT_CHAR == rAnchor.GetAnchorId() ) ) )
1309                         {
1310 							aSave.SetType( 0x2000 );
1311 							aSave.SetContent( pAPos->nContent.GetIndex() );
1312 
1313 							OSL_ENSURE( nNode == pAPos->nNode.GetIndex(),
1314 									"_SaveCntntIdx: Wrong Node-Index" );
1315                             if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
1316 							{
1317 								if( nCntnt <= aSave.GetContent() )
1318 								{
1319 									if( SAVEFLY_SPLIT == nSaveFly )
1320 										aSave.IncType(); // = 0x2001;
1321 									else
1322 										continue;
1323 								}
1324 							}
1325 							aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() );
1326 							while( aSave.GetCount() &&
1327                                     &rFmt != (*pDoc->GetSpzFrmFmts())[
1328                                     aSave.DecCount() ] )
1329 								; // nothing
1330                             OSL_ENSURE( &rFmt == (*pDoc->GetSpzFrmFmts())[
1331 													aSave.GetCount() ],
1332 									"_SaveCntntIdx: Lost FrameFormat" );
1333 							aSave.Add( rSaveArr );
1334 						}
1335 					}
1336 				}
1337 			}
1338 			else // Schade, kein Layout, dann ist es eben etwas teurer...
1339 			{
1340 				for( aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() );
1341 						aSave.GetCount() ; )
1342 				{
1343 					SwFrmFmt* pFrmFmt = (*pDoc->GetSpzFrmFmts())[
1344 												aSave.DecCount() ];
1345 					if ( RES_FLYFRMFMT != pFrmFmt->Which() &&
1346 							RES_DRAWFRMFMT != pFrmFmt->Which() )
1347 						continue;
1348 
1349 					const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
1350                     SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
1351                     if ( pAPos && ( nNode == pAPos->nNode.GetIndex() ) &&
1352                          ( FLY_AT_PARA == rAnchor.GetAnchorId() ||
1353                            FLY_AT_CHAR == rAnchor.GetAnchorId() ) )
1354                     {
1355 						aSave.SetType( 0x2000 );
1356 						aSave.SetContent( pAPos->nContent.GetIndex() );
1357                         if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
1358 						{
1359 							if( nCntnt <= aSave.GetContent() )
1360 							{
1361 								if( SAVEFLY_SPLIT == nSaveFly )
1362 									aSave.IncType(); // = 0x2001;
1363 								else
1364 									continue;
1365 							}
1366 						}
1367 						aSave.Add( rSaveArr );
1368 					}
1369 				}
1370 			}
1371 		}
1372 	}
1373 	// 5. CrsrShell
1374 	{
1375 		SwCrsrShell* pShell = pDoc->GetEditShell();
1376 		if( pShell )
1377 		{
1378 			aSave.SetTypeAndCount( 0x800, 0 );
1379 			FOREACHSHELL_START( pShell )
1380 				SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
1381 				if( _pStkCrsr )
1382 				do {
1383 					lcl_ChkPaM( rSaveArr, nNode, nCntnt, *_pStkCrsr,
1384 								aSave, sal_False );
1385 					aSave.IncCount();
1386 				} while ( (_pStkCrsr != 0 ) &&
1387 					((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
1388 
1389 				FOREACHPAM_START( PCURSH->_GetCrsr() )
1390 					lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR,
1391 								aSave, sal_False );
1392 					aSave.IncCount();
1393 				FOREACHPAM_END()
1394 
1395 			FOREACHSHELL_END( pShell )
1396 		}
1397 	}
1398 	// 6. UnoCrsr
1399 	{
1400 		aSave.SetTypeAndCount( 0x400, 0 );
1401 		const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
1402 		for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
1403 		{
1404 			FOREACHPAM_START( rTbl[ n ] )
1405 				lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False );
1406 				aSave.IncCount();
1407 			FOREACHPAM_END()
1408 
1409             SwUnoTableCrsr* pUnoTblCrsr =
1410                 dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]);
1411 			if( pUnoTblCrsr )
1412 			{
1413 				FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
1414 					lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False );
1415 					aSave.IncCount();
1416 				FOREACHPAM_END()
1417 			}
1418 		}
1419 	}
1420 }
1421 
1422 
1423 void _RestoreCntntIdx(SwDoc* pDoc,
1424     SvULongs& rSaveArr,
1425     sal_uLong nNode,
1426     xub_StrLen nOffset,
1427     sal_Bool bAuto)
1428 {
1429 	SwCntntNode* pCNd = pDoc->GetNodes()[ nNode ]->GetCntntNode();
1430 	const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
1431 	SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
1432     IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1433 	sal_uInt16 n = 0;
1434 	while( n < rSaveArr.Count() )
1435 	{
1436 		_SwSaveTypeCountContent aSave( rSaveArr, n );
1437 		SwPosition* pPos = 0;
1438         switch( aSave.GetType() )
1439         {
1440             case 0x8000:
1441             {
1442                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
1443                 SwPosition aNewPos(pMark->GetMarkPos());
1444                 aNewPos.nNode = *pCNd;
1445                 aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
1446                 pMark->SetMarkPos(aNewPos);
1447             }
1448             break;
1449             case 0x8001:
1450             {
1451                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
1452                 SwPosition aNewPos(pMark->GetOtherMarkPos());
1453                 aNewPos.nNode = *pCNd;
1454                 aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
1455                 pMark->SetOtherMarkPos(aNewPos);
1456             }
1457             break;
1458             case 0x1001:
1459                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
1460                 break;
1461             case 0x1000:
1462                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
1463                 break;
1464             case 0x2000:
1465                 {
1466                     SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
1467                     const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
1468                     if( rFlyAnchor.GetCntntAnchor() )
1469                     {
1470                         SwFmtAnchor aNew( rFlyAnchor );
1471                         SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
1472                         aNewPos.nNode = *pCNd;
1473                         if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
1474                         {
1475                             aNewPos.nContent.Assign( pCNd,
1476                                                      aSave.GetContent() + nOffset );
1477                         }
1478                         else
1479                         {
1480                             aNewPos.nContent.Assign( 0, 0 );
1481                         }
1482                         aNew.SetAnchor( &aNewPos );
1483                         pFrmFmt->SetFmtAttr( aNew );
1484                     }
1485                 }
1486                 break;
1487             case 0x2001:
1488                 if( bAuto )
1489                 {
1490                     SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
1491                     SfxPoolItem *pAnchor = (SfxPoolItem*)&pFrmFmt->GetAnchor();
1492                     pFrmFmt->NotifyClients( pAnchor, pAnchor );
1493                 }
1494                 break;
1495 
1496             case 0x0800:
1497             case 0x0801:
1498                 {
1499                     sal_uInt16 nCnt = 0;
1500                     SwCrsrShell* pShell = pDoc->GetEditShell();
1501                     if( pShell )
1502                     {
1503                         FOREACHSHELL_START( pShell )
1504                             SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
1505                             if( _pStkCrsr )
1506                             do {
1507                                 if( aSave.GetCount() == nCnt )
1508                                 {
1509                                     pPos = &_pStkCrsr->GetBound( 0x0800 ==
1510                                                         aSave.GetType() );
1511                                     break;
1512                                 }
1513                                 ++nCnt;
1514                             } while ( (_pStkCrsr != 0 ) &&
1515                                 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
1516 
1517                             if( pPos )
1518                                 break;
1519 
1520                             FOREACHPAM_START( PCURSH->_GetCrsr() )
1521                                 if( aSave.GetCount() == nCnt )
1522                                 {
1523                                     pPos = &PCURCRSR->GetBound( 0x0800 ==
1524                                                         aSave.GetType() );
1525                                     break;
1526                                 }
1527                                 ++nCnt;
1528                             FOREACHPAM_END()
1529                             if( pPos )
1530                                 break;
1531 
1532                         FOREACHSHELL_END( pShell )
1533                     }
1534             }
1535             break;
1536 
1537         case 0x0400:
1538         case 0x0401:
1539             {
1540                 sal_uInt16 nCnt = 0;
1541                 const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
1542                 for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
1543                 {
1544                     FOREACHPAM_START( rTbl[ i ] )
1545                         if( aSave.GetCount() == nCnt )
1546                         {
1547                             pPos = &PCURCRSR->GetBound( 0x0400 ==
1548                                                     aSave.GetType() );
1549                             break;
1550                         }
1551                         ++nCnt;
1552                     FOREACHPAM_END()
1553                     if( pPos )
1554                         break;
1555 
1556                     SwUnoTableCrsr* pUnoTblCrsr =
1557                         dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]);
1558                     if ( pUnoTblCrsr )
1559                     {
1560                         FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
1561                             if( aSave.GetCount() == nCnt )
1562                             {
1563                                 pPos = &PCURCRSR->GetBound( 0x0400 ==
1564                                                     aSave.GetType() );
1565                                 break;
1566                             }
1567                             ++nCnt;
1568                         FOREACHPAM_END()
1569                     }
1570                     if ( pPos )
1571                         break;
1572                 }
1573             }
1574             break;
1575         }
1576 
1577         if( pPos )
1578         {
1579             pPos->nNode = *pCNd;
1580             pPos->nContent.Assign( pCNd, aSave.GetContent() + nOffset );
1581         }
1582     }
1583 }
1584 
1585 void _RestoreCntntIdx(SvULongs& rSaveArr,
1586     const SwNode& rNd,
1587     xub_StrLen nLen,
1588     xub_StrLen nChkLen)
1589 {
1590     const SwDoc* pDoc = rNd.GetDoc();
1591     const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
1592     const SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
1593     const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1594     SwCntntNode* pCNd = (SwCntntNode*)rNd.GetCntntNode();
1595 
1596     sal_uInt16 n = 0;
1597     while( n < rSaveArr.Count() )
1598     {
1599         _SwSaveTypeCountContent aSave( rSaveArr, n );
1600         if( aSave.GetContent() >= nChkLen )
1601             rSaveArr[ n-1 ] -= nChkLen;
1602         else
1603         {
1604             SwPosition* pPos = 0;
1605             switch( aSave.GetType() )
1606             {
1607             case 0x8000:
1608             {
1609                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
1610                 SwPosition aNewPos(pMark->GetMarkPos());
1611                 aNewPos.nNode = rNd;
1612                 aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
1613                 pMark->SetMarkPos(aNewPos);
1614             }
1615             break;
1616             case 0x8001:
1617             {
1618                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
1619                 SwPosition aNewPos(pMark->GetOtherMarkPos());
1620                 aNewPos.nNode = rNd;
1621                 aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
1622                 pMark->SetOtherMarkPos(aNewPos);
1623             }
1624             break;
1625             case 0x1001:
1626                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
1627                 break;
1628             case 0x1000:
1629                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
1630                 break;
1631             case 0x2000:
1632             case 0x2001:
1633                 {
1634                     SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
1635                     const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
1636                     if( rFlyAnchor.GetCntntAnchor() )
1637                     {
1638                         SwFmtAnchor aNew( rFlyAnchor );
1639                         SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
1640                         aNewPos.nNode = rNd;
1641                         if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
1642                         {
1643                             aNewPos.nContent.Assign( pCNd, Min(
1644                                                      aSave.GetContent(), nLen ) );
1645                         }
1646                         else
1647                         {
1648                             aNewPos.nContent.Assign( 0, 0 );
1649                         }
1650                         aNew.SetAnchor( &aNewPos );
1651                         pFrmFmt->SetFmtAttr( aNew );
1652                     }
1653                 }
1654                 break;
1655 
1656             case 0x0800:
1657             case 0x0801:
1658                 {
1659                     sal_uInt16 nCnt = 0;
1660                     SwCrsrShell* pShell = pDoc->GetEditShell();
1661                     if( pShell )
1662                     {
1663                         FOREACHSHELL_START( pShell )
1664                             SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
1665                             if( _pStkCrsr )
1666                             do {
1667                                 if( aSave.GetCount() == nCnt )
1668                                 {
1669                                     pPos = &_pStkCrsr->GetBound( 0x0800 ==
1670                                                 aSave.GetType() );
1671                                     break;
1672                                 }
1673                                 ++nCnt;
1674                             } while ( (_pStkCrsr != 0 ) &&
1675                                 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
1676 
1677                             if( pPos )
1678                                 break;
1679 
1680                             FOREACHPAM_START( PCURSH->_GetCrsr() )
1681                                 if( aSave.GetCount() == nCnt )
1682                                 {
1683                                     pPos = &PCURCRSR->GetBound( 0x0800 ==
1684                                                 aSave.GetType() );
1685                                     break;
1686                                 }
1687                                 ++nCnt;
1688                             FOREACHPAM_END()
1689                             if( pPos )
1690                                 break;
1691 
1692                         FOREACHSHELL_END( pShell )
1693                     }
1694                 }
1695                 break;
1696 
1697             case 0x0400:
1698             case 0x0401:
1699                 {
1700                     sal_uInt16 nCnt = 0;
1701                     const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
1702                     for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
1703                     {
1704                         FOREACHPAM_START( rTbl[ i ] )
1705                             if( aSave.GetCount() == nCnt )
1706                             {
1707                                 pPos = &PCURCRSR->GetBound( 0x0400 ==
1708                                                     aSave.GetType() );
1709                                 break;
1710                             }
1711                             ++nCnt;
1712                         FOREACHPAM_END()
1713                         if( pPos )
1714                             break;
1715 
1716                         SwUnoTableCrsr* pUnoTblCrsr =
1717                             dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]);
1718                         if ( pUnoTblCrsr )
1719                         {
1720                             FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
1721                                 if( aSave.GetCount() == nCnt )
1722                                 {
1723                                     pPos = &PCURCRSR->GetBound( 0x0400 ==
1724                                                     aSave.GetType() );
1725                                     break;
1726                                 }
1727                                 ++nCnt;
1728                             FOREACHPAM_END()
1729                         }
1730                         if ( pPos )
1731                             break;
1732                     }
1733                 }
1734                 break;
1735             }
1736 
1737             if( pPos )
1738             {
1739                 pPos->nNode = rNd;
1740                 pPos->nContent.Assign( pCNd, Min( aSave.GetContent(), nLen ) );
1741             }
1742             n -= 2;
1743             rSaveArr.Remove( n, 2 );
1744         }
1745     }
1746 }
1747