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