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