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