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