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