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