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 pDdeBookmark->DeregisterFromDoc(m_pDoc); 739 m_vMarks.erase(m_vMarks.begin() + (ppMark - m_vMarks.begin())); // clumsy const-cast 740 } 741 742 void MarkManager::deleteMark(const IMark* const pMark) 743 { 744 OSL_PRECOND(pMark->GetMarkPos().GetDoc() == m_pDoc, 745 "<MarkManager::repositionMark(..)>" 746 " - Mark is not in my doc."); 747 // finds the last Mark that is starting before pMark 748 // (pMarkLow < pMark) 749 iterator_t pMarkLow = lower_bound( 750 m_vMarks.begin(), m_vMarks.end(), 751 pMark->GetMarkStart(), 752 bind(&IMark::StartsBefore, _1, _2)); 753 // finds the first Mark that pMark is starting before 754 // (pMark < pMarkHigh) 755 //iterator_t pMarkHigh = upper_bound( 756 // pMarkLow, m_vMarks.end(), 757 // pMark->GetMarkStart(), 758 // bind(&IMark::StartsBefore, _2, _1)); 759 // since it should be rare that pMark isnt found at all 760 // we skip the bisect search on the upper bound 761 iterator_t pMarkHigh = m_vMarks.end(); 762 iterator_t pMarkFound = find_if( 763 pMarkLow, pMarkHigh, 764 bind(equal_to<const IMark*>(), bind(&boost::shared_ptr<IMark>::get, _1), pMark)); 765 if(pMarkFound != pMarkHigh) 766 deleteMark(pMarkFound); 767 } 768 769 void MarkManager::clearAllMarks() 770 { 771 m_vFieldmarks.clear(); 772 m_vBookmarks.clear(); 773 #ifdef DEBUG 774 for(iterator_t pBkmk = m_vMarks.begin(); 775 pBkmk != m_vMarks.end(); 776 ++pBkmk) 777 OSL_ENSURE(pBkmk->unique(), 778 "<MarkManager::clearAllMarks(..)>" 779 " - a Bookmark is still in use."); 780 #endif 781 m_vMarks.clear(); 782 } 783 784 IDocumentMarkAccess::const_iterator_t MarkManager::findMark(const ::rtl::OUString& rName) const 785 { 786 return lcl_FindMarkByName(rName, m_vMarks.begin(), m_vMarks.end()); 787 } 788 789 IDocumentMarkAccess::const_iterator_t MarkManager::findBookmark(const ::rtl::OUString& rName) const 790 { 791 return lcl_FindMarkByName(rName, m_vBookmarks.begin(), m_vBookmarks.end()); 792 } 793 794 IDocumentMarkAccess::const_iterator_t MarkManager::getMarksBegin() const 795 { return m_vMarks.begin(); } 796 797 IDocumentMarkAccess::const_iterator_t MarkManager::getMarksEnd() const 798 { return m_vMarks.end(); } 799 800 sal_Int32 MarkManager::getMarksCount() const 801 { return m_vMarks.size(); } 802 803 IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksBegin() const 804 { return m_vBookmarks.begin(); } 805 806 IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksEnd() const 807 { return m_vBookmarks.end(); } 808 809 sal_Int32 MarkManager::getBookmarksCount() const 810 { return m_vBookmarks.size(); } 811 812 IFieldmark* MarkManager::getFieldmarkFor(const SwPosition& rPos) const 813 { 814 const_iterator_t pFieldmark = find_if( 815 m_vFieldmarks.begin(), 816 m_vFieldmarks.end( ), 817 bind(&IMark::IsCoveringPosition, _1, rPos)); 818 if(pFieldmark == m_vFieldmarks.end()) return NULL; 819 return dynamic_cast<IFieldmark*>(pFieldmark->get()); 820 } 821 822 IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos) const 823 { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, rPos)); } 824 825 IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const 826 { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos)); } 827 828 ::rtl::OUString MarkManager::getUniqueMarkName(const ::rtl::OUString& rName) const 829 { 830 OSL_ENSURE(rName.getLength(), 831 "<MarkManager::getUniqueMarkName(..)>" 832 " - a name should be proposed"); 833 if(findMark(rName) == getMarksEnd()) return rName; 834 ::rtl::OUStringBuffer sBuf; 835 ::rtl::OUString sTmp; 836 for(sal_Int32 nCnt = 1; nCnt < SAL_MAX_INT32; nCnt++) 837 { 838 sTmp = sBuf.append(rName).append(nCnt).makeStringAndClear(); 839 if(findMark(sTmp) == getMarksEnd()) break; 840 } 841 return sTmp; 842 } 843 844 void MarkManager::sortMarks() 845 { 846 sort(m_vMarks.begin(), m_vMarks.end(), &lcl_MarkOrderingByStart); 847 sort(m_vBookmarks.begin(), m_vBookmarks.end(), &lcl_MarkOrderingByStart); 848 sort(m_vFieldmarks.begin(), m_vFieldmarks.end(), &lcl_MarkOrderingByStart); 849 } 850 851 }} // namespace ::sw::mark 852 853 854 // old implementation 855 856 //SV_IMPL_OP_PTRARR_SORT(SwBookmarks, SwBookmarkPtr) 857 858 #define PCURCRSR (_pCurrCrsr) 859 #define FOREACHPAM_START(pSttCrsr) \ 860 {\ 861 SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \ 862 do { 863 864 #define FOREACHPAM_END() \ 865 } while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \ 866 } 867 #define PCURSH ((SwCrsrShell*)_pStartShell) 868 #define FOREACHSHELL_START( pEShell ) \ 869 {\ 870 ViewShell *_pStartShell = pEShell; \ 871 do { \ 872 if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \ 873 { 874 875 #define FOREACHSHELL_END( pEShell ) \ 876 } \ 877 } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \ 878 } 879 880 namespace 881 { 882 // Aufbau vom Array: 2 longs, 883 // 1. Long enthaelt Type und Position im DocArray, 884 // 2. die ContentPosition 885 // 886 // CntntType -- 887 // 0x8000 = Bookmark Pos1 888 // 0x8001 = Bookmark Pos2 889 // 0x2000 = Absatzgebundener Rahmen 890 // 0x2001 = Auto-Absatzgebundener Rahmen, der umgehaengt werden soll 891 // 0x1000 = Redline Mark 892 // 0x1001 = Redline Point 893 // 0x0800 = Crsr aus der CrsrShell Mark 894 // 0x0801 = Crsr aus der CrsrShell Point 895 // 0x0400 = UnoCrsr Mark 896 // 0x0401 = UnoCrsr Point 897 // 898 899 class _SwSaveTypeCountContent 900 { 901 union { 902 struct { sal_uInt16 nType, nCount; } TC; 903 sal_uLong nTypeCount; 904 } TYPECOUNT; 905 xub_StrLen nContent; 906 907 public: 908 _SwSaveTypeCountContent() { TYPECOUNT.nTypeCount = 0; nContent = 0; } 909 _SwSaveTypeCountContent( sal_uInt16 nType ) 910 { 911 SetTypeAndCount( nType, 0 ); 912 nContent = 0; 913 } 914 _SwSaveTypeCountContent( const SvULongs& rArr, sal_uInt16& rPos ) 915 { 916 TYPECOUNT.nTypeCount = rArr[ rPos++ ]; 917 nContent = static_cast<xub_StrLen>(rArr[ rPos++ ]); 918 } 919 void Add( SvULongs& rArr ) 920 { 921 rArr.Insert( TYPECOUNT.nTypeCount, rArr.Count() ); 922 rArr.Insert( nContent, rArr.Count() ); 923 } 924 925 void SetType( sal_uInt16 n ) { TYPECOUNT.TC.nType = n; } 926 sal_uInt16 GetType() const { return TYPECOUNT.TC.nType; } 927 void IncType() { ++TYPECOUNT.TC.nType; } 928 void DecType() { --TYPECOUNT.TC.nType; } 929 930 void SetCount( sal_uInt16 n ) { TYPECOUNT.TC.nCount = n; } 931 sal_uInt16 GetCount() const { return TYPECOUNT.TC.nCount; } 932 sal_uInt16 IncCount() { return ++TYPECOUNT.TC.nCount; } 933 sal_uInt16 DecCount() { return --TYPECOUNT.TC.nCount; } 934 935 void SetTypeAndCount( sal_uInt16 nT, sal_uInt16 nC ) 936 { TYPECOUNT.TC.nCount = nC; TYPECOUNT.TC.nType = nT; } 937 938 void SetContent( xub_StrLen n ) { nContent = n; } 939 xub_StrLen GetContent() const { return nContent; } 940 }; 941 942 // #i59534: If a paragraph will be splitted we have to restore some redline positions 943 // This help function checks a position compared with a node and an content index 944 945 static const int BEFORE_NODE = 0; // Position before the given node index 946 static const int BEFORE_SAME_NODE = 1; // Same node index but content index before given content index 947 static const int SAME_POSITION = 2; // Same node index and samecontent index 948 static const int BEHIND_SAME_NODE = 3; // Same node index but content index behind given content index 949 static const int BEHIND_NODE = 4; // Position behind the given node index 950 951 static int lcl_RelativePosition( const SwPosition& rPos, sal_uLong nNode, xub_StrLen nCntnt ) 952 { 953 sal_uLong nIndex = rPos.nNode.GetIndex(); 954 int nReturn = BEFORE_NODE; 955 if( nIndex == nNode ) 956 { 957 xub_StrLen nCntIdx = rPos.nContent.GetIndex(); 958 if( nCntIdx < nCntnt ) 959 nReturn = BEFORE_SAME_NODE; 960 else if( nCntIdx == nCntnt ) 961 nReturn = SAME_POSITION; 962 else 963 nReturn = BEHIND_SAME_NODE; 964 } 965 else if( nIndex > nNode ) 966 nReturn = BEHIND_NODE; 967 return nReturn; 968 } 969 970 971 static inline int lcl_Greater( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx ) 972 { 973 return rPos.nNode > rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent > pIdx->GetIndex() ); 974 } 975 976 static void lcl_ChkPaM( SvULongs& rSaveArr, sal_uLong nNode, xub_StrLen nCntnt, 977 const SwPaM& rPam, _SwSaveTypeCountContent& rSave, 978 sal_Bool bChkSelDirection ) 979 { 980 // SelektionsRichtung beachten 981 bool bBound1IsStart = !bChkSelDirection ? sal_True : 982 ( *rPam.GetPoint() < *rPam.GetMark() 983 ? rPam.GetPoint() == &rPam.GetBound() 984 : rPam.GetMark() == &rPam.GetBound()); 985 986 const SwPosition* pPos = &rPam.GetBound( sal_True ); 987 if( pPos->nNode.GetIndex() == nNode && 988 ( bBound1IsStart ? pPos->nContent.GetIndex() < nCntnt 989 : pPos->nContent.GetIndex() <= nCntnt )) 990 { 991 rSave.SetContent( pPos->nContent.GetIndex() ); 992 rSave.Add( rSaveArr ); 993 } 994 995 pPos = &rPam.GetBound( sal_False ); 996 if( pPos->nNode.GetIndex() == nNode && 997 ( (bBound1IsStart && bChkSelDirection) 998 ? pPos->nContent.GetIndex() <= nCntnt 999 : pPos->nContent.GetIndex() < nCntnt )) 1000 { 1001 rSave.SetContent( pPos->nContent.GetIndex() ); 1002 rSave.IncType(); 1003 rSave.Add( rSaveArr ); 1004 rSave.DecType(); 1005 } 1006 } 1007 1008 } 1009 1010 1011 // IDocumentMarkAccess for SwDoc 1012 1013 IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess() 1014 { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); } 1015 1016 const IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess() const 1017 { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); } 1018 1019 // SaveBookmark 1020 1021 SaveBookmark::SaveBookmark( 1022 bool bSavePos, 1023 bool bSaveOtherPos, 1024 const IMark& rBkmk, 1025 const SwNodeIndex & rMvPos, 1026 const SwIndex* pIdx) 1027 : m_aName(rBkmk.GetName()) 1028 , m_aShortName() 1029 , m_aCode() 1030 , m_bSavePos(bSavePos) 1031 , m_bSaveOtherPos(bSaveOtherPos) 1032 , m_eOrigBkmType(IDocumentMarkAccess::GetType(rBkmk)) 1033 { 1034 const IBookmark* const pBookmark = dynamic_cast< const IBookmark* >(&rBkmk); 1035 if(pBookmark) 1036 { 1037 m_aShortName = pBookmark->GetShortName(); 1038 m_aCode = pBookmark->GetKeyCode(); 1039 1040 ::sfx2::Metadatable const*const pMetadatable( 1041 dynamic_cast< ::sfx2::Metadatable const* >(pBookmark)); 1042 if (pMetadatable) 1043 { 1044 m_pMetadataUndo = pMetadatable->CreateUndo(); 1045 } 1046 } 1047 m_nNode1 = rBkmk.GetMarkPos().nNode.GetIndex(); 1048 m_nCntnt1 = rBkmk.GetMarkPos().nContent.GetIndex(); 1049 1050 if(m_bSavePos) 1051 { 1052 m_nNode1 -= rMvPos.GetIndex(); 1053 if(pIdx && !m_nNode1) 1054 m_nCntnt1 -= pIdx->GetIndex(); 1055 } 1056 1057 if(rBkmk.IsExpanded()) 1058 { 1059 m_nNode2 = rBkmk.GetOtherMarkPos().nNode.GetIndex(); 1060 m_nCntnt2 = rBkmk.GetOtherMarkPos().nContent.GetIndex(); 1061 1062 if(m_bSaveOtherPos) 1063 { 1064 m_nNode2 -= rMvPos.GetIndex(); 1065 if(pIdx && !m_nNode2) 1066 m_nCntnt2 -= pIdx->GetIndex(); 1067 } 1068 } 1069 else 1070 m_nNode2 = ULONG_MAX, m_nCntnt2 = STRING_NOTFOUND; 1071 } 1072 1073 void SaveBookmark::SetInDoc( 1074 SwDoc* pDoc, 1075 const SwNodeIndex& rNewPos, 1076 const SwIndex* pIdx) 1077 { 1078 SwPaM aPam(rNewPos.GetNode()); 1079 if(pIdx) 1080 aPam.GetPoint()->nContent = *pIdx; 1081 1082 if(ULONG_MAX != m_nNode2) 1083 { 1084 aPam.SetMark(); 1085 1086 if(m_bSaveOtherPos) 1087 { 1088 aPam.GetMark()->nNode += m_nNode2; 1089 if(pIdx && !m_nNode2) 1090 aPam.GetMark()->nContent += m_nCntnt2; 1091 else 1092 aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2); 1093 } 1094 else 1095 { 1096 aPam.GetMark()->nNode = m_nNode2; 1097 aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2); 1098 } 1099 } 1100 1101 if(m_bSavePos) 1102 { 1103 aPam.GetPoint()->nNode += m_nNode1; 1104 1105 if(pIdx && !m_nNode1) 1106 aPam.GetPoint()->nContent += m_nCntnt1; 1107 else 1108 aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1); 1109 } 1110 else 1111 { 1112 aPam.GetPoint()->nNode = m_nNode1; 1113 aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1); 1114 } 1115 1116 if(!aPam.HasMark() 1117 || CheckNodesRange(aPam.GetPoint()->nNode, aPam.GetMark()->nNode, sal_True)) 1118 { 1119 ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pDoc->getIDocumentMarkAccess()->makeMark(aPam, m_aName, m_eOrigBkmType)); 1120 if(pBookmark) 1121 { 1122 pBookmark->SetKeyCode(m_aCode); 1123 pBookmark->SetShortName(m_aShortName); 1124 if (m_pMetadataUndo) 1125 { 1126 ::sfx2::Metadatable * const pMeta( 1127 dynamic_cast< ::sfx2::Metadatable* >(pBookmark)); 1128 OSL_ENSURE(pMeta, "metadata undo, but not metadatable?"); 1129 if (pMeta) 1130 { 1131 pMeta->RestoreMetadata(m_pMetadataUndo); 1132 } 1133 } 1134 } 1135 } 1136 } 1137 1138 // _DelBookmarks, _{Save,Restore}CntntIdx 1139 1140 void _DelBookmarks( 1141 const SwNodeIndex& rStt, 1142 const SwNodeIndex& rEnd, 1143 ::std::vector<SaveBookmark> * pSaveBkmk, 1144 const SwIndex* pSttIdx, 1145 const SwIndex* pEndIdx) 1146 { 1147 // illegal range ?? 1148 if(rStt.GetIndex() > rEnd.GetIndex() 1149 || (rStt == rEnd && (!pSttIdx || pSttIdx->GetIndex() >= pEndIdx->GetIndex()))) 1150 return; 1151 SwDoc* const pDoc = rStt.GetNode().GetDoc(); 1152 1153 pDoc->getIDocumentMarkAccess()->deleteMarks(rStt, rEnd, pSaveBkmk, pSttIdx, pEndIdx); 1154 1155 // kopiere alle Redlines, die im Move Bereich stehen in ein 1156 // Array, das alle Angaben auf die Position als Offset speichert. 1157 // Die neue Zuordung erfolgt nach dem Moven. 1158 SwRedlineTbl& rTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl(); 1159 for(sal_uInt16 nCnt = 0; nCnt < rTbl.Count(); ++nCnt ) 1160 { 1161 // liegt auf der Position ?? 1162 SwRedline* pRedl = rTbl[ nCnt ]; 1163 1164 SwPosition *pRStt = &pRedl->GetBound(sal_True), 1165 *pREnd = &pRedl->GetBound(sal_False); 1166 if( *pRStt > *pREnd ) 1167 { 1168 SwPosition *pTmp = pRStt; pRStt = pREnd, pREnd = pTmp; 1169 } 1170 1171 if( lcl_Greater( *pRStt, rStt, pSttIdx ) && lcl_Lower( *pRStt, rEnd, pEndIdx )) 1172 { 1173 pRStt->nNode = rEnd; 1174 if( pEndIdx ) 1175 pRStt->nContent = *pEndIdx; 1176 else 1177 { 1178 sal_Bool bStt = sal_True; 1179 SwCntntNode* pCNd = pRStt->nNode.GetNode().GetCntntNode(); 1180 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoNext( &pRStt->nNode )) ) 1181 { 1182 bStt = sal_False; 1183 pRStt->nNode = rStt; 1184 if( 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pRStt->nNode )) ) 1185 { 1186 pRStt->nNode = pREnd->nNode; 1187 pCNd = pRStt->nNode.GetNode().GetCntntNode(); 1188 } 1189 } 1190 xub_StrLen nTmp = bStt ? 0 : pCNd->Len(); 1191 pRStt->nContent.Assign( pCNd, nTmp ); 1192 } 1193 } 1194 if( lcl_Greater( *pREnd, rStt, pSttIdx ) && lcl_Lower( *pREnd, rEnd, pEndIdx )) 1195 { 1196 pREnd->nNode = rStt; 1197 if( pSttIdx ) 1198 pREnd->nContent = *pSttIdx; 1199 else 1200 { 1201 sal_Bool bStt = sal_False; 1202 SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode(); 1203 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pREnd->nNode )) ) 1204 { 1205 bStt = sal_True; 1206 pREnd->nNode = rEnd; 1207 if( 0 == ( pCNd = pDoc->GetNodes().GoNext( &pREnd->nNode )) ) 1208 { 1209 pREnd->nNode = pRStt->nNode; 1210 pCNd = pREnd->nNode.GetNode().GetCntntNode(); 1211 } 1212 } 1213 xub_StrLen nTmp = bStt ? 0 : pCNd->Len(); 1214 pREnd->nContent.Assign( pCNd, nTmp ); 1215 } 1216 } 1217 } 1218 } 1219 1220 void _SaveCntntIdx(SwDoc* pDoc, 1221 sal_uLong nNode, 1222 xub_StrLen nCntnt, 1223 SvULongs& rSaveArr, 1224 sal_uInt8 nSaveFly) 1225 { 1226 // 1. Bookmarks 1227 _SwSaveTypeCountContent aSave; 1228 aSave.SetTypeAndCount( 0x8000, 0 ); 1229 1230 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess(); 1231 const sal_Int32 nBkmks = pMarkAccess->getMarksCount(); 1232 for(; aSave.GetCount() < nBkmks; aSave.IncCount()) 1233 { 1234 bool bEqual = false; 1235 bool bLower = false; 1236 const ::sw::mark::IMark* pBkmk = (pMarkAccess->getMarksBegin() + aSave.GetCount())->get(); 1237 if(pBkmk->GetMarkPos().nNode.GetIndex() == nNode 1238 && pBkmk->GetMarkPos().nContent.GetIndex() <= nCntnt) 1239 { 1240 if(pBkmk->GetMarkPos().nContent.GetIndex() < nCntnt) 1241 { 1242 bLower = true; // a hint for the other position... 1243 aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex()); 1244 aSave.Add(rSaveArr); 1245 } 1246 else // if a bookmark position is equal nCntnt, the other position 1247 bEqual = true; // has to decide if it is added to the array 1248 } 1249 1250 if(pBkmk->IsExpanded() 1251 && pBkmk->GetOtherMarkPos().nNode.GetIndex() == nNode 1252 && pBkmk->GetOtherMarkPos().nContent.GetIndex() <= nCntnt) 1253 { 1254 if(bLower || pBkmk->GetOtherMarkPos().nContent.GetIndex() < nCntnt) 1255 { 1256 if(bEqual) 1257 { // the other position is before, the (main) position is equal 1258 aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex()); 1259 aSave.Add(rSaveArr); 1260 } 1261 aSave.SetContent(pBkmk->GetOtherMarkPos().nContent.GetIndex()); 1262 aSave.IncType(); 1263 aSave.Add(rSaveArr); 1264 aSave.DecType(); 1265 } 1266 } 1267 } 1268 1269 // 2. Redlines 1270 aSave.SetTypeAndCount( 0x1000, 0 ); 1271 const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl(); 1272 for( ; aSave.GetCount() < rRedlTbl.Count(); aSave.IncCount() ) 1273 { 1274 const SwRedline* pRdl = rRedlTbl[ aSave.GetCount() ]; 1275 int nPointPos = lcl_RelativePosition( *pRdl->GetPoint(), nNode, nCntnt ); 1276 int nMarkPos = pRdl->HasMark() ? lcl_RelativePosition( *pRdl->GetMark(), nNode, nCntnt ) : 1277 nPointPos; 1278 // #i59534: We have to store the positions inside the same node before the insert position 1279 // and the one at the insert position if the corresponding Point/Mark position is before 1280 // the insert position. 1281 if( nPointPos == BEFORE_SAME_NODE || 1282 ( nPointPos == SAME_POSITION && nMarkPos < SAME_POSITION ) ) 1283 { 1284 aSave.SetContent( pRdl->GetPoint()->nContent.GetIndex() ); 1285 aSave.IncType(); 1286 aSave.Add( rSaveArr ); 1287 aSave.DecType(); 1288 } 1289 if( pRdl->HasMark() && ( nMarkPos == BEFORE_SAME_NODE || 1290 ( nMarkPos == SAME_POSITION && nPointPos < SAME_POSITION ) ) ) 1291 { 1292 aSave.SetContent( pRdl->GetMark()->nContent.GetIndex() ); 1293 aSave.Add( rSaveArr ); 1294 } 1295 } 1296 1297 // 4. Absatzgebundene Objekte 1298 { 1299 SwCntntNode *pNode = pDoc->GetNodes()[nNode]->GetCntntNode(); 1300 if( pNode ) 1301 { 1302 1303 SwFrm* pFrm = pNode->getLayoutFrm( pDoc->GetCurrentLayout() ); 1304 #if OSL_DEBUG_LEVEL > 1 1305 static sal_Bool bViaDoc = sal_False; 1306 if( bViaDoc ) 1307 pFrm = NULL; 1308 #endif 1309 if( pFrm ) // gibt es ein Layout? Dann ist etwas billiger... 1310 { 1311 if( pFrm->GetDrawObjs() ) 1312 { 1313 const SwSortedObjs& rDObj = *pFrm->GetDrawObjs(); 1314 for( sal_uInt32 n = rDObj.Count(); n; ) 1315 { 1316 SwAnchoredObject* pObj = rDObj[ --n ]; 1317 const SwFrmFmt& rFmt = pObj->GetFrmFmt(); 1318 const SwFmtAnchor& rAnchor = rFmt.GetAnchor(); 1319 SwPosition const*const pAPos = rAnchor.GetCntntAnchor(); 1320 if ( pAPos && 1321 ( ( nSaveFly && 1322 FLY_AT_PARA == rAnchor.GetAnchorId() ) || 1323 ( FLY_AT_CHAR == rAnchor.GetAnchorId() ) ) ) 1324 { 1325 aSave.SetType( 0x2000 ); 1326 aSave.SetContent( pAPos->nContent.GetIndex() ); 1327 1328 OSL_ENSURE( nNode == pAPos->nNode.GetIndex(), 1329 "_SaveCntntIdx: Wrong Node-Index" ); 1330 if ( FLY_AT_CHAR == rAnchor.GetAnchorId() ) 1331 { 1332 if( nCntnt <= aSave.GetContent() ) 1333 { 1334 if( SAVEFLY_SPLIT == nSaveFly ) 1335 aSave.IncType(); // = 0x2001; 1336 else 1337 continue; 1338 } 1339 } 1340 aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() ); 1341 while( aSave.GetCount() && 1342 &rFmt != (*pDoc->GetSpzFrmFmts())[ 1343 aSave.DecCount() ] ) 1344 ; // nothing 1345 OSL_ENSURE( &rFmt == (*pDoc->GetSpzFrmFmts())[ 1346 aSave.GetCount() ], 1347 "_SaveCntntIdx: Lost FrameFormat" ); 1348 aSave.Add( rSaveArr ); 1349 } 1350 } 1351 } 1352 } 1353 else // Schade, kein Layout, dann ist es eben etwas teurer... 1354 { 1355 for( aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() ); 1356 aSave.GetCount() ; ) 1357 { 1358 SwFrmFmt* pFrmFmt = (*pDoc->GetSpzFrmFmts())[ 1359 aSave.DecCount() ]; 1360 if ( RES_FLYFRMFMT != pFrmFmt->Which() && 1361 RES_DRAWFRMFMT != pFrmFmt->Which() ) 1362 continue; 1363 1364 const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor(); 1365 SwPosition const*const pAPos = rAnchor.GetCntntAnchor(); 1366 if ( pAPos && ( nNode == pAPos->nNode.GetIndex() ) && 1367 ( FLY_AT_PARA == rAnchor.GetAnchorId() || 1368 FLY_AT_CHAR == rAnchor.GetAnchorId() ) ) 1369 { 1370 aSave.SetType( 0x2000 ); 1371 aSave.SetContent( pAPos->nContent.GetIndex() ); 1372 if ( FLY_AT_CHAR == rAnchor.GetAnchorId() ) 1373 { 1374 if( nCntnt <= aSave.GetContent() ) 1375 { 1376 if( SAVEFLY_SPLIT == nSaveFly ) 1377 aSave.IncType(); // = 0x2001; 1378 else 1379 continue; 1380 } 1381 } 1382 aSave.Add( rSaveArr ); 1383 } 1384 } 1385 } 1386 } 1387 } 1388 // 5. CrsrShell 1389 { 1390 SwCrsrShell* pShell = pDoc->GetEditShell(); 1391 if( pShell ) 1392 { 1393 aSave.SetTypeAndCount( 0x800, 0 ); 1394 FOREACHSHELL_START( pShell ) 1395 SwPaM *_pStkCrsr = PCURSH->GetStkCrsr(); 1396 if( _pStkCrsr ) 1397 do { 1398 lcl_ChkPaM( rSaveArr, nNode, nCntnt, *_pStkCrsr, 1399 aSave, sal_False ); 1400 aSave.IncCount(); 1401 } while ( (_pStkCrsr != 0 ) && 1402 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) ); 1403 1404 FOREACHPAM_START( PCURSH->_GetCrsr() ) 1405 lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, 1406 aSave, sal_False ); 1407 aSave.IncCount(); 1408 FOREACHPAM_END() 1409 1410 FOREACHSHELL_END( pShell ) 1411 } 1412 } 1413 // 6. UnoCrsr 1414 { 1415 aSave.SetTypeAndCount( 0x400, 0 ); 1416 const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl(); 1417 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 1418 { 1419 FOREACHPAM_START( rTbl[ n ] ) 1420 lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False ); 1421 aSave.IncCount(); 1422 FOREACHPAM_END() 1423 1424 SwUnoTableCrsr* pUnoTblCrsr = 1425 dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]); 1426 if( pUnoTblCrsr ) 1427 { 1428 FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() ) 1429 lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False ); 1430 aSave.IncCount(); 1431 FOREACHPAM_END() 1432 } 1433 } 1434 } 1435 } 1436 1437 1438 void _RestoreCntntIdx(SwDoc* pDoc, 1439 SvULongs& rSaveArr, 1440 sal_uLong nNode, 1441 xub_StrLen nOffset, 1442 sal_Bool bAuto) 1443 { 1444 SwCntntNode* pCNd = pDoc->GetNodes()[ nNode ]->GetCntntNode(); 1445 const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl(); 1446 SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts(); 1447 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess(); 1448 sal_uInt16 n = 0; 1449 while( n < rSaveArr.Count() ) 1450 { 1451 _SwSaveTypeCountContent aSave( rSaveArr, n ); 1452 SwPosition* pPos = 0; 1453 switch( aSave.GetType() ) 1454 { 1455 case 0x8000: 1456 { 1457 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get()); 1458 SwPosition aNewPos(pMark->GetMarkPos()); 1459 aNewPos.nNode = *pCNd; 1460 aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset); 1461 pMark->SetMarkPos(aNewPos); 1462 } 1463 break; 1464 case 0x8001: 1465 { 1466 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get()); 1467 SwPosition aNewPos(pMark->GetOtherMarkPos()); 1468 aNewPos.nNode = *pCNd; 1469 aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset); 1470 pMark->SetOtherMarkPos(aNewPos); 1471 } 1472 break; 1473 case 0x1001: 1474 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint(); 1475 break; 1476 case 0x1000: 1477 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark(); 1478 break; 1479 case 0x2000: 1480 { 1481 SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ]; 1482 const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor(); 1483 if( rFlyAnchor.GetCntntAnchor() ) 1484 { 1485 SwFmtAnchor aNew( rFlyAnchor ); 1486 SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() ); 1487 aNewPos.nNode = *pCNd; 1488 if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() ) 1489 { 1490 aNewPos.nContent.Assign( pCNd, 1491 aSave.GetContent() + nOffset ); 1492 } 1493 else 1494 { 1495 aNewPos.nContent.Assign( 0, 0 ); 1496 } 1497 aNew.SetAnchor( &aNewPos ); 1498 pFrmFmt->SetFmtAttr( aNew ); 1499 } 1500 } 1501 break; 1502 case 0x2001: 1503 if( bAuto ) 1504 { 1505 SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ]; 1506 SfxPoolItem *pAnchor = (SfxPoolItem*)&pFrmFmt->GetAnchor(); 1507 pFrmFmt->NotifyClients( pAnchor, pAnchor ); 1508 } 1509 break; 1510 1511 case 0x0800: 1512 case 0x0801: 1513 { 1514 sal_uInt16 nCnt = 0; 1515 SwCrsrShell* pShell = pDoc->GetEditShell(); 1516 if( pShell ) 1517 { 1518 FOREACHSHELL_START( pShell ) 1519 SwPaM *_pStkCrsr = PCURSH->GetStkCrsr(); 1520 if( _pStkCrsr ) 1521 do { 1522 if( aSave.GetCount() == nCnt ) 1523 { 1524 pPos = &_pStkCrsr->GetBound( 0x0800 == 1525 aSave.GetType() ); 1526 break; 1527 } 1528 ++nCnt; 1529 } while ( (_pStkCrsr != 0 ) && 1530 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) ); 1531 1532 if( pPos ) 1533 break; 1534 1535 FOREACHPAM_START( PCURSH->_GetCrsr() ) 1536 if( aSave.GetCount() == nCnt ) 1537 { 1538 pPos = &PCURCRSR->GetBound( 0x0800 == 1539 aSave.GetType() ); 1540 break; 1541 } 1542 ++nCnt; 1543 FOREACHPAM_END() 1544 if( pPos ) 1545 break; 1546 1547 FOREACHSHELL_END( pShell ) 1548 } 1549 } 1550 break; 1551 1552 case 0x0400: 1553 case 0x0401: 1554 { 1555 sal_uInt16 nCnt = 0; 1556 const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl(); 1557 for( sal_uInt16 i = 0; i < rTbl.Count(); ++i ) 1558 { 1559 FOREACHPAM_START( rTbl[ i ] ) 1560 if( aSave.GetCount() == nCnt ) 1561 { 1562 pPos = &PCURCRSR->GetBound( 0x0400 == 1563 aSave.GetType() ); 1564 break; 1565 } 1566 ++nCnt; 1567 FOREACHPAM_END() 1568 if( pPos ) 1569 break; 1570 1571 SwUnoTableCrsr* pUnoTblCrsr = 1572 dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]); 1573 if ( pUnoTblCrsr ) 1574 { 1575 FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() ) 1576 if( aSave.GetCount() == nCnt ) 1577 { 1578 pPos = &PCURCRSR->GetBound( 0x0400 == 1579 aSave.GetType() ); 1580 break; 1581 } 1582 ++nCnt; 1583 FOREACHPAM_END() 1584 } 1585 if ( pPos ) 1586 break; 1587 } 1588 } 1589 break; 1590 } 1591 1592 if( pPos ) 1593 { 1594 pPos->nNode = *pCNd; 1595 pPos->nContent.Assign( pCNd, aSave.GetContent() + nOffset ); 1596 } 1597 } 1598 } 1599 1600 void _RestoreCntntIdx(SvULongs& rSaveArr, 1601 const SwNode& rNd, 1602 xub_StrLen nLen, 1603 xub_StrLen nChkLen) 1604 { 1605 const SwDoc* pDoc = rNd.GetDoc(); 1606 const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl(); 1607 const SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts(); 1608 const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess(); 1609 SwCntntNode* pCNd = (SwCntntNode*)rNd.GetCntntNode(); 1610 1611 sal_uInt16 n = 0; 1612 while( n < rSaveArr.Count() ) 1613 { 1614 _SwSaveTypeCountContent aSave( rSaveArr, n ); 1615 if( aSave.GetContent() >= nChkLen ) 1616 rSaveArr[ n-1 ] -= nChkLen; 1617 else 1618 { 1619 SwPosition* pPos = 0; 1620 switch( aSave.GetType() ) 1621 { 1622 case 0x8000: 1623 { 1624 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get()); 1625 SwPosition aNewPos(pMark->GetMarkPos()); 1626 aNewPos.nNode = rNd; 1627 aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen)); 1628 pMark->SetMarkPos(aNewPos); 1629 } 1630 break; 1631 case 0x8001: 1632 { 1633 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get()); 1634 SwPosition aNewPos(pMark->GetOtherMarkPos()); 1635 aNewPos.nNode = rNd; 1636 aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen)); 1637 pMark->SetOtherMarkPos(aNewPos); 1638 } 1639 break; 1640 case 0x1001: 1641 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint(); 1642 break; 1643 case 0x1000: 1644 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark(); 1645 break; 1646 case 0x2000: 1647 case 0x2001: 1648 { 1649 SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ]; 1650 const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor(); 1651 if( rFlyAnchor.GetCntntAnchor() ) 1652 { 1653 SwFmtAnchor aNew( rFlyAnchor ); 1654 SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() ); 1655 aNewPos.nNode = rNd; 1656 if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() ) 1657 { 1658 aNewPos.nContent.Assign( pCNd, Min( 1659 aSave.GetContent(), nLen ) ); 1660 } 1661 else 1662 { 1663 aNewPos.nContent.Assign( 0, 0 ); 1664 } 1665 aNew.SetAnchor( &aNewPos ); 1666 pFrmFmt->SetFmtAttr( aNew ); 1667 } 1668 } 1669 break; 1670 1671 case 0x0800: 1672 case 0x0801: 1673 { 1674 sal_uInt16 nCnt = 0; 1675 SwCrsrShell* pShell = pDoc->GetEditShell(); 1676 if( pShell ) 1677 { 1678 FOREACHSHELL_START( pShell ) 1679 SwPaM *_pStkCrsr = PCURSH->GetStkCrsr(); 1680 if( _pStkCrsr ) 1681 do { 1682 if( aSave.GetCount() == nCnt ) 1683 { 1684 pPos = &_pStkCrsr->GetBound( 0x0800 == 1685 aSave.GetType() ); 1686 break; 1687 } 1688 ++nCnt; 1689 } while ( (_pStkCrsr != 0 ) && 1690 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) ); 1691 1692 if( pPos ) 1693 break; 1694 1695 FOREACHPAM_START( PCURSH->_GetCrsr() ) 1696 if( aSave.GetCount() == nCnt ) 1697 { 1698 pPos = &PCURCRSR->GetBound( 0x0800 == 1699 aSave.GetType() ); 1700 break; 1701 } 1702 ++nCnt; 1703 FOREACHPAM_END() 1704 if( pPos ) 1705 break; 1706 1707 FOREACHSHELL_END( pShell ) 1708 } 1709 } 1710 break; 1711 1712 case 0x0400: 1713 case 0x0401: 1714 { 1715 sal_uInt16 nCnt = 0; 1716 const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl(); 1717 for( sal_uInt16 i = 0; i < rTbl.Count(); ++i ) 1718 { 1719 FOREACHPAM_START( rTbl[ i ] ) 1720 if( aSave.GetCount() == nCnt ) 1721 { 1722 pPos = &PCURCRSR->GetBound( 0x0400 == 1723 aSave.GetType() ); 1724 break; 1725 } 1726 ++nCnt; 1727 FOREACHPAM_END() 1728 if( pPos ) 1729 break; 1730 1731 SwUnoTableCrsr* pUnoTblCrsr = 1732 dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]); 1733 if ( pUnoTblCrsr ) 1734 { 1735 FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() ) 1736 if( aSave.GetCount() == nCnt ) 1737 { 1738 pPos = &PCURCRSR->GetBound( 0x0400 == 1739 aSave.GetType() ); 1740 break; 1741 } 1742 ++nCnt; 1743 FOREACHPAM_END() 1744 } 1745 if ( pPos ) 1746 break; 1747 } 1748 } 1749 break; 1750 } 1751 1752 if( pPos ) 1753 { 1754 pPos->nNode = rNd; 1755 pPos->nContent.Assign( pCNd, Min( aSave.GetContent(), nLen ) ); 1756 } 1757 n -= 2; 1758 rSaveArr.Remove( n, 2 ); 1759 } 1760 } 1761 } 1762