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