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