xref: /trunk/main/sw/source/core/doc/docbm.cxx (revision b0b7a757)
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         {
739             pDdeBookmark->DeregisterFromDoc(m_pDoc);
740         }
741         // keep a temporary instance of the to-be-deleted mark in order to avoid
742         // recursive deletion of the mark triggered via its destructor.
743         // the temporary hold instance assures that the mark is deleted after the
744         // mark container has been updated. Thus, the mark could not be found anymore
745         // in the mark container by other calls trying to recursively delete the mark.
746         iterator_t aToBeDeletedMarkIter = m_vMarks.begin() + (ppMark - m_vMarks.begin());
747         pMark_t pToBeDeletedMark = *aToBeDeletedMarkIter;
748         m_vMarks.erase( aToBeDeletedMarkIter );
749     }
750 
751     void MarkManager::deleteMark(const IMark* const pMark)
752     {
753         OSL_PRECOND(pMark->GetMarkPos().GetDoc() == m_pDoc,
754             "<MarkManager::repositionMark(..)>"
755             " - Mark is not in my doc.");
756         // finds the last Mark that is starting before pMark
757         // (pMarkLow < pMark)
758         iterator_t pMarkLow = lower_bound(
759             m_vMarks.begin(), m_vMarks.end(),
760             pMark->GetMarkStart(),
761             bind(&IMark::StartsBefore, _1, _2));
762         // finds the first Mark that pMark is starting before
763         // (pMark < pMarkHigh)
764         //iterator_t pMarkHigh = upper_bound(
765         //    pMarkLow, m_vMarks.end(),
766         //    pMark->GetMarkStart(),
767         //    bind(&IMark::StartsBefore, _2, _1));
768         // since it should be rare that pMark isnt found at all
769         // we skip the bisect search on the upper bound
770         iterator_t pMarkHigh = m_vMarks.end();
771         iterator_t pMarkFound = find_if(
772             pMarkLow, pMarkHigh,
773             bind(equal_to<const IMark*>(), bind(&boost::shared_ptr<IMark>::get, _1), pMark));
774         if(pMarkFound != pMarkHigh)
775             deleteMark(pMarkFound);
776     }
777 
778     void MarkManager::clearAllMarks()
779     {
780         m_vFieldmarks.clear();
781         m_vBookmarks.clear();
782 #ifdef DEBUG
783         for(iterator_t pBkmk = m_vMarks.begin();
784             pBkmk != m_vMarks.end();
785             ++pBkmk)
786             OSL_ENSURE(pBkmk->unique(),
787                 "<MarkManager::clearAllMarks(..)>"
788                 " - a Bookmark is still in use.");
789 #endif
790         m_vMarks.clear();
791     }
792 
793     IDocumentMarkAccess::const_iterator_t MarkManager::findMark(const ::rtl::OUString& rName) const
794     {
795         return lcl_FindMarkByName(rName, m_vMarks.begin(), m_vMarks.end());
796     }
797 
798     IDocumentMarkAccess::const_iterator_t MarkManager::findBookmark(const ::rtl::OUString& rName) const
799     {
800         return lcl_FindMarkByName(rName, m_vBookmarks.begin(), m_vBookmarks.end());
801     }
802 
803     IDocumentMarkAccess::const_iterator_t MarkManager::getMarksBegin() const
804         { return m_vMarks.begin(); }
805 
806     IDocumentMarkAccess::const_iterator_t MarkManager::getMarksEnd() const
807         { return m_vMarks.end(); }
808 
809     sal_Int32 MarkManager::getMarksCount() const
810         { return m_vMarks.size(); }
811 
812     IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksBegin() const
813         { return m_vBookmarks.begin(); }
814 
815     IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksEnd() const
816         { return m_vBookmarks.end(); }
817 
818     sal_Int32 MarkManager::getBookmarksCount() const
819         { return m_vBookmarks.size(); }
820 
821     IFieldmark* MarkManager::getFieldmarkFor(const SwPosition& rPos) const
822     {
823         const_iterator_t pFieldmark = find_if(
824             m_vFieldmarks.begin(),
825             m_vFieldmarks.end( ),
826             bind(&IMark::IsCoveringPosition, _1, rPos));
827         if(pFieldmark == m_vFieldmarks.end()) return NULL;
828         return dynamic_cast<IFieldmark*>(pFieldmark->get());
829     }
830 
831     IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos) const
832         { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, rPos)); }
833 
834     IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const
835         { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos)); }
836 
837     ::rtl::OUString MarkManager::getUniqueMarkName(const ::rtl::OUString& rName) const
838     {
839         OSL_ENSURE(rName.getLength(),
840             "<MarkManager::getUniqueMarkName(..)>"
841             " - a name should be proposed");
842         if(findMark(rName) == getMarksEnd()) return rName;
843         ::rtl::OUStringBuffer sBuf;
844         ::rtl::OUString sTmp;
845         for(sal_Int32 nCnt = 1; nCnt < SAL_MAX_INT32; nCnt++)
846         {
847             sTmp = sBuf.append(rName).append(nCnt).makeStringAndClear();
848             if(findMark(sTmp) == getMarksEnd()) break;
849         }
850         return sTmp;
851     }
852 
853     void MarkManager::sortMarks()
854     {
855         sort(m_vMarks.begin(), m_vMarks.end(), &lcl_MarkOrderingByStart);
856         sort(m_vBookmarks.begin(), m_vBookmarks.end(), &lcl_MarkOrderingByStart);
857         sort(m_vFieldmarks.begin(), m_vFieldmarks.end(), &lcl_MarkOrderingByStart);
858     }
859 
860 }} // namespace ::sw::mark
861 
862 
863 // old implementation
864 
865 //SV_IMPL_OP_PTRARR_SORT(SwBookmarks, SwBookmarkPtr)
866 
867 #define PCURCRSR (_pCurrCrsr)
868 #define FOREACHPAM_START(pSttCrsr) \
869 	{\
870 		SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \
871 		do {
872 
873 #define FOREACHPAM_END() \
874 		} while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \
875 	}
876 #define PCURSH ((SwCrsrShell*)_pStartShell)
877 #define FOREACHSHELL_START( pEShell ) \
878     {\
879 		ViewShell *_pStartShell = pEShell; \
880 		do { \
881 			if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
882 			{
883 
884 #define FOREACHSHELL_END( pEShell ) \
885 			} \
886         } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \
887 	}
888 
889 namespace
890 {
891     // Aufbau vom Array: 2 longs,
892     //	1. Long enthaelt Type und Position im DocArray,
893     //	2. die ContentPosition
894     //
895     //	CntntType --
896     //			0x8000 = Bookmark Pos1
897     //			0x8001 = Bookmark Pos2
898     //			0x2000 = Absatzgebundener Rahmen
899     //			0x2001 = Auto-Absatzgebundener Rahmen, der umgehaengt werden soll
900     //			0x1000 = Redline Mark
901     //			0x1001 = Redline Point
902     //			0x0800 = Crsr aus der CrsrShell Mark
903     //			0x0801 = Crsr aus der CrsrShell Point
904     //			0x0400 = UnoCrsr Mark
905     //			0x0401 = UnoCrsr Point
906     //
907 
908     class _SwSaveTypeCountContent
909     {
910         union {
911             struct { sal_uInt16 nType, nCount; } TC;
912             sal_uLong nTypeCount;
913             } TYPECOUNT;
914         xub_StrLen nContent;
915 
916     public:
917         _SwSaveTypeCountContent() { TYPECOUNT.nTypeCount = 0; nContent = 0; }
918         _SwSaveTypeCountContent( sal_uInt16 nType )
919             {
920                 SetTypeAndCount( nType, 0 );
921                 nContent = 0;
922             }
923         _SwSaveTypeCountContent( const SvULongs& rArr, sal_uInt16& rPos )
924             {
925                 TYPECOUNT.nTypeCount = rArr[ rPos++ ];
926                 nContent = static_cast<xub_StrLen>(rArr[ rPos++ ]);
927             }
928         void Add( SvULongs& rArr )
929         {
930             rArr.Insert( TYPECOUNT.nTypeCount, rArr.Count() );
931             rArr.Insert( nContent, rArr.Count() );
932         }
933 
934         void SetType( sal_uInt16 n )		{ TYPECOUNT.TC.nType = n; }
935         sal_uInt16 GetType() const 			{ return TYPECOUNT.TC.nType; }
936         void IncType() 	 				{ ++TYPECOUNT.TC.nType; }
937         void DecType() 	 				{ --TYPECOUNT.TC.nType; }
938 
939         void SetCount( sal_uInt16 n ) 		{ TYPECOUNT.TC.nCount = n; }
940         sal_uInt16 GetCount() const 		{ return TYPECOUNT.TC.nCount; }
941         sal_uInt16 IncCount()  				{ return ++TYPECOUNT.TC.nCount; }
942         sal_uInt16 DecCount()  				{ return --TYPECOUNT.TC.nCount; }
943 
944         void SetTypeAndCount( sal_uInt16 nT, sal_uInt16 nC )
945             { TYPECOUNT.TC.nCount = nC; TYPECOUNT.TC.nType = nT; }
946 
947         void SetContent( xub_StrLen n )		{ nContent = n; }
948         xub_StrLen GetContent() const		{ return nContent; }
949     };
950 
951     // #i59534: If a paragraph will be splitted we have to restore some redline positions
952     // This help function checks a position compared with a node and an content index
953 
954     static const int BEFORE_NODE = 0;          // Position before the given node index
955     static const int BEFORE_SAME_NODE = 1;     // Same node index but content index before given content index
956     static const int SAME_POSITION = 2;        // Same node index and samecontent index
957     static const int BEHIND_SAME_NODE = 3;     // Same node index but content index behind given content index
958     static const int BEHIND_NODE = 4;          // Position behind the given node index
959 
960     static int lcl_RelativePosition( const SwPosition& rPos, sal_uLong nNode, xub_StrLen nCntnt )
961     {
962         sal_uLong nIndex = rPos.nNode.GetIndex();
963         int nReturn = BEFORE_NODE;
964         if( nIndex == nNode )
965         {
966             xub_StrLen nCntIdx = rPos.nContent.GetIndex();
967             if( nCntIdx < nCntnt )
968                 nReturn = BEFORE_SAME_NODE;
969             else if( nCntIdx == nCntnt )
970                 nReturn = SAME_POSITION;
971             else
972                 nReturn = BEHIND_SAME_NODE;
973         }
974         else if( nIndex > nNode )
975             nReturn = BEHIND_NODE;
976         return nReturn;
977     }
978 
979 
980     static inline int lcl_Greater( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
981     {
982         return rPos.nNode > rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent > pIdx->GetIndex() );
983     }
984 
985     static void lcl_ChkPaM( SvULongs& rSaveArr, sal_uLong nNode, xub_StrLen nCntnt,
986                     const SwPaM& rPam, _SwSaveTypeCountContent& rSave,
987                     sal_Bool bChkSelDirection )
988     {
989         // SelektionsRichtung beachten
990         bool bBound1IsStart = !bChkSelDirection ? sal_True :
991                             ( *rPam.GetPoint() < *rPam.GetMark()
992                                 ? rPam.GetPoint() == &rPam.GetBound()
993                                 : rPam.GetMark() == &rPam.GetBound());
994 
995         const SwPosition* pPos = &rPam.GetBound( sal_True );
996         if( pPos->nNode.GetIndex() == nNode &&
997             ( bBound1IsStart ? pPos->nContent.GetIndex() < nCntnt
998                                 : pPos->nContent.GetIndex() <= nCntnt ))
999         {
1000             rSave.SetContent( pPos->nContent.GetIndex() );
1001             rSave.Add( rSaveArr );
1002         }
1003 
1004         pPos = &rPam.GetBound( sal_False );
1005         if( pPos->nNode.GetIndex() == nNode &&
1006             ( (bBound1IsStart && bChkSelDirection)
1007                         ? pPos->nContent.GetIndex() <= nCntnt
1008                         : pPos->nContent.GetIndex() < nCntnt ))
1009         {
1010             rSave.SetContent( pPos->nContent.GetIndex() );
1011             rSave.IncType();
1012             rSave.Add( rSaveArr );
1013             rSave.DecType();
1014         }
1015     }
1016 
1017 }
1018 
1019 
1020 // IDocumentMarkAccess for SwDoc
1021 
1022 IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess()
1023     { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
1024 
1025 const IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess() const
1026     { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
1027 
1028 // SaveBookmark
1029 
1030 SaveBookmark::SaveBookmark(
1031     bool bSavePos,
1032     bool bSaveOtherPos,
1033     const IMark& rBkmk,
1034     const SwNodeIndex & rMvPos,
1035     const SwIndex* pIdx)
1036     : m_aName(rBkmk.GetName())
1037     , m_aShortName()
1038     , m_aCode()
1039     , m_bSavePos(bSavePos)
1040     , m_bSaveOtherPos(bSaveOtherPos)
1041     , m_eOrigBkmType(IDocumentMarkAccess::GetType(rBkmk))
1042 {
1043     const IBookmark* const pBookmark = dynamic_cast< const IBookmark* >(&rBkmk);
1044     if(pBookmark)
1045     {
1046         m_aShortName = pBookmark->GetShortName();
1047         m_aCode = pBookmark->GetKeyCode();
1048 
1049         ::sfx2::Metadatable const*const pMetadatable(
1050                 dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
1051         if (pMetadatable)
1052         {
1053             m_pMetadataUndo = pMetadatable->CreateUndo();
1054         }
1055     }
1056     m_nNode1 = rBkmk.GetMarkPos().nNode.GetIndex();
1057     m_nCntnt1 = rBkmk.GetMarkPos().nContent.GetIndex();
1058 
1059     if(m_bSavePos)
1060     {
1061         m_nNode1 -= rMvPos.GetIndex();
1062         if(pIdx && !m_nNode1)
1063             m_nCntnt1 -= pIdx->GetIndex();
1064     }
1065 
1066     if(rBkmk.IsExpanded())
1067     {
1068         m_nNode2 = rBkmk.GetOtherMarkPos().nNode.GetIndex();
1069         m_nCntnt2 = rBkmk.GetOtherMarkPos().nContent.GetIndex();
1070 
1071         if(m_bSaveOtherPos)
1072         {
1073             m_nNode2 -= rMvPos.GetIndex();
1074             if(pIdx && !m_nNode2)
1075                 m_nCntnt2 -= pIdx->GetIndex();
1076         }
1077     }
1078     else
1079         m_nNode2 = ULONG_MAX, m_nCntnt2 = STRING_NOTFOUND;
1080 }
1081 
1082 void SaveBookmark::SetInDoc(
1083     SwDoc* pDoc,
1084     const SwNodeIndex& rNewPos,
1085     const SwIndex* pIdx)
1086 {
1087     SwPaM aPam(rNewPos.GetNode());
1088     if(pIdx)
1089         aPam.GetPoint()->nContent = *pIdx;
1090 
1091     if(ULONG_MAX != m_nNode2)
1092     {
1093         aPam.SetMark();
1094 
1095         if(m_bSaveOtherPos)
1096         {
1097             aPam.GetMark()->nNode += m_nNode2;
1098             if(pIdx && !m_nNode2)
1099                 aPam.GetMark()->nContent += m_nCntnt2;
1100             else
1101                 aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
1102         }
1103         else
1104         {
1105             aPam.GetMark()->nNode = m_nNode2;
1106             aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
1107         }
1108     }
1109 
1110     if(m_bSavePos)
1111     {
1112         aPam.GetPoint()->nNode += m_nNode1;
1113 
1114         if(pIdx && !m_nNode1)
1115             aPam.GetPoint()->nContent += m_nCntnt1;
1116         else
1117             aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
1118     }
1119     else
1120     {
1121         aPam.GetPoint()->nNode = m_nNode1;
1122         aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
1123     }
1124 
1125     if(!aPam.HasMark()
1126         || CheckNodesRange(aPam.GetPoint()->nNode, aPam.GetMark()->nNode, sal_True))
1127     {
1128         ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pDoc->getIDocumentMarkAccess()->makeMark(aPam, m_aName, m_eOrigBkmType));
1129         if(pBookmark)
1130         {
1131             pBookmark->SetKeyCode(m_aCode);
1132             pBookmark->SetShortName(m_aShortName);
1133             if (m_pMetadataUndo)
1134             {
1135                 ::sfx2::Metadatable * const pMeta(
1136                     dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
1137                 OSL_ENSURE(pMeta, "metadata undo, but not metadatable?");
1138                 if (pMeta)
1139                 {
1140                     pMeta->RestoreMetadata(m_pMetadataUndo);
1141                 }
1142             }
1143         }
1144     }
1145 }
1146 
1147 // _DelBookmarks, _{Save,Restore}CntntIdx
1148 
1149 void _DelBookmarks(
1150     const SwNodeIndex& rStt,
1151     const SwNodeIndex& rEnd,
1152     ::std::vector<SaveBookmark> * pSaveBkmk,
1153     const SwIndex* pSttIdx,
1154     const SwIndex* pEndIdx)
1155 {
1156     // illegal range ??
1157     if(rStt.GetIndex() > rEnd.GetIndex()
1158         || (rStt == rEnd && (!pSttIdx || pSttIdx->GetIndex() >= pEndIdx->GetIndex())))
1159         return;
1160     SwDoc* const pDoc = rStt.GetNode().GetDoc();
1161 
1162     pDoc->getIDocumentMarkAccess()->deleteMarks(rStt, rEnd, pSaveBkmk, pSttIdx, pEndIdx);
1163 
1164     // kopiere alle Redlines, die im Move Bereich stehen in ein
1165     // Array, das alle Angaben auf die Position als Offset speichert.
1166     // Die neue Zuordung erfolgt nach dem Moven.
1167     SwRedlineTbl& rTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
1168     for(sal_uInt16 nCnt = 0; nCnt < rTbl.Count(); ++nCnt )
1169     {
1170         // liegt auf der Position ??
1171         SwRedline* pRedl = rTbl[ nCnt ];
1172 
1173         SwPosition *pRStt = &pRedl->GetBound(sal_True),
1174                    *pREnd = &pRedl->GetBound(sal_False);
1175         if( *pRStt > *pREnd )
1176         {
1177             SwPosition *pTmp = pRStt; pRStt = pREnd, pREnd = pTmp;
1178         }
1179 
1180         if( lcl_Greater( *pRStt, rStt, pSttIdx ) && lcl_Lower( *pRStt, rEnd, pEndIdx ))
1181         {
1182             pRStt->nNode = rEnd;
1183             if( pEndIdx )
1184                 pRStt->nContent = *pEndIdx;
1185             else
1186             {
1187                 sal_Bool bStt = sal_True;
1188                 SwCntntNode* pCNd = pRStt->nNode.GetNode().GetCntntNode();
1189                 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoNext( &pRStt->nNode )) )
1190                 {
1191                     bStt = sal_False;
1192                     pRStt->nNode = rStt;
1193                     if( 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pRStt->nNode )) )
1194                     {
1195                         pRStt->nNode = pREnd->nNode;
1196                         pCNd = pRStt->nNode.GetNode().GetCntntNode();
1197                     }
1198                 }
1199                 xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
1200                 pRStt->nContent.Assign( pCNd, nTmp );
1201             }
1202         }
1203         if( lcl_Greater( *pREnd, rStt, pSttIdx ) && lcl_Lower( *pREnd, rEnd, pEndIdx ))
1204         {
1205             pREnd->nNode = rStt;
1206             if( pSttIdx )
1207                 pREnd->nContent = *pSttIdx;
1208             else
1209             {
1210                 sal_Bool bStt = sal_False;
1211                 SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
1212                 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pREnd->nNode )) )
1213                 {
1214                     bStt = sal_True;
1215                     pREnd->nNode = rEnd;
1216                     if( 0 == ( pCNd = pDoc->GetNodes().GoNext( &pREnd->nNode )) )
1217                     {
1218                         pREnd->nNode = pRStt->nNode;
1219                         pCNd = pREnd->nNode.GetNode().GetCntntNode();
1220                     }
1221                 }
1222                 xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
1223                 pREnd->nContent.Assign( pCNd, nTmp );
1224             }
1225         }
1226     }
1227 }
1228 
1229 void _SaveCntntIdx(SwDoc* pDoc,
1230     sal_uLong nNode,
1231     xub_StrLen nCntnt,
1232     SvULongs& rSaveArr,
1233     sal_uInt8 nSaveFly)
1234 {
1235     // 1. Bookmarks
1236     _SwSaveTypeCountContent aSave;
1237     aSave.SetTypeAndCount( 0x8000, 0 );
1238 
1239     IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1240     const sal_Int32 nBkmks = pMarkAccess->getMarksCount();
1241     for(; aSave.GetCount() < nBkmks; aSave.IncCount())
1242     {
1243         bool bEqual = false;
1244         bool bLower = false;
1245         const ::sw::mark::IMark* pBkmk = (pMarkAccess->getMarksBegin() + aSave.GetCount())->get();
1246         if(pBkmk->GetMarkPos().nNode.GetIndex() == nNode
1247             && pBkmk->GetMarkPos().nContent.GetIndex() <= nCntnt)
1248         {
1249             if(pBkmk->GetMarkPos().nContent.GetIndex() < nCntnt)
1250             {
1251                 bLower = true; // a hint for the other position...
1252                 aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
1253                 aSave.Add(rSaveArr);
1254             }
1255             else // if a bookmark position is equal nCntnt, the other position
1256                 bEqual = true; // has to decide if it is added to the array
1257         }
1258 
1259         if(pBkmk->IsExpanded()
1260             && pBkmk->GetOtherMarkPos().nNode.GetIndex() == nNode
1261             && pBkmk->GetOtherMarkPos().nContent.GetIndex() <= nCntnt)
1262         {
1263             if(bLower || pBkmk->GetOtherMarkPos().nContent.GetIndex() < nCntnt)
1264             {
1265                 if(bEqual)
1266                 { // the other position is before, the (main) position is equal
1267                     aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
1268                     aSave.Add(rSaveArr);
1269                 }
1270                 aSave.SetContent(pBkmk->GetOtherMarkPos().nContent.GetIndex());
1271                 aSave.IncType();
1272                 aSave.Add(rSaveArr);
1273                 aSave.DecType();
1274             }
1275         }
1276     }
1277 
1278 	// 2. Redlines
1279 	aSave.SetTypeAndCount( 0x1000, 0 );
1280 	const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
1281 	for( ; aSave.GetCount() < rRedlTbl.Count(); aSave.IncCount() )
1282 	{
1283 		const SwRedline* pRdl = rRedlTbl[ aSave.GetCount() ];
1284         int nPointPos = lcl_RelativePosition( *pRdl->GetPoint(), nNode, nCntnt );
1285         int nMarkPos = pRdl->HasMark() ? lcl_RelativePosition( *pRdl->GetMark(), nNode, nCntnt ) :
1286                                           nPointPos;
1287         // #i59534: We have to store the positions inside the same node before the insert position
1288         // and the one at the insert position if the corresponding Point/Mark position is before
1289         // the insert position.
1290         if( nPointPos == BEFORE_SAME_NODE ||
1291             ( nPointPos == SAME_POSITION && nMarkPos < SAME_POSITION ) )
1292 		{
1293 			aSave.SetContent( pRdl->GetPoint()->nContent.GetIndex() );
1294 			aSave.IncType();
1295 			aSave.Add( rSaveArr );
1296 			aSave.DecType();
1297 		}
1298 		if( pRdl->HasMark() && ( nMarkPos == BEFORE_SAME_NODE ||
1299             ( nMarkPos == SAME_POSITION && nPointPos < SAME_POSITION ) ) )
1300         {
1301 			aSave.SetContent( pRdl->GetMark()->nContent.GetIndex() );
1302 			aSave.Add( rSaveArr );
1303 		}
1304 	}
1305 
1306 	// 4. Absatzgebundene Objekte
1307 	{
1308 		SwCntntNode *pNode = pDoc->GetNodes()[nNode]->GetCntntNode();
1309 		if( pNode )
1310 		{
1311 
1312 			SwFrm* pFrm = pNode->getLayoutFrm( pDoc->GetCurrentLayout() );
1313 #if OSL_DEBUG_LEVEL > 1
1314 			static sal_Bool bViaDoc = sal_False;
1315 			if( bViaDoc )
1316 				pFrm = NULL;
1317 #endif
1318 			if( pFrm ) // gibt es ein Layout? Dann ist etwas billiger...
1319 			{
1320 				if( pFrm->GetDrawObjs() )
1321 				{
1322                     const SwSortedObjs& rDObj = *pFrm->GetDrawObjs();
1323                     for( sal_uInt32 n = rDObj.Count(); n; )
1324 					{
1325                         SwAnchoredObject* pObj = rDObj[ --n ];
1326                         const SwFrmFmt& rFmt = pObj->GetFrmFmt();
1327                         const SwFmtAnchor& rAnchor = rFmt.GetAnchor();
1328                         SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
1329                         if ( pAPos &&
1330                              ( ( nSaveFly &&
1331                                  FLY_AT_PARA == rAnchor.GetAnchorId() ) ||
1332                                ( FLY_AT_CHAR == rAnchor.GetAnchorId() ) ) )
1333                         {
1334 							aSave.SetType( 0x2000 );
1335 							aSave.SetContent( pAPos->nContent.GetIndex() );
1336 
1337 							OSL_ENSURE( nNode == pAPos->nNode.GetIndex(),
1338 									"_SaveCntntIdx: Wrong Node-Index" );
1339                             if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
1340 							{
1341 								if( nCntnt <= aSave.GetContent() )
1342 								{
1343 									if( SAVEFLY_SPLIT == nSaveFly )
1344 										aSave.IncType(); // = 0x2001;
1345 									else
1346 										continue;
1347 								}
1348 							}
1349 							aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() );
1350 							while( aSave.GetCount() &&
1351                                     &rFmt != (*pDoc->GetSpzFrmFmts())[
1352                                     aSave.DecCount() ] )
1353 								; // nothing
1354                             OSL_ENSURE( &rFmt == (*pDoc->GetSpzFrmFmts())[
1355 													aSave.GetCount() ],
1356 									"_SaveCntntIdx: Lost FrameFormat" );
1357 							aSave.Add( rSaveArr );
1358 						}
1359 					}
1360 				}
1361 			}
1362 			else // Schade, kein Layout, dann ist es eben etwas teurer...
1363 			{
1364 				for( aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() );
1365 						aSave.GetCount() ; )
1366 				{
1367 					SwFrmFmt* pFrmFmt = (*pDoc->GetSpzFrmFmts())[
1368 												aSave.DecCount() ];
1369 					if ( RES_FLYFRMFMT != pFrmFmt->Which() &&
1370 							RES_DRAWFRMFMT != pFrmFmt->Which() )
1371 						continue;
1372 
1373 					const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
1374                     SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
1375                     if ( pAPos && ( nNode == pAPos->nNode.GetIndex() ) &&
1376                          ( FLY_AT_PARA == rAnchor.GetAnchorId() ||
1377                            FLY_AT_CHAR == rAnchor.GetAnchorId() ) )
1378                     {
1379 						aSave.SetType( 0x2000 );
1380 						aSave.SetContent( pAPos->nContent.GetIndex() );
1381                         if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
1382 						{
1383 							if( nCntnt <= aSave.GetContent() )
1384 							{
1385 								if( SAVEFLY_SPLIT == nSaveFly )
1386 									aSave.IncType(); // = 0x2001;
1387 								else
1388 									continue;
1389 							}
1390 						}
1391 						aSave.Add( rSaveArr );
1392 					}
1393 				}
1394 			}
1395 		}
1396 	}
1397 	// 5. CrsrShell
1398 	{
1399 		SwCrsrShell* pShell = pDoc->GetEditShell();
1400 		if( pShell )
1401 		{
1402 			aSave.SetTypeAndCount( 0x800, 0 );
1403 			FOREACHSHELL_START( pShell )
1404 				SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
1405 				if( _pStkCrsr )
1406 				do {
1407 					lcl_ChkPaM( rSaveArr, nNode, nCntnt, *_pStkCrsr,
1408 								aSave, sal_False );
1409 					aSave.IncCount();
1410 				} while ( (_pStkCrsr != 0 ) &&
1411 					((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
1412 
1413 				FOREACHPAM_START( PCURSH->_GetCrsr() )
1414 					lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR,
1415 								aSave, sal_False );
1416 					aSave.IncCount();
1417 				FOREACHPAM_END()
1418 
1419 			FOREACHSHELL_END( pShell )
1420 		}
1421 	}
1422 	// 6. UnoCrsr
1423 	{
1424 		aSave.SetTypeAndCount( 0x400, 0 );
1425 		const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
1426 		for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
1427 		{
1428 			FOREACHPAM_START( rTbl[ n ] )
1429 				lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False );
1430 				aSave.IncCount();
1431 			FOREACHPAM_END()
1432 
1433             SwUnoTableCrsr* pUnoTblCrsr =
1434                 dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]);
1435 			if( pUnoTblCrsr )
1436 			{
1437 				FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
1438 					lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False );
1439 					aSave.IncCount();
1440 				FOREACHPAM_END()
1441 			}
1442 		}
1443 	}
1444 }
1445 
1446 
1447 void _RestoreCntntIdx(SwDoc* pDoc,
1448     SvULongs& rSaveArr,
1449     sal_uLong nNode,
1450     xub_StrLen nOffset,
1451     sal_Bool bAuto)
1452 {
1453 	SwCntntNode* pCNd = pDoc->GetNodes()[ nNode ]->GetCntntNode();
1454 	const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
1455 	SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
1456     IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1457 	sal_uInt16 n = 0;
1458 	while( n < rSaveArr.Count() )
1459 	{
1460 		_SwSaveTypeCountContent aSave( rSaveArr, n );
1461 		SwPosition* pPos = 0;
1462         switch( aSave.GetType() )
1463         {
1464             case 0x8000:
1465             {
1466                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
1467                 SwPosition aNewPos(pMark->GetMarkPos());
1468                 aNewPos.nNode = *pCNd;
1469                 aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
1470                 pMark->SetMarkPos(aNewPos);
1471             }
1472             break;
1473             case 0x8001:
1474             {
1475                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
1476                 SwPosition aNewPos(pMark->GetOtherMarkPos());
1477                 aNewPos.nNode = *pCNd;
1478                 aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
1479                 pMark->SetOtherMarkPos(aNewPos);
1480             }
1481             break;
1482             case 0x1001:
1483                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
1484                 break;
1485             case 0x1000:
1486                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
1487                 break;
1488             case 0x2000:
1489                 {
1490                     SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
1491                     const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
1492                     if( rFlyAnchor.GetCntntAnchor() )
1493                     {
1494                         SwFmtAnchor aNew( rFlyAnchor );
1495                         SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
1496                         aNewPos.nNode = *pCNd;
1497                         if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
1498                         {
1499                             aNewPos.nContent.Assign( pCNd,
1500                                                      aSave.GetContent() + nOffset );
1501                         }
1502                         else
1503                         {
1504                             aNewPos.nContent.Assign( 0, 0 );
1505                         }
1506                         aNew.SetAnchor( &aNewPos );
1507                         pFrmFmt->SetFmtAttr( aNew );
1508                     }
1509                 }
1510                 break;
1511             case 0x2001:
1512                 if( bAuto )
1513                 {
1514                     SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
1515                     SfxPoolItem *pAnchor = (SfxPoolItem*)&pFrmFmt->GetAnchor();
1516                     pFrmFmt->NotifyClients( pAnchor, pAnchor );
1517                 }
1518                 break;
1519 
1520             case 0x0800:
1521             case 0x0801:
1522                 {
1523                     sal_uInt16 nCnt = 0;
1524                     SwCrsrShell* pShell = pDoc->GetEditShell();
1525                     if( pShell )
1526                     {
1527                         FOREACHSHELL_START( pShell )
1528                             SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
1529                             if( _pStkCrsr )
1530                             do {
1531                                 if( aSave.GetCount() == nCnt )
1532                                 {
1533                                     pPos = &_pStkCrsr->GetBound( 0x0800 ==
1534                                                         aSave.GetType() );
1535                                     break;
1536                                 }
1537                                 ++nCnt;
1538                             } while ( (_pStkCrsr != 0 ) &&
1539                                 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
1540 
1541                             if( pPos )
1542                                 break;
1543 
1544                             FOREACHPAM_START( PCURSH->_GetCrsr() )
1545                                 if( aSave.GetCount() == nCnt )
1546                                 {
1547                                     pPos = &PCURCRSR->GetBound( 0x0800 ==
1548                                                         aSave.GetType() );
1549                                     break;
1550                                 }
1551                                 ++nCnt;
1552                             FOREACHPAM_END()
1553                             if( pPos )
1554                                 break;
1555 
1556                         FOREACHSHELL_END( pShell )
1557                     }
1558             }
1559             break;
1560 
1561         case 0x0400:
1562         case 0x0401:
1563             {
1564                 sal_uInt16 nCnt = 0;
1565                 const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
1566                 for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
1567                 {
1568                     FOREACHPAM_START( rTbl[ i ] )
1569                         if( aSave.GetCount() == nCnt )
1570                         {
1571                             pPos = &PCURCRSR->GetBound( 0x0400 ==
1572                                                     aSave.GetType() );
1573                             break;
1574                         }
1575                         ++nCnt;
1576                     FOREACHPAM_END()
1577                     if( pPos )
1578                         break;
1579 
1580                     SwUnoTableCrsr* pUnoTblCrsr =
1581                         dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]);
1582                     if ( pUnoTblCrsr )
1583                     {
1584                         FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
1585                             if( aSave.GetCount() == nCnt )
1586                             {
1587                                 pPos = &PCURCRSR->GetBound( 0x0400 ==
1588                                                     aSave.GetType() );
1589                                 break;
1590                             }
1591                             ++nCnt;
1592                         FOREACHPAM_END()
1593                     }
1594                     if ( pPos )
1595                         break;
1596                 }
1597             }
1598             break;
1599         }
1600 
1601         if( pPos )
1602         {
1603             pPos->nNode = *pCNd;
1604             pPos->nContent.Assign( pCNd, aSave.GetContent() + nOffset );
1605         }
1606     }
1607 }
1608 
1609 void _RestoreCntntIdx(SvULongs& rSaveArr,
1610     const SwNode& rNd,
1611     xub_StrLen nLen,
1612     xub_StrLen nChkLen)
1613 {
1614     const SwDoc* pDoc = rNd.GetDoc();
1615     const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
1616     const SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
1617     const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1618     SwCntntNode* pCNd = (SwCntntNode*)rNd.GetCntntNode();
1619 
1620     sal_uInt16 n = 0;
1621     while( n < rSaveArr.Count() )
1622     {
1623         _SwSaveTypeCountContent aSave( rSaveArr, n );
1624         if( aSave.GetContent() >= nChkLen )
1625             rSaveArr[ n-1 ] -= nChkLen;
1626         else
1627         {
1628             SwPosition* pPos = 0;
1629             switch( aSave.GetType() )
1630             {
1631             case 0x8000:
1632             {
1633                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
1634                 SwPosition aNewPos(pMark->GetMarkPos());
1635                 aNewPos.nNode = rNd;
1636                 aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
1637                 pMark->SetMarkPos(aNewPos);
1638             }
1639             break;
1640             case 0x8001:
1641             {
1642                 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
1643                 SwPosition aNewPos(pMark->GetOtherMarkPos());
1644                 aNewPos.nNode = rNd;
1645                 aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
1646                 pMark->SetOtherMarkPos(aNewPos);
1647             }
1648             break;
1649             case 0x1001:
1650                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
1651                 break;
1652             case 0x1000:
1653                 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
1654                 break;
1655             case 0x2000:
1656             case 0x2001:
1657                 {
1658                     SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
1659                     const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
1660                     if( rFlyAnchor.GetCntntAnchor() )
1661                     {
1662                         SwFmtAnchor aNew( rFlyAnchor );
1663                         SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
1664                         aNewPos.nNode = rNd;
1665                         if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
1666                         {
1667                             aNewPos.nContent.Assign( pCNd, Min(
1668                                                      aSave.GetContent(), nLen ) );
1669                         }
1670                         else
1671                         {
1672                             aNewPos.nContent.Assign( 0, 0 );
1673                         }
1674                         aNew.SetAnchor( &aNewPos );
1675                         pFrmFmt->SetFmtAttr( aNew );
1676                     }
1677                 }
1678                 break;
1679 
1680             case 0x0800:
1681             case 0x0801:
1682                 {
1683                     sal_uInt16 nCnt = 0;
1684                     SwCrsrShell* pShell = pDoc->GetEditShell();
1685                     if( pShell )
1686                     {
1687                         FOREACHSHELL_START( pShell )
1688                             SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
1689                             if( _pStkCrsr )
1690                             do {
1691                                 if( aSave.GetCount() == nCnt )
1692                                 {
1693                                     pPos = &_pStkCrsr->GetBound( 0x0800 ==
1694                                                 aSave.GetType() );
1695                                     break;
1696                                 }
1697                                 ++nCnt;
1698                             } while ( (_pStkCrsr != 0 ) &&
1699                                 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
1700 
1701                             if( pPos )
1702                                 break;
1703 
1704                             FOREACHPAM_START( PCURSH->_GetCrsr() )
1705                                 if( aSave.GetCount() == nCnt )
1706                                 {
1707                                     pPos = &PCURCRSR->GetBound( 0x0800 ==
1708                                                 aSave.GetType() );
1709                                     break;
1710                                 }
1711                                 ++nCnt;
1712                             FOREACHPAM_END()
1713                             if( pPos )
1714                                 break;
1715 
1716                         FOREACHSHELL_END( pShell )
1717                     }
1718                 }
1719                 break;
1720 
1721             case 0x0400:
1722             case 0x0401:
1723                 {
1724                     sal_uInt16 nCnt = 0;
1725                     const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
1726                     for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
1727                     {
1728                         FOREACHPAM_START( rTbl[ i ] )
1729                             if( aSave.GetCount() == nCnt )
1730                             {
1731                                 pPos = &PCURCRSR->GetBound( 0x0400 ==
1732                                                     aSave.GetType() );
1733                                 break;
1734                             }
1735                             ++nCnt;
1736                         FOREACHPAM_END()
1737                         if( pPos )
1738                             break;
1739 
1740                         SwUnoTableCrsr* pUnoTblCrsr =
1741                             dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]);
1742                         if ( pUnoTblCrsr )
1743                         {
1744                             FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
1745                                 if( aSave.GetCount() == nCnt )
1746                                 {
1747                                     pPos = &PCURCRSR->GetBound( 0x0400 ==
1748                                                     aSave.GetType() );
1749                                     break;
1750                                 }
1751                                 ++nCnt;
1752                             FOREACHPAM_END()
1753                         }
1754                         if ( pPos )
1755                             break;
1756                     }
1757                 }
1758                 break;
1759             }
1760 
1761             if( pPos )
1762             {
1763                 pPos->nNode = rNd;
1764                 pPos->nContent.Assign( pCNd, Min( aSave.GetContent(), nLen ) );
1765             }
1766             n -= 2;
1767             rSaveArr.Remove( n, 2 );
1768         }
1769     }
1770 }
1771