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