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 sal_Bool SwCrsrShell::GetCharRectAt( SwRect& rOrig, const SwPosition& rPos, 1237 SwCrsrMoveState* pCMS ) const 1238 { 1239 SwCntntFrm * pFrm = GetCurrFrm(); 1240 return pFrm ? pFrm->GetCharRect( rOrig, rPos, pCMS ) : sal_False; 1241 } 1242 1243 1244 void SwCrsrShell::Paint( const Rectangle &rRect) 1245 { 1246 SET_CURR_SHELL( this ); 1247 1248 // beim Painten immer alle Cursor ausschalten 1249 SwRect aRect( rRect ); 1250 1251 sal_Bool bVis = sal_False; 1252 // ist Cursor sichtbar, dann verstecke den SV-Cursor 1253 if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) ) //JP 18.06.97: ??? 1254 { 1255 bVis = sal_True; 1256 pVisCrsr->Hide(); 1257 } 1258 1259 // Bereich neu painten 1260 ViewShell::Paint( rRect ); 1261 1262 if( bHasFocus && !bBasicHideCrsr ) 1263 { 1264 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; 1265 // pAktCrsr->Invalidate( aRect ); 1266 if( !ActionPend() ) 1267 { 1268 // damit nicht rechts/unten die Raender abgeschnitten werden 1269 pAktCrsr->Invalidate( VisArea() ); 1270 pAktCrsr->Show(); 1271 } 1272 else 1273 pAktCrsr->Invalidate( aRect ); 1274 1275 } 1276 if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen 1277 pVisCrsr->Show(); 1278 } 1279 1280 1281 1282 void SwCrsrShell::VisPortChgd( const SwRect & rRect ) 1283 { 1284 SET_CURR_SHELL( this ); 1285 sal_Bool bVis; // beim Scrollen immer alle Cursor ausschalten 1286 1287 // ist Cursor sichtbar, dann verstecke den SV-Cursor 1288 if( sal_True == ( bVis = pVisCrsr->IsVisible() )) 1289 pVisCrsr->Hide(); 1290 1291 bVisPortChgd = sal_True; 1292 aOldRBPos.X() = VisArea().Right(); 1293 aOldRBPos.Y() = VisArea().Bottom(); 1294 1295 //Damit es es keine Probleme mit dem SV-Cursor gibt, wird in 1296 //ViewShell::VisPo.. ein Update() auf das Window gerufen. 1297 //Waehrend des Paintens duerfen aber nun wieder keine Selectionen 1298 //angezeigt werden, deshalb wird der Aufruf hier geklammert. 1299 ViewShell::VisPortChgd( rRect ); // Bereich verschieben 1300 1301 /* 1302 SwRect aRect( rRect ); 1303 if( VisArea().IsOver( aRect ) ) 1304 pCurCrsr->Invalidate( aRect ); 1305 */ 1306 1307 if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen 1308 pVisCrsr->Show(); 1309 1310 if( nCrsrMove ) 1311 bInCMvVisportChgd = sal_True; 1312 1313 bVisPortChgd = sal_False; 1314 } 1315 1316 // aktualisiere den Crsrs, d.H. setze ihn wieder in den Content. 1317 // Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim 1318 // Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position 1319 // ergibt sich aus seiner aktuellen Position im Layout !! 1320 1321 1322 void SwCrsrShell::UpdateCrsrPos() 1323 { 1324 SET_CURR_SHELL( this ); 1325 ++nStartAction; 1326 SwShellCrsr* pShellCrsr = getShellCrsr( true ); 1327 Size aOldSz( GetDocSize() ); 1328 SwCntntNode *pCNode = pShellCrsr->GetCntntNode(); 1329 SwCntntFrm *pFrm = pCNode ? 1330 pCNode->getLayoutFrm( GetLayout(), &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ) :0; 1331 if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) ) 1332 { 1333 SwCrsrMoveState aTmpState( MV_NONE ); 1334 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 1335 GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(), 1336 &aTmpState ); 1337 if( pShellCrsr->HasMark()) 1338 pShellCrsr->DeleteMark(); 1339 } 1340 IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0; 1341 if( pGrammarContact ) 1342 pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() ); 1343 --nStartAction; 1344 if( aOldSz != GetDocSize() ) 1345 SizeChgNotify(); 1346 } 1347 1348 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen 1349 // stehen, so mussen diese daraus verschoben werden 1350 static void lcl_CheckHiddenSection( SwNodeIndex& rIdx ) 1351 { 1352 const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode(); 1353 if( pSectNd && pSectNd->GetSection().IsHiddenFlag() ) 1354 { 1355 SwNodeIndex aTmp( *pSectNd ); 1356 #if OSL_DEBUG_LEVEL > 1 1357 const SwNode* pFrmNd = 1358 #endif 1359 rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() ); 1360 1361 #if OSL_DEBUG_LEVEL > 1 1362 (void) pFrmNd; 1363 ASSERT( pFrmNd, "keinen Node mit Frames gefunden" ); 1364 #endif 1365 rIdx = aTmp; 1366 } 1367 } 1368 1369 // Try to set the cursor to the next visible content node. 1370 static void lcl_CheckHiddenPara( SwPosition& rPos ) 1371 { 1372 SwNodeIndex aTmp( rPos.nNode ); 1373 SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode(); 1374 while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) ) 1375 { 1376 SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp ); 1377 if ( pCntnt && pCntnt->IsTxtNode() ) 1378 pTxtNd = (SwTxtNode*)pCntnt; 1379 else 1380 pTxtNd = 0; 1381 } 1382 1383 if ( pTxtNd ) 1384 rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) ); 1385 } 1386 1387 // --> OD 2005-12-14 #i27301# - helper class, which notifies the accessibility 1388 // about invalid text selections in its destructor 1389 class SwNotifyAccAboutInvalidTextSelections 1390 { 1391 private: 1392 SwCrsrShell& mrCrsrSh; 1393 1394 public: 1395 SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh ) 1396 : mrCrsrSh( _rCrsrSh ) 1397 {} 1398 1399 ~SwNotifyAccAboutInvalidTextSelections() 1400 { 1401 mrCrsrSh.InvalidateAccessibleParaTextSelection(); 1402 } 1403 }; 1404 // <-- 1405 void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, sal_Bool bIdleEnd ) 1406 { 1407 SET_CURR_SHELL( this ); 1408 1409 ClearUpCrsrs(); 1410 1411 // erfrage den Count fuer die Start-/End-Actions und ob die Shell 1412 // ueberhaupt den Focus hat 1413 // if( ActionPend() /*|| !bHasFocus*/ ) 1414 //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction der 1415 // Cursor geupdatet werden; um z.B. den TabellenCursor zu 1416 // erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen! 1417 if( ActionPend() && BasicActionPend() ) 1418 { 1419 if ( eFlags & SwCrsrShell::READONLY ) 1420 bIgnoreReadonly = sal_True; 1421 return; // wenn nicht, dann kein Update !! 1422 } 1423 1424 SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this ); 1425 1426 if ( bIgnoreReadonly ) 1427 { 1428 bIgnoreReadonly = sal_False; 1429 eFlags |= SwCrsrShell::READONLY; 1430 } 1431 1432 if( eFlags & SwCrsrShell::CHKRANGE ) // alle Cursor-Bewegungen auf 1433 CheckRange( pCurCrsr ); // ueberlappende Bereiche testen 1434 1435 if( !bIdleEnd ) 1436 CheckTblBoxCntnt(); 1437 1438 // steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen 1439 // (oder ist noch TabellenMode), dann gilt der Tabellen Mode 1440 SwPaM* pTstCrsr = getShellCrsr( true ); 1441 if( pTstCrsr->HasMark() && !pBlockCrsr && 1442 pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) && 1443 ( pTblCrsr || 1444 pTstCrsr->GetNode( sal_True )->StartOfSectionNode() != 1445 pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) ) 1446 { 1447 SwShellCrsr* pITmpCrsr = getShellCrsr( true ); 1448 Point aTmpPt( pITmpCrsr->GetPtPos() ); 1449 Point aTmpMk( pITmpCrsr->GetMkPos() ); 1450 SwPosition* pPos = pITmpCrsr->GetPoint(); 1451 1452 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen 1453 // stehen, so mussen diese daraus verschoben werden 1454 lcl_CheckHiddenSection( pPos->nNode ); 1455 lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode ); 1456 1457 // Move cursor out of hidden paragraphs 1458 if ( !GetViewOptions()->IsShowHiddenChar() ) 1459 { 1460 lcl_CheckHiddenPara( *pPos ); 1461 lcl_CheckHiddenPara( *pITmpCrsr->GetMark() ); 1462 } 1463 1464 SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()-> 1465 getLayoutFrm( GetLayout(), &aTmpPt, pPos, sal_False ); 1466 1467 ASSERT( pTblFrm, "Tabelle Crsr nicht im Content ??" ); 1468 1469 // --> FME 2005-12-02 #126107# Make code robust. The table 1470 // cursor may point to a table in a currently inactive header. 1471 SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0; 1472 // <-- 1473 1474 if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 ) 1475 { 1476 // First check if point is in repeated headline: 1477 bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm ); 1478 1479 // Second check if mark is in repeated headline: 1480 if ( !bInRepeatedHeadline ) 1481 { 1482 SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( sal_False )-> 1483 getLayoutFrm( GetLayout(), &aTmpMk, pITmpCrsr->GetMark(), sal_False ); 1484 ASSERT( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" ); 1485 1486 if ( pMarkTblFrm ) 1487 { 1488 SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm(); 1489 ASSERT( pMarkTab, "Tabelle Crsr nicht im Content ??" ); 1490 1491 // --> FME 2005-11-28 #120360# Make code robust: 1492 if ( pMarkTab ) 1493 { 1494 bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm ); 1495 } 1496 // <-- 1497 } 1498 } 1499 1500 // No table cursor in repeaded headlines: 1501 if ( bInRepeatedHeadline ) 1502 { 1503 pTblFrm = 0; 1504 1505 SwPosSection fnPosSect = *pPos < *pITmpCrsr->GetMark() 1506 ? fnSectionStart 1507 : fnSectionEnd; 1508 1509 // dann nur innerhalb der Box selektieren 1510 if( pTblCrsr ) 1511 { 1512 pCurCrsr->SetMark(); 1513 *pCurCrsr->GetMark() = *pTblCrsr->GetMark(); 1514 pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos(); 1515 pTblCrsr->DeleteMark(); 1516 pTblCrsr->SwSelPaintRects::Hide(); 1517 } 1518 1519 *pCurCrsr->GetPoint() = *pCurCrsr->GetMark(); 1520 (*fnSectionCurr)( *pCurCrsr, fnPosSect ); 1521 } 1522 } 1523 1524 // wir wollen wirklich eine Tabellen-Selektion 1525 if( pTab && pTblFrm ) 1526 { 1527 if( !pTblCrsr ) 1528 { 1529 pTblCrsr = new SwShellTableCrsr( *this, 1530 *pCurCrsr->GetMark(), pCurCrsr->GetMkPos(), 1531 *pPos, aTmpPt ); 1532 pCurCrsr->DeleteMark(); 1533 pCurCrsr->SwSelPaintRects::Hide(); 1534 1535 CheckTblBoxCntnt(); 1536 } 1537 1538 SwCrsrMoveState aTmpState( MV_NONE ); 1539 aTmpState.bRealHeight = sal_True; 1540 if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) ) 1541 { 1542 Point aCentrPt( aCharRect.Center() ); 1543 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 1544 pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState ); 1545 #ifndef DBG_UTIL 1546 pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ); 1547 #else 1548 if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) ) 1549 ASSERT( !this, "GetCharRect failed." ); 1550 #endif 1551 } 1552 // ALIGNRECT( aCharRect ); 1553 1554 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken 1555 // Curosr in den sichtbaren Bereich scrollen 1556 if( (eFlags & SwCrsrShell::SCROLLWIN) && 1557 (HasSelection() || eFlags & SwCrsrShell::READONLY || 1558 !IsCrsrReadonly()) ) 1559 { 1560 SwFrm* pBoxFrm = pTblFrm; 1561 while( pBoxFrm && !pBoxFrm->IsCellFrm() ) 1562 pBoxFrm = pBoxFrm->GetUpper(); 1563 if( pBoxFrm && pBoxFrm->Frm().HasArea() ) 1564 MakeVisible( pBoxFrm->Frm() ); 1565 else 1566 MakeVisible( aCharRect ); 1567 } 1568 1569 // lasse vom Layout die Crsr in den Boxen erzeugen 1570 if( pTblCrsr->IsCrsrMovedUpdt() ) 1571 GetLayout()->MakeTblCrsrs( *pTblCrsr ); 1572 if( bHasFocus && !bBasicHideCrsr ) 1573 pTblCrsr->Show(); 1574 1575 // Cursor-Points auf die neuen Positionen setzen 1576 pTblCrsr->GetPtPos().X() = aCharRect.Left(); 1577 pTblCrsr->GetPtPos().Y() = aCharRect.Top(); 1578 1579 if( bSVCrsrVis ) 1580 { 1581 aCrsrHeight.X() = 0; 1582 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ? 1583 -aCharRect.Width() : aCharRect.Height(); 1584 pVisCrsr->Show(); // wieder anzeigen 1585 } 1586 eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst 1587 if( pTblFrm && Imp()->IsAccessible() ) 1588 Imp()->InvalidateAccessibleCursorPosition( pTblFrm ); 1589 return; 1590 } 1591 } 1592 1593 if( pTblCrsr ) 1594 { 1595 // Cursor Ring loeschen 1596 while( pCurCrsr->GetNext() != pCurCrsr ) 1597 delete pCurCrsr->GetNext(); 1598 pCurCrsr->DeleteMark(); 1599 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint(); 1600 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos(); 1601 delete pTblCrsr, pTblCrsr = 0; 1602 } 1603 1604 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken 1605 1606 // sind wir vielleicht in einer geschuetzten/versteckten Section ? 1607 { 1608 SwShellCrsr* pShellCrsr = getShellCrsr( true ); 1609 sal_Bool bChgState = sal_True; 1610 const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode(); 1611 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() || 1612 ( !IsReadOnlyAvailable() && 1613 pSectNd->GetSection().IsProtectFlag() && 1614 ( !pDoc->GetDocShell() || 1615 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) ) 1616 { 1617 if( !FindValidCntntNode( !HasDrawView() || 1618 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount())) 1619 { 1620 // alles ist geschuetzt / versteckt -> besonderer Mode 1621 if( bAllProtect && !IsReadOnlyAvailable() && 1622 pSectNd->GetSection().IsProtectFlag() ) 1623 bChgState = sal_False; 1624 else 1625 { 1626 eMvState = MV_NONE; // Status fuers Crsr-Travelling 1627 bAllProtect = sal_True; 1628 if( GetDoc()->GetDocShell() ) 1629 { 1630 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True ); 1631 CallChgLnk(); // UI bescheid sagen! 1632 } 1633 return; 1634 } 1635 } 1636 } 1637 if( bChgState ) 1638 { 1639 sal_Bool bWasAllProtect = bAllProtect; 1640 bAllProtect = sal_False; 1641 if( bWasAllProtect && GetDoc()->GetDocShell() && 1642 GetDoc()->GetDocShell()->IsReadOnlyUI() ) 1643 { 1644 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False ); 1645 CallChgLnk(); // UI bescheid sagen! 1646 } 1647 } 1648 } 1649 1650 UpdateCrsrPos(); 1651 1652 // #100722# The cursor must always point into content; there's some code 1653 // that relies on this. (E.g. in SwEditShell::GetScriptType, which always 1654 // loops _behind_ the last node in the selection, which always works if you 1655 // are in content.) To achieve this, we'll force cursor(s) to point into 1656 // content, if UpdateCrsrPos() hasn't already done so. 1657 SwPaM* pCmp = pCurCrsr; 1658 do 1659 { 1660 // start will move forwards, end will move backwards 1661 bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() ); 1662 1663 // move point; forward if it's the start, backwards if it's the end 1664 if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() ) 1665 pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward, 1666 fnGoCntnt ); 1667 1668 // move mark (if exists); forward if it's the start, else backwards 1669 if( pCmp->HasMark() ) 1670 { 1671 if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() ) 1672 { 1673 pCmp->Exchange(); 1674 pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward, 1675 fnGoCntnt ); 1676 pCmp->Exchange(); 1677 } 1678 } 1679 1680 // iterate to next PaM in ring 1681 pCmp = static_cast<SwPaM*>( pCmp->GetNext() ); 1682 } 1683 while( pCmp != pCurCrsr ); 1684 1685 1686 SwRect aOld( aCharRect ); 1687 sal_Bool bFirst = sal_True; 1688 SwCntntFrm *pFrm; 1689 int nLoopCnt = 100; 1690 SwShellCrsr* pShellCrsr = getShellCrsr( true ); 1691 1692 do { 1693 sal_Bool bAgainst; 1694 do { 1695 bAgainst = sal_False; 1696 pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(), 1697 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ); 1698 // ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout 1699 // erzeugt werden, weil ja mal hier einer vorhanden war !! 1700 if ( !pFrm ) 1701 { 1702 do 1703 { 1704 CalcLayout(); 1705 pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(), 1706 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ); 1707 } while( !pFrm ); 1708 } 1709 else if ( Imp()->IsIdleAction() ) 1710 //Wir stellen sicher, dass anstaendig Formatiert wurde #42224# 1711 pFrm->PrepareCrsr(); 1712 1713 // im geschuetzten Fly? aber bei Rahmenselektion ignorieren 1714 if( !IsReadOnlyAvailable() && pFrm->IsProtected() && 1715 ( !Imp()->GetDrawView() || 1716 !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) && 1717 (!pDoc->GetDocShell() || 1718 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) ) 1719 { 1720 // dann suche eine gueltige Position 1721 sal_Bool bChgState = sal_True; 1722 if( !FindValidCntntNode(!HasDrawView() || 1723 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount())) 1724 { 1725 // alles ist geschuetzt / versteckt -> besonderer Mode 1726 if( bAllProtect ) 1727 bChgState = sal_False; 1728 else 1729 { 1730 eMvState = MV_NONE; // Status fuers Crsr-Travelling 1731 bAllProtect = sal_True; 1732 if( GetDoc()->GetDocShell() ) 1733 { 1734 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True ); 1735 CallChgLnk(); // UI bescheid sagen! 1736 } 1737 return; 1738 } 1739 } 1740 1741 if( bChgState ) 1742 { 1743 sal_Bool bWasAllProtect = bAllProtect; 1744 bAllProtect = sal_False; 1745 if( bWasAllProtect && GetDoc()->GetDocShell() && 1746 GetDoc()->GetDocShell()->IsReadOnlyUI() ) 1747 { 1748 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False ); 1749 CallChgLnk(); // UI bescheid sagen! 1750 } 1751 bAllProtect = sal_False; 1752 bAgainst = sal_True; // nochmal den richigen Frm suchen 1753 } 1754 } 1755 } while( bAgainst ); 1756 1757 if( !( eFlags & SwCrsrShell::NOCALRECT )) 1758 { 1759 SwCrsrMoveState aTmpState( eMvState ); 1760 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 1761 aTmpState.bRealHeight = sal_True; 1762 aTmpState.bRealWidth = IsOverwriteCrsr(); 1763 aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel(); 1764 1765 // #i27615#,#i30453# 1766 SwSpecialPos aSpecialPos; 1767 aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE; 1768 if (pShellCrsr->IsInFrontOfLabel()) 1769 { 1770 aTmpState.pSpecialPos = &aSpecialPos; 1771 } 1772 1773 if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) ) 1774 { 1775 Point& rPt = pShellCrsr->GetPtPos(); 1776 rPt = aCharRect.Center(); 1777 pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState ); 1778 } 1779 // ALIGNRECT( aCharRect ); 1780 1781 if( !pShellCrsr->HasMark() ) 1782 aCrsrHeight = aTmpState.aRealHeight; 1783 else 1784 { 1785 aCrsrHeight.X() = 0; 1786 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ? 1787 -aCharRect.Width() : aCharRect.Height(); 1788 } 1789 } 1790 else 1791 { 1792 aCrsrHeight.X() = 0; 1793 aCrsrHeight.Y() = aCharRect.Height(); 1794 } 1795 1796 if( !bFirst && aOld == aCharRect ) 1797 break; 1798 1799 // falls das Layout meint, nach dem 100 durchlauf ist man immer noch 1800 // im Fluss, sollte man die akt. Pos. als gegeben hinnehmen! 1801 // siehe Bug: 29658 1802 if( !--nLoopCnt ) 1803 { 1804 ASSERT( !this, "Endlosschleife? CharRect != OldCharRect "); 1805 break; 1806 } 1807 aOld = aCharRect; 1808 bFirst = sal_False; 1809 1810 // Cursor-Points auf die neuen Positionen setzen 1811 pShellCrsr->GetPtPos().X() = aCharRect.Left(); 1812 pShellCrsr->GetPtPos().Y() = aCharRect.Top(); 1813 1814 if( !(eFlags & SwCrsrShell::UPDOWN )) // alte Pos. von Up/Down loeschen 1815 { 1816 pFrm->Calc(); 1817 nUpDownX = pFrm->IsVertical() ? 1818 aCharRect.Top() - pFrm->Frm().Top() : 1819 aCharRect.Left() - pFrm->Frm().Left(); 1820 } 1821 1822 // Curosr in den sichtbaren Bereich scrollen 1823 if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN && 1824 (HasSelection() || eFlags & SwCrsrShell::READONLY || 1825 !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) ) 1826 { 1827 //JP 30.04.99: damit das EndAction, beim evtuellen Scrollen, den 1828 // SV-Crsr nicht wieder sichtbar macht, wird hier das Flag 1829 // gesichert und zurueckgesetzt. 1830 sal_Bool bSav = bSVCrsrVis; bSVCrsrVis = sal_False; 1831 MakeSelVisible(); 1832 bSVCrsrVis = bSav; 1833 } 1834 1835 } while( eFlags & SwCrsrShell::SCROLLWIN ); 1836 1837 if( pBlockCrsr ) 1838 RefreshBlockCursor(); 1839 1840 if( !bIdleEnd && bHasFocus && !bBasicHideCrsr ) 1841 { 1842 if( pTblCrsr ) 1843 pTblCrsr->SwSelPaintRects::Show(); 1844 else 1845 { 1846 pCurCrsr->SwSelPaintRects::Show(); 1847 if( pBlockCrsr ) 1848 { 1849 SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext()); 1850 while( pNxt && pNxt != pCurCrsr ) 1851 { 1852 pNxt->SwSelPaintRects::Show(); 1853 pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext()); 1854 } 1855 } 1856 } 1857 } 1858 1859 eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst 1860 1861 if( pFrm && Imp()->IsAccessible() ) 1862 Imp()->InvalidateAccessibleCursorPosition( pFrm ); 1863 1864 // switch from blinking cursor to read-only-text-selection cursor 1865 static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME; 1866 const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings(). 1867 GetCursorBlinkTime(); 1868 1869 if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) == 1870 ( nBlinkTime != nNoBlinkTime ) ) 1871 { 1872 // non blinking cursor in read only - text selection mode 1873 AllSettings aSettings = GetOut()->GetSettings(); 1874 StyleSettings aStyleSettings = aSettings.GetStyleSettings(); 1875 const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ? 1876 Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() : 1877 nNoBlinkTime; 1878 aStyleSettings.SetCursorBlinkTime( nNewBlinkTime ); 1879 aSettings.SetStyleSettings( aStyleSettings ); 1880 GetOut()->SetSettings( aSettings ); 1881 } 1882 1883 if( bSVCrsrVis ) 1884 pVisCrsr->Show(); // wieder anzeigen 1885 } 1886 1887 void SwCrsrShell::RefreshBlockCursor() 1888 { 1889 ASSERT( pBlockCrsr, "Don't call me without a block cursor" ); 1890 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr(); 1891 Point aPt = rBlock.GetPtPos(); 1892 SwCntntFrm* pFrm = rBlock.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, rBlock.GetPoint(), sal_False ); 1893 Point aMk; 1894 if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() ) 1895 { 1896 aPt = *pBlockCrsr->getStartPoint(); 1897 aMk = *pBlockCrsr->getEndPoint(); 1898 } 1899 else 1900 { 1901 aPt = rBlock.GetPtPos(); 1902 if( pFrm ) 1903 { 1904 if( pFrm->IsVertical() ) 1905 aPt.Y() = pFrm->Frm().Top() + GetUpDownX(); 1906 else 1907 aPt.X() = pFrm->Frm().Left() + GetUpDownX(); 1908 } 1909 aMk = rBlock.GetMkPos(); 1910 } 1911 SwRect aRect( aMk, aPt ); 1912 aRect.Justify(); 1913 SwSelectionList aSelList( pFrm ); 1914 1915 if( GetLayout()->FillSelection( aSelList, aRect ) ) 1916 { 1917 SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext(); 1918 while( pNxt != pCurCrsr ) 1919 { 1920 delete pNxt; 1921 pNxt = (SwCursor*)pCurCrsr->GetNext(); 1922 } 1923 1924 std::list<SwPaM*>::iterator pStart = aSelList.getStart(); 1925 std::list<SwPaM*>::iterator pPam = aSelList.getEnd(); 1926 ASSERT( pPam != pStart, "FillSelection should deliver at least one PaM" ) 1927 pCurCrsr->SetMark(); 1928 --pPam; 1929 // If there is only one text portion inside the rectangle, a simple 1930 // selection is created 1931 if( pPam == pStart ) 1932 { 1933 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); 1934 if( (*pPam)->HasMark() ) 1935 *pCurCrsr->GetMark() = *(*pPam)->GetMark(); 1936 else 1937 pCurCrsr->DeleteMark(); 1938 delete *pPam; 1939 pCurCrsr->SetColumnSelection( false ); 1940 } 1941 else 1942 { 1943 // The order of the SwSelectionList has to be preserved but 1944 // the order inside the ring created by CreateCrsr() is not like 1945 // exspected => First create the selections before the last one 1946 // downto the first selection. 1947 // At least create the cursor for the last selection 1948 --pPam; 1949 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections) 1950 if( (*pPam)->HasMark() ) 1951 *pCurCrsr->GetMark() = *(*pPam)->GetMark(); 1952 else 1953 pCurCrsr->DeleteMark(); 1954 delete *pPam; 1955 pCurCrsr->SetColumnSelection( true ); 1956 while( pPam != pStart ) 1957 { 1958 --pPam; 1959 1960 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr ); 1961 pNew->Insert( pCurCrsr, 0 ); 1962 pCurCrsr->Remove( 0, pCurCrsr->Count() ); 1963 pCurCrsr->DeleteMark(); 1964 1965 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1 1966 if( (*pPam)->HasMark() ) 1967 { 1968 pCurCrsr->SetMark(); 1969 *pCurCrsr->GetMark() = *(*pPam)->GetMark(); 1970 } 1971 else 1972 pCurCrsr->DeleteMark(); 1973 pCurCrsr->SetColumnSelection( true ); 1974 delete *pPam; 1975 } 1976 { 1977 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr ); 1978 pNew->Insert( pCurCrsr, 0 ); 1979 pCurCrsr->Remove( 0, pCurCrsr->Count() ); 1980 pCurCrsr->DeleteMark(); 1981 } 1982 pPam = aSelList.getEnd(); 1983 --pPam; 1984 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection 1985 if( (*pPam)->HasMark() ) 1986 { 1987 pCurCrsr->SetMark(); 1988 *pCurCrsr->GetMark() = *(*pPam)->GetMark(); 1989 } 1990 else 1991 pCurCrsr->DeleteMark(); 1992 pCurCrsr->SetColumnSelection( true ); 1993 delete *pPam; 1994 } 1995 } 1996 } 1997 1998 // erzeuge eine Kopie vom Cursor und speicher diese im Stack 1999 2000 2001 void SwCrsrShell::Push() 2002 { 2003 pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(), 2004 pCurCrsr->GetPtPos(), pCrsrStk ); 2005 2006 if( pCurCrsr->HasMark() ) 2007 { 2008 pCrsrStk->SetMark(); 2009 *pCrsrStk->GetMark() = *pCurCrsr->GetMark(); 2010 } 2011 } 2012 2013 /* 2014 * Loescht einen Cursor (gesteuert durch bOldCrsr) 2015 * - vom Stack oder ( bOldCrsr = sal_True ) 2016 * - den aktuellen und der auf dem Stack stehende wird zum aktuellen 2017 * 2018 * Return: es war auf dem Stack noch einer vorhanden 2019 */ 2020 2021 2022 sal_Bool SwCrsrShell::Pop( sal_Bool bOldCrsr ) 2023 { 2024 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 2025 2026 // noch weitere vorhanden ? 2027 if( 0 == pCrsrStk ) 2028 return sal_False; 2029 2030 SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk; 2031 2032 // der Nachfolger wird der Aktuelle 2033 if( pCrsrStk->GetNext() != pCrsrStk ) 2034 { 2035 pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext()); 2036 } 2037 2038 if( bOldCrsr ) // loesche vom Stack 2039 delete pCrsrStk; // 2040 2041 pCrsrStk = pTmp; // neu zuweisen 2042 2043 if( !bOldCrsr ) 2044 { 2045 SwCrsrSaveState aSaveState( *pCurCrsr ); 2046 2047 // wurde die sichtbare SSelection nicht veraendert 2048 if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() || 2049 pOldStk->GetPtPos() == pCurCrsr->GetMkPos() ) 2050 { 2051 // "Selektions-Rechtecke" verschieben 2052 pCurCrsr->Insert( pOldStk, 0 ); 2053 pOldStk->Remove( 0, pOldStk->Count() ); 2054 } 2055 2056 if( pOldStk->HasMark() ) 2057 { 2058 pCurCrsr->SetMark(); 2059 *pCurCrsr->GetMark() = *pOldStk->GetMark(); 2060 pCurCrsr->GetMkPos() = pOldStk->GetMkPos(); 2061 } 2062 else 2063 // keine Selection also alte aufheben und auf die alte Pos setzen 2064 pCurCrsr->DeleteMark(); 2065 *pCurCrsr->GetPoint() = *pOldStk->GetPoint(); 2066 pCurCrsr->GetPtPos() = pOldStk->GetPtPos(); 2067 delete pOldStk; 2068 2069 if( !pCurCrsr->IsInProtectTable( sal_True ) && 2070 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 2071 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) ) 2072 UpdateCrsr(); // akt. Cursor Updaten 2073 } 2074 return sal_True; 2075 } 2076 2077 /* 2078 * Verbinde zwei Cursor miteinander. 2079 * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen. 2080 */ 2081 2082 2083 void SwCrsrShell::Combine() 2084 { 2085 // noch weitere vorhanden ? 2086 if( 0 == pCrsrStk ) 2087 return; 2088 2089 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 2090 SwCrsrSaveState aSaveState( *pCurCrsr ); 2091 if( pCrsrStk->HasMark() ) // nur wenn GetMark gesetzt wurde 2092 { 2093 #ifndef DBG_UTIL 2094 CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True ); 2095 #else 2096 if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True )) 2097 ASSERT( !this, "StackCrsr & akt. Crsr nicht in gleicher Section." ); 2098 #endif 2099 // kopiere das GetMark 2100 if( !pCurCrsr->HasMark() ) 2101 pCurCrsr->SetMark(); 2102 *pCurCrsr->GetMark() = *pCrsrStk->GetMark(); 2103 pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos(); 2104 } 2105 2106 SwShellCrsr * pTmp = 0; 2107 if( pCrsrStk->GetNext() != pCrsrStk ) 2108 { 2109 pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext()); 2110 } 2111 delete pCrsrStk; 2112 pCrsrStk = pTmp; 2113 if( !pCurCrsr->IsInProtectTable( sal_True ) && 2114 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 2115 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) ) 2116 UpdateCrsr(); // akt. Cursor Updaten 2117 } 2118 2119 2120 void SwCrsrShell::HideCrsrs() 2121 { 2122 if( !bHasFocus || bBasicHideCrsr ) 2123 return; 2124 2125 // ist Cursor sichtbar, dann verstecke den SV-Cursor 2126 if( pVisCrsr->IsVisible() ) 2127 { 2128 SET_CURR_SHELL( this ); 2129 pVisCrsr->Hide(); 2130 } 2131 // hebe die Invertierung der SSelection auf 2132 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; 2133 pAktCrsr->Hide(); 2134 } 2135 2136 2137 2138 void SwCrsrShell::ShowCrsrs( sal_Bool bCrsrVis ) 2139 { 2140 if( !bHasFocus || bAllProtect || bBasicHideCrsr ) 2141 return; 2142 2143 SET_CURR_SHELL( this ); 2144 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; 2145 pAktCrsr->Show(); 2146 2147 if( bSVCrsrVis && bCrsrVis ) // auch SV-Cursor wieder anzeigen 2148 pVisCrsr->Show(); 2149 } 2150 2151 // Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors 2152 2153 2154 void SwCrsrShell::ShowCrsr() 2155 { 2156 if( !bBasicHideCrsr ) 2157 { 2158 bSVCrsrVis = sal_True; 2159 pCurCrsr->SetShowTxtInputFldOverlay( true ); 2160 UpdateCrsr(); 2161 } 2162 } 2163 2164 2165 void SwCrsrShell::HideCrsr() 2166 { 2167 if( !bBasicHideCrsr ) 2168 { 2169 bSVCrsrVis = sal_False; 2170 // evt. die sel. Bereiche aufheben !! 2171 SET_CURR_SHELL( this ); 2172 pCurCrsr->SetShowTxtInputFldOverlay( false ); 2173 pVisCrsr->Hide(); 2174 } 2175 } 2176 2177 2178 void SwCrsrShell::ShLooseFcs() 2179 { 2180 if( !bBasicHideCrsr ) 2181 HideCrsrs(); 2182 bHasFocus = sal_False; 2183 } 2184 2185 2186 void SwCrsrShell::ShGetFcs( sal_Bool bUpdate ) 2187 { 2188 bHasFocus = sal_True; 2189 if( !bBasicHideCrsr && VisArea().Width() ) 2190 { 2191 UpdateCrsr( static_cast<sal_uInt16>( bUpdate ? 2192 SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN 2193 : SwCrsrShell::CHKRANGE ) ); 2194 ShowCrsrs( bSVCrsrVis ? sal_True : sal_False ); 2195 } 2196 } 2197 2198 // gebe den aktuellen Frame, in dem der Cursor steht, zurueck 2199 2200 SwCntntFrm *SwCrsrShell::GetCurrFrm( const sal_Bool bCalcFrm ) const 2201 { 2202 SET_CURR_SHELL( (ViewShell*)this ); 2203 SwCntntFrm *pRet = 0; 2204 SwCntntNode *pNd = pCurCrsr->GetCntntNode(); 2205 if ( pNd ) 2206 { 2207 if ( bCalcFrm ) 2208 { 2209 const sal_uInt16* pST = &nStartAction; 2210 ++(*((sal_uInt16*)pST)); 2211 const Size aOldSz( GetDocSize() ); 2212 pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() ); 2213 --(*((sal_uInt16*)pST)); 2214 if( aOldSz != GetDocSize() ) 2215 ((SwCrsrShell*)this)->SizeChgNotify(); 2216 } 2217 else 2218 pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), sal_False); 2219 } 2220 return pRet; 2221 } 2222 2223 2224 // alle Attribut/Format-Aenderungen am akt. Node werden an den 2225 // Link weitergeleitet. 2226 2227 2228 void SwCrsrShell::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 2229 { 2230 const sal_uInt16 nWhich = pOld ? 2231 pOld->Which() : 2232 pNew ? 2233 pNew->Which() : 2234 sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN); 2235 2236 if( bCallChgLnk && 2237 ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END || 2238 nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR || 2239 nWhich == RES_ATTRSET_CHG )) 2240 // die Messages werden nicht weitergemeldet 2241 //MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom 2242 //SwTxtNode::Insert(SwTxtHint*, sal_uInt16) abgesetzt; hier wird reagiert und 2243 //vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden. 2244 CallChgLnk(); 2245 2246 if( aGrfArrivedLnk.IsSet() && 2247 ( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich )) 2248 aGrfArrivedLnk.Call( this ); 2249 } 2250 2251 2252 // Abfrage, ob der aktuelle Cursor eine Selektion aufspannt, 2253 // also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind. 2254 2255 2256 sal_Bool SwCrsrShell::HasSelection() const 2257 { 2258 const SwPaM* pCrsr = getShellCrsr( true ); 2259 return( IsTableMode() || ( pCrsr->HasMark() && 2260 *pCrsr->GetPoint() != *pCrsr->GetMark()) 2261 ? sal_True : sal_False ); 2262 } 2263 2264 2265 void SwCrsrShell::CallChgLnk() 2266 { 2267 // innerhalb von Start-/End-Action kein Call, sondern nur merken, 2268 // das sich etwas geaendert hat. Wird bei EndAction beachtet. 2269 if( BasicActionPend() ) 2270 bChgCallFlag = sal_True; // das Change merken 2271 else if( aChgLnk.IsSet() ) 2272 { 2273 if( bCallChgLnk ) 2274 aChgLnk.Call( this ); 2275 bChgCallFlag = sal_False; // Flag zuruecksetzen 2276 } 2277 } 2278 2279 // returne den am akt.Cursor selektierten Text eines Nodes. 2280 2281 2282 String SwCrsrShell::GetSelTxt() const 2283 { 2284 String aTxt; 2285 if( pCurCrsr->GetPoint()->nNode.GetIndex() == 2286 pCurCrsr->GetMark()->nNode.GetIndex() ) 2287 { 2288 SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode(); 2289 if( pTxtNd ) 2290 { 2291 xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex(); 2292 aTxt = pTxtNd->GetExpandTxt( nStt, 2293 pCurCrsr->End()->nContent.GetIndex() - nStt ); 2294 } 2295 } 2296 return aTxt; 2297 } 2298 2299 // gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde) 2300 2301 2302 String SwCrsrShell::GetText() const 2303 { 2304 String aTxt; 2305 if( pCurCrsr->GetPoint()->nNode.GetIndex() == 2306 pCurCrsr->GetMark()->nNode.GetIndex() ) 2307 { 2308 SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode(); 2309 if( pTxtNd ) 2310 aTxt = pTxtNd->GetTxt().Copy( 2311 pCurCrsr->GetPoint()->nContent.GetIndex() ); 2312 } 2313 return aTxt; 2314 } 2315 2316 // hole vom Start/Ende der akt. SSelection das nte Zeichen 2317 sal_Unicode SwCrsrShell::GetChar( sal_Bool bEnd, long nOffset ) 2318 { 2319 if( IsTableMode() ) // im TabelleMode nicht moeglich 2320 return 0; 2321 2322 const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint() 2323 : bEnd ? pCurCrsr->End() : pCurCrsr->Start(); 2324 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode(); 2325 if( !pTxtNd ) 2326 return 0; 2327 2328 xub_StrLen nPos = pPos->nContent.GetIndex(); 2329 const String& rStr = pTxtNd->GetTxt(); 2330 sal_Unicode cCh = 0; 2331 2332 if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() ) 2333 cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) ); 2334 2335 return cCh; 2336 } 2337 2338 // erweiter die akt. SSelection am Anfang/Ende um n Zeichen 2339 2340 2341 sal_Bool SwCrsrShell::ExtendSelection( sal_Bool bEnd, xub_StrLen nCount ) 2342 { 2343 if( !pCurCrsr->HasMark() || IsTableMode() ) 2344 return sal_False; // keine Selektion 2345 2346 SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start(); 2347 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode(); 2348 ASSERT( pTxtNd, "kein TextNode, wie soll erweitert werden?" ); 2349 2350 xub_StrLen nPos = pPos->nContent.GetIndex(); 2351 if( bEnd ) 2352 { 2353 if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() ) 2354 nPos = nPos + nCount; 2355 else 2356 return sal_False; // nicht mehr moeglich 2357 } 2358 else if( nPos >= nCount ) 2359 nPos = nPos - nCount; 2360 else 2361 return sal_False; // nicht mehr moeglich 2362 2363 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, 2364 2365 pPos->nContent = nPos; 2366 UpdateCrsr(); 2367 2368 return sal_True; 2369 } 2370 2371 // setze nur den sichtbaren Cursor an die angegebene Dokument-Pos. 2372 // returnt sal_False: wenn der SPoint vom Layout korrigiert wurde. 2373 2374 sal_Bool SwCrsrShell::SetVisCrsr( const Point &rPt ) 2375 { 2376 SET_CURR_SHELL( this ); 2377 Point aPt( rPt ); 2378 SwPosition aPos( *pCurCrsr->GetPoint() ); 2379 SwCrsrMoveState aTmpState( MV_SETONLYTEXT ); 2380 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 2381 aTmpState.bRealHeight = sal_True; 2382 2383 sal_Bool bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ ); 2384 2385 SetInFrontOfLabel( sal_False ); // #i27615# 2386 2387 // nur in TextNodes anzeigen !! 2388 SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode(); 2389 if( !pTxtNd ) 2390 return sal_False; 2391 2392 const SwSectionNode* pSectNd = pTxtNd->FindSectionNode(); 2393 if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() || 2394 ( !IsReadOnlyAvailable() && 2395 pSectNd->GetSection().IsProtectFlag())) ) 2396 return sal_False; 2397 2398 SwCntntFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, &aPos ); 2399 if ( Imp()->IsIdleAction() ) 2400 pFrm->PrepareCrsr(); 2401 SwRect aTmp( aCharRect ); 2402 2403 pFrm->GetCharRect( aCharRect, aPos, &aTmpState ); 2404 // ALIGNRECT( aCharRect ); 2405 2406 if( aTmp == aCharRect && // BUG 10137: bleibt der Cursor auf der 2407 pVisCrsr->IsVisible() ) // Position nicht hidden & showen 2408 return sal_True; 2409 2410 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken 2411 if( IsScrollMDI( this, aCharRect )) 2412 { 2413 MakeVisible( aCharRect ); 2414 pCurCrsr->Show(); 2415 } 2416 2417 // Bug 29584: bei Rahmenselektion ist der Cursor versteckt, aber den 2418 // D&D-Cursor will man trotzdem haben 2419 // if( bSVCrsrVis ) 2420 { 2421 if( aTmpState.bRealHeight ) 2422 aCrsrHeight = aTmpState.aRealHeight; 2423 else 2424 { 2425 aCrsrHeight.X() = 0; 2426 aCrsrHeight.Y() = aCharRect.Height(); 2427 } 2428 2429 pVisCrsr->SetDragCrsr( sal_True ); 2430 pVisCrsr->Show(); // wieder anzeigen 2431 } 2432 return bRet; 2433 } 2434 2435 sal_Bool SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const 2436 { 2437 Point aPt( rPt ); 2438 SwPaM aPam( *pCurCrsr->GetPoint() ); 2439 GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt ); 2440 return aPam.HasReadonlySel( GetViewOptions()->IsFormView() ); 2441 } 2442 2443 2444 // returne die Anzahl der Cursor im Ring (Flag besagt ob man nur 2445 // aufgepspannte haben will - sprich etwas selektiert ist (Basic)) 2446 sal_uInt16 SwCrsrShell::GetCrsrCnt( sal_Bool bAll ) const 2447 { 2448 Ring* pTmp = GetCrsr()->GetNext(); 2449 sal_uInt16 n = (bAll || ( pCurCrsr->HasMark() && 2450 *pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0; 2451 while( pTmp != pCurCrsr ) 2452 { 2453 if( bAll || ( ((SwPaM*)pTmp)->HasMark() && 2454 *((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark())) 2455 ++n; 2456 pTmp = pTmp->GetNext(); 2457 } 2458 return n; 2459 } 2460 2461 2462 sal_Bool SwCrsrShell::IsStartOfDoc() const 2463 { 2464 if( pCurCrsr->GetPoint()->nContent.GetIndex() ) 2465 return sal_False; 2466 2467 // Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd) 2468 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 ); 2469 if( !aIdx.GetNode().IsCntntNode() ) 2470 GetDoc()->GetNodes().GoNext( &aIdx ); 2471 return aIdx == pCurCrsr->GetPoint()->nNode; 2472 } 2473 2474 2475 sal_Bool SwCrsrShell::IsEndOfDoc() const 2476 { 2477 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 ); 2478 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode(); 2479 if( !pCNd ) 2480 pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx ); 2481 2482 return aIdx == pCurCrsr->GetPoint()->nNode && 2483 pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex(); 2484 } 2485 2486 2487 // loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten 2488 // Cursor auf seinen TextNode (oder StartNode?). 2489 // Beim naechsten ::GetCrsr werden sie wieder alle erzeugt 2490 // Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt. 2491 sal_Bool SwCrsrShell::ParkTblCrsr() 2492 { 2493 if( !pTblCrsr ) 2494 return sal_False; 2495 2496 pTblCrsr->ParkCrsr(); 2497 2498 while( pCurCrsr->GetNext() != pCurCrsr ) 2499 delete pCurCrsr->GetNext(); 2500 2501 // vom Cursor !immer! SPoint und Mark umsetzen 2502 pCurCrsr->SetMark(); 2503 *pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint(); 2504 pCurCrsr->DeleteMark(); 2505 2506 return sal_True; 2507 } 2508 2509 /*********************************************************************** 2510 #* Class : SwCrsrShell 2511 #* Methode : ParkCrsr 2512 #* Beschreibung: Vernichtet Selektionen und zus. Crsr aller Shell der 2513 #* verbleibende Crsr der Shell wird geparkt. 2514 #* Datum : MA 05. Nov. 92 2515 #* Update : JP 19.09.97 2516 #***********************************************************************/ 2517 2518 void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing ) 2519 { 2520 const SwPosition *pStt = pDelRg->Start(), 2521 *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint(); 2522 2523 SwPaM *pTmpDel = 0, *pTmp = *ppDelRing; 2524 2525 // durchsuche den gesamten Ring 2526 sal_Bool bGoNext; 2527 do { 2528 const SwPosition *pTmpStt = pTmp->Start(), 2529 *pTmpEnd = pTmp->GetPoint() == pTmpStt ? 2530 pTmp->GetMark() : pTmp->GetPoint(); 2531 /* 2532 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich 2533 * muss der alte Bereich aufgehoben werden. 2534 * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum 2535 * Bereich gehoert ! 2536 */ 2537 if( *pStt <= *pTmpStt ) 2538 { 2539 if( *pEnd > *pTmpStt || 2540 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd )) 2541 pTmpDel = pTmp; 2542 } 2543 else 2544 if( *pStt < *pTmpEnd ) 2545 pTmpDel = pTmp; 2546 2547 bGoNext = sal_True; 2548 if( pTmpDel ) // ist der Pam im Bereich ?? loesche ihn 2549 { 2550 sal_Bool bDelete = sal_True; 2551 if( *ppDelRing == pTmpDel ) 2552 { 2553 if( *ppDelRing == pCurCrsr ) 2554 { 2555 if( sal_True == ( bDelete = GoNextCrsr() )) 2556 { 2557 bGoNext = sal_False; 2558 pTmp = (SwPaM*)pTmp->GetNext(); 2559 } 2560 } 2561 else 2562 bDelete = sal_False; // StackCrsr nie loeschen !! 2563 } 2564 2565 if( bDelete ) 2566 delete pTmpDel; // hebe alten Bereich auf 2567 else 2568 { 2569 pTmpDel->GetPoint()->nContent.Assign( 0, 0 ); 2570 pTmpDel->GetPoint()->nNode = 0; 2571 pTmpDel->SetMark(); 2572 pTmpDel->DeleteMark(); 2573 } 2574 pTmpDel = 0; 2575 } 2576 else if( !pTmp->HasMark() ) // sorge auf jedenfall dafuer, das 2577 { // nicht benutzte Indizies beachtet werden! 2578 pTmp->SetMark(); // SPoint liegt nicht im Bereich, 2579 pTmp->DeleteMark(); // aber vielleicht GetMark, also setzen 2580 } 2581 if( bGoNext ) 2582 pTmp = (SwPaM*)pTmp->GetNext(); 2583 } while( !bGoNext || *ppDelRing != pTmp ); 2584 } 2585 2586 void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx ) 2587 { 2588 SwNode *pNode = &rIdx.GetNode(); 2589 2590 // erzeuge einen neuen Pam 2591 SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() ); 2592 if( pNode->GetStartNode() ) 2593 { 2594 if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() ) 2595 { 2596 // der angegebene Node steht in einer Tabelle, also Parke 2597 // den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle) 2598 pNew->GetPoint()->nNode = *pNode->StartOfSectionNode(); 2599 } 2600 else // also auf dem StartNode selbst. 2601 // Dann immer ueber seinen EndNode den StartNode erfragen !!! 2602 // (StartOfSection vom StartNode ist der Parent !) 2603 pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode(); 2604 } 2605 else 2606 pNew->GetPoint()->nNode = *pNode->StartOfSectionNode(); 2607 pNew->SetMark(); 2608 pNew->GetPoint()->nNode = *pNode->EndOfSectionNode(); 2609 2610 //Alle Shells wollen etwas davon haben. 2611 ViewShell *pTmp = this; 2612 do { 2613 if( pTmp->IsA( TYPE( SwCrsrShell ))) 2614 { 2615 SwCrsrShell* pSh = (SwCrsrShell*)pTmp; 2616 if( pSh->pCrsrStk ) 2617 pSh->_ParkPams( pNew, &pSh->pCrsrStk ); 2618 2619 pSh->_ParkPams( pNew, &pSh->pCurCrsr ); 2620 if( pSh->pTblCrsr ) 2621 { 2622 // setze den Tabellen Cursor immer auf 0, den aktuellen 2623 // immer auf den Anfang der Tabelle 2624 SwPaM* pTCrsr = pSh->GetTblCrs(); 2625 SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode(); 2626 if ( pTblNd ) 2627 { 2628 pTCrsr->GetPoint()->nContent.Assign( 0, 0 ); 2629 pTCrsr->GetPoint()->nNode = 0; 2630 pTCrsr->SetMark(); 2631 pTCrsr->DeleteMark(); 2632 pSh->pCurCrsr->GetPoint()->nNode = *pTblNd; 2633 } 2634 } 2635 } 2636 } while ( this != (pTmp = (ViewShell*)pTmp->GetNext() )); 2637 delete pNew; 2638 } 2639 2640 //========================================================================= 2641 2642 /* 2643 * der Copy-Constructor 2644 * Cursor-Position kopieren, in den Ring eingetragen. 2645 * Alle Ansichten eines Dokumentes stehen im Ring der Shells. 2646 */ 2647 2648 SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin ) 2649 : ViewShell( rShell, pInitWin ), 2650 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ), 2651 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ), 2652 eMvState( MV_NONE ), 2653 // --> OD 2008-04-02 #refactorlists# 2654 sMarkedListId(), 2655 nMarkedListLevel( 0 ) 2656 // <-- 2657 { 2658 SET_CURR_SHELL( this ); 2659 // Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen 2660 pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) ); 2661 pCurCrsr->GetCntntNode()->Add( this ); 2662 2663 bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd = 2664 bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr = 2665 bOverwriteCrsr = sal_False; 2666 bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True; 2667 bSetCrsrInReadOnly = sal_True; 2668 pVisCrsr = new SwVisCrsr( this ); 2669 // UpdateCrsr( 0 ); 2670 // OD 11.02.2003 #100556# 2671 mbMacroExecAllowed = rShell.IsMacroExecAllowed(); 2672 oldColFrm = NULL; 2673 } 2674 2675 2676 /* 2677 * der normale Constructor 2678 */ 2679 2680 SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin, 2681 const SwViewOption *pInitOpt ) 2682 : ViewShell( rDoc, pInitWin, pInitOpt ), 2683 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ), 2684 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ), 2685 eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst 2686 // --> OD 2008-04-02 #refactorlists# 2687 sMarkedListId(), 2688 nMarkedListLevel( 0 ) 2689 // <-- 2690 { 2691 SET_CURR_SHELL( this ); 2692 /* 2693 * Erzeugen des initialen Cursors, wird auf die erste 2694 * Inhaltsposition gesetzt 2695 */ 2696 SwNodes& rNds = rDoc.GetNodes(); 2697 2698 SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() ); 2699 SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode 2700 2701 pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 ))); 2702 2703 // melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle 2704 // Attribut-Aenderungen ueber den Link weiter gemeldet werden. 2705 pCNd->Add( this ); 2706 2707 bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd = 2708 bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr = 2709 bOverwriteCrsr = sal_False; 2710 bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True; 2711 bSetCrsrInReadOnly = sal_True; 2712 2713 pVisCrsr = new SwVisCrsr( this ); 2714 // UpdateCrsr( 0 ); 2715 // OD 11.02.2003 #100556# 2716 mbMacroExecAllowed = true; 2717 } 2718 2719 2720 2721 SwCrsrShell::~SwCrsrShell() 2722 { 2723 // wenn es nicht die letzte View so sollte zu mindest das 2724 // Feld noch geupdatet werden. 2725 if( GetNext() != this ) 2726 CheckTblBoxCntnt( pCurCrsr->GetPoint() ); 2727 else 2728 ClearTblBoxCntnt(); 2729 2730 delete pVisCrsr; 2731 delete pBlockCrsr; 2732 delete pTblCrsr; 2733 2734 /* 2735 * Freigabe der Cursor 2736 */ 2737 while(pCurCrsr->GetNext() != pCurCrsr) 2738 delete pCurCrsr->GetNext(); 2739 delete pCurCrsr; 2740 2741 // Stack freigeben 2742 if( pCrsrStk ) 2743 { 2744 while( pCrsrStk->GetNext() != pCrsrStk ) 2745 delete pCrsrStk->GetNext(); 2746 delete pCrsrStk; 2747 } 2748 2749 // JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in 2750 // der CursorShell haengt keine Chance geben, sich an den 2751 // TextNode zu haengen. 2752 if( GetRegisteredIn() ) 2753 GetRegisteredInNonConst()->Remove( this ); 2754 } 2755 2756 SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock ) 2757 { 2758 if( pTblCrsr ) 2759 return pTblCrsr; 2760 if( pBlockCrsr && bBlock ) 2761 return &pBlockCrsr->getShellCrsr(); 2762 return pCurCrsr; 2763 } 2764 2765 //Sollte fuer das Clipboard der WaitPtr geschaltet werden? 2766 //Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen. 2767 2768 sal_Bool SwCrsrShell::ShouldWait() const 2769 { 2770 if ( IsTableMode() || GetCrsrCnt() > 1 ) 2771 return sal_True; 2772 2773 if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() ) 2774 return sal_True; 2775 2776 SwPaM* pPam = GetCrsr(); 2777 return pPam->Start()->nNode.GetIndex() + 10 < 2778 pPam->End()->nNode.GetIndex(); 2779 } 2780 2781 2782 sal_uInt16 SwCrsrShell::UpdateTblSelBoxes() 2783 { 2784 if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() )) 2785 GetLayout()->MakeTblCrsrs( *pTblCrsr ); 2786 return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0; 2787 } 2788 2789 // zeige das akt. selektierte "Object" an 2790 void SwCrsrShell::MakeSelVisible() 2791 { 2792 ASSERT( bHasFocus, "kein Focus aber Cursor sichtbar machen?" ); 2793 if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() ) 2794 { 2795 SwRect aTmp( aCharRect ); 2796 long nDiff = aCharRect.Height() - VisArea().Height(); 2797 if( nDiff < aCrsrHeight.X() ) 2798 aTmp.Top( nDiff + aCharRect.Top() ); 2799 else 2800 { 2801 aTmp.Top( aCrsrHeight.X() + aCharRect.Top() ); 2802 aTmp.Height( aCrsrHeight.Y() ); 2803 } 2804 if( !aTmp.HasArea() ) 2805 { 2806 aTmp.SSize().Height() += 1; 2807 aTmp.SSize().Width() += 1; 2808 } 2809 MakeVisible( aTmp ); 2810 } 2811 else 2812 { 2813 if( aCharRect.HasArea() ) 2814 MakeVisible( aCharRect ); 2815 else 2816 { 2817 SwRect aTmp( aCharRect ); 2818 aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1; 2819 MakeVisible( aTmp ); 2820 } 2821 } 2822 } 2823 2824 2825 // suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt) 2826 sal_Bool SwCrsrShell::FindValidCntntNode( sal_Bool bOnlyText ) 2827 { 2828 if( pTblCrsr ) // was soll ich jetzt machen ?? 2829 { 2830 ASSERT( !this, "TabellenSelection nicht aufgehoben!" ); 2831 return sal_False; 2832 } 2833 2834 //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt 2835 if( !bAllProtect && GetDoc()->GetDocShell() && 2836 GetDoc()->GetDocShell()->IsReadOnlyUI() ) 2837 return sal_True; 2838 2839 // dann raus da! 2840 if( pCurCrsr->HasMark() ) 2841 ClearMark(); 2842 2843 // als erstes mal auf Rahmen abpruefen 2844 SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode; 2845 sal_uLong nNdIdx = rNdIdx.GetIndex(); // sichern 2846 SwNodes& rNds = pDoc->GetNodes(); 2847 SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode(); 2848 const SwCntntFrm * pFrm; 2849 2850 if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetLayout(),0,pCurCrsr->GetPoint(),sal_False)) && 2851 !IsReadOnlyAvailable() && pFrm->IsProtected() && 2852 nNdIdx < rNds.GetEndOfExtras().GetIndex() ) 2853 { 2854 // geschuetzter Rahmen ueberspringen 2855 SwPaM aPam( *pCurCrsr->GetPoint() ); 2856 aPam.SetMark(); 2857 aPam.GetMark()->nNode = rNds.GetEndOfContent(); 2858 aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode(); 2859 2860 sal_Bool bFirst = sal_False; 2861 if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, sal_False ))) 2862 { 2863 aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode(); 2864 pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, sal_False ); 2865 } 2866 2867 if( !pCNd ) // sollte nie passieren !!! 2868 { 2869 rNdIdx = nNdIdx; // alten Node zurueck 2870 return sal_False; 2871 } 2872 *pCurCrsr->GetPoint() = *aPam.GetPoint(); 2873 } 2874 else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() ) 2875 { 2876 // dann auf den Anfang vom Doc stellen 2877 rNdIdx = pDoc->GetNodes().GetEndOfExtras(); 2878 pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext( 2879 &rNdIdx ), 0 ); 2880 nNdIdx = rNdIdx.GetIndex(); 2881 } 2882 2883 sal_Bool bOk = sal_True; 2884 2885 // #i9059# cursor may not stand in protected cells 2886 // (unless cursor in protected areas is OK.) 2887 const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode(); 2888 if( !IsReadOnlyAvailable() && 2889 pTableNode != NULL && rNdIdx.GetNode().IsProtect() ) 2890 { 2891 // we're in a table, and we're in a protected area, so we're 2892 // probably in a protected cell. 2893 2894 // move forward into non-protected area. 2895 SwPaM aPam( rNdIdx.GetNode(), 0 ); 2896 while( aPam.GetNode()->IsProtect() && 2897 aPam.Move( fnMoveForward, fnGoCntnt ) ) 2898 ; // nothing to do in the loop; the aPam.Move does the moving! 2899 2900 // didn't work? then go backwards! 2901 if( aPam.GetNode()->IsProtect() ) 2902 { 2903 SwPaM aTmpPaM( rNdIdx.GetNode(), 0 ); 2904 aPam = aTmpPaM; 2905 while( aPam.GetNode()->IsProtect() && 2906 aPam.Move( fnMoveBackward, fnGoCntnt ) ) 2907 ; // nothing to do in the loop; the aPam.Move does the moving! 2908 } 2909 2910 // if we're successful, set the new position 2911 if( ! aPam.GetNode()->IsProtect() ) 2912 { 2913 *pCurCrsr->GetPoint() = *aPam.GetPoint(); 2914 } 2915 } 2916 2917 // in einem geschuetzten Bereich 2918 const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode(); 2919 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() || 2920 ( !IsReadOnlyAvailable() && 2921 pSectNd->GetSection().IsProtectFlag() )) ) 2922 { 2923 typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const; 2924 FNGoSection funcGoSection = &SwNodes::GoNextSection; 2925 2926 bOk = sal_False; 2927 2928 for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt ) 2929 { 2930 sal_Bool bWeiter; 2931 do { 2932 bWeiter = sal_False; 2933 while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx, 2934 sal_True, !IsReadOnlyAvailable() )) ) 2935 { 2936 // in eine Tabelle verschoben -> pruefe ob die 2937 // vielleicht geschuetzt ist 2938 if( pCNd->FindTableNode() ) 2939 { 2940 SwCallLink aTmp( *this ); 2941 SwCrsrSaveState aSaveState( *pCurCrsr ); 2942 aTmp.nNdTyp = 0; // im DTOR nichts machen! 2943 if( !pCurCrsr->IsInProtectTable( sal_True, sal_True ) ) 2944 { 2945 const SwSectionNode* pSNd = pCNd->FindSectionNode(); 2946 if( !pSNd || !pSNd->GetSection().IsHiddenFlag() 2947 || (!IsReadOnlyAvailable() && 2948 pSNd->GetSection().IsProtectFlag() )) 2949 { 2950 bOk = sal_True; 2951 break; // eine nicht geschuetzte Zelle gef. 2952 } 2953 continue; // dann weiter suchen 2954 } 2955 } 2956 else 2957 { 2958 bOk = sal_True; 2959 break; // eine nicht geschuetzte Zelle gef. 2960 } 2961 } 2962 2963 if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() ) 2964 { 2965 // Teste mal auf Fly - kann auch noch geschuetzt sein!! 2966 if( 0 == (pFrm = pCNd->getLayoutFrm( GetLayout(),0,0,sal_False)) || 2967 ( !IsReadOnlyAvailable() && pFrm->IsProtected() ) || 2968 ( bOnlyText && pCNd->IsNoTxtNode() ) ) 2969 { 2970 // dann weiter suchen! 2971 bOk = sal_False; 2972 bWeiter = sal_True; 2973 } 2974 } 2975 } while( bWeiter ); 2976 2977 if( !bOk ) 2978 { 2979 if( !nLoopCnt ) 2980 funcGoSection = &SwNodes::GoPrevSection; 2981 rNdIdx = nNdIdx; 2982 } 2983 } 2984 } 2985 if( bOk ) 2986 { 2987 pCNd = rNdIdx.GetNode().GetCntntNode(); 2988 // sal_uInt16 nCntnt = Min( pCNd->Len(), pCurCrsr->GetPoint()->nContent.GetIndex() ); 2989 xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0; 2990 pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt ); 2991 } 2992 else 2993 { 2994 pCNd = rNdIdx.GetNode().GetCntntNode(); 2995 2996 // falls Cursor im versteckten Bereich ist, auf jedenfall schon mal 2997 // verschieben!! 2998 if( !pCNd || !pCNd->getLayoutFrm( GetLayout(),0,0,sal_False) ) 2999 { 3000 SwCrsrMoveState aTmpState( MV_NONE ); 3001 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 3002 GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(), 3003 &aTmpState ); 3004 } 3005 } 3006 return bOk; 3007 } 3008 3009 3010 sal_Bool SwCrsrShell::IsCrsrReadonly() const 3011 { 3012 if ( GetViewOptions()->IsReadonly() || 3013 GetViewOptions()->IsFormView() ) // Formular view 3014 { 3015 SwFrm *pFrm = GetCurrFrm( sal_False ); 3016 const SwFlyFrm* pFly; 3017 const SwSection* pSection; 3018 3019 if( pFrm && pFrm->IsInFly() && 3020 (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() && 3021 pFly->Lower() && 3022 !pFly->Lower()->IsNoTxtFrm() && 3023 !GetDrawView()->GetMarkedObjectList().GetMarkCount() ) 3024 { 3025 return sal_False; 3026 } 3027 // edit in readonly sections 3028 else if ( pFrm && pFrm->IsInSct() && 3029 0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) && 3030 pSection->IsEditInReadonlyFlag() ) 3031 { 3032 return sal_False; 3033 } 3034 else if ( !IsMultiSelection() && CrsrInsideInputFld() ) 3035 { 3036 return sal_False; 3037 } 3038 3039 return sal_True; 3040 } 3041 return sal_False; 3042 } 3043 3044 3045 // darf der Cursor in ReadOnlyBereiche? 3046 void SwCrsrShell::SetReadOnlyAvailable( sal_Bool bFlag ) 3047 { 3048 // im GlobalDoc darf NIE umgeschaltet werden 3049 if( (!GetDoc()->GetDocShell() || 3050 !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) && 3051 bFlag != bSetCrsrInReadOnly ) 3052 { 3053 // wenn das Flag ausgeschaltet wird, dann muessen erstmal alle 3054 // Selektionen aufgehoben werden. Denn sonst wird sich darauf 3055 // verlassen, das nichts geschuetztes selektiert ist! 3056 if( !bFlag ) 3057 { 3058 ClearMark(); 3059 } 3060 bSetCrsrInReadOnly = bFlag; 3061 UpdateCrsr(); 3062 } 3063 } 3064 3065 sal_Bool SwCrsrShell::HasReadonlySel() const 3066 { 3067 sal_Bool bRet = sal_False; 3068 if ( IsReadOnlyAvailable() || GetViewOptions()->IsFormView() ) 3069 { 3070 if ( pTblCrsr != NULL ) 3071 { 3072 bRet = pTblCrsr->HasReadOnlyBoxSel() 3073 || pTblCrsr->HasReadonlySel( GetViewOptions()->IsFormView() ); 3074 } 3075 else 3076 { 3077 const SwPaM* pCrsr = pCurCrsr; 3078 3079 do 3080 { 3081 if ( pCrsr->HasReadonlySel( GetViewOptions()->IsFormView() ) ) 3082 { 3083 bRet = sal_True; 3084 } 3085 3086 pCrsr = (SwPaM*)pCrsr->GetNext(); 3087 } while ( !bRet && pCrsr != pCurCrsr ); 3088 } 3089 } 3090 return bRet; 3091 } 3092 3093 sal_Bool SwCrsrShell::IsSelFullPara() const 3094 { 3095 sal_Bool bRet = sal_False; 3096 3097 if( pCurCrsr->GetPoint()->nNode.GetIndex() == 3098 pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() ) 3099 { 3100 xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(), 3101 nEnd = pCurCrsr->GetMark()->nContent.GetIndex(); 3102 if( nStt > nEnd ) 3103 { 3104 xub_StrLen nTmp = nStt; 3105 nStt = nEnd; 3106 nEnd = nTmp; 3107 } 3108 const SwCntntNode* pCNd = pCurCrsr->GetCntntNode(); 3109 bRet = pCNd && !nStt && nEnd == pCNd->Len(); 3110 } 3111 return bRet; 3112 } 3113 3114 short SwCrsrShell::GetTextDirection( const Point* pPt ) const 3115 { 3116 SwPosition aPos( *pCurCrsr->GetPoint() ); 3117 Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() ); 3118 if( pPt ) 3119 { 3120 SwCrsrMoveState aTmpState( MV_NONE ); 3121 aTmpState.bSetInReadOnly = IsReadOnlyAvailable(); 3122 3123 GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState ); 3124 } 3125 3126 return pDoc->GetTextDirection( aPos, &aPt ); 3127 } 3128 3129 sal_Bool SwCrsrShell::IsInVerticalText( const Point* pPt ) const 3130 { 3131 const short nDir = GetTextDirection( pPt ); 3132 return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir; 3133 } 3134 3135 sal_Bool SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const 3136 { 3137 const short nDir = GetTextDirection( pPt ); 3138 // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in 3139 // vertical environment 3140 return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir; 3141 } 3142 3143 // 3144 // If the current cursor position is inside a hidden range, the hidden range 3145 // is selected: 3146 // 3147 bool SwCrsrShell::SelectHiddenRange() 3148 { 3149 bool bRet = false; 3150 if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() ) 3151 { 3152 SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint(); 3153 const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode(); 3154 if ( pNode ) 3155 { 3156 const xub_StrLen nPos = rPt.nContent.GetIndex(); 3157 3158 // check if nPos is in hidden range 3159 xub_StrLen nHiddenStart; 3160 xub_StrLen nHiddenEnd; 3161 SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd ); 3162 if ( STRING_LEN != nHiddenStart ) 3163 { 3164 // make selection: 3165 pCurCrsr->SetMark(); 3166 pCurCrsr->GetMark()->nContent = nHiddenEnd; 3167 bRet = true; 3168 } 3169 } 3170 } 3171 3172 return bRet; 3173 } 3174 3175 /* */ 3176 3177 // die Suchfunktionen 3178 sal_uLong SwCrsrShell::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes, 3179 SwDocPositions eStart, SwDocPositions eEnde, 3180 sal_Bool& bCancel, 3181 FindRanges eRng, int bReplace ) 3182 { 3183 if( pTblCrsr ) 3184 GetCrsr(); 3185 delete pTblCrsr, pTblCrsr = 0; 3186 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 3187 sal_uLong nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace ); 3188 if( nRet || bCancel ) 3189 UpdateCrsr(); 3190 return nRet; 3191 } 3192 3193 sal_uLong SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl, 3194 SwDocPositions eStart, SwDocPositions eEnde, 3195 sal_Bool& bCancel, 3196 FindRanges eRng, const SwTxtFmtColl* pReplFmt ) 3197 { 3198 if( pTblCrsr ) 3199 GetCrsr(); 3200 delete pTblCrsr, pTblCrsr = 0; 3201 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 3202 sal_uLong nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt ); 3203 if( nRet ) 3204 UpdateCrsr(); 3205 return nRet; 3206 } 3207 3208 sal_uLong SwCrsrShell::Find( const SfxItemSet& rSet, sal_Bool bNoCollections, 3209 SwDocPositions eStart, SwDocPositions eEnde, 3210 sal_Bool& bCancel, 3211 FindRanges eRng, const SearchOptions* pSearchOpt, 3212 const SfxItemSet* rReplSet ) 3213 { 3214 if( pTblCrsr ) 3215 GetCrsr(); 3216 delete pTblCrsr, pTblCrsr = 0; 3217 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 3218 sal_uLong nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel, 3219 eRng, pSearchOpt, rReplSet ); 3220 if( nRet ) 3221 UpdateCrsr(); 3222 return nRet; 3223 } 3224 3225 void SwCrsrShell::SetSelection( const SwPaM& rCrsr ) 3226 { 3227 StartAction(); 3228 SwPaM* pCrsr = GetCrsr(); 3229 *pCrsr->GetPoint() = *rCrsr.GetPoint(); 3230 if(rCrsr.HasMark()) 3231 { 3232 pCrsr->SetMark(); 3233 *pCrsr->GetMark() = *rCrsr.GetMark(); 3234 } 3235 if((SwPaM*)rCrsr.GetNext() != &rCrsr) 3236 { 3237 const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext(); 3238 do 3239 { 3240 SwPaM* pCurrentCrsr = CreateCrsr(); 3241 *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint(); 3242 if(_pStartCrsr->HasMark()) 3243 { 3244 pCurrentCrsr->SetMark(); 3245 *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark(); 3246 } 3247 } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr ); 3248 } 3249 EndAction(); 3250 } 3251 3252 void lcl_RemoveMark( SwPaM* pPam ) 3253 { 3254 ASSERT( pPam->HasMark(), "Don't remove pPoint!" ) 3255 pPam->GetMark()->nContent.Assign( 0, 0 ); 3256 pPam->GetMark()->nNode = 0; 3257 pPam->DeleteMark(); 3258 } 3259 3260 const SwStartNode* lcl_NodeContext( const SwNode& rNode ) 3261 { 3262 const SwStartNode *pRet = rNode.StartOfSectionNode(); 3263 while( pRet->IsSectionNode() || pRet->IsTableNode() || 3264 pRet->GetStartNodeType() == SwTableBoxStartNode ) 3265 { 3266 pRet = pRet->StartOfSectionNode(); 3267 } 3268 return pRet; 3269 } 3270 3271 /** 3272 Checks if a position is valid. To be valid the position's node must 3273 be a content node and the content must not be unregistered. 3274 3275 @param aPos the position to check. 3276 */ 3277 bool lcl_PosOk(const SwPosition & aPos) 3278 { 3279 return NULL != aPos.nNode.GetNode().GetCntntNode() && 3280 SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg(); 3281 } 3282 3283 /** 3284 Checks if a PaM is valid. For a PaM to be valid its point must be 3285 valid. Additionally if the PaM has a mark this has to be valid, too. 3286 3287 @param aPam the PaM to check 3288 */ 3289 static bool lcl_CrsrOk(SwPaM & aPam) 3290 { 3291 return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark() 3292 || lcl_PosOk(*aPam.GetMark())); 3293 } 3294 3295 void SwCrsrShell::ClearUpCrsrs() 3296 { 3297 // start of the ring 3298 SwPaM * pStartCrsr = GetCrsr(); 3299 // start loop with second entry of the ring 3300 SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext(); 3301 SwPaM * pTmpCrsr; 3302 bool bChanged = false; 3303 3304 /* 3305 For all entries in the ring except the start entry delete the 3306 entry if it is invalid. 3307 */ 3308 while (pCrsr != pStartCrsr) 3309 { 3310 pTmpCrsr = (SwPaM *) pCrsr->GetNext(); 3311 3312 if ( ! lcl_CrsrOk(*pCrsr)) 3313 { 3314 delete pCrsr; 3315 3316 bChanged = true; 3317 } 3318 3319 pCrsr = pTmpCrsr; 3320 } 3321 3322 if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) ) 3323 { 3324 lcl_RemoveMark( pStartCrsr ); 3325 bChanged = true; 3326 } 3327 if( !lcl_PosOk( *pStartCrsr->GetPoint() ) ) 3328 { 3329 SwNodes & aNodes = GetDoc()->GetNodes(); 3330 const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() ); 3331 SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode ); 3332 SwNode * pNode = aNodes.GoPrevious(&aIdx); 3333 if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart ) 3334 aNodes.GoNext( &aIdx ); 3335 if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart ) 3336 { 3337 /* 3338 If the start entry of the ring is invalid replace it with a 3339 cursor pointing to the beginning of the first content node in 3340 the document. 3341 */ 3342 aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode())); 3343 pNode = aNodes.GoNext( &aIdx ); 3344 } 3345 bool bFound = (pNode != NULL); 3346 3347 ASSERT(bFound, "no content node found"); 3348 3349 if (bFound) 3350 { 3351 SwPaM aTmpPam(*pNode); 3352 *pStartCrsr = aTmpPam; 3353 } 3354 3355 bChanged = true; 3356 } 3357 3358 /* 3359 If at least one of the cursors in the ring have been deleted or 3360 replaced, remove the table cursor. 3361 */ 3362 if (pTblCrsr != NULL && bChanged) 3363 TblCrsrToCursor(); 3364 } 3365 3366 // #111827# 3367 String SwCrsrShell::GetCrsrDescr() const 3368 { 3369 String aResult; 3370 3371 if (IsMultiSelection()) 3372 aResult += String(SW_RES(STR_MULTISEL)); 3373 else 3374 aResult = GetDoc()->GetPaMDescr(*GetCrsr()); 3375 3376 return aResult; 3377 } 3378 3379 // SMARTTAGS 3380 3381 void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes, 3382 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps, 3383 const SwWrongList& rSmartTagList, xub_StrLen nCurrent ) 3384 { 3385 // Insert smart tag information 3386 std::vector< rtl::OUString > aSmartTagTypes; 3387 std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps; 3388 3389 for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i ) 3390 { 3391 const xub_StrLen nSTPos = rSmartTagList.Pos( i ); 3392 const xub_StrLen nSTLen = rSmartTagList.Len( i ); 3393 3394 if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen ) 3395 { 3396 const SwWrongArea* pArea = rSmartTagList.GetElement( i ); 3397 if ( pArea ) 3398 { 3399 aSmartTagTypes.push_back( pArea->maType ); 3400 aStringKeyMaps.push_back( pArea->mxPropertyBag ); 3401 } 3402 } 3403 } 3404 3405 if ( aSmartTagTypes.size() ) 3406 { 3407 rSmartTagTypes.realloc( aSmartTagTypes.size() ); 3408 rStringKeyMaps.realloc( aSmartTagTypes.size() ); 3409 3410 std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin(); 3411 sal_uInt16 i = 0; 3412 for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter ) 3413 rSmartTagTypes[i++] = *aTypesIter; 3414 3415 std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin(); 3416 i = 0; 3417 for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter ) 3418 rStringKeyMaps[i++] = *aMapsIter; 3419 } 3420 } 3421 3422 void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange, 3423 SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen ) 3424 { 3425 // create SwPosition for nStartIndex 3426 SwIndex aIndex( &rNode, nBegin ); 3427 SwPosition aStartPos( rNode, aIndex ); 3428 3429 // create SwPosition for nEndIndex 3430 SwPosition aEndPos( aStartPos ); 3431 aEndPos.nContent = nBegin + nLen; 3432 3433 const uno::Reference<text::XTextRange> xRange = 3434 SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos); 3435 3436 rRange = xRange; 3437 } 3438 3439 void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes, 3440 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps, 3441 uno::Reference< text::XTextRange>& rRange ) const 3442 { 3443 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() ) 3444 return; 3445 3446 SwPaM* pCrsr = GetCrsr(); 3447 SwPosition aPos( *pCrsr->GetPoint() ); 3448 SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode(); 3449 if ( pNode && !pNode->IsInProtectSect() ) 3450 { 3451 const SwWrongList *pSmartTagList = pNode->GetSmartTags(); 3452 if ( pSmartTagList ) 3453 { 3454 xub_StrLen nCurrent = aPos.nContent.GetIndex(); 3455 xub_StrLen nBegin = nCurrent; 3456 xub_StrLen nLen = 1; 3457 3458 if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) ) 3459 { 3460 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin ); 3461 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex ); 3462 if ( pSubList ) 3463 { 3464 pSmartTagList = pSubList; 3465 nCurrent = 0; 3466 } 3467 3468 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent ); 3469 lcl_FillTextRange( rRange, *pNode, nBegin, nLen ); 3470 } 3471 } 3472 } 3473 } 3474 3475 // see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect ) 3476 void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect, 3477 uno::Sequence< rtl::OUString >& rSmartTagTypes, 3478 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps, 3479 uno::Reference<text::XTextRange>& rRange ) 3480 { 3481 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() ) 3482 return; 3483 3484 SwPaM* pCrsr = GetCrsr(); 3485 SwPosition aPos( *pCrsr->GetPoint() ); 3486 Point aPt( rPt ); 3487 SwCrsrMoveState eTmpState( MV_SETONLYTEXT ); 3488 SwSpecialPos aSpecialPos; 3489 eTmpState.pSpecialPos = &aSpecialPos; 3490 SwTxtNode *pNode; 3491 const SwWrongList *pSmartTagList; 3492 3493 if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) && 3494 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) && 3495 0 != (pSmartTagList = pNode->GetSmartTags()) && 3496 !pNode->IsInProtectSect() ) 3497 { 3498 xub_StrLen nCurrent = aPos.nContent.GetIndex(); 3499 xub_StrLen nBegin = nCurrent; 3500 xub_StrLen nLen = 1; 3501 3502 if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) ) 3503 { 3504 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin ); 3505 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex ); 3506 if ( pSubList ) 3507 { 3508 pSmartTagList = pSubList; 3509 nCurrent = eTmpState.pSpecialPos->nCharOfst; 3510 } 3511 3512 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent ); 3513 lcl_FillTextRange( rRange, *pNode, nBegin, nLen ); 3514 3515 // get smarttag word 3516 String aText( pNode->GetTxt().Copy( nBegin, nLen ) ); 3517 3518 //save the start and end positons of the line and the starting point 3519 Push(); 3520 LeftMargin(); 3521 xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex(); 3522 RightMargin(); 3523 xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex(); 3524 Pop(sal_False); 3525 3526 // make sure the selection build later from the 3527 // data below does not include footnotes and other 3528 // "in word" character to the left and right in order 3529 // to preserve those. Therefore count those "in words" 3530 // in order to modify the selection accordingly. 3531 const sal_Unicode* pChar = aText.GetBuffer(); 3532 xub_StrLen nLeft = 0; 3533 while (pChar && *pChar++ == CH_TXTATR_INWORD) 3534 ++nLeft; 3535 pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0; 3536 xub_StrLen nRight = 0; 3537 while (pChar && *pChar-- == CH_TXTATR_INWORD) 3538 ++nRight; 3539 3540 aPos.nContent = nBegin + nLeft; 3541 pCrsr = GetCrsr(); 3542 *pCrsr->GetPoint() = aPos; 3543 pCrsr->SetMark(); 3544 ExtendSelection( sal_True, nLen - nLeft - nRight ); 3545 //no determine the rectangle in the current line 3546 xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft; 3547 //take one less than the line end - otherwise the next line would be calculated 3548 xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight); 3549 Push(); 3550 pCrsr->DeleteMark(); 3551 SwIndex& rContent = GetCrsr()->GetPoint()->nContent; 3552 rContent = nWordStart; 3553 SwRect aStartRect; 3554 SwCrsrMoveState aState; 3555 aState.bRealWidth = sal_True; 3556 SwCntntNode* pCntntNode = pCrsr->GetCntntNode(); 3557 SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), &rPt, pCrsr->GetPoint(), sal_False); 3558 3559 pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState ); 3560 rContent = nWordEnd; 3561 SwRect aEndRect; 3562 pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState ); 3563 rSelectRect = aStartRect.Union( aEndRect ); 3564 Pop(sal_False); 3565 } 3566 } 3567 } 3568 3569