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