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