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