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 #include <com/sun/star/util/SearchOptions.hpp> 27 #include <com/sun/star/text/XTextRange.hpp> 28 #include <hintids.hxx> 29 #include <svx/svdmodel.hxx> 30 #include <editeng/frmdiritem.hxx> 31 32 #include <SwSmartTagMgr.hxx> 33 #include <doc.hxx> 34 #include <rootfrm.hxx> 35 #include <pagefrm.hxx> 36 #include <cntfrm.hxx> 37 #include <viewimp.hxx> 38 #include <pam.hxx> 39 #include <swselectionlist.hxx> 40 #include <IBlockCursor.hxx> 41 #include "BlockCursor.hxx" 42 #include <ndtxt.hxx> 43 #include <flyfrm.hxx> 44 #include <dview.hxx> 45 #include <viewopt.hxx> 46 #include <frmtool.hxx> 47 #include <crsrsh.hxx> 48 #include <tabfrm.hxx> 49 #include <txtfrm.hxx> 50 #include <sectfrm.hxx> 51 #include <swtable.hxx> 52 #include <callnk.hxx> 53 #include <viscrs.hxx> 54 #include <section.hxx> 55 #include <docsh.hxx> 56 #include <scriptinfo.hxx> 57 #include <globdoc.hxx> 58 #include <pamtyp.hxx> 59 #include <mdiexp.hxx> // ...Percent() 60 #include <fmteiro.hxx> 61 #include <wrong.hxx> // SMARTTAGS 62 #include <unotextrange.hxx> // SMARTTAGS 63 #include <vcl/svapp.hxx> 64 #include <numrule.hxx> 65 #include <IGrammarContact.hxx> 66 67 #include <globals.hrc> 68 69 #include <comcore.hrc> 70 71 using namespace com::sun::star; 72 using namespace util; 73 74 TYPEINIT2(SwCrsrShell,ViewShell,SwModify); 75 76 77 // Funktion loescht, alle ueberlappenden Cursor aus einem Cursor-Ring 78 void CheckRange( SwCursor* ); 79 80 //----------------------------------------------------------------------- 81 82 /* 83 * Ueberpruefe ob der pCurCrsr in einen schon bestehenden Bereich zeigt. 84 * Wenn ja, dann hebe den alten Bereich auf. 85 */ 86 87 88 void CheckRange( SwCursor* pCurCrsr ) 89 { 90 const SwPosition *pStt = pCurCrsr->Start(), 91 *pEnd = pCurCrsr->GetPoint() == pStt ? pCurCrsr->GetMark() : pCurCrsr->GetPoint(); 92 93 SwPaM *pTmpDel = 0, 94 *pTmp = (SwPaM*)pCurCrsr->GetNext(); 95 96 // durchsuche den gesamten Ring 97 while( pTmp != pCurCrsr ) 98 { 99 const SwPosition *pTmpStt = pTmp->Start(), 100 *pTmpEnd = pTmp->GetPoint() == pTmpStt ? 101 pTmp->GetMark() : pTmp->GetPoint(); 102 if( *pStt <= *pTmpStt ) 103 { 104 if( *pEnd > *pTmpStt || 105 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd )) 106 pTmpDel = pTmp; 107 } 108 else 109 if( *pStt < *pTmpEnd ) 110 pTmpDel = pTmp; 111 /* 112 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich 113 * muss der alte Bereich aufgehoben werden. 114 * Beim Vergleich ist darauf zu achten, das SPoint nicht mehr zum 115 * Bereich gehoert ! 116 */ 117 pTmp = (SwPaM*)pTmp->GetNext(); 118 if( pTmpDel ) 119 { 120 delete pTmpDel; // hebe alten Bereich auf 121 pTmpDel = 0; 122 } 123 } 124 } 125 126 // -------------- Methoden von der SwCrsrShell ------------- 127 128 SwPaM * SwCrsrShell::CreateCrsr() 129 { 130 // Innerhalb der Tabellen-SSelection keinen neuen Crsr anlegen 131 ASSERT( !IsTableMode(), "in Tabellen SSelection" ); 132 133 // neuen Cursor als Kopie vom akt. und in den Ring aufnehmen 134 // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts 135 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr ); 136 137 // hier den akt. Pam nur logisch Hiden, weil sonst die Invertierung 138 // vom kopierten Pam aufgehoben wird !! 139 140 // #i75172# to be able to make a complete content swap, i moved this to a method 141 // pNew->Insert( pCurCrsr, 0 ); 142 // pCurCrsr->Remove( 0, pCurCrsr->Count() ); 143 pNew->swapContent(*pCurCrsr); 144 145 pCurCrsr->DeleteMark(); 146 147 UpdateCrsr( SwCrsrShell::SCROLLWIN ); 148 // return pCurCrsr; 149 return pNew; 150 } 151 152 // loesche den aktuellen Cursor und der folgende wird zum Aktuellen 153 154 155 sal_Bool SwCrsrShell::DestroyCrsr() 156 { 157 // Innerhalb der Tabellen-SSelection keinen neuen Crsr loeschen 158 ASSERT( !IsTableMode(), "in Tabellen SSelection" ); 159 160 // ist ueberhaupt ein naechtser vorhanden ? 161 if(pCurCrsr->GetNext() == pCurCrsr) 162 return sal_False; 163 164 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, 165 SwCursor* pNextCrsr = (SwCursor*)pCurCrsr->GetNext(); 166 delete pCurCrsr; 167 pCurCrsr = dynamic_cast<SwShellCrsr*>(pNextCrsr); 168 UpdateCrsr(); 169 return sal_True; 170 } 171 172 173 SwPaM & SwCrsrShell::CreateNewShellCursor() 174 { 175 if (HasSelection()) 176 { 177 (void) CreateCrsr(); // n.b. returns old cursor 178 } 179 return *GetCrsr(); 180 } 181 182 SwPaM & SwCrsrShell::GetCurrentShellCursor() 183 { 184 return *GetCrsr(); 185 } 186 187 188 // gebe den aktuellen zurueck 189 190 SwPaM* SwCrsrShell::GetCrsr( sal_Bool bMakeTblCrsr ) const 191 { 192 if( pTblCrsr ) 193 { 194 if( bMakeTblCrsr && pTblCrsr->IsCrsrMovedUpdt() ) 195 { 196 // geparkte Cursor werden nicht wieder erzeugt 197 const SwCntntNode* pCNd; 198 if( pTblCrsr->GetPoint()->nNode.GetIndex() && 199 pTblCrsr->GetMark()->nNode.GetIndex() && 200 0 != ( pCNd = pTblCrsr->GetCntntNode() ) && pCNd->getLayoutFrm( GetLayout() ) && 201 0 != ( pCNd = pTblCrsr->GetCntntNode(sal_False) ) && pCNd->getLayoutFrm( GetLayout() ) ) 202 { 203 SwShellTableCrsr* pTC = (SwShellTableCrsr*)pTblCrsr; 204 GetLayout()->MakeTblCrsrs( *pTC ); 205 } 206 } 207 208 if( pTblCrsr->IsChgd() ) 209 { 210 const_cast<SwCrsrShell*>(this)->pCurCrsr = 211 dynamic_cast<SwShellCrsr*>(pTblCrsr->MakeBoxSels( pCurCrsr )); 212 } 213 } 214 return pCurCrsr; 215 } 216 217 218 void SwCrsrShell::StartAction() 219 { 220 if( !ActionPend() ) 221 { 222 // fuer das Update des Ribbon-Bars merken 223 const SwNode& rNd = pCurCrsr->GetPoint()->nNode.GetNode(); 224 nAktNode = rNd.GetIndex(); 225 nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex(); 226 nAktNdTyp = rNd.GetNodeType(); 227 bAktSelection = *pCurCrsr->GetPoint() != *pCurCrsr->GetMark(); 228 if( ND_TEXTNODE & nAktNdTyp ) 229 nLeftFrmPos = SwCallLink::getLayoutFrm( GetLayout(), (SwTxtNode&)rNd, nAktCntnt, sal_True ); 230 else 231 nLeftFrmPos = 0; 232 } 233 ViewShell::StartAction(); // zur ViewShell 234 } 235 236 237 void SwCrsrShell::EndAction( const sal_Bool bIdleEnd ) 238 { 239 /* 240 //OS: Wird z.B. eine Basic-Action im Hintergrund ausgefuehrt, geht es so nicht 241 if( !bHasFocus ) 242 { 243 // hat die Shell nicht den Focus, dann nur das EndAction an 244 // die ViewShell weitergeben. 245 ViewShell::EndAction( bIdleEnd ); 246 return; 247 } 248 */ 249 250 sal_Bool bVis = bSVCrsrVis; 251 252 // Idle-Formatierung ? 253 if( bIdleEnd && Imp()->GetRegion() ) 254 { 255 pCurCrsr->Hide(); 256 257 #ifdef SHOW_IDLE_REGION 258 if( GetWin() ) 259 { 260 GetWin()->Push(); 261 GetWin()->ChangePen( Pen( Color( COL_YELLOW ))); 262 for( sal_uInt16 n = 0; n < aPntReg.Count(); ++n ) 263 { 264 SwRect aIRect( aPntReg[n] ); 265 GetWin()->DrawRect( aIRect.SVRect() ); 266 } 267 GetWin()->Pop(); 268 } 269 #endif 270 271 } 272 273 // vor der letzten Action alle invaliden Numerierungen updaten 274 if( 1 == nStartAction ) 275 GetDoc()->UpdateNumRule(); 276 277 // Task: 76923: dont show the cursor in the ViewShell::EndAction() - call. 278 // Only the UpdateCrsr shows the cursor. 279 sal_Bool bSavSVCrsrVis = bSVCrsrVis; 280 bSVCrsrVis = sal_False; 281 282 ViewShell::EndAction( bIdleEnd ); //der ViewShell den Vortritt lassen 283 284 bSVCrsrVis = bSavSVCrsrVis; 285 286 if( ActionPend() ) 287 { 288 if( bVis ) // auch SV-Cursor wieder anzeigen 289 pVisCrsr->Show(); 290 291 // falls noch ein ChgCall vorhanden ist und nur noch die Basic 292 // Klammerung vorhanden ist, dann rufe ihn. Dadurch wird die interne 293 // mit der Basic-Klammerung entkoppelt; die Shells werden umgeschaltet 294 if( !BasicActionPend() ) 295 { 296 //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction 297 // der Cursor geupdatet werden; um z.B. den 298 // TabellenCursor zu erzeugen. Im UpdateCrsr wird 299 // das jetzt beruecksichtigt! 300 UpdateCrsr( SwCrsrShell::CHKRANGE, bIdleEnd ); 301 302 { 303 // Crsr-Moves ueberwachen, evt. Link callen 304 // der DTOR ist das interressante!! 305 SwCallLink aLk( *this, nAktNode, nAktCntnt, (sal_uInt8)nAktNdTyp, 306 nLeftFrmPos, bAktSelection ); 307 308 } 309 if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() ) 310 { 311 aChgLnk.Call( this ); 312 bChgCallFlag = sal_False; // Flag zuruecksetzen 313 } 314 } 315 return; 316 } 317 318 sal_uInt16 nParm = SwCrsrShell::CHKRANGE; 319 if ( !bIdleEnd ) 320 nParm |= SwCrsrShell::SCROLLWIN; 321 // if( !IsViewLocked() ) 322 UpdateCrsr( nParm, bIdleEnd ); // Cursor-Aenderungen anzeigen 323 324 { 325 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, 326 aLk.nNode = nAktNode; // evt. Link callen 327 aLk.nNdTyp = (sal_uInt8)nAktNdTyp; 328 aLk.nCntnt = nAktCntnt; 329 aLk.nLeftFrmPos = nLeftFrmPos; 330 331 if( !nCrsrMove || 332 ( 1 == nCrsrMove && bInCMvVisportChgd ) ) 333 ShowCrsrs( bSVCrsrVis ? sal_True : sal_False ); // Cursor & Selektionen wieder anzeigen 334 } 335 // falls noch ein ChgCall vorhanden ist, dann rufe ihn 336 if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() ) 337 { 338 aChgLnk.Call( this ); 339 bChgCallFlag = sal_False; // Flag zuruecksetzen 340 } 341 } 342 343 344 #if defined(DBG_UTIL) 345 346 void SwCrsrShell::SttCrsrMove() 347 { 348 ASSERT( nCrsrMove < USHRT_MAX, "To many nested CrsrMoves." ); 349 ++nCrsrMove; 350 StartAction(); 351 } 352 353 void SwCrsrShell::EndCrsrMove( const sal_Bool bIdleEnd ) 354 { 355 ASSERT( nCrsrMove, "EndCrsrMove() ohne SttCrsrMove()." ); 356 EndAction( bIdleEnd ); 357 if( !--nCrsrMove ) 358 bInCMvVisportChgd = sal_False; 359 } 360 361 #endif 362 363 364 sal_Bool SwCrsrShell::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, 365 sal_Bool bVisualAllowed ) 366 { 367 if( IsTableMode() ) 368 return bLeft ? GoPrevCell() : GoNextCell(); 369 370 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 371 sal_Bool bRet = sal_False; 372 373 // #i27615# Handle cursor in front of label. 374 const SwTxtNode* pTxtNd = 0; 375 376 if( pBlockCrsr ) 377 pBlockCrsr->clearPoints(); 378 379 // 380 // 1. CASE: Cursor is in front of label. A move to the right 381 // will simply reset the bInFrontOfLabel flag: 382 // 383 SwShellCrsr* pShellCrsr = getShellCrsr( true ); 384 if ( !bLeft && pShellCrsr->IsInFrontOfLabel() ) 385 { 386 SetInFrontOfLabel( sal_False ); 387 bRet = sal_True; 388 } 389 // 390 // 2. CASE: Cursor is at beginning of numbered paragraph. A move 391 // to the left will simply set the bInFrontOfLabel flag: 392 // 393 else if ( bLeft && 0 == pShellCrsr->GetPoint()->nContent.GetIndex() && 394 !pShellCrsr->IsInFrontOfLabel() && !pShellCrsr->HasMark() && 395 0 != ( pTxtNd = pShellCrsr->GetNode()->GetTxtNode() ) && 396 pTxtNd->HasVisibleNumberingOrBullet() ) 397 { 398 SetInFrontOfLabel( sal_True ); 399 bRet = sal_True; 400 } 401 // 402 // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag: 403 // 404 else 405 { 406 const sal_Bool bSkipHidden = !GetViewOptions()->IsShowHiddenChar(); 407 // --> OD 2009-12-30 #i107447# 408 // To avoid loop the reset of <bInFrontOfLabel> flag is no longer 409 // reflected in the return value <bRet>. 410 const bool bResetOfInFrontOfLabel = SetInFrontOfLabel( sal_False ); 411 bRet = pShellCrsr->LeftRight( bLeft, nCnt, nMode, bVisualAllowed, 412 bSkipHidden, !IsOverwriteCrsr() ); 413 if ( !bRet && bLeft && bResetOfInFrontOfLabel ) 414 { 415 // undo reset of <bInFrontOfLabel> flag 416 SetInFrontOfLabel( sal_True ); 417 } 418 // <-- 419 } 420 421 if( bRet ) 422 { 423 UpdateCrsr(); 424 } 425 return bRet; 426 } 427 //IAccessibility2 Implementation 2009----- 428 void SwCrsrShell::FirePageChangeEvent(sal_uInt16 nOldPage, sal_uInt16 nNewPage) 429 { 430 #ifdef ACCESSIBLE_LAYOUT 431 if( Imp()->IsAccessible() ) 432 Imp()->FirePageChangeEvent( nOldPage, nNewPage ); 433 #endif 434 } 435 436 void SwCrsrShell::FireColumnChangeEvent(sal_uInt16 nOldColumn, sal_uInt16 nNewColumn) 437 { 438 #ifdef ACCESSIBLE_LAYOUT 439 if( Imp()->IsAccessible() ) 440 Imp()->FireColumnChangeEvent( nOldColumn, nNewColumn); 441 #endif 442 } 443 444 445 void SwCrsrShell::FireSectionChangeEvent(sal_uInt16 nOldSection, sal_uInt16 nNewSection) 446 { 447 #ifdef ACCESSIBLE_LAYOUT 448 if( Imp()->IsAccessible() ) 449 Imp()->FireSectionChangeEvent( nOldSection, nNewSection ); 450 #endif 451 } 452 bool SwCrsrShell::bColumnChange() 453 { 454 455 sal_uInt16 nCurrCol = 0; 456 SwFrm* pCurrFrm = GetCurrFrm(sal_False); 457 458 if (pCurrFrm == NULL) 459 { 460 return sal_False; 461 } 462 463 SwFrm* pCurrCol=((SwFrm*)pCurrFrm)->FindColFrm(); 464 465 while(pCurrCol== NULL && pCurrFrm!=NULL ) 466 { 467 SwLayoutFrm* pParent = pCurrFrm->GetUpper(); 468 if(pParent!=NULL) 469 { 470 pCurrCol=((SwFrm*)pParent)->FindColFrm(); 471 pCurrFrm = (SwFrm*)pParent; 472 } 473 else 474 { 475 break; 476 } 477 } 478 if(oldColFrm == pCurrCol) 479 return sal_False; 480 else 481 { 482 oldColFrm = pCurrCol; 483 return sal_True; 484 } 485 } 486 //-----IAccessibility2 Implementation 2009 487 488 // --> OD 2008-04-02 #refactorlists# 489 void SwCrsrShell::MarkListLevel( const String& sListId, 490 const int nListLevel ) 491 { 492 if ( sListId != sMarkedListId || 493 nListLevel != nMarkedListLevel) 494 { 495 if ( sMarkedListId.Len() > 0 ) 496 pDoc->MarkListLevel( sMarkedListId, nMarkedListLevel, sal_False ); 497 498 if ( sListId.Len() > 0 ) 499 { 500 pDoc->MarkListLevel( sListId, nListLevel, sal_True ); 501 } 502 503 sMarkedListId = sListId; 504 nMarkedListLevel = nListLevel; 505 } 506 } 507 508 void SwCrsrShell::UpdateMarkedListLevel() 509 { 510 SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode(); 511 512 if ( pTxtNd ) 513 { 514 if ( !pTxtNd->IsNumbered() ) 515 { 516 pCurCrsr->_SetInFrontOfLabel( sal_False ); 517 MarkListLevel( String(), 0 ); 518 } 519 else if ( pCurCrsr->IsInFrontOfLabel() ) 520 { 521 if ( pTxtNd->IsInList() ) 522 { 523 ASSERT( pTxtNd->GetActualListLevel() >= 0 && 524 pTxtNd->GetActualListLevel() < MAXLEVEL, "Which level?") 525 MarkListLevel( pTxtNd->GetListId(), 526 pTxtNd->GetActualListLevel() ); 527 } 528 } 529 else 530 { 531 MarkListLevel( String(), 0 ); 532 } 533 } 534 } 535 // <-- 536 537 sal_Bool SwCrsrShell::UpDown( sal_Bool bUp, sal_uInt16 nCnt ) 538 { 539 SET_CURR_SHELL( this ); 540 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 541 542 sal_Bool bTableMode = IsTableMode(); 543 SwShellCrsr* pTmpCrsr = getShellCrsr( true ); 544 545 sal_Bool bRet = pTmpCrsr->UpDown( bUp, nCnt ); 546 // --> FME 2005-01-10 #i40019# UpDown should always reset the 547 // bInFrontOfLabel flag: 548 bRet = SetInFrontOfLabel(sal_False) || bRet; 549 // <-- 550 551 if( pBlockCrsr ) 552 pBlockCrsr->clearPoints(); 553 554 if( bRet ) 555 { 556 eMvState = MV_UPDOWN; // Status fuers Crsr-Travelling - GetCrsrOfst 557 if( !ActionPend() ) 558 { 559 CrsrFlag eUpdtMode = SwCrsrShell::SCROLLWIN; 560 if( !bTableMode ) 561 eUpdtMode = (CrsrFlag) (eUpdtMode 562 | SwCrsrShell::UPDOWN | SwCrsrShell::CHKRANGE); 563 UpdateCrsr( static_cast<sal_uInt16>(eUpdtMode) ); 564 } 565 } 566 return bRet; 567 } 568 569 570 sal_Bool SwCrsrShell::LRMargin( sal_Bool bLeft, sal_Bool bAPI) 571 { 572 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 573 SET_CURR_SHELL( this ); 574 eMvState = MV_LEFTMARGIN; // Status fuers Crsr-Travelling - GetCrsrOfst 575 576 const sal_Bool bTableMode = IsTableMode(); 577 SwShellCrsr* pTmpCrsr = getShellCrsr( true ); 578 579 if( pBlockCrsr ) 580 pBlockCrsr->clearPoints(); 581 582 const sal_Bool bWasAtLM = 583 ( 0 == _GetCrsr()->GetPoint()->nContent.GetIndex() ); 584 585 sal_Bool bRet = pTmpCrsr->LeftRightMargin( bLeft, bAPI ); 586 587 if ( bLeft && !bTableMode && bRet && bWasAtLM && !_GetCrsr()->HasMark() ) 588 { 589 const SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode(); 590 if ( pTxtNd && pTxtNd->HasVisibleNumberingOrBullet() ) 591 SetInFrontOfLabel( sal_True ); 592 } 593 else if ( !bLeft ) 594 { 595 bRet = SetInFrontOfLabel( sal_False ) || bRet; 596 } 597 598 if( bRet ) 599 { 600 UpdateCrsr(); 601 } 602 return bRet; 603 } 604 605 sal_Bool SwCrsrShell::IsAtLRMargin( sal_Bool bLeft, sal_Bool bAPI ) const 606 { 607 const SwShellCrsr* pTmpCrsr = getShellCrsr( true ); 608 return pTmpCrsr->IsAtLeftRightMargin( bLeft, bAPI ); 609 } 610 611 612 sal_Bool SwCrsrShell::SttEndDoc( sal_Bool bStt ) 613 { 614 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 615 616 SwShellCrsr* pTmpCrsr = pBlockCrsr ? &pBlockCrsr->getShellCrsr() : pCurCrsr; 617 sal_Bool bRet = pTmpCrsr->SttEndDoc( bStt ); 618 if( bRet ) 619 { 620 if( bStt ) 621 pTmpCrsr->GetPtPos().Y() = 0; // expl. 0 setzen (TabellenHeader) 622 if( pBlockCrsr ) 623 { 624 pBlockCrsr->clearPoints(); 625 RefreshBlockCursor(); 626 } 627 628 UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY); 629 } 630 return bRet; 631 } 632 633 void SwCrsrShell::ExtendedSelectAll() 634 { 635 SwNodes& rNodes = GetDoc()->GetNodes(); 636 SwPosition* pPos = pCurCrsr->GetPoint(); 637 pPos->nNode = rNodes.GetEndOfPostIts(); 638 pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 ); 639 pPos = pCurCrsr->GetMark(); 640 pPos->nNode = rNodes.GetEndOfContent(); 641 SwCntntNode* pCNd = rNodes.GoPrevious( &pPos->nNode ); 642 pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 ); 643 } 644 645 sal_Bool SwCrsrShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage ) 646 { 647 sal_Bool bRet = sal_False; 648 649 // Springe beim Selektieren nie ueber Section-Grenzen !! 650 if( !pCurCrsr->HasMark() || !pCurCrsr->IsNoCntnt() ) 651 { 652 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 653 SET_CURR_SHELL( this ); 654 655 SwCrsrSaveState aSaveState( *pCurCrsr ); 656 Point& rPt = pCurCrsr->GetPtPos(); 657 SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()-> 658 getLayoutFrm( GetLayout(), &rPt, pCurCrsr->GetPoint(), sal_False ); 659 if( pFrm && sal_True == ( bRet = GetFrmInPage( pFrm, fnWhichPage, 660 fnPosPage, pCurCrsr ) ) && 661 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 662 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS )) 663 UpdateCrsr(); 664 else 665 bRet = sal_False; 666 } 667 return bRet; 668 } 669 670 671 sal_Bool SwCrsrShell::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara ) 672 { 673 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 674 SwCursor* pTmpCrsr = getShellCrsr( true ); 675 sal_Bool bRet = pTmpCrsr->MovePara( fnWhichPara, fnPosPara ); 676 if( bRet ) 677 UpdateCrsr(); 678 return bRet; 679 } 680 681 682 sal_Bool SwCrsrShell::MoveSection( SwWhichSection fnWhichSect, 683 SwPosSection fnPosSect) 684 { 685 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 686 SwCursor* pTmpCrsr = getShellCrsr( true ); 687 sal_Bool bRet = pTmpCrsr->MoveSection( fnWhichSect, fnPosSect ); 688 if( bRet ) 689 UpdateCrsr(); 690 return bRet; 691 692 } 693 694 695 // Positionieren des Cursors 696 697 698 SwFrm* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt ) 699 { 700 SwFrm* pFrm = 0; 701 SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode(); 702 if( pCNd ) 703 { 704 pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &rPt, 0, sal_False )->GetUpper(); 705 while( pFrm && !pFrm->IsHeaderFrm() && !pFrm->IsFooterFrm() ) 706 pFrm = pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->AnchorFrm() 707 : pFrm->GetUpper(); 708 } 709 return pFrm; 710 } 711 712 sal_Bool SwCrsrShell::IsInHeaderFooter( sal_Bool* pbInHeader ) const 713 { 714 Point aPt; 715 SwFrm* pFrm = ::lcl_IsInHeaderFooter( pCurCrsr->GetPoint()->nNode, aPt ); 716 if( pFrm && pbInHeader ) 717 *pbInHeader = pFrm->IsHeaderFrm(); 718 return 0 != pFrm; 719 } 720 721 int SwCrsrShell::SetCrsr( const Point &rLPt, sal_Bool bOnlyText, bool bBlock ) 722 { 723 SET_CURR_SHELL( this ); 724 725 SwShellCrsr* pCrsr = getShellCrsr( bBlock ); 726 SwPosition aPos( *pCrsr->GetPoint() ); 727 Point aPt( rLPt ); 728 Point & rAktCrsrPt = pCrsr->GetPtPos(); 729 SwCrsrMoveState aTmpState( IsTableMode() ? MV_TBLSEL : 730 bOnlyText ? MV_SETONLYTEXT : MV_NONE ); 731 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 732 733 SwTxtNode * pTxtNd = pCrsr->GetNode()->GetTxtNode(); 734 735 if ( pTxtNd && !IsTableMode() && 736 // --> FME 2004-11-25 #i37515# No bInFrontOfLabel during selection 737 !pCrsr->HasMark() && 738 // <-- 739 pTxtNd->HasVisibleNumberingOrBullet() ) 740 { 741 aTmpState.bInFrontOfLabel = sal_True; // #i27615# 742 } 743 else 744 { 745 aTmpState.bInFrontOfLabel = sal_False; 746 } 747 748 int bRet = CRSR_POSOLD | 749 ( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState ) 750 ? 0 : CRSR_POSCHG ); 751 752 const bool bOldInFrontOfLabel = IsInFrontOfLabel(); 753 const bool bNewInFrontOfLabel = aTmpState.bInFrontOfLabel; 754 755 pCrsr->SetCrsrBidiLevel( aTmpState.nCursorBidiLevel ); 756 757 if( MV_RIGHTMARGIN == aTmpState.eState ) 758 eMvState = MV_RIGHTMARGIN; 759 // steht neu Pos im Header/Footer ? 760 SwFrm* pFrm = lcl_IsInHeaderFooter( aPos.nNode, aPt ); 761 if( IsTableMode() && !pFrm && aPos.nNode.GetNode().StartOfSectionNode() == 762 pCrsr->GetPoint()->nNode.GetNode().StartOfSectionNode() ) 763 // gleiche Tabellenzelle und nicht im Header/Footer 764 // -> zurueck 765 return bRet; 766 767 if( pBlockCrsr && bBlock ) 768 { 769 pBlockCrsr->setEndPoint( rLPt ); 770 if( !pCrsr->HasMark() ) 771 pBlockCrsr->setStartPoint( rLPt ); 772 else if( !pBlockCrsr->getStartPoint() ) 773 pBlockCrsr->setStartPoint( pCrsr->GetMkPos() ); 774 } 775 if( !pCrsr->HasMark() ) 776 { 777 // steht an der gleichen Position und wenn im Header/Footer, 778 // dann im gleichen 779 if( aPos == *pCrsr->GetPoint() && 780 bOldInFrontOfLabel == bNewInFrontOfLabel ) 781 { 782 if( pFrm ) 783 { 784 if( pFrm->Frm().IsInside( rAktCrsrPt )) 785 return bRet; 786 } 787 else if( aPos.nNode.GetNode().IsCntntNode() ) 788 { 789 // im gleichen Frame gelandet? 790 SwFrm* pOld = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm( 791 GetLayout(), &aCharRect.Pos(), 0, sal_False ); 792 SwFrm* pNew = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm( 793 GetLayout(), &aPt, 0, sal_False ); 794 if( pNew == pOld ) 795 return bRet; 796 } 797 } 798 } 799 else 800 { 801 // SSelection ueber nicht erlaubte Sections oder wenn im Header/Footer 802 // dann in verschiedene 803 if( !CheckNodesRange( aPos.nNode, pCrsr->GetMark()->nNode, sal_True ) 804 || ( pFrm && !pFrm->Frm().IsInside( pCrsr->GetMkPos() ) )) 805 return bRet; 806 807 // steht an der gleichen Position und nicht im Header/Footer 808 if( aPos == *pCrsr->GetPoint() ) 809 return bRet; 810 } 811 812 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 813 SwCrsrSaveState aSaveState( *pCrsr ); 814 815 *pCrsr->GetPoint() = aPos; 816 rAktCrsrPt = aPt; 817 818 // --> FME 2005-01-31 #i41424# Only update the marked number levels if necessary 819 // Force update of marked number levels if necessary. 820 if ( bNewInFrontOfLabel || bOldInFrontOfLabel ) 821 pCurCrsr->_SetInFrontOfLabel( !bNewInFrontOfLabel ); 822 SetInFrontOfLabel( bNewInFrontOfLabel ); 823 // <-- 824 825 if( !pCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) ) 826 { 827 sal_uInt16 nFlag = SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE; 828 UpdateCrsr( nFlag ); 829 bRet &= ~CRSR_POSOLD; 830 } 831 else if( bOnlyText && !pCurCrsr->HasMark() ) 832 { 833 if( FindValidCntntNode( bOnlyText ) ) 834 { 835 // Cursor in einen gueltigen Content stellen 836 if( aPos == *pCrsr->GetPoint() ) 837 bRet = CRSR_POSOLD; 838 else 839 { 840 UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE ); 841 bRet &= ~CRSR_POSOLD; 842 } 843 } 844 else 845 { 846 // es gibt keinen gueltigen Inhalt -> Cursor verstecken 847 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken 848 eMvState = MV_NONE; // Status fuers Crsr-Travelling 849 bAllProtect = sal_True; 850 if( GetDoc()->GetDocShell() ) 851 { 852 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True ); 853 CallChgLnk(); // UI bescheid sagen! 854 } 855 } 856 } 857 858 return bRet; 859 } 860 861 862 void SwCrsrShell::TblCrsrToCursor() 863 { 864 ASSERT( pTblCrsr, "TblCrsrToCursor: Why?" ); 865 delete pTblCrsr, pTblCrsr = 0; 866 } 867 868 void SwCrsrShell::BlockCrsrToCrsr() 869 { 870 ASSERT( pBlockCrsr, "BlockCrsrToCrsr: Why?" ); 871 if( pBlockCrsr && !HasSelection() ) 872 { 873 SwPaM& rPam = pBlockCrsr->getShellCrsr(); 874 pCurCrsr->SetMark(); 875 *pCurCrsr->GetPoint() = *rPam.GetPoint(); 876 if( rPam.HasMark() ) 877 *pCurCrsr->GetMark() = *rPam.GetMark(); 878 else 879 pCurCrsr->DeleteMark(); 880 } 881 delete pBlockCrsr, pBlockCrsr = 0; 882 } 883 884 void SwCrsrShell::CrsrToBlockCrsr() 885 { 886 if( !pBlockCrsr ) 887 { 888 SwPosition aPos( *pCurCrsr->GetPoint() ); 889 pBlockCrsr = createBlockCursor( *this, aPos ); 890 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr(); 891 rBlock.GetPtPos() = pCurCrsr->GetPtPos(); 892 if( pCurCrsr->HasMark() ) 893 { 894 rBlock.SetMark(); 895 *rBlock.GetMark() = *pCurCrsr->GetMark(); 896 rBlock.GetMkPos() = pCurCrsr->GetMkPos(); 897 } 898 } 899 pBlockCrsr->clearPoints(); 900 RefreshBlockCursor(); 901 } 902 903 void SwCrsrShell::ClearMark() 904 { 905 // ist ueberhaupt ein GetMark gesetzt ? 906 if( pTblCrsr ) 907 { 908 while( pCurCrsr->GetNext() != pCurCrsr ) 909 delete pCurCrsr->GetNext(); 910 pTblCrsr->DeleteMark(); 911 912 if( pCurCrsr->HasMark() ) 913 { 914 // falls doch nicht alle Indizies richtig verschoben werden 915 // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom 916 // Mark aufs Nodes-Array setzen 917 SwPosition& rPos = *pCurCrsr->GetMark(); 918 rPos.nNode.Assign( pDoc->GetNodes(), 0 ); 919 rPos.nContent.Assign( 0, 0 ); 920 pCurCrsr->DeleteMark(); 921 } 922 923 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint(); 924 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos(); 925 delete pTblCrsr, pTblCrsr = 0; 926 pCurCrsr->SwSelPaintRects::Show(); 927 } 928 else 929 { 930 if( !pCurCrsr->HasMark() ) 931 return; 932 // falls doch nicht alle Indizies richtig verschoben werden 933 // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom 934 // Mark aufs Nodes-Array setzen 935 SwPosition& rPos = *pCurCrsr->GetMark(); 936 rPos.nNode.Assign( pDoc->GetNodes(), 0 ); 937 rPos.nContent.Assign( 0, 0 ); 938 pCurCrsr->DeleteMark(); 939 if( !nCrsrMove ) 940 pCurCrsr->SwSelPaintRects::Show(); 941 } 942 } 943 944 945 void SwCrsrShell::NormalizePam(sal_Bool bPointFirst) 946 { 947 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 948 pCurCrsr->Normalize(bPointFirst); 949 } 950 951 void SwCrsrShell::SwapPam() 952 { 953 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 954 pCurCrsr->Exchange(); 955 } 956 957 958 // suche innerhalb der Selektierten-Bereiche nach einer Selektion, die 959 // den angebenen SPoint umschliesst 960 // Ist das Flag bTstOnly gesetzt, dann wird nur getestet, ob dort eine 961 // SSelection besteht; des akt. Cursr wird nicht umgesetzt! 962 // Ansonsten wird er auf die gewaehlte SSelection gesetzt. 963 964 965 sal_Bool SwCrsrShell::ChgCurrPam( const Point & rPt, 966 sal_Bool bTstOnly, sal_Bool bTstHit ) 967 { 968 SET_CURR_SHELL( this ); 969 970 // Pruefe ob der SPoint in einer Tabellen-Selektion liegt 971 if( bTstOnly && pTblCrsr ) 972 return pTblCrsr->IsInside( rPt ); 973 974 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 975 // Suche die Position rPt im Dokument 976 SwPosition aPtPos( *pCurCrsr->GetPoint() ); 977 Point aPt( rPt ); 978 979 SwCrsrMoveState aTmpState( MV_NONE ); 980 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 981 if ( !GetLayout()->GetCrsrOfst( &aPtPos, aPt, &aTmpState ) && bTstHit ) 982 return sal_False; 983 984 // suche in allen Selektionen nach dieser Position 985 SwShellCrsr* pCmp = (SwShellCrsr*)pCurCrsr; // sicher den Pointer auf Cursor 986 do { 987 if( pCmp->HasMark() && 988 *pCmp->Start() <= aPtPos && *pCmp->End() > aPtPos ) 989 { 990 if( bTstOnly || pCurCrsr == pCmp ) // ist der aktuelle. 991 return sal_True; // return ohne Update 992 993 pCurCrsr = pCmp; 994 UpdateCrsr(); // Cursor steht schon richtig 995 return sal_True; 996 } 997 } while( pCurCrsr != 998 ( pCmp = dynamic_cast<SwShellCrsr*>(pCmp->GetNext()) ) ); 999 return sal_False; 1000 } 1001 1002 1003 void SwCrsrShell::KillPams() 1004 { 1005 // keiner zum loeschen vorhanden? 1006 if( !pTblCrsr && !pBlockCrsr && pCurCrsr->GetNext() == pCurCrsr ) 1007 return; 1008 1009 while( pCurCrsr->GetNext() != pCurCrsr ) 1010 delete pCurCrsr->GetNext(); 1011 pCurCrsr->SetColumnSelection( false ); 1012 1013 if( pTblCrsr ) 1014 { 1015 // Cursor Ring loeschen 1016 pCurCrsr->DeleteMark(); 1017 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint(); 1018 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos(); 1019 delete pTblCrsr; 1020 pTblCrsr = 0; 1021 } 1022 else if( pBlockCrsr ) 1023 { 1024 // delete the ring of cursors 1025 pCurCrsr->DeleteMark(); 1026 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr(); 1027 *pCurCrsr->GetPoint() = *rBlock.GetPoint(); 1028 pCurCrsr->GetPtPos() = rBlock.GetPtPos(); 1029 rBlock.DeleteMark(); 1030 pBlockCrsr->clearPoints(); 1031 } 1032 UpdateCrsr( SwCrsrShell::SCROLLWIN ); 1033 } 1034 1035 1036 int SwCrsrShell::CompareCursor( CrsrCompareType eType ) const 1037 { 1038 int nRet = 0; 1039 const SwPosition *pFirst = 0, *pSecond = 0; 1040 const SwPaM *pCur = GetCrsr(), *pStk = pCrsrStk; 1041 if( CurrPtCurrMk != eType && pStk ) 1042 { 1043 switch ( eType) 1044 { 1045 case StackPtStackMk: 1046 pFirst = pStk->GetPoint(); 1047 pSecond = pStk->GetMark(); 1048 break; 1049 case StackPtCurrPt: 1050 pFirst = pStk->GetPoint(); 1051 pSecond = pCur->GetPoint(); 1052 break; 1053 case StackPtCurrMk: 1054 pFirst = pStk->GetPoint(); 1055 pSecond = pCur->GetMark(); 1056 break; 1057 case StackMkCurrPt: 1058 pFirst = pStk->GetMark(); 1059 pSecond = pCur->GetPoint(); 1060 break; 1061 case StackMkCurrMk: 1062 pFirst = pStk->GetMark(); 1063 pSecond = pStk->GetMark(); 1064 break; 1065 case CurrPtCurrMk: 1066 pFirst = pCur->GetPoint(); 1067 pSecond = pCur->GetMark(); 1068 break; 1069 } 1070 } 1071 if( !pFirst || !pSecond ) 1072 nRet = INT_MAX; 1073 else if( *pFirst < *pSecond ) 1074 nRet = -1; 1075 else if( *pFirst == *pSecond ) 1076 nRet = 0; 1077 else 1078 nRet = 1; 1079 return nRet; 1080 } 1081 1082 1083 sal_Bool SwCrsrShell::IsSttPara() const 1084 { return( pCurCrsr->GetPoint()->nContent == 0 ? sal_True : sal_False ); } 1085 1086 1087 sal_Bool SwCrsrShell::IsEndPara() const 1088 { return( pCurCrsr->GetPoint()->nContent == pCurCrsr->GetCntntNode()->Len() ? sal_True : sal_False ); } 1089 1090 1091 sal_Bool SwCrsrShell::IsInFrontOfLabel() const 1092 { 1093 return pCurCrsr->IsInFrontOfLabel(); 1094 } 1095 1096 bool SwCrsrShell::SetInFrontOfLabel( sal_Bool bNew ) 1097 { 1098 if ( bNew != IsInFrontOfLabel() ) 1099 { 1100 pCurCrsr->_SetInFrontOfLabel( bNew ); 1101 UpdateMarkedListLevel(); 1102 return true; 1103 } 1104 return false; 1105 } 1106 1107 sal_Bool SwCrsrShell::GotoPage( sal_uInt16 nPage ) 1108 { 1109 SET_CURR_SHELL( this ); 1110 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 1111 SwCrsrSaveState aSaveState( *pCurCrsr ); 1112 sal_Bool bRet = GetLayout()->SetCurrPage( pCurCrsr, nPage ) && 1113 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 1114 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ); 1115 if( bRet ) 1116 UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY); 1117 return bRet; 1118 } 1119 1120 1121 void SwCrsrShell::GetPageNum( sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum, 1122 sal_Bool bAtCrsrPos, const sal_Bool bCalcFrm ) 1123 { 1124 SET_CURR_SHELL( this ); 1125 // Seitennummer: die erste sichtbare Seite oder die am Cursor 1126 const SwCntntFrm* pCFrm; 1127 const SwPageFrm *pPg = 0; 1128 1129 if( !bAtCrsrPos || 0 == (pCFrm = GetCurrFrm( bCalcFrm )) || 1130 0 == (pPg = pCFrm->FindPageFrm()) ) 1131 { 1132 pPg = Imp()->GetFirstVisPage(); 1133 while( pPg && pPg->IsEmptyPage() ) 1134 pPg = (const SwPageFrm *)pPg->GetNext(); 1135 } 1136 // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit 1137 // standard.vor sein. 1138 rnPhyNum = pPg? pPg->GetPhyPageNum() : 1; 1139 rnVirtNum = pPg? pPg->GetVirtPageNum() : 1; 1140 } 1141 1142 1143 sal_uInt16 SwCrsrShell::GetNextPrevPageNum( sal_Bool bNext ) 1144 { 1145 SET_CURR_SHELL( this ); 1146 1147 // Seitennummer: die erste sichtbare Seite oder die am Cursor 1148 const SwPageFrm *pPg = Imp()->GetFirstVisPage(); 1149 if( pPg ) 1150 { 1151 const SwTwips nPageTop = pPg->Frm().Top(); 1152 1153 if( bNext ) 1154 { 1155 // go to next view layout row: 1156 do 1157 { 1158 pPg = (const SwPageFrm *)pPg->GetNext(); 1159 } 1160 while( pPg && pPg->Frm().Top() == nPageTop ); 1161 1162 while( pPg && pPg->IsEmptyPage() ) 1163 pPg = (const SwPageFrm *)pPg->GetNext(); 1164 } 1165 else 1166 { 1167 // go to previous view layout row: 1168 do 1169 { 1170 pPg = (const SwPageFrm *)pPg->GetPrev(); 1171 } 1172 while( pPg && pPg->Frm().Top() == nPageTop ); 1173 1174 while( pPg && pPg->IsEmptyPage() ) 1175 pPg = (const SwPageFrm *)pPg->GetPrev(); 1176 } 1177 } 1178 // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit 1179 // standard.vor sein. 1180 return pPg ? pPg->GetPhyPageNum() : USHRT_MAX; 1181 } 1182 1183 1184 sal_uInt16 SwCrsrShell::GetPageCnt() 1185 { 1186 SET_CURR_SHELL( this ); 1187 // gebe die Anzahl der Seiten zurueck 1188 return GetLayout()->GetPageNum(); 1189 } 1190 1191 // Gehe zur naechsten SSelection 1192 1193 1194 sal_Bool SwCrsrShell::GoNextCrsr() 1195 { 1196 // besteht ueberhaupt ein Ring ? 1197 if( pCurCrsr->GetNext() == pCurCrsr ) 1198 return sal_False; 1199 1200 SET_CURR_SHELL( this ); 1201 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 1202 pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext()); 1203 1204 // Bug 24086: auch alle anderen anzeigen 1205 if( !ActionPend() ) 1206 { 1207 UpdateCrsr(); 1208 pCurCrsr->Show(); 1209 } 1210 return sal_True; 1211 } 1212 1213 // gehe zur vorherigen SSelection 1214 1215 1216 sal_Bool SwCrsrShell::GoPrevCrsr() 1217 { 1218 // besteht ueberhaupt ein Ring ? 1219 if( pCurCrsr->GetNext() == pCurCrsr ) 1220 return sal_False; 1221 1222 SET_CURR_SHELL( this ); 1223 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 1224 pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetPrev()); 1225 1226 // Bug 24086: auch alle anderen anzeigen 1227 if( !ActionPend() ) 1228 { 1229 UpdateCrsr(); 1230 pCurCrsr->Show(); 1231 } 1232 1233 return sal_True; 1234 } 1235 1236 1237 void SwCrsrShell::Paint( const Rectangle &rRect) 1238 { 1239 SET_CURR_SHELL( this ); 1240 1241 // beim Painten immer alle Cursor ausschalten 1242 SwRect aRect( rRect ); 1243 1244 sal_Bool bVis = sal_False; 1245 // ist Cursor sichtbar, dann verstecke den SV-Cursor 1246 if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) ) //JP 18.06.97: ??? 1247 { 1248 bVis = sal_True; 1249 pVisCrsr->Hide(); 1250 } 1251 1252 // Bereich neu painten 1253 ViewShell::Paint( rRect ); 1254 1255 if( bHasFocus && !bBasicHideCrsr ) 1256 { 1257 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; 1258 // pAktCrsr->Invalidate( aRect ); 1259 if( !ActionPend() ) 1260 { 1261 // damit nicht rechts/unten die Raender abgeschnitten werden 1262 pAktCrsr->Invalidate( VisArea() ); 1263 pAktCrsr->Show(); 1264 } 1265 else 1266 pAktCrsr->Invalidate( aRect ); 1267 1268 } 1269 if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen 1270 pVisCrsr->Show(); 1271 } 1272 1273 1274 1275 void SwCrsrShell::VisPortChgd( const SwRect & rRect ) 1276 { 1277 SET_CURR_SHELL( this ); 1278 sal_Bool bVis; // beim Scrollen immer alle Cursor ausschalten 1279 1280 // ist Cursor sichtbar, dann verstecke den SV-Cursor 1281 if( sal_True == ( bVis = pVisCrsr->IsVisible() )) 1282 pVisCrsr->Hide(); 1283 1284 bVisPortChgd = sal_True; 1285 aOldRBPos.X() = VisArea().Right(); 1286 aOldRBPos.Y() = VisArea().Bottom(); 1287 1288 //Damit es es keine Probleme mit dem SV-Cursor gibt, wird in 1289 //ViewShell::VisPo.. ein Update() auf das Window gerufen. 1290 //Waehrend des Paintens duerfen aber nun wieder keine Selectionen 1291 //angezeigt werden, deshalb wird der Aufruf hier geklammert. 1292 ViewShell::VisPortChgd( rRect ); // Bereich verschieben 1293 1294 /* 1295 SwRect aRect( rRect ); 1296 if( VisArea().IsOver( aRect ) ) 1297 pCurCrsr->Invalidate( aRect ); 1298 */ 1299 1300 if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen 1301 pVisCrsr->Show(); 1302 1303 if( nCrsrMove ) 1304 bInCMvVisportChgd = sal_True; 1305 1306 bVisPortChgd = sal_False; 1307 } 1308 1309 // aktualisiere den Crsrs, d.H. setze ihn wieder in den Content. 1310 // Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim 1311 // Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position 1312 // ergibt sich aus seiner aktuellen Position im Layout !! 1313 1314 1315 void SwCrsrShell::UpdateCrsrPos() 1316 { 1317 SET_CURR_SHELL( this ); 1318 ++nStartAction; 1319 SwShellCrsr* pShellCrsr = getShellCrsr( true ); 1320 Size aOldSz( GetDocSize() ); 1321 SwCntntNode *pCNode = pShellCrsr->GetCntntNode(); 1322 SwCntntFrm *pFrm = pCNode ? 1323 pCNode->getLayoutFrm( GetLayout(), &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ) :0; 1324 if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) ) 1325 { 1326 SwCrsrMoveState aTmpState( MV_NONE ); 1327 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 1328 GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(), 1329 &aTmpState ); 1330 if( pShellCrsr->HasMark()) 1331 pShellCrsr->DeleteMark(); 1332 } 1333 IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0; 1334 if( pGrammarContact ) 1335 pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() ); 1336 --nStartAction; 1337 if( aOldSz != GetDocSize() ) 1338 SizeChgNotify(); 1339 } 1340 1341 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen 1342 // stehen, so mussen diese daraus verschoben werden 1343 static void lcl_CheckHiddenSection( SwNodeIndex& rIdx ) 1344 { 1345 const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode(); 1346 if( pSectNd && pSectNd->GetSection().IsHiddenFlag() ) 1347 { 1348 SwNodeIndex aTmp( *pSectNd ); 1349 #if OSL_DEBUG_LEVEL > 1 1350 const SwNode* pFrmNd = 1351 #endif 1352 rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() ); 1353 1354 #if OSL_DEBUG_LEVEL > 1 1355 (void) pFrmNd; 1356 ASSERT( pFrmNd, "keinen Node mit Frames gefunden" ); 1357 #endif 1358 rIdx = aTmp; 1359 } 1360 } 1361 1362 // Try to set the cursor to the next visible content node. 1363 static void lcl_CheckHiddenPara( SwPosition& rPos ) 1364 { 1365 SwNodeIndex aTmp( rPos.nNode ); 1366 SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode(); 1367 while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) ) 1368 { 1369 SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp ); 1370 if ( pCntnt && pCntnt->IsTxtNode() ) 1371 pTxtNd = (SwTxtNode*)pCntnt; 1372 else 1373 pTxtNd = 0; 1374 } 1375 1376 if ( pTxtNd ) 1377 rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) ); 1378 } 1379 1380 // --> OD 2005-12-14 #i27301# - helper class, which notifies the accessibility 1381 // about invalid text selections in its destructor 1382 class SwNotifyAccAboutInvalidTextSelections 1383 { 1384 private: 1385 SwCrsrShell& mrCrsrSh; 1386 1387 public: 1388 SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh ) 1389 : mrCrsrSh( _rCrsrSh ) 1390 {} 1391 1392 ~SwNotifyAccAboutInvalidTextSelections() 1393 { 1394 mrCrsrSh.InvalidateAccessibleParaTextSelection(); 1395 } 1396 }; 1397 // <-- 1398 void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, sal_Bool bIdleEnd ) 1399 { 1400 SET_CURR_SHELL( this ); 1401 1402 ClearUpCrsrs(); 1403 1404 // erfrage den Count fuer die Start-/End-Actions und ob die Shell 1405 // ueberhaupt den Focus hat 1406 // if( ActionPend() /*|| !bHasFocus*/ ) 1407 //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction der 1408 // Cursor geupdatet werden; um z.B. den TabellenCursor zu 1409 // erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen! 1410 if( ActionPend() && BasicActionPend() ) 1411 { 1412 if ( eFlags & SwCrsrShell::READONLY ) 1413 bIgnoreReadonly = sal_True; 1414 return; // wenn nicht, dann kein Update !! 1415 } 1416 1417 // --> OD 2005-12-14 #i27301# 1418 SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this ); 1419 // <-- 1420 1421 if ( bIgnoreReadonly ) 1422 { 1423 bIgnoreReadonly = sal_False; 1424 eFlags |= SwCrsrShell::READONLY; 1425 } 1426 1427 if( eFlags & SwCrsrShell::CHKRANGE ) // alle Cursor-Bewegungen auf 1428 CheckRange( pCurCrsr ); // ueberlappende Bereiche testen 1429 1430 if( !bIdleEnd ) 1431 CheckTblBoxCntnt(); 1432 1433 // steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen 1434 // (oder ist noch TabellenMode), dann gilt der Tabellen Mode 1435 SwPaM* pTstCrsr = getShellCrsr( true ); 1436 if( pTstCrsr->HasMark() && !pBlockCrsr && 1437 pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) && 1438 ( pTblCrsr || 1439 pTstCrsr->GetNode( sal_True )->StartOfSectionNode() != 1440 pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) ) 1441 { 1442 SwShellCrsr* pITmpCrsr = getShellCrsr( true ); 1443 Point aTmpPt( pITmpCrsr->GetPtPos() ); 1444 Point aTmpMk( pITmpCrsr->GetMkPos() ); 1445 SwPosition* pPos = pITmpCrsr->GetPoint(); 1446 1447 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen 1448 // stehen, so mussen diese daraus verschoben werden 1449 lcl_CheckHiddenSection( pPos->nNode ); 1450 lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode ); 1451 1452 // Move cursor out of hidden paragraphs 1453 if ( !GetViewOptions()->IsShowHiddenChar() ) 1454 { 1455 lcl_CheckHiddenPara( *pPos ); 1456 lcl_CheckHiddenPara( *pITmpCrsr->GetMark() ); 1457 } 1458 1459 SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()-> 1460 getLayoutFrm( GetLayout(), &aTmpPt, pPos, sal_False ); 1461 1462 ASSERT( pTblFrm, "Tabelle Crsr nicht im Content ??" ); 1463 1464 // --> FME 2005-12-02 #126107# Make code robust. The table 1465 // cursor may point to a table in a currently inactive header. 1466 SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0; 1467 // <-- 1468 1469 if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 ) 1470 { 1471 // First check if point is in repeated headline: 1472 bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm ); 1473 1474 // Second check if mark is in repeated headline: 1475 if ( !bInRepeatedHeadline ) 1476 { 1477 SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( sal_False )-> 1478 getLayoutFrm( GetLayout(), &aTmpMk, pITmpCrsr->GetMark(), sal_False ); 1479 ASSERT( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" ); 1480 1481 if ( pMarkTblFrm ) 1482 { 1483 SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm(); 1484 ASSERT( pMarkTab, "Tabelle Crsr nicht im Content ??" ); 1485 1486 // --> FME 2005-11-28 #120360# Make code robust: 1487 if ( pMarkTab ) 1488 { 1489 bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm ); 1490 } 1491 // <-- 1492 } 1493 } 1494 1495 // No table cursor in repeaded headlines: 1496 if ( bInRepeatedHeadline ) 1497 { 1498 pTblFrm = 0; 1499 1500 SwPosSection fnPosSect = *pPos < *pITmpCrsr->GetMark() 1501 ? fnSectionStart 1502 : fnSectionEnd; 1503 1504 // dann nur innerhalb der Box selektieren 1505 if( pTblCrsr ) 1506 { 1507 pCurCrsr->SetMark(); 1508 *pCurCrsr->GetMark() = *pTblCrsr->GetMark(); 1509 pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos(); 1510 pTblCrsr->DeleteMark(); 1511 pTblCrsr->SwSelPaintRects::Hide(); 1512 } 1513 1514 *pCurCrsr->GetPoint() = *pCurCrsr->GetMark(); 1515 (*fnSectionCurr)( *pCurCrsr, fnPosSect ); 1516 } 1517 } 1518 1519 // wir wollen wirklich eine Tabellen-Selektion 1520 if( pTab && pTblFrm ) 1521 { 1522 if( !pTblCrsr ) 1523 { 1524 pTblCrsr = new SwShellTableCrsr( *this, 1525 *pCurCrsr->GetMark(), pCurCrsr->GetMkPos(), 1526 *pPos, aTmpPt ); 1527 pCurCrsr->DeleteMark(); 1528 pCurCrsr->SwSelPaintRects::Hide(); 1529 1530 CheckTblBoxCntnt(); 1531 } 1532 1533 SwCrsrMoveState aTmpState( MV_NONE ); 1534 aTmpState.bRealHeight = sal_True; 1535 if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) ) 1536 { 1537 Point aCentrPt( aCharRect.Center() ); 1538 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 1539 pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState ); 1540 #ifndef DBG_UTIL 1541 pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ); 1542 #else 1543 if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) ) 1544 ASSERT( !this, "GetCharRect failed." ); 1545 #endif 1546 } 1547 // ALIGNRECT( aCharRect ); 1548 1549 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken 1550 // Curosr in den sichtbaren Bereich scrollen 1551 if( (eFlags & SwCrsrShell::SCROLLWIN) && 1552 (HasSelection() || eFlags & SwCrsrShell::READONLY || 1553 !IsCrsrReadonly()) ) 1554 { 1555 SwFrm* pBoxFrm = pTblFrm; 1556 while( pBoxFrm && !pBoxFrm->IsCellFrm() ) 1557 pBoxFrm = pBoxFrm->GetUpper(); 1558 if( pBoxFrm && pBoxFrm->Frm().HasArea() ) 1559 MakeVisible( pBoxFrm->Frm() ); 1560 else 1561 MakeVisible( aCharRect ); 1562 } 1563 1564 // lasse vom Layout die Crsr in den Boxen erzeugen 1565 if( pTblCrsr->IsCrsrMovedUpdt() ) 1566 GetLayout()->MakeTblCrsrs( *pTblCrsr ); 1567 if( bHasFocus && !bBasicHideCrsr ) 1568 pTblCrsr->Show(); 1569 1570 // Cursor-Points auf die neuen Positionen setzen 1571 pTblCrsr->GetPtPos().X() = aCharRect.Left(); 1572 pTblCrsr->GetPtPos().Y() = aCharRect.Top(); 1573 1574 if( bSVCrsrVis ) 1575 { 1576 aCrsrHeight.X() = 0; 1577 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ? 1578 -aCharRect.Width() : aCharRect.Height(); 1579 pVisCrsr->Show(); // wieder anzeigen 1580 } 1581 eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst 1582 if( pTblFrm && Imp()->IsAccessible() ) 1583 Imp()->InvalidateAccessibleCursorPosition( pTblFrm ); 1584 return; 1585 } 1586 } 1587 1588 if( pTblCrsr ) 1589 { 1590 // Cursor Ring loeschen 1591 while( pCurCrsr->GetNext() != pCurCrsr ) 1592 delete pCurCrsr->GetNext(); 1593 pCurCrsr->DeleteMark(); 1594 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint(); 1595 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos(); 1596 delete pTblCrsr, pTblCrsr = 0; 1597 } 1598 1599 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken 1600 1601 // sind wir vielleicht in einer geschuetzten/versteckten Section ? 1602 { 1603 SwShellCrsr* pShellCrsr = getShellCrsr( true ); 1604 sal_Bool bChgState = sal_True; 1605 const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode(); 1606 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() || 1607 ( !IsReadOnlyAvailable() && 1608 pSectNd->GetSection().IsProtectFlag() && 1609 ( !pDoc->GetDocShell() || 1610 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) ) 1611 { 1612 if( !FindValidCntntNode( !HasDrawView() || 1613 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount())) 1614 { 1615 // alles ist geschuetzt / versteckt -> besonderer Mode 1616 if( bAllProtect && !IsReadOnlyAvailable() && 1617 pSectNd->GetSection().IsProtectFlag() ) 1618 bChgState = sal_False; 1619 else 1620 { 1621 eMvState = MV_NONE; // Status fuers Crsr-Travelling 1622 bAllProtect = sal_True; 1623 if( GetDoc()->GetDocShell() ) 1624 { 1625 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True ); 1626 CallChgLnk(); // UI bescheid sagen! 1627 } 1628 return; 1629 } 1630 } 1631 } 1632 if( bChgState ) 1633 { 1634 sal_Bool bWasAllProtect = bAllProtect; 1635 bAllProtect = sal_False; 1636 if( bWasAllProtect && GetDoc()->GetDocShell() && 1637 GetDoc()->GetDocShell()->IsReadOnlyUI() ) 1638 { 1639 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False ); 1640 CallChgLnk(); // UI bescheid sagen! 1641 } 1642 } 1643 } 1644 1645 UpdateCrsrPos(); 1646 1647 // #100722# The cursor must always point into content; there's some code 1648 // that relies on this. (E.g. in SwEditShell::GetScriptType, which always 1649 // loops _behind_ the last node in the selection, which always works if you 1650 // are in content.) To achieve this, we'll force cursor(s) to point into 1651 // content, if UpdateCrsrPos() hasn't already done so. 1652 SwPaM* pCmp = pCurCrsr; 1653 do 1654 { 1655 // start will move forwards, end will move backwards 1656 bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() ); 1657 1658 // move point; forward if it's the start, backwards if it's the end 1659 if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() ) 1660 pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward, 1661 fnGoCntnt ); 1662 1663 // move mark (if exists); forward if it's the start, else backwards 1664 if( pCmp->HasMark() ) 1665 { 1666 if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() ) 1667 { 1668 pCmp->Exchange(); 1669 pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward, 1670 fnGoCntnt ); 1671 pCmp->Exchange(); 1672 } 1673 } 1674 1675 // iterate to next PaM in ring 1676 pCmp = static_cast<SwPaM*>( pCmp->GetNext() ); 1677 } 1678 while( pCmp != pCurCrsr ); 1679 1680 1681 SwRect aOld( aCharRect ); 1682 sal_Bool bFirst = sal_True; 1683 SwCntntFrm *pFrm; 1684 int nLoopCnt = 100; 1685 SwShellCrsr* pShellCrsr = getShellCrsr( true ); 1686 1687 do { 1688 sal_Bool bAgainst; 1689 do { 1690 bAgainst = sal_False; 1691 pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(), 1692 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ); 1693 // ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout 1694 // erzeugt werden, weil ja mal hier einer vorhanden war !! 1695 if ( !pFrm ) 1696 { 1697 do 1698 { 1699 CalcLayout(); 1700 pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(), 1701 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ); 1702 } while( !pFrm ); 1703 } 1704 else if ( Imp()->IsIdleAction() ) 1705 //Wir stellen sicher, dass anstaendig Formatiert wurde #42224# 1706 pFrm->PrepareCrsr(); 1707 1708 // im geschuetzten Fly? aber bei Rahmenselektion ignorieren 1709 if( !IsReadOnlyAvailable() && pFrm->IsProtected() && 1710 ( !Imp()->GetDrawView() || 1711 !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) && 1712 (!pDoc->GetDocShell() || 1713 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) ) 1714 { 1715 // dann suche eine gueltige Position 1716 sal_Bool bChgState = sal_True; 1717 if( !FindValidCntntNode(!HasDrawView() || 1718 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount())) 1719 { 1720 // alles ist geschuetzt / versteckt -> besonderer Mode 1721 if( bAllProtect ) 1722 bChgState = sal_False; 1723 else 1724 { 1725 eMvState = MV_NONE; // Status fuers Crsr-Travelling 1726 bAllProtect = sal_True; 1727 if( GetDoc()->GetDocShell() ) 1728 { 1729 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True ); 1730 CallChgLnk(); // UI bescheid sagen! 1731 } 1732 return; 1733 } 1734 } 1735 1736 if( bChgState ) 1737 { 1738 sal_Bool bWasAllProtect = bAllProtect; 1739 bAllProtect = sal_False; 1740 if( bWasAllProtect && GetDoc()->GetDocShell() && 1741 GetDoc()->GetDocShell()->IsReadOnlyUI() ) 1742 { 1743 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False ); 1744 CallChgLnk(); // UI bescheid sagen! 1745 } 1746 bAllProtect = sal_False; 1747 bAgainst = sal_True; // nochmal den richigen Frm suchen 1748 } 1749 } 1750 } while( bAgainst ); 1751 1752 if( !( eFlags & SwCrsrShell::NOCALRECT )) 1753 { 1754 SwCrsrMoveState aTmpState( eMvState ); 1755 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 1756 aTmpState.bRealHeight = sal_True; 1757 aTmpState.bRealWidth = IsOverwriteCrsr(); 1758 aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel(); 1759 1760 // #i27615#,#i30453# 1761 SwSpecialPos aSpecialPos; 1762 aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE; 1763 if (pShellCrsr->IsInFrontOfLabel()) 1764 { 1765 aTmpState.pSpecialPos = &aSpecialPos; 1766 } 1767 1768 if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) ) 1769 { 1770 Point& rPt = pShellCrsr->GetPtPos(); 1771 rPt = aCharRect.Center(); 1772 pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState ); 1773 } 1774 // ALIGNRECT( aCharRect ); 1775 1776 if( !pShellCrsr->HasMark() ) 1777 aCrsrHeight = aTmpState.aRealHeight; 1778 else 1779 { 1780 aCrsrHeight.X() = 0; 1781 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ? 1782 -aCharRect.Width() : aCharRect.Height(); 1783 } 1784 } 1785 else 1786 { 1787 aCrsrHeight.X() = 0; 1788 aCrsrHeight.Y() = aCharRect.Height(); 1789 } 1790 1791 if( !bFirst && aOld == aCharRect ) 1792 break; 1793 1794 // falls das Layout meint, nach dem 100 durchlauf ist man immer noch 1795 // im Fluss, sollte man die akt. Pos. als gegeben hinnehmen! 1796 // siehe Bug: 29658 1797 if( !--nLoopCnt ) 1798 { 1799 ASSERT( !this, "Endlosschleife? CharRect != OldCharRect "); 1800 break; 1801 } 1802 aOld = aCharRect; 1803 bFirst = sal_False; 1804 1805 // Cursor-Points auf die neuen Positionen setzen 1806 pShellCrsr->GetPtPos().X() = aCharRect.Left(); 1807 pShellCrsr->GetPtPos().Y() = aCharRect.Top(); 1808 1809 if( !(eFlags & SwCrsrShell::UPDOWN )) // alte Pos. von Up/Down loeschen 1810 { 1811 pFrm->Calc(); 1812 nUpDownX = pFrm->IsVertical() ? 1813 aCharRect.Top() - pFrm->Frm().Top() : 1814 aCharRect.Left() - pFrm->Frm().Left(); 1815 } 1816 1817 // Curosr in den sichtbaren Bereich scrollen 1818 if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN && 1819 (HasSelection() || eFlags & SwCrsrShell::READONLY || 1820 !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) ) 1821 { 1822 //JP 30.04.99: damit das EndAction, beim evtuellen Scrollen, den 1823 // SV-Crsr nicht wieder sichtbar macht, wird hier das Flag 1824 // gesichert und zurueckgesetzt. 1825 sal_Bool bSav = bSVCrsrVis; bSVCrsrVis = sal_False; 1826 MakeSelVisible(); 1827 bSVCrsrVis = bSav; 1828 } 1829 1830 } while( eFlags & SwCrsrShell::SCROLLWIN ); 1831 1832 if( pBlockCrsr ) 1833 RefreshBlockCursor(); 1834 1835 if( !bIdleEnd && bHasFocus && !bBasicHideCrsr ) 1836 { 1837 if( pTblCrsr ) 1838 pTblCrsr->SwSelPaintRects::Show(); 1839 else 1840 { 1841 pCurCrsr->SwSelPaintRects::Show(); 1842 if( pBlockCrsr ) 1843 { 1844 SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext()); 1845 while( pNxt && pNxt != pCurCrsr ) 1846 { 1847 pNxt->SwSelPaintRects::Show(); 1848 pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext()); 1849 } 1850 } 1851 } 1852 } 1853 1854 eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst 1855 1856 if( pFrm && Imp()->IsAccessible() ) 1857 Imp()->InvalidateAccessibleCursorPosition( pFrm ); 1858 1859 // switch from blinking cursor to read-only-text-selection cursor 1860 static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME; 1861 const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings(). 1862 GetCursorBlinkTime(); 1863 1864 if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) == 1865 ( nBlinkTime != nNoBlinkTime ) ) 1866 { 1867 // non blinking cursor in read only - text selection mode 1868 AllSettings aSettings = GetOut()->GetSettings(); 1869 StyleSettings aStyleSettings = aSettings.GetStyleSettings(); 1870 const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ? 1871 Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() : 1872 nNoBlinkTime; 1873 aStyleSettings.SetCursorBlinkTime( nNewBlinkTime ); 1874 aSettings.SetStyleSettings( aStyleSettings ); 1875 GetOut()->SetSettings( aSettings ); 1876 } 1877 1878 if( bSVCrsrVis ) 1879 pVisCrsr->Show(); // wieder anzeigen 1880 } 1881 1882 void SwCrsrShell::RefreshBlockCursor() 1883 { 1884 ASSERT( pBlockCrsr, "Don't call me without a block cursor" ); 1885 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr(); 1886 Point aPt = rBlock.GetPtPos(); 1887 SwCntntFrm* pFrm = rBlock.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, rBlock.GetPoint(), sal_False ); 1888 Point aMk; 1889 if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() ) 1890 { 1891 aPt = *pBlockCrsr->getStartPoint(); 1892 aMk = *pBlockCrsr->getEndPoint(); 1893 } 1894 else 1895 { 1896 aPt = rBlock.GetPtPos(); 1897 if( pFrm ) 1898 { 1899 if( pFrm->IsVertical() ) 1900 aPt.Y() = pFrm->Frm().Top() + GetUpDownX(); 1901 else 1902 aPt.X() = pFrm->Frm().Left() + GetUpDownX(); 1903 } 1904 aMk = rBlock.GetMkPos(); 1905 } 1906 SwRect aRect( aMk, aPt ); 1907 aRect.Justify(); 1908 SwSelectionList aSelList( pFrm ); 1909 1910 if( GetLayout()->FillSelection( aSelList, aRect ) ) 1911 { 1912 SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext(); 1913 while( pNxt != pCurCrsr ) 1914 { 1915 delete pNxt; 1916 pNxt = (SwCursor*)pCurCrsr->GetNext(); 1917 } 1918 1919 std::list<SwPaM*>::iterator pStart = aSelList.getStart(); 1920 std::list<SwPaM*>::iterator pPam = aSelList.getEnd(); 1921 ASSERT( pPam != pStart, "FillSelection should deliver at least one PaM" ) 1922 pCurCrsr->SetMark(); 1923 --pPam; 1924 // If there is only one text portion inside the rectangle, a simple 1925 // selection is created 1926 if( pPam == pStart ) 1927 { 1928 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); 1929 if( (*pPam)->HasMark() ) 1930 *pCurCrsr->GetMark() = *(*pPam)->GetMark(); 1931 else 1932 pCurCrsr->DeleteMark(); 1933 delete *pPam; 1934 pCurCrsr->SetColumnSelection( false ); 1935 } 1936 else 1937 { 1938 // The order of the SwSelectionList has to be preserved but 1939 // the order inside the ring created by CreateCrsr() is not like 1940 // exspected => First create the selections before the last one 1941 // downto the first selection. 1942 // At least create the cursor for the last selection 1943 --pPam; 1944 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections) 1945 if( (*pPam)->HasMark() ) 1946 *pCurCrsr->GetMark() = *(*pPam)->GetMark(); 1947 else 1948 pCurCrsr->DeleteMark(); 1949 delete *pPam; 1950 pCurCrsr->SetColumnSelection( true ); 1951 while( pPam != pStart ) 1952 { 1953 --pPam; 1954 1955 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr ); 1956 pNew->Insert( pCurCrsr, 0 ); 1957 pCurCrsr->Remove( 0, pCurCrsr->Count() ); 1958 pCurCrsr->DeleteMark(); 1959 1960 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1 1961 if( (*pPam)->HasMark() ) 1962 { 1963 pCurCrsr->SetMark(); 1964 *pCurCrsr->GetMark() = *(*pPam)->GetMark(); 1965 } 1966 else 1967 pCurCrsr->DeleteMark(); 1968 pCurCrsr->SetColumnSelection( true ); 1969 delete *pPam; 1970 } 1971 { 1972 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr ); 1973 pNew->Insert( pCurCrsr, 0 ); 1974 pCurCrsr->Remove( 0, pCurCrsr->Count() ); 1975 pCurCrsr->DeleteMark(); 1976 } 1977 pPam = aSelList.getEnd(); 1978 --pPam; 1979 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection 1980 if( (*pPam)->HasMark() ) 1981 { 1982 pCurCrsr->SetMark(); 1983 *pCurCrsr->GetMark() = *(*pPam)->GetMark(); 1984 } 1985 else 1986 pCurCrsr->DeleteMark(); 1987 pCurCrsr->SetColumnSelection( true ); 1988 delete *pPam; 1989 } 1990 } 1991 } 1992 1993 // erzeuge eine Kopie vom Cursor und speicher diese im Stack 1994 1995 1996 void SwCrsrShell::Push() 1997 { 1998 pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(), 1999 pCurCrsr->GetPtPos(), pCrsrStk ); 2000 2001 if( pCurCrsr->HasMark() ) 2002 { 2003 pCrsrStk->SetMark(); 2004 *pCrsrStk->GetMark() = *pCurCrsr->GetMark(); 2005 } 2006 } 2007 2008 /* 2009 * Loescht einen Cursor (gesteuert durch bOldCrsr) 2010 * - vom Stack oder ( bOldCrsr = sal_True ) 2011 * - den aktuellen und der auf dem Stack stehende wird zum aktuellen 2012 * 2013 * Return: es war auf dem Stack noch einer vorhanden 2014 */ 2015 2016 2017 sal_Bool SwCrsrShell::Pop( sal_Bool bOldCrsr ) 2018 { 2019 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 2020 2021 // noch weitere vorhanden ? 2022 if( 0 == pCrsrStk ) 2023 return sal_False; 2024 2025 SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk; 2026 2027 // der Nachfolger wird der Aktuelle 2028 if( pCrsrStk->GetNext() != pCrsrStk ) 2029 { 2030 pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext()); 2031 } 2032 2033 if( bOldCrsr ) // loesche vom Stack 2034 delete pCrsrStk; // 2035 2036 pCrsrStk = pTmp; // neu zuweisen 2037 2038 if( !bOldCrsr ) 2039 { 2040 SwCrsrSaveState aSaveState( *pCurCrsr ); 2041 2042 // wurde die sichtbare SSelection nicht veraendert 2043 if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() || 2044 pOldStk->GetPtPos() == pCurCrsr->GetMkPos() ) 2045 { 2046 // "Selektions-Rechtecke" verschieben 2047 pCurCrsr->Insert( pOldStk, 0 ); 2048 pOldStk->Remove( 0, pOldStk->Count() ); 2049 } 2050 2051 if( pOldStk->HasMark() ) 2052 { 2053 pCurCrsr->SetMark(); 2054 *pCurCrsr->GetMark() = *pOldStk->GetMark(); 2055 pCurCrsr->GetMkPos() = pOldStk->GetMkPos(); 2056 } 2057 else 2058 // keine Selection also alte aufheben und auf die alte Pos setzen 2059 pCurCrsr->DeleteMark(); 2060 *pCurCrsr->GetPoint() = *pOldStk->GetPoint(); 2061 pCurCrsr->GetPtPos() = pOldStk->GetPtPos(); 2062 delete pOldStk; 2063 2064 if( !pCurCrsr->IsInProtectTable( sal_True ) && 2065 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 2066 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) ) 2067 UpdateCrsr(); // akt. Cursor Updaten 2068 } 2069 return sal_True; 2070 } 2071 2072 /* 2073 * Verbinde zwei Cursor miteinander. 2074 * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen. 2075 */ 2076 2077 2078 void SwCrsrShell::Combine() 2079 { 2080 // noch weitere vorhanden ? 2081 if( 0 == pCrsrStk ) 2082 return; 2083 2084 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 2085 SwCrsrSaveState aSaveState( *pCurCrsr ); 2086 if( pCrsrStk->HasMark() ) // nur wenn GetMark gesetzt wurde 2087 { 2088 #ifndef DBG_UTIL 2089 CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True ); 2090 #else 2091 if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True )) 2092 ASSERT( !this, "StackCrsr & akt. Crsr nicht in gleicher Section." ); 2093 #endif 2094 // kopiere das GetMark 2095 if( !pCurCrsr->HasMark() ) 2096 pCurCrsr->SetMark(); 2097 *pCurCrsr->GetMark() = *pCrsrStk->GetMark(); 2098 pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos(); 2099 } 2100 2101 SwShellCrsr * pTmp = 0; 2102 if( pCrsrStk->GetNext() != pCrsrStk ) 2103 { 2104 pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext()); 2105 } 2106 delete pCrsrStk; 2107 pCrsrStk = pTmp; 2108 if( !pCurCrsr->IsInProtectTable( sal_True ) && 2109 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 2110 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) ) 2111 UpdateCrsr(); // akt. Cursor Updaten 2112 } 2113 2114 2115 void SwCrsrShell::HideCrsrs() 2116 { 2117 if( !bHasFocus || bBasicHideCrsr ) 2118 return; 2119 2120 // ist Cursor sichtbar, dann verstecke den SV-Cursor 2121 if( pVisCrsr->IsVisible() ) 2122 { 2123 SET_CURR_SHELL( this ); 2124 pVisCrsr->Hide(); 2125 } 2126 // hebe die Invertierung der SSelection auf 2127 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; 2128 pAktCrsr->Hide(); 2129 } 2130 2131 2132 2133 void SwCrsrShell::ShowCrsrs( sal_Bool bCrsrVis ) 2134 { 2135 if( !bHasFocus || bAllProtect || bBasicHideCrsr ) 2136 return; 2137 2138 SET_CURR_SHELL( this ); 2139 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; 2140 pAktCrsr->Show(); 2141 2142 if( bSVCrsrVis && bCrsrVis ) // auch SV-Cursor wieder anzeigen 2143 pVisCrsr->Show(); 2144 } 2145 2146 // Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors 2147 2148 2149 void SwCrsrShell::ShowCrsr() 2150 { 2151 if( !bBasicHideCrsr ) 2152 { 2153 bSVCrsrVis = sal_True; 2154 UpdateCrsr(); 2155 } 2156 } 2157 2158 2159 void SwCrsrShell::HideCrsr() 2160 { 2161 if( !bBasicHideCrsr ) 2162 { 2163 bSVCrsrVis = sal_False; 2164 // evt. die sel. Bereiche aufheben !! 2165 SET_CURR_SHELL( this ); 2166 pVisCrsr->Hide(); 2167 } 2168 } 2169 2170 2171 void SwCrsrShell::ShLooseFcs() 2172 { 2173 if( !bBasicHideCrsr ) 2174 HideCrsrs(); 2175 bHasFocus = sal_False; 2176 } 2177 2178 2179 void SwCrsrShell::ShGetFcs( sal_Bool bUpdate ) 2180 { 2181 bHasFocus = sal_True; 2182 if( !bBasicHideCrsr && VisArea().Width() ) 2183 { 2184 UpdateCrsr( static_cast<sal_uInt16>( bUpdate ? 2185 SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN 2186 : SwCrsrShell::CHKRANGE ) ); 2187 ShowCrsrs( bSVCrsrVis ? sal_True : sal_False ); 2188 } 2189 } 2190 2191 // gebe den aktuellen Frame, in dem der Cursor steht, zurueck 2192 2193 SwCntntFrm *SwCrsrShell::GetCurrFrm( const sal_Bool bCalcFrm ) const 2194 { 2195 SET_CURR_SHELL( (ViewShell*)this ); 2196 SwCntntFrm *pRet = 0; 2197 SwCntntNode *pNd = pCurCrsr->GetCntntNode(); 2198 if ( pNd ) 2199 { 2200 if ( bCalcFrm ) 2201 { 2202 const sal_uInt16* pST = &nStartAction; 2203 ++(*((sal_uInt16*)pST)); 2204 const Size aOldSz( GetDocSize() ); 2205 pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() ); 2206 --(*((sal_uInt16*)pST)); 2207 if( aOldSz != GetDocSize() ) 2208 ((SwCrsrShell*)this)->SizeChgNotify(); 2209 } 2210 else 2211 pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), sal_False); 2212 } 2213 return pRet; 2214 } 2215 2216 2217 // alle Attribut/Format-Aenderungen am akt. Node werden an den 2218 // Link weitergeleitet. 2219 2220 2221 void SwCrsrShell::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 2222 { 2223 const sal_uInt16 nWhich = pOld ? 2224 pOld->Which() : 2225 pNew ? 2226 pNew->Which() : 2227 sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN); 2228 2229 if( bCallChgLnk && 2230 ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END || 2231 nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR || 2232 nWhich == RES_ATTRSET_CHG )) 2233 // die Messages werden nicht weitergemeldet 2234 //MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom 2235 //SwTxtNode::Insert(SwTxtHint*, sal_uInt16) abgesetzt; hier wird reagiert und 2236 //vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden. 2237 CallChgLnk(); 2238 2239 if( aGrfArrivedLnk.IsSet() && 2240 ( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich )) 2241 aGrfArrivedLnk.Call( this ); 2242 } 2243 2244 2245 // Abfrage, ob der aktuelle Cursor eine Selektion aufspannt, 2246 // also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind. 2247 2248 2249 sal_Bool SwCrsrShell::HasSelection() const 2250 { 2251 const SwPaM* pCrsr = getShellCrsr( true ); 2252 return( IsTableMode() || ( pCrsr->HasMark() && 2253 *pCrsr->GetPoint() != *pCrsr->GetMark()) 2254 ? sal_True : sal_False ); 2255 } 2256 2257 2258 void SwCrsrShell::CallChgLnk() 2259 { 2260 // innerhalb von Start-/End-Action kein Call, sondern nur merken, 2261 // das sich etwas geaendert hat. Wird bei EndAction beachtet. 2262 if( BasicActionPend() ) 2263 bChgCallFlag = sal_True; // das Change merken 2264 else if( aChgLnk.IsSet() ) 2265 { 2266 if( bCallChgLnk ) 2267 aChgLnk.Call( this ); 2268 bChgCallFlag = sal_False; // Flag zuruecksetzen 2269 } 2270 } 2271 2272 // returne den am akt.Cursor selektierten Text eines Nodes. 2273 2274 2275 String SwCrsrShell::GetSelTxt() const 2276 { 2277 String aTxt; 2278 if( pCurCrsr->GetPoint()->nNode.GetIndex() == 2279 pCurCrsr->GetMark()->nNode.GetIndex() ) 2280 { 2281 SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode(); 2282 if( pTxtNd ) 2283 { 2284 xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex(); 2285 aTxt = pTxtNd->GetExpandTxt( nStt, 2286 pCurCrsr->End()->nContent.GetIndex() - nStt ); 2287 } 2288 } 2289 return aTxt; 2290 } 2291 2292 // gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde) 2293 2294 2295 String SwCrsrShell::GetText() const 2296 { 2297 String aTxt; 2298 if( pCurCrsr->GetPoint()->nNode.GetIndex() == 2299 pCurCrsr->GetMark()->nNode.GetIndex() ) 2300 { 2301 SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode(); 2302 if( pTxtNd ) 2303 aTxt = pTxtNd->GetTxt().Copy( 2304 pCurCrsr->GetPoint()->nContent.GetIndex() ); 2305 } 2306 return aTxt; 2307 } 2308 2309 // hole vom Start/Ende der akt. SSelection das nte Zeichen 2310 sal_Unicode SwCrsrShell::GetChar( sal_Bool bEnd, long nOffset ) 2311 { 2312 if( IsTableMode() ) // im TabelleMode nicht moeglich 2313 return 0; 2314 2315 const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint() 2316 : bEnd ? pCurCrsr->End() : pCurCrsr->Start(); 2317 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode(); 2318 if( !pTxtNd ) 2319 return 0; 2320 2321 xub_StrLen nPos = pPos->nContent.GetIndex(); 2322 const String& rStr = pTxtNd->GetTxt(); 2323 sal_Unicode cCh = 0; 2324 2325 if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() ) 2326 cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) ); 2327 2328 return cCh; 2329 } 2330 2331 // erweiter die akt. SSelection am Anfang/Ende um n Zeichen 2332 2333 2334 sal_Bool SwCrsrShell::ExtendSelection( sal_Bool bEnd, xub_StrLen nCount ) 2335 { 2336 if( !pCurCrsr->HasMark() || IsTableMode() ) 2337 return sal_False; // keine Selektion 2338 2339 SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start(); 2340 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode(); 2341 ASSERT( pTxtNd, "kein TextNode, wie soll erweitert werden?" ); 2342 2343 xub_StrLen nPos = pPos->nContent.GetIndex(); 2344 if( bEnd ) 2345 { 2346 if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() ) 2347 nPos = nPos + nCount; 2348 else 2349 return sal_False; // nicht mehr moeglich 2350 } 2351 else if( nPos >= nCount ) 2352 nPos = nPos - nCount; 2353 else 2354 return sal_False; // nicht mehr moeglich 2355 2356 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, 2357 2358 pPos->nContent = nPos; 2359 UpdateCrsr(); 2360 2361 return sal_True; 2362 } 2363 2364 // setze nur den sichtbaren Cursor an die angegebene Dokument-Pos. 2365 // returnt sal_False: wenn der SPoint vom Layout korrigiert wurde. 2366 2367 sal_Bool SwCrsrShell::SetVisCrsr( const Point &rPt ) 2368 { 2369 SET_CURR_SHELL( this ); 2370 Point aPt( rPt ); 2371 SwPosition aPos( *pCurCrsr->GetPoint() ); 2372 SwCrsrMoveState aTmpState( MV_SETONLYTEXT ); 2373 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 2374 aTmpState.bRealHeight = sal_True; 2375 2376 sal_Bool bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ ); 2377 2378 SetInFrontOfLabel( sal_False ); // #i27615# 2379 2380 // nur in TextNodes anzeigen !! 2381 SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode(); 2382 if( !pTxtNd ) 2383 return sal_False; 2384 2385 const SwSectionNode* pSectNd = pTxtNd->FindSectionNode(); 2386 if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() || 2387 ( !IsReadOnlyAvailable() && 2388 pSectNd->GetSection().IsProtectFlag())) ) 2389 return sal_False; 2390 2391 SwCntntFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, &aPos ); 2392 if ( Imp()->IsIdleAction() ) 2393 pFrm->PrepareCrsr(); 2394 SwRect aTmp( aCharRect ); 2395 2396 pFrm->GetCharRect( aCharRect, aPos, &aTmpState ); 2397 // ALIGNRECT( aCharRect ); 2398 2399 if( aTmp == aCharRect && // BUG 10137: bleibt der Cursor auf der 2400 pVisCrsr->IsVisible() ) // Position nicht hidden & showen 2401 return sal_True; 2402 2403 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken 2404 if( IsScrollMDI( this, aCharRect )) 2405 { 2406 MakeVisible( aCharRect ); 2407 pCurCrsr->Show(); 2408 } 2409 2410 // Bug 29584: bei Rahmenselektion ist der Cursor versteckt, aber den 2411 // D&D-Cursor will man trotzdem haben 2412 // if( bSVCrsrVis ) 2413 { 2414 if( aTmpState.bRealHeight ) 2415 aCrsrHeight = aTmpState.aRealHeight; 2416 else 2417 { 2418 aCrsrHeight.X() = 0; 2419 aCrsrHeight.Y() = aCharRect.Height(); 2420 } 2421 2422 pVisCrsr->SetDragCrsr( sal_True ); 2423 pVisCrsr->Show(); // wieder anzeigen 2424 } 2425 return bRet; 2426 } 2427 2428 sal_Bool SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const 2429 { 2430 Point aPt( rPt ); 2431 SwPaM aPam( *pCurCrsr->GetPoint() ); 2432 GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt ); 2433 // --> FME 2004-06-29 #114856# Formular view 2434 return aPam.HasReadonlySel( GetViewOptions()->IsFormView() ); 2435 // <-- 2436 } 2437 2438 2439 // returne die Anzahl der Cursor im Ring (Flag besagt ob man nur 2440 // aufgepspannte haben will - sprich etwas selektiert ist (Basic)) 2441 sal_uInt16 SwCrsrShell::GetCrsrCnt( sal_Bool bAll ) const 2442 { 2443 Ring* pTmp = GetCrsr()->GetNext(); 2444 sal_uInt16 n = (bAll || ( pCurCrsr->HasMark() && 2445 *pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0; 2446 while( pTmp != pCurCrsr ) 2447 { 2448 if( bAll || ( ((SwPaM*)pTmp)->HasMark() && 2449 *((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark())) 2450 ++n; 2451 pTmp = pTmp->GetNext(); 2452 } 2453 return n; 2454 } 2455 2456 2457 sal_Bool SwCrsrShell::IsStartOfDoc() const 2458 { 2459 if( pCurCrsr->GetPoint()->nContent.GetIndex() ) 2460 return sal_False; 2461 2462 // Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd) 2463 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 ); 2464 if( !aIdx.GetNode().IsCntntNode() ) 2465 GetDoc()->GetNodes().GoNext( &aIdx ); 2466 return aIdx == pCurCrsr->GetPoint()->nNode; 2467 } 2468 2469 2470 sal_Bool SwCrsrShell::IsEndOfDoc() const 2471 { 2472 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 ); 2473 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode(); 2474 if( !pCNd ) 2475 pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx ); 2476 2477 return aIdx == pCurCrsr->GetPoint()->nNode && 2478 pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex(); 2479 } 2480 2481 2482 // loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten 2483 // Cursor auf seinen TextNode (oder StartNode?). 2484 // Beim naechsten ::GetCrsr werden sie wieder alle erzeugt 2485 // Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt. 2486 sal_Bool SwCrsrShell::ParkTblCrsr() 2487 { 2488 if( !pTblCrsr ) 2489 return sal_False; 2490 2491 pTblCrsr->ParkCrsr(); 2492 2493 while( pCurCrsr->GetNext() != pCurCrsr ) 2494 delete pCurCrsr->GetNext(); 2495 2496 // vom Cursor !immer! SPoint und Mark umsetzen 2497 pCurCrsr->SetMark(); 2498 *pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint(); 2499 pCurCrsr->DeleteMark(); 2500 2501 return sal_True; 2502 } 2503 2504 /*********************************************************************** 2505 #* Class : SwCrsrShell 2506 #* Methode : ParkCrsr 2507 #* Beschreibung: Vernichtet Selektionen und zus. Crsr aller Shell der 2508 #* verbleibende Crsr der Shell wird geparkt. 2509 #* Datum : MA 05. Nov. 92 2510 #* Update : JP 19.09.97 2511 #***********************************************************************/ 2512 2513 void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing ) 2514 { 2515 const SwPosition *pStt = pDelRg->Start(), 2516 *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint(); 2517 2518 SwPaM *pTmpDel = 0, *pTmp = *ppDelRing; 2519 2520 // durchsuche den gesamten Ring 2521 sal_Bool bGoNext; 2522 do { 2523 const SwPosition *pTmpStt = pTmp->Start(), 2524 *pTmpEnd = pTmp->GetPoint() == pTmpStt ? 2525 pTmp->GetMark() : pTmp->GetPoint(); 2526 /* 2527 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich 2528 * muss der alte Bereich aufgehoben werden. 2529 * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum 2530 * Bereich gehoert ! 2531 */ 2532 if( *pStt <= *pTmpStt ) 2533 { 2534 if( *pEnd > *pTmpStt || 2535 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd )) 2536 pTmpDel = pTmp; 2537 } 2538 else 2539 if( *pStt < *pTmpEnd ) 2540 pTmpDel = pTmp; 2541 2542 bGoNext = sal_True; 2543 if( pTmpDel ) // ist der Pam im Bereich ?? loesche ihn 2544 { 2545 sal_Bool bDelete = sal_True; 2546 if( *ppDelRing == pTmpDel ) 2547 { 2548 if( *ppDelRing == pCurCrsr ) 2549 { 2550 if( sal_True == ( bDelete = GoNextCrsr() )) 2551 { 2552 bGoNext = sal_False; 2553 pTmp = (SwPaM*)pTmp->GetNext(); 2554 } 2555 } 2556 else 2557 bDelete = sal_False; // StackCrsr nie loeschen !! 2558 } 2559 2560 if( bDelete ) 2561 delete pTmpDel; // hebe alten Bereich auf 2562 else 2563 { 2564 pTmpDel->GetPoint()->nContent.Assign( 0, 0 ); 2565 pTmpDel->GetPoint()->nNode = 0; 2566 pTmpDel->SetMark(); 2567 pTmpDel->DeleteMark(); 2568 } 2569 pTmpDel = 0; 2570 } 2571 else if( !pTmp->HasMark() ) // sorge auf jedenfall dafuer, das 2572 { // nicht benutzte Indizies beachtet werden! 2573 pTmp->SetMark(); // SPoint liegt nicht im Bereich, 2574 pTmp->DeleteMark(); // aber vielleicht GetMark, also setzen 2575 } 2576 if( bGoNext ) 2577 pTmp = (SwPaM*)pTmp->GetNext(); 2578 } while( !bGoNext || *ppDelRing != pTmp ); 2579 } 2580 2581 void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx ) 2582 { 2583 SwNode *pNode = &rIdx.GetNode(); 2584 2585 // erzeuge einen neuen Pam 2586 SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() ); 2587 if( pNode->GetStartNode() ) 2588 { 2589 if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() ) 2590 { 2591 // der angegebene Node steht in einer Tabelle, also Parke 2592 // den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle) 2593 pNew->GetPoint()->nNode = *pNode->StartOfSectionNode(); 2594 } 2595 else // also auf dem StartNode selbst. 2596 // Dann immer ueber seinen EndNode den StartNode erfragen !!! 2597 // (StartOfSection vom StartNode ist der Parent !) 2598 pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode(); 2599 } 2600 else 2601 pNew->GetPoint()->nNode = *pNode->StartOfSectionNode(); 2602 pNew->SetMark(); 2603 pNew->GetPoint()->nNode = *pNode->EndOfSectionNode(); 2604 2605 //Alle Shells wollen etwas davon haben. 2606 ViewShell *pTmp = this; 2607 do { 2608 if( pTmp->IsA( TYPE( SwCrsrShell ))) 2609 { 2610 SwCrsrShell* pSh = (SwCrsrShell*)pTmp; 2611 if( pSh->pCrsrStk ) 2612 pSh->_ParkPams( pNew, &pSh->pCrsrStk ); 2613 2614 pSh->_ParkPams( pNew, &pSh->pCurCrsr ); 2615 if( pSh->pTblCrsr ) 2616 { 2617 // setze den Tabellen Cursor immer auf 0, den aktuellen 2618 // immer auf den Anfang der Tabelle 2619 SwPaM* pTCrsr = pSh->GetTblCrs(); 2620 SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode(); 2621 if ( pTblNd ) 2622 { 2623 pTCrsr->GetPoint()->nContent.Assign( 0, 0 ); 2624 pTCrsr->GetPoint()->nNode = 0; 2625 pTCrsr->SetMark(); 2626 pTCrsr->DeleteMark(); 2627 pSh->pCurCrsr->GetPoint()->nNode = *pTblNd; 2628 } 2629 } 2630 } 2631 } while ( this != (pTmp = (ViewShell*)pTmp->GetNext() )); 2632 delete pNew; 2633 } 2634 2635 //========================================================================= 2636 2637 /* 2638 * der Copy-Constructor 2639 * Cursor-Position kopieren, in den Ring eingetragen. 2640 * Alle Ansichten eines Dokumentes stehen im Ring der Shells. 2641 */ 2642 2643 SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin ) 2644 : ViewShell( rShell, pInitWin ), 2645 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ), 2646 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ), 2647 eMvState( MV_NONE ), 2648 // --> OD 2008-04-02 #refactorlists# 2649 sMarkedListId(), 2650 nMarkedListLevel( 0 ) 2651 // <-- 2652 { 2653 SET_CURR_SHELL( this ); 2654 // Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen 2655 pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) ); 2656 pCurCrsr->GetCntntNode()->Add( this ); 2657 2658 bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd = 2659 bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr = 2660 bOverwriteCrsr = sal_False; 2661 bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True; 2662 bSetCrsrInReadOnly = sal_True; 2663 pVisCrsr = new SwVisCrsr( this ); 2664 // UpdateCrsr( 0 ); 2665 // OD 11.02.2003 #100556# 2666 mbMacroExecAllowed = rShell.IsMacroExecAllowed(); 2667 //IAccessibility2 Implementation 2009----- 2668 oldColFrm = NULL; 2669 //-----IAccessibility2 Implementation 2009 2670 } 2671 2672 2673 /* 2674 * der normale Constructor 2675 */ 2676 2677 SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin, 2678 const SwViewOption *pInitOpt ) 2679 : ViewShell( rDoc, pInitWin, pInitOpt ), 2680 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ), 2681 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ), 2682 eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst 2683 // --> OD 2008-04-02 #refactorlists# 2684 sMarkedListId(), 2685 nMarkedListLevel( 0 ) 2686 // <-- 2687 { 2688 SET_CURR_SHELL( this ); 2689 /* 2690 * Erzeugen des initialen Cursors, wird auf die erste 2691 * Inhaltsposition gesetzt 2692 */ 2693 SwNodes& rNds = rDoc.GetNodes(); 2694 2695 SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() ); 2696 SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode 2697 2698 pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 ))); 2699 2700 // melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle 2701 // Attribut-Aenderungen ueber den Link weiter gemeldet werden. 2702 pCNd->Add( this ); 2703 2704 bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd = 2705 bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr = 2706 bOverwriteCrsr = sal_False; 2707 bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True; 2708 bSetCrsrInReadOnly = sal_True; 2709 2710 pVisCrsr = new SwVisCrsr( this ); 2711 // UpdateCrsr( 0 ); 2712 // OD 11.02.2003 #100556# 2713 mbMacroExecAllowed = true; 2714 } 2715 2716 2717 2718 SwCrsrShell::~SwCrsrShell() 2719 { 2720 // wenn es nicht die letzte View so sollte zu mindest das 2721 // Feld noch geupdatet werden. 2722 if( GetNext() != this ) 2723 CheckTblBoxCntnt( pCurCrsr->GetPoint() ); 2724 else 2725 ClearTblBoxCntnt(); 2726 2727 delete pVisCrsr; 2728 delete pBlockCrsr; 2729 delete pTblCrsr; 2730 2731 /* 2732 * Freigabe der Cursor 2733 */ 2734 while(pCurCrsr->GetNext() != pCurCrsr) 2735 delete pCurCrsr->GetNext(); 2736 delete pCurCrsr; 2737 2738 // Stack freigeben 2739 if( pCrsrStk ) 2740 { 2741 while( pCrsrStk->GetNext() != pCrsrStk ) 2742 delete pCrsrStk->GetNext(); 2743 delete pCrsrStk; 2744 } 2745 2746 // JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in 2747 // der CursorShell haengt keine Chance geben, sich an den 2748 // TextNode zu haengen. 2749 if( GetRegisteredIn() ) 2750 GetRegisteredInNonConst()->Remove( this ); 2751 } 2752 2753 SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock ) 2754 { 2755 if( pTblCrsr ) 2756 return pTblCrsr; 2757 if( pBlockCrsr && bBlock ) 2758 return &pBlockCrsr->getShellCrsr(); 2759 return pCurCrsr; 2760 } 2761 2762 //Sollte fuer das Clipboard der WaitPtr geschaltet werden? 2763 //Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen. 2764 2765 sal_Bool SwCrsrShell::ShouldWait() const 2766 { 2767 if ( IsTableMode() || GetCrsrCnt() > 1 ) 2768 return sal_True; 2769 2770 if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() ) 2771 return sal_True; 2772 2773 SwPaM* pPam = GetCrsr(); 2774 return pPam->Start()->nNode.GetIndex() + 10 < 2775 pPam->End()->nNode.GetIndex(); 2776 } 2777 2778 2779 sal_uInt16 SwCrsrShell::UpdateTblSelBoxes() 2780 { 2781 if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() )) 2782 GetLayout()->MakeTblCrsrs( *pTblCrsr ); 2783 return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0; 2784 } 2785 2786 // zeige das akt. selektierte "Object" an 2787 void SwCrsrShell::MakeSelVisible() 2788 { 2789 ASSERT( bHasFocus, "kein Focus aber Cursor sichtbar machen?" ); 2790 if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() ) 2791 { 2792 SwRect aTmp( aCharRect ); 2793 long nDiff = aCharRect.Height() - VisArea().Height(); 2794 if( nDiff < aCrsrHeight.X() ) 2795 aTmp.Top( nDiff + aCharRect.Top() ); 2796 else 2797 { 2798 aTmp.Top( aCrsrHeight.X() + aCharRect.Top() ); 2799 aTmp.Height( aCrsrHeight.Y() ); 2800 } 2801 if( !aTmp.HasArea() ) 2802 { 2803 aTmp.SSize().Height() += 1; 2804 aTmp.SSize().Width() += 1; 2805 } 2806 MakeVisible( aTmp ); 2807 } 2808 else 2809 { 2810 if( aCharRect.HasArea() ) 2811 MakeVisible( aCharRect ); 2812 else 2813 { 2814 SwRect aTmp( aCharRect ); 2815 aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1; 2816 MakeVisible( aTmp ); 2817 } 2818 } 2819 } 2820 2821 2822 // suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt) 2823 sal_Bool SwCrsrShell::FindValidCntntNode( sal_Bool bOnlyText ) 2824 { 2825 if( pTblCrsr ) // was soll ich jetzt machen ?? 2826 { 2827 ASSERT( !this, "TabellenSelection nicht aufgehoben!" ); 2828 return sal_False; 2829 } 2830 2831 //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt 2832 if( !bAllProtect && GetDoc()->GetDocShell() && 2833 GetDoc()->GetDocShell()->IsReadOnlyUI() ) 2834 return sal_True; 2835 2836 // dann raus da! 2837 if( pCurCrsr->HasMark() ) 2838 ClearMark(); 2839 2840 // als erstes mal auf Rahmen abpruefen 2841 SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode; 2842 sal_uLong nNdIdx = rNdIdx.GetIndex(); // sichern 2843 SwNodes& rNds = pDoc->GetNodes(); 2844 SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode(); 2845 const SwCntntFrm * pFrm; 2846 2847 if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetLayout(),0,pCurCrsr->GetPoint(),sal_False)) && 2848 !IsReadOnlyAvailable() && pFrm->IsProtected() && 2849 nNdIdx < rNds.GetEndOfExtras().GetIndex() ) 2850 { 2851 // geschuetzter Rahmen ueberspringen 2852 SwPaM aPam( *pCurCrsr->GetPoint() ); 2853 aPam.SetMark(); 2854 aPam.GetMark()->nNode = rNds.GetEndOfContent(); 2855 aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode(); 2856 2857 sal_Bool bFirst = sal_False; 2858 if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, sal_False ))) 2859 { 2860 aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode(); 2861 pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, sal_False ); 2862 } 2863 2864 if( !pCNd ) // sollte nie passieren !!! 2865 { 2866 rNdIdx = nNdIdx; // alten Node zurueck 2867 return sal_False; 2868 } 2869 *pCurCrsr->GetPoint() = *aPam.GetPoint(); 2870 } 2871 else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() ) 2872 { 2873 // dann auf den Anfang vom Doc stellen 2874 rNdIdx = pDoc->GetNodes().GetEndOfExtras(); 2875 pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext( 2876 &rNdIdx ), 0 ); 2877 nNdIdx = rNdIdx.GetIndex(); 2878 } 2879 2880 sal_Bool bOk = sal_True; 2881 2882 // #i9059# cursor may not stand in protected cells 2883 // (unless cursor in protected areas is OK.) 2884 const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode(); 2885 if( !IsReadOnlyAvailable() && 2886 pTableNode != NULL && rNdIdx.GetNode().IsProtect() ) 2887 { 2888 // we're in a table, and we're in a protected area, so we're 2889 // probably in a protected cell. 2890 2891 // move forward into non-protected area. 2892 SwPaM aPam( rNdIdx.GetNode(), 0 ); 2893 while( aPam.GetNode()->IsProtect() && 2894 aPam.Move( fnMoveForward, fnGoCntnt ) ) 2895 ; // nothing to do in the loop; the aPam.Move does the moving! 2896 2897 // didn't work? then go backwards! 2898 if( aPam.GetNode()->IsProtect() ) 2899 { 2900 SwPaM aTmpPaM( rNdIdx.GetNode(), 0 ); 2901 aPam = aTmpPaM; 2902 while( aPam.GetNode()->IsProtect() && 2903 aPam.Move( fnMoveBackward, fnGoCntnt ) ) 2904 ; // nothing to do in the loop; the aPam.Move does the moving! 2905 } 2906 2907 // if we're successful, set the new position 2908 if( ! aPam.GetNode()->IsProtect() ) 2909 { 2910 *pCurCrsr->GetPoint() = *aPam.GetPoint(); 2911 } 2912 } 2913 2914 // in einem geschuetzten Bereich 2915 const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode(); 2916 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() || 2917 ( !IsReadOnlyAvailable() && 2918 pSectNd->GetSection().IsProtectFlag() )) ) 2919 { 2920 typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const; 2921 FNGoSection funcGoSection = &SwNodes::GoNextSection; 2922 2923 bOk = sal_False; 2924 2925 for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt ) 2926 { 2927 sal_Bool bWeiter; 2928 do { 2929 bWeiter = sal_False; 2930 while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx, 2931 sal_True, !IsReadOnlyAvailable() )) ) 2932 { 2933 // in eine Tabelle verschoben -> pruefe ob die 2934 // vielleicht geschuetzt ist 2935 if( pCNd->FindTableNode() ) 2936 { 2937 SwCallLink aTmp( *this ); 2938 SwCrsrSaveState aSaveState( *pCurCrsr ); 2939 aTmp.nNdTyp = 0; // im DTOR nichts machen! 2940 if( !pCurCrsr->IsInProtectTable( sal_True, sal_True ) ) 2941 { 2942 const SwSectionNode* pSNd = pCNd->FindSectionNode(); 2943 if( !pSNd || !pSNd->GetSection().IsHiddenFlag() 2944 || (!IsReadOnlyAvailable() && 2945 pSNd->GetSection().IsProtectFlag() )) 2946 { 2947 bOk = sal_True; 2948 break; // eine nicht geschuetzte Zelle gef. 2949 } 2950 continue; // dann weiter suchen 2951 } 2952 } 2953 else 2954 { 2955 bOk = sal_True; 2956 break; // eine nicht geschuetzte Zelle gef. 2957 } 2958 } 2959 2960 if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() ) 2961 { 2962 // Teste mal auf Fly - kann auch noch geschuetzt sein!! 2963 if( 0 == (pFrm = pCNd->getLayoutFrm( GetLayout(),0,0,sal_False)) || 2964 ( !IsReadOnlyAvailable() && pFrm->IsProtected() ) || 2965 ( bOnlyText && pCNd->IsNoTxtNode() ) ) 2966 { 2967 // dann weiter suchen! 2968 bOk = sal_False; 2969 bWeiter = sal_True; 2970 } 2971 } 2972 } while( bWeiter ); 2973 2974 if( !bOk ) 2975 { 2976 if( !nLoopCnt ) 2977 funcGoSection = &SwNodes::GoPrevSection; 2978 rNdIdx = nNdIdx; 2979 } 2980 } 2981 } 2982 if( bOk ) 2983 { 2984 pCNd = rNdIdx.GetNode().GetCntntNode(); 2985 // sal_uInt16 nCntnt = Min( pCNd->Len(), pCurCrsr->GetPoint()->nContent.GetIndex() ); 2986 xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0; 2987 pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt ); 2988 } 2989 else 2990 { 2991 pCNd = rNdIdx.GetNode().GetCntntNode(); 2992 2993 // falls Cursor im versteckten Bereich ist, auf jedenfall schon mal 2994 // verschieben!! 2995 if( !pCNd || !pCNd->getLayoutFrm( GetLayout(),0,0,sal_False) ) 2996 { 2997 SwCrsrMoveState aTmpState( MV_NONE ); 2998 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 2999 GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(), 3000 &aTmpState ); 3001 } 3002 } 3003 return bOk; 3004 } 3005 3006 3007 void SwCrsrShell::NewCoreSelection() 3008 { 3009 } 3010 3011 3012 sal_Bool SwCrsrShell::IsCrsrReadonly() const 3013 { 3014 if ( GetViewOptions()->IsReadonly() || 3015 // --> FME 2004-06-29 #114856# Formular view 3016 GetViewOptions()->IsFormView() ) 3017 // <-- 3018 { 3019 SwFrm *pFrm = GetCurrFrm( sal_False ); 3020 const SwFlyFrm* pFly; 3021 const SwSection* pSection; 3022 3023 if( pFrm && pFrm->IsInFly() && 3024 (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() && 3025 pFly->Lower() && 3026 !pFly->Lower()->IsNoTxtFrm() && 3027 !GetDrawView()->GetMarkedObjectList().GetMarkCount() ) 3028 { 3029 return sal_False; 3030 } 3031 // --> FME 2004-06-22 #114856# edit in readonly sections 3032 else if ( pFrm && pFrm->IsInSct() && 3033 0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) && 3034 pSection->IsEditInReadonlyFlag() ) 3035 { 3036 return sal_False; 3037 } 3038 // <-- 3039 3040 return sal_True; 3041 } 3042 return sal_False; 3043 } 3044 3045 3046 // darf der Cursor in ReadOnlyBereiche? 3047 void SwCrsrShell::SetReadOnlyAvailable( sal_Bool bFlag ) 3048 { 3049 // im GlobalDoc darf NIE umgeschaltet werden 3050 if( (!GetDoc()->GetDocShell() || 3051 !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) && 3052 bFlag != bSetCrsrInReadOnly ) 3053 { 3054 // wenn das Flag ausgeschaltet wird, dann muessen erstmal alle 3055 // Selektionen aufgehoben werden. Denn sonst wird sich darauf 3056 // verlassen, das nichts geschuetztes selektiert ist! 3057 if( !bFlag ) 3058 { 3059 ClearMark(); 3060 } 3061 bSetCrsrInReadOnly = bFlag; 3062 UpdateCrsr(); 3063 } 3064 } 3065 3066 sal_Bool SwCrsrShell::HasReadonlySel() const 3067 { 3068 sal_Bool bRet = sal_False; 3069 if( IsReadOnlyAvailable() || 3070 // --> FME 2004-06-29 #114856# Formular view 3071 GetViewOptions()->IsFormView() ) 3072 // <-- 3073 { 3074 if( pTblCrsr ) 3075 bRet = pTblCrsr->HasReadOnlyBoxSel() || 3076 pTblCrsr->HasReadonlySel( 3077 // --> FME 2004-06-29 #114856# Formular view 3078 GetViewOptions()->IsFormView() ); 3079 // <-- 3080 else 3081 { 3082 const SwPaM* pCrsr = pCurCrsr; 3083 3084 do { 3085 if( pCrsr->HasReadonlySel( 3086 // --> FME 2004-06-29 #114856# Formular view 3087 GetViewOptions()->IsFormView() ) ) 3088 // <-- 3089 bRet = sal_True; 3090 } while( !bRet && pCurCrsr != ( pCrsr = (SwPaM*)pCrsr->GetNext() )); 3091 } 3092 } 3093 return bRet; 3094 } 3095 3096 sal_Bool SwCrsrShell::IsSelFullPara() const 3097 { 3098 sal_Bool bRet = sal_False; 3099 3100 if( pCurCrsr->GetPoint()->nNode.GetIndex() == 3101 pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() ) 3102 { 3103 xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(), 3104 nEnd = pCurCrsr->GetMark()->nContent.GetIndex(); 3105 if( nStt > nEnd ) 3106 { 3107 xub_StrLen nTmp = nStt; 3108 nStt = nEnd; 3109 nEnd = nTmp; 3110 } 3111 const SwCntntNode* pCNd = pCurCrsr->GetCntntNode(); 3112 bRet = pCNd && !nStt && nEnd == pCNd->Len(); 3113 } 3114 return bRet; 3115 } 3116 3117 short SwCrsrShell::GetTextDirection( const Point* pPt ) const 3118 { 3119 SwPosition aPos( *pCurCrsr->GetPoint() ); 3120 Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() ); 3121 if( pPt ) 3122 { 3123 SwCrsrMoveState aTmpState( MV_NONE ); 3124 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 3125 3126 GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState ); 3127 } 3128 3129 return pDoc->GetTextDirection( aPos, &aPt ); 3130 } 3131 3132 sal_Bool SwCrsrShell::IsInVerticalText( const Point* pPt ) const 3133 { 3134 const short nDir = GetTextDirection( pPt ); 3135 return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir; 3136 } 3137 3138 sal_Bool SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const 3139 { 3140 const short nDir = GetTextDirection( pPt ); 3141 // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in 3142 // vertical environment 3143 return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir; 3144 } 3145 3146 // 3147 // If the current cursor position is inside a hidden range, the hidden range 3148 // is selected: 3149 // 3150 bool SwCrsrShell::SelectHiddenRange() 3151 { 3152 bool bRet = false; 3153 if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() ) 3154 { 3155 SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint(); 3156 const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode(); 3157 if ( pNode ) 3158 { 3159 const xub_StrLen nPos = rPt.nContent.GetIndex(); 3160 3161 // check if nPos is in hidden range 3162 xub_StrLen nHiddenStart; 3163 xub_StrLen nHiddenEnd; 3164 SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd ); 3165 if ( STRING_LEN != nHiddenStart ) 3166 { 3167 // make selection: 3168 pCurCrsr->SetMark(); 3169 pCurCrsr->GetMark()->nContent = nHiddenEnd; 3170 bRet = true; 3171 } 3172 } 3173 } 3174 3175 return bRet; 3176 } 3177 3178 /* */ 3179 3180 // die Suchfunktionen 3181 sal_uLong SwCrsrShell::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes, 3182 SwDocPositions eStart, SwDocPositions eEnde, 3183 sal_Bool& bCancel, 3184 FindRanges eRng, int bReplace ) 3185 { 3186 if( pTblCrsr ) 3187 GetCrsr(); 3188 delete pTblCrsr, pTblCrsr = 0; 3189 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 3190 sal_uLong nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace ); 3191 if( nRet || bCancel ) 3192 UpdateCrsr(); 3193 return nRet; 3194 } 3195 3196 sal_uLong SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl, 3197 SwDocPositions eStart, SwDocPositions eEnde, 3198 sal_Bool& bCancel, 3199 FindRanges eRng, const SwTxtFmtColl* pReplFmt ) 3200 { 3201 if( pTblCrsr ) 3202 GetCrsr(); 3203 delete pTblCrsr, pTblCrsr = 0; 3204 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 3205 sal_uLong nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt ); 3206 if( nRet ) 3207 UpdateCrsr(); 3208 return nRet; 3209 } 3210 3211 sal_uLong SwCrsrShell::Find( const SfxItemSet& rSet, sal_Bool bNoCollections, 3212 SwDocPositions eStart, SwDocPositions eEnde, 3213 sal_Bool& bCancel, 3214 FindRanges eRng, const SearchOptions* pSearchOpt, 3215 const SfxItemSet* rReplSet ) 3216 { 3217 if( pTblCrsr ) 3218 GetCrsr(); 3219 delete pTblCrsr, pTblCrsr = 0; 3220 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 3221 sal_uLong nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel, 3222 eRng, pSearchOpt, rReplSet ); 3223 if( nRet ) 3224 UpdateCrsr(); 3225 return nRet; 3226 } 3227 3228 void SwCrsrShell::SetSelection( const SwPaM& rCrsr ) 3229 { 3230 StartAction(); 3231 SwPaM* pCrsr = GetCrsr(); 3232 *pCrsr->GetPoint() = *rCrsr.GetPoint(); 3233 if(rCrsr.HasMark()) 3234 { 3235 pCrsr->SetMark(); 3236 *pCrsr->GetMark() = *rCrsr.GetMark(); 3237 } 3238 if((SwPaM*)rCrsr.GetNext() != &rCrsr) 3239 { 3240 const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext(); 3241 do 3242 { 3243 SwPaM* pCurrentCrsr = CreateCrsr(); 3244 *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint(); 3245 if(_pStartCrsr->HasMark()) 3246 { 3247 pCurrentCrsr->SetMark(); 3248 *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark(); 3249 } 3250 } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr ); 3251 } 3252 EndAction(); 3253 } 3254 3255 void lcl_RemoveMark( SwPaM* pPam ) 3256 { 3257 ASSERT( pPam->HasMark(), "Don't remove pPoint!" ) 3258 pPam->GetMark()->nContent.Assign( 0, 0 ); 3259 pPam->GetMark()->nNode = 0; 3260 pPam->DeleteMark(); 3261 } 3262 3263 const SwStartNode* lcl_NodeContext( const SwNode& rNode ) 3264 { 3265 const SwStartNode *pRet = rNode.StartOfSectionNode(); 3266 while( pRet->IsSectionNode() || pRet->IsTableNode() || 3267 pRet->GetStartNodeType() == SwTableBoxStartNode ) 3268 { 3269 pRet = pRet->StartOfSectionNode(); 3270 } 3271 return pRet; 3272 } 3273 3274 /** 3275 Checks if a position is valid. To be valid the position's node must 3276 be a content node and the content must not be unregistered. 3277 3278 @param aPos the position to check. 3279 */ 3280 bool lcl_PosOk(const SwPosition & aPos) 3281 { 3282 return NULL != aPos.nNode.GetNode().GetCntntNode() && 3283 SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg(); 3284 } 3285 3286 /** 3287 Checks if a PaM is valid. For a PaM to be valid its point must be 3288 valid. Additionaly if the PaM has a mark this has to be valid, too. 3289 3290 @param aPam the PaM to check 3291 */ 3292 static bool lcl_CrsrOk(SwPaM & aPam) 3293 { 3294 return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark() 3295 || lcl_PosOk(*aPam.GetMark())); 3296 } 3297 3298 void SwCrsrShell::ClearUpCrsrs() 3299 { 3300 // start of the ring 3301 SwPaM * pStartCrsr = GetCrsr(); 3302 // start loop with second entry of the ring 3303 SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext(); 3304 SwPaM * pTmpCrsr; 3305 bool bChanged = false; 3306 3307 /* 3308 For all entries in the ring except the start entry delete the 3309 entry if it is invalid. 3310 */ 3311 while (pCrsr != pStartCrsr) 3312 { 3313 pTmpCrsr = (SwPaM *) pCrsr->GetNext(); 3314 3315 if ( ! lcl_CrsrOk(*pCrsr)) 3316 { 3317 delete pCrsr; 3318 3319 bChanged = true; 3320 } 3321 3322 pCrsr = pTmpCrsr; 3323 } 3324 3325 if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) ) 3326 { 3327 lcl_RemoveMark( pStartCrsr ); 3328 bChanged = true; 3329 } 3330 if( !lcl_PosOk( *pStartCrsr->GetPoint() ) ) 3331 { 3332 SwNodes & aNodes = GetDoc()->GetNodes(); 3333 const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() ); 3334 SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode ); 3335 SwNode * pNode = aNodes.GoPrevious(&aIdx); 3336 if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart ) 3337 aNodes.GoNext( &aIdx ); 3338 if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart ) 3339 { 3340 /* 3341 If the start entry of the ring is invalid replace it with a 3342 cursor pointing to the beginning of the first content node in 3343 the document. 3344 */ 3345 aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode())); 3346 pNode = aNodes.GoNext( &aIdx ); 3347 } 3348 bool bFound = (pNode != NULL); 3349 3350 ASSERT(bFound, "no content node found"); 3351 3352 if (bFound) 3353 { 3354 SwPaM aTmpPam(*pNode); 3355 *pStartCrsr = aTmpPam; 3356 } 3357 3358 bChanged = true; 3359 } 3360 3361 /* 3362 If at least one of the cursors in the ring have been deleted or 3363 replaced, remove the table cursor. 3364 */ 3365 if (pTblCrsr != NULL && bChanged) 3366 TblCrsrToCursor(); 3367 } 3368 3369 // #111827# 3370 String SwCrsrShell::GetCrsrDescr() const 3371 { 3372 String aResult; 3373 3374 if (IsMultiSelection()) 3375 aResult += String(SW_RES(STR_MULTISEL)); 3376 else 3377 aResult = GetDoc()->GetPaMDescr(*GetCrsr()); 3378 3379 return aResult; 3380 } 3381 3382 // SMARTTAGS 3383 3384 void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes, 3385 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps, 3386 const SwWrongList& rSmartTagList, xub_StrLen nCurrent ) 3387 { 3388 // Insert smart tag information 3389 std::vector< rtl::OUString > aSmartTagTypes; 3390 std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps; 3391 3392 for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i ) 3393 { 3394 const xub_StrLen nSTPos = rSmartTagList.Pos( i ); 3395 const xub_StrLen nSTLen = rSmartTagList.Len( i ); 3396 3397 if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen ) 3398 { 3399 const SwWrongArea* pArea = rSmartTagList.GetElement( i ); 3400 if ( pArea ) 3401 { 3402 aSmartTagTypes.push_back( pArea->maType ); 3403 aStringKeyMaps.push_back( pArea->mxPropertyBag ); 3404 } 3405 } 3406 } 3407 3408 if ( aSmartTagTypes.size() ) 3409 { 3410 rSmartTagTypes.realloc( aSmartTagTypes.size() ); 3411 rStringKeyMaps.realloc( aSmartTagTypes.size() ); 3412 3413 std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin(); 3414 sal_uInt16 i = 0; 3415 for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter ) 3416 rSmartTagTypes[i++] = *aTypesIter; 3417 3418 std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin(); 3419 i = 0; 3420 for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter ) 3421 rStringKeyMaps[i++] = *aMapsIter; 3422 } 3423 } 3424 3425 void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange, 3426 SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen ) 3427 { 3428 // create SwPosition for nStartIndex 3429 SwIndex aIndex( &rNode, nBegin ); 3430 SwPosition aStartPos( rNode, aIndex ); 3431 3432 // create SwPosition for nEndIndex 3433 SwPosition aEndPos( aStartPos ); 3434 aEndPos.nContent = nBegin + nLen; 3435 3436 const uno::Reference<text::XTextRange> xRange = 3437 SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos); 3438 3439 rRange = xRange; 3440 } 3441 3442 void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes, 3443 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps, 3444 uno::Reference< text::XTextRange>& rRange ) const 3445 { 3446 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() ) 3447 return; 3448 3449 SwPaM* pCrsr = GetCrsr(); 3450 SwPosition aPos( *pCrsr->GetPoint() ); 3451 SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode(); 3452 if ( pNode && !pNode->IsInProtectSect() ) 3453 { 3454 const SwWrongList *pSmartTagList = pNode->GetSmartTags(); 3455 if ( pSmartTagList ) 3456 { 3457 xub_StrLen nCurrent = aPos.nContent.GetIndex(); 3458 xub_StrLen nBegin = nCurrent; 3459 xub_StrLen nLen = 1; 3460 3461 if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) ) 3462 { 3463 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin ); 3464 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex ); 3465 if ( pSubList ) 3466 { 3467 pSmartTagList = pSubList; 3468 nCurrent = 0; 3469 } 3470 3471 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent ); 3472 lcl_FillTextRange( rRange, *pNode, nBegin, nLen ); 3473 } 3474 } 3475 } 3476 } 3477 3478 // see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect ) 3479 void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect, 3480 uno::Sequence< rtl::OUString >& rSmartTagTypes, 3481 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps, 3482 uno::Reference<text::XTextRange>& rRange ) 3483 { 3484 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() ) 3485 return; 3486 3487 SwPaM* pCrsr = GetCrsr(); 3488 SwPosition aPos( *pCrsr->GetPoint() ); 3489 Point aPt( rPt ); 3490 SwCrsrMoveState eTmpState( MV_SETONLYTEXT ); 3491 SwSpecialPos aSpecialPos; 3492 eTmpState.pSpecialPos = &aSpecialPos; 3493 SwTxtNode *pNode; 3494 const SwWrongList *pSmartTagList; 3495 3496 if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) && 3497 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) && 3498 0 != (pSmartTagList = pNode->GetSmartTags()) && 3499 !pNode->IsInProtectSect() ) 3500 { 3501 xub_StrLen nCurrent = aPos.nContent.GetIndex(); 3502 xub_StrLen nBegin = nCurrent; 3503 xub_StrLen nLen = 1; 3504 3505 if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) ) 3506 { 3507 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin ); 3508 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex ); 3509 if ( pSubList ) 3510 { 3511 pSmartTagList = pSubList; 3512 nCurrent = eTmpState.pSpecialPos->nCharOfst; 3513 } 3514 3515 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent ); 3516 lcl_FillTextRange( rRange, *pNode, nBegin, nLen ); 3517 3518 // get smarttag word 3519 String aText( pNode->GetTxt().Copy( nBegin, nLen ) ); 3520 3521 //save the start and end positons of the line and the starting point 3522 Push(); 3523 LeftMargin(); 3524 xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex(); 3525 RightMargin(); 3526 xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex(); 3527 Pop(sal_False); 3528 3529 // make sure the selection build later from the 3530 // data below does not include footnotes and other 3531 // "in word" character to the left and right in order 3532 // to preserve those. Therefore count those "in words" 3533 // in order to modify the selection accordingly. 3534 const sal_Unicode* pChar = aText.GetBuffer(); 3535 xub_StrLen nLeft = 0; 3536 while (pChar && *pChar++ == CH_TXTATR_INWORD) 3537 ++nLeft; 3538 pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0; 3539 xub_StrLen nRight = 0; 3540 while (pChar && *pChar-- == CH_TXTATR_INWORD) 3541 ++nRight; 3542 3543 aPos.nContent = nBegin + nLeft; 3544 pCrsr = GetCrsr(); 3545 *pCrsr->GetPoint() = aPos; 3546 pCrsr->SetMark(); 3547 ExtendSelection( sal_True, nLen - nLeft - nRight ); 3548 //no determine the rectangle in the current line 3549 xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft; 3550 //take one less than the line end - otherwise the next line would be calculated 3551 xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight); 3552 Push(); 3553 pCrsr->DeleteMark(); 3554 SwIndex& rContent = GetCrsr()->GetPoint()->nContent; 3555 rContent = nWordStart; 3556 SwRect aStartRect; 3557 SwCrsrMoveState aState; 3558 aState.bRealWidth = sal_True; 3559 SwCntntNode* pCntntNode = pCrsr->GetCntntNode(); 3560 SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), &rPt, pCrsr->GetPoint(), sal_False); 3561 3562 pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState ); 3563 rContent = nWordEnd; 3564 SwRect aEndRect; 3565 pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState ); 3566 rSelectRect = aStartRect.Union( aEndRect ); 3567 Pop(sal_False); 3568 } 3569 } 3570 } 3571 3572