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