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