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 <hintids.hxx> 27 #include <hints.hxx> 28 #include <svl/ctloptions.hxx> 29 #include <sfx2/printer.hxx> 30 #include <sfx2/sfxuno.hxx> 31 #include <editeng/langitem.hxx> 32 #include <editeng/lspcitem.hxx> 33 #include <editeng/lrspitem.hxx> 34 #include <editeng/ulspitem.hxx> 35 #include <editeng/brshitem.hxx> 36 #include <editeng/pgrditem.hxx> 37 #include <swmodule.hxx> 38 #include <SwSmartTagMgr.hxx> 39 #include <doc.hxx> // GetDoc() 40 #include "rootfrm.hxx" 41 #include <pagefrm.hxx> // InvalidateSpelling 42 #include <rootfrm.hxx> 43 #include <viewsh.hxx> // ViewShell 44 #include <pam.hxx> // SwPosition 45 #include <ndtxt.hxx> // SwTxtNode 46 #include <txtatr.hxx> 47 #include <paratr.hxx> 48 #include <viewopt.hxx> 49 #include <dflyobj.hxx> 50 #include <flyfrm.hxx> 51 #include <tabfrm.hxx> 52 #include <frmtool.hxx> 53 #include <pagedesc.hxx> // SwPageDesc 54 #include <tgrditem.hxx> 55 #include <dbg_lay.hxx> 56 #include <fmtfld.hxx> 57 #include <fmtftn.hxx> 58 #include <txtfld.hxx> 59 #include <txtftn.hxx> 60 #include <charatr.hxx> 61 #include <ftninfo.hxx> 62 #include <fmtline.hxx> 63 #include <txtfrm.hxx> // SwTxtFrm 64 #include <sectfrm.hxx> // SwSectFrm 65 #include <txtcfg.hxx> // DBG_LOOP 66 #include <itrform2.hxx> // Iteratoren 67 #include <widorp.hxx> // SwFrmBreak 68 #include <txtcache.hxx> 69 #include <fntcache.hxx> // GetLineSpace benutzt pLastFont 70 #include <SwGrammarMarkUp.hxx> 71 #include <lineinfo.hxx> 72 #include <SwPortionHandler.hxx> 73 #include <dcontact.hxx> 74 #include <sortedobjs.hxx> 75 #include <txtflcnt.hxx> // SwTxtFlyCnt 76 #include <fmtflcnt.hxx> // SwFmtFlyCnt 77 #include <fmtcntnt.hxx> // SwFmtCntnt 78 #include <numrule.hxx> 79 #include <swtable.hxx> 80 #include <fldupde.hxx> 81 #include <IGrammarContact.hxx> 82 #include <switerator.hxx> 83 84 #if OSL_DEBUG_LEVEL > 1 85 #include <txtpaint.hxx> // DbgRect 86 extern const sal_Char *GetPrepName( const enum PrepareHint ePrep ); 87 #endif 88 89 90 TYPEINIT1( SwTxtFrm, SwCntntFrm ); 91 92 // Switches width and height of the text frame 93 void SwTxtFrm::SwapWidthAndHeight() 94 { 95 if ( ! bIsSwapped ) 96 { 97 const long nPrtOfstX = Prt().Pos().X(); 98 Prt().Pos().X() = Prt().Pos().Y(); 99 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 100 if( IsVertLR() ) 101 Prt().Pos().Y() = nPrtOfstX; 102 else 103 Prt().Pos().Y() = Frm().Width() - ( nPrtOfstX + Prt().Width() ); 104 105 } 106 else 107 { 108 const long nPrtOfstY = Prt().Pos().Y(); 109 Prt().Pos().Y() = Prt().Pos().X(); 110 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 111 if( IsVertLR() ) 112 Prt().Pos().X() = nPrtOfstY; 113 else 114 Prt().Pos().X() = Frm().Height() - ( nPrtOfstY + Prt().Height() ); 115 } 116 117 const long nFrmWidth = Frm().Width(); 118 Frm().Width( Frm().Height() ); 119 Frm().Height( nFrmWidth ); 120 const long nPrtWidth = Prt().Width(); 121 Prt().Width( Prt().Height() ); 122 Prt().Height( nPrtWidth ); 123 124 bIsSwapped = ! bIsSwapped; 125 } 126 127 // Calculates the coordinates of a rectangle when switching from 128 // horizontal to vertical layout. 129 void SwTxtFrm::SwitchHorizontalToVertical( SwRect& rRect ) const 130 { 131 // calc offset inside frame 132 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 133 long nOfstX, nOfstY; 134 if ( IsVertLR() ) 135 { 136 nOfstX = rRect.Left() - Frm().Left(); 137 nOfstY = rRect.Top() - Frm().Top(); 138 } 139 else 140 { 141 nOfstX = rRect.Left() - Frm().Left(); 142 nOfstY = rRect.Top() + rRect.Height() - Frm().Top(); 143 } 144 145 const long nWidth = rRect.Width(); 146 const long nHeight = rRect.Height(); 147 148 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 149 if ( IsVertLR() ) 150 rRect.Left(Frm().Left() + nOfstY); 151 else 152 { 153 if ( bIsSwapped ) 154 rRect.Left( Frm().Left() + Frm().Height() - nOfstY ); 155 else 156 // frame is rotated 157 rRect.Left( Frm().Left() + Frm().Width() - nOfstY ); 158 } 159 160 rRect.Top( Frm().Top() + nOfstX ); 161 rRect.Width( nHeight ); 162 rRect.Height( nWidth ); 163 } 164 165 // Calculates the coordinates of a point when switching from 166 // horizontal to vertical layout. 167 void SwTxtFrm::SwitchHorizontalToVertical( Point& rPoint ) const 168 { 169 // calc offset inside frame 170 const long nOfstX = rPoint.X() - Frm().Left(); 171 const long nOfstY = rPoint.Y() - Frm().Top(); 172 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 173 if ( IsVertLR() ) 174 rPoint.X() = Frm().Left() + nOfstY; 175 else 176 { 177 if ( bIsSwapped ) 178 rPoint.X() = Frm().Left() + Frm().Height() - nOfstY; 179 else 180 // calc rotated coords 181 rPoint.X() = Frm().Left() + Frm().Width() - nOfstY; 182 } 183 184 rPoint.Y() = Frm().Top() + nOfstX; 185 } 186 187 // Calculates the a limit value when switching from 188 // horizontal to vertical layout. 189 long SwTxtFrm::SwitchHorizontalToVertical( long nLimit ) const 190 { 191 Point aTmp( 0, nLimit ); 192 SwitchHorizontalToVertical( aTmp ); 193 return aTmp.X(); 194 } 195 196 // Calculates the coordinates of a rectangle when switching from 197 // vertical to horizontal layout. 198 void SwTxtFrm::SwitchVerticalToHorizontal( SwRect& rRect ) const 199 { 200 long nOfstX; 201 202 // calc offset inside frame 203 204 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 205 if ( IsVertLR() ) 206 nOfstX = rRect.Left() - Frm().Left(); 207 else 208 { 209 if ( bIsSwapped ) 210 nOfstX = Frm().Left() + Frm().Height() - ( rRect.Left() + rRect.Width() ); 211 else 212 nOfstX = Frm().Left() + Frm().Width() - ( rRect.Left() + rRect.Width() ); 213 } 214 215 const long nOfstY = rRect.Top() - Frm().Top(); 216 const long nWidth = rRect.Height(); 217 const long nHeight = rRect.Width(); 218 219 // calc rotated coords 220 rRect.Left( Frm().Left() + nOfstY ); 221 rRect.Top( Frm().Top() + nOfstX ); 222 rRect.Width( nWidth ); 223 rRect.Height( nHeight ); 224 } 225 226 // Calculates the coordinates of a point when switching from 227 // vertical to horizontal layout. 228 void SwTxtFrm::SwitchVerticalToHorizontal( Point& rPoint ) const 229 { 230 long nOfstX; 231 232 // calc offset inside frame 233 234 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 235 if ( IsVertLR() ) 236 nOfstX = rPoint.X() - Frm().Left(); 237 else 238 { 239 if ( bIsSwapped ) 240 nOfstX = Frm().Left() + Frm().Height() - rPoint.X(); 241 else 242 nOfstX = Frm().Left() + Frm().Width() - rPoint.X(); 243 } 244 245 const long nOfstY = rPoint.Y() - Frm().Top(); 246 247 // calc rotated coords 248 rPoint.X() = Frm().Left() + nOfstY; 249 rPoint.Y() = Frm().Top() + nOfstX; 250 } 251 252 // Calculates the a limit value when switching from 253 // vertical to horizontal layout. 254 long SwTxtFrm::SwitchVerticalToHorizontal( long nLimit ) const 255 { 256 Point aTmp( nLimit, 0 ); 257 SwitchVerticalToHorizontal( aTmp ); 258 return aTmp.Y(); 259 } 260 261 SwFrmSwapper::SwFrmSwapper( const SwTxtFrm* pTxtFrm, sal_Bool bSwapIfNotSwapped ) 262 : pFrm( pTxtFrm ), bUndo( sal_False ) 263 { 264 if ( pFrm->IsVertical() && 265 ( ( bSwapIfNotSwapped && ! pFrm->IsSwapped() ) || 266 ( ! bSwapIfNotSwapped && pFrm->IsSwapped() ) ) ) 267 { 268 bUndo = sal_True; 269 ((SwTxtFrm*)pFrm)->SwapWidthAndHeight(); 270 } 271 } 272 273 SwFrmSwapper::~SwFrmSwapper() 274 { 275 if ( bUndo ) 276 ((SwTxtFrm*)pFrm)->SwapWidthAndHeight(); 277 } 278 279 void SwTxtFrm::SwitchLTRtoRTL( SwRect& rRect ) const 280 { 281 SWAP_IF_NOT_SWAPPED( this ) 282 283 long nWidth = rRect.Width(); 284 rRect.Left( 2 * ( Frm().Left() + Prt().Left() ) + 285 Prt().Width() - rRect.Right() - 1 ); 286 287 rRect.Width( nWidth ); 288 289 UNDO_SWAP( this ) 290 } 291 292 void SwTxtFrm::SwitchLTRtoRTL( Point& rPoint ) const 293 { 294 SWAP_IF_NOT_SWAPPED( this ) 295 296 rPoint.X() = 2 * ( Frm().Left() + Prt().Left() ) + Prt().Width() - rPoint.X() - 1; 297 298 UNDO_SWAP( this ) 299 } 300 301 SwLayoutModeModifier::SwLayoutModeModifier( const OutputDevice& rOutp ) : 302 rOut( rOutp ), nOldLayoutMode( rOutp.GetLayoutMode() ) 303 { 304 } 305 306 SwLayoutModeModifier::~SwLayoutModeModifier() 307 { 308 ((OutputDevice&)rOut).SetLayoutMode( nOldLayoutMode ); 309 } 310 311 void SwLayoutModeModifier::Modify( sal_Bool bChgToRTL ) 312 { 313 ((OutputDevice&)rOut).SetLayoutMode( bChgToRTL ? 314 TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL : 315 TEXT_LAYOUT_BIDI_STRONG ); 316 } 317 318 void SwLayoutModeModifier::SetAuto() 319 { 320 const sal_uLong nNewLayoutMode = nOldLayoutMode & ~TEXT_LAYOUT_BIDI_STRONG; 321 ((OutputDevice&)rOut).SetLayoutMode( nNewLayoutMode ); 322 } 323 324 SwDigitModeModifier::SwDigitModeModifier( const OutputDevice& rOutp, LanguageType eCurLang ) : 325 rOut( rOutp ), nOldLanguageType( rOutp.GetDigitLanguage() ) 326 { 327 LanguageType eLang = eCurLang; 328 const SvtCTLOptions::TextNumerals nTextNumerals = SW_MOD()->GetCTLOptions().GetCTLTextNumerals(); 329 330 if ( SvtCTLOptions::NUMERALS_HINDI == nTextNumerals ) 331 eLang = LANGUAGE_ARABIC_SAUDI_ARABIA; 332 else if ( SvtCTLOptions::NUMERALS_ARABIC == nTextNumerals ) 333 eLang = LANGUAGE_ENGLISH; 334 else if ( SvtCTLOptions::NUMERALS_SYSTEM == nTextNumerals ) 335 eLang = (LanguageType)::GetAppLanguage(); 336 337 ((OutputDevice&)rOut).SetDigitLanguage( eLang ); 338 } 339 340 SwDigitModeModifier::~SwDigitModeModifier() 341 { 342 ((OutputDevice&)rOut).SetDigitLanguage( nOldLanguageType ); 343 } 344 345 /************************************************************************* 346 * SwTxtFrm::Init() 347 *************************************************************************/ 348 349 void SwTxtFrm::Init() 350 { 351 ASSERT( !IsLocked(), "+SwTxtFrm::Init: this ist locked." ); 352 if( !IsLocked() ) 353 { 354 ClearPara(); 355 ResetBlinkPor(); 356 //Die Flags direkt setzen um ResetPreps und damit ein unnuetzes GetPara 357 //einzusparen. 358 // Nicht bOrphan, bLocked oder bWait auf sal_False setzen ! 359 // bOrphan = bFlag7 = bFlag8 = sal_False; 360 } 361 } 362 363 /************************************************************************* 364 |* SwTxtFrm::CTORen/DTOR 365 |*************************************************************************/ 366 367 void SwTxtFrm::InitCtor() 368 { 369 nCacheIdx = MSHRT_MAX; 370 nOfst = 0; 371 nAllLines = 0; 372 nThisLines = 0; 373 mnFlyAnchorOfst = 0; 374 mnFlyAnchorOfstNoWrap = 0; 375 mnFtnLine = 0; 376 // OD 2004-03-17 #i11860# 377 mnHeightOfLastLine = 0; 378 // --> OD 2008-01-31 #newlistlevelattrs# 379 mnAdditionalFirstLineOffset = 0; 380 // <-- 381 382 nType = FRMC_TXT; 383 bLocked = bFormatted = bWidow = bUndersized = bJustWidow = 384 bEmpty = bInFtnConnect = bFtn = bRepaint = bBlinkPor = 385 bFieldFollow = bHasAnimation = bIsSwapped = sal_False; 386 // OD 14.03.2003 #i11760# 387 mbFollowFormatAllowed = sal_True; 388 } 389 390 /************************************************************************* 391 * SwTxtFrm::SwTxtFrm() 392 *************************************************************************/ 393 SwTxtFrm::SwTxtFrm(SwTxtNode * const pNode, SwFrm* pSib ) 394 : SwCntntFrm( pNode, pSib ) 395 { 396 InitCtor(); 397 } 398 399 /************************************************************************* 400 * SwTxtFrm::~SwTxtFrm() 401 *************************************************************************/ 402 SwTxtFrm::~SwTxtFrm() 403 { 404 // Remove associated SwParaPortion from pTxtCache 405 ClearPara(); 406 } 407 408 const XubString& SwTxtFrm::GetTxt() const 409 { 410 return GetTxtNode()->GetTxt(); 411 } 412 413 void SwTxtFrm::ResetPreps() 414 { 415 if ( GetCacheIdx() != MSHRT_MAX ) 416 { 417 SwParaPortion *pPara; 418 if( 0 != (pPara = GetPara()) ) 419 pPara->ResetPreps(); 420 } 421 } 422 423 /************************************************************************* 424 * SwTxtFrm::IsHiddenNow() 425 *************************************************************************/ 426 sal_Bool SwTxtFrm::IsHiddenNow() const 427 { 428 SwFrmSwapper aSwapper( this, sal_True ); 429 430 if( !Frm().Width() && IsValid() && GetUpper()->IsValid() ) 431 //bei Stackueberlauf (StackHack) invalid! 432 { 433 // ASSERT( false, "SwTxtFrm::IsHiddenNow: thin frame" ); 434 return sal_True; 435 } 436 437 const bool bHiddenCharsHidePara = GetTxtNode()->HasHiddenCharAttribute( true ); 438 const bool bHiddenParaField = GetTxtNode()->HasHiddenParaField(); 439 const ViewShell* pVsh = getRootFrm()->GetCurrShell(); 440 441 if ( pVsh && ( bHiddenCharsHidePara || bHiddenParaField ) ) 442 { 443 if ( 444 ( bHiddenParaField && 445 ( !pVsh->GetViewOptions()->IsShowHiddenPara() && 446 !pVsh->GetViewOptions()->IsFldName() ) ) || 447 ( bHiddenCharsHidePara && 448 !pVsh->GetViewOptions()->IsShowHiddenChar() ) ) 449 { 450 return sal_True; 451 } 452 } 453 454 return sal_False; 455 } 456 457 458 /************************************************************************* 459 * SwTxtFrm::HideHidden() 460 *************************************************************************/ 461 // Entfernt die Anhaengsel des Textfrms wenn dieser hidden ist 462 463 void SwTxtFrm::HideHidden() 464 { 465 ASSERT( !GetFollow() && IsHiddenNow(), 466 "HideHidden on visible frame of hidden frame has follow" ); 467 468 const xub_StrLen nEnd = STRING_LEN; 469 HideFootnotes( GetOfst(), nEnd ); 470 // OD 2004-01-15 #110582# 471 HideAndShowObjects(); 472 473 //Die Formatinfos sind jetzt obsolete 474 ClearPara(); 475 } 476 477 /************************************************************************* 478 * SwTxtFrm::HideFootnotes() 479 *************************************************************************/ 480 void SwTxtFrm::HideFootnotes( xub_StrLen nStart, xub_StrLen nEnd ) 481 { 482 const SwpHints *pHints = GetTxtNode()->GetpSwpHints(); 483 if( pHints ) 484 { 485 const sal_uInt16 nSize = pHints->Count(); 486 SwPageFrm *pPage = 0; 487 for ( sal_uInt16 i = 0; i < nSize; ++i ) 488 { 489 const SwTxtAttr *pHt = (*pHints)[i]; 490 if ( pHt->Which() == RES_TXTATR_FTN ) 491 { 492 const xub_StrLen nIdx = *pHt->GetStart(); 493 if ( nEnd < nIdx ) 494 break; 495 if( nStart <= nIdx ) 496 { 497 if( !pPage ) 498 pPage = FindPageFrm(); 499 pPage->RemoveFtn( this, (SwTxtFtn*)pHt ); 500 } 501 } 502 } 503 } 504 } 505 506 // --> OD 2005-03-30 #120729# - hotfix: WW8 documents contain at its end hidden, 507 // as-character anchored graphics, which are used for a graphic bullet list. 508 // As long as these graphic bullet list aren't imported, do not hide a 509 // at-character anchored object, if 510 // (a) the document is an imported WW8 document - 511 // checked by checking certain compatibility options -, 512 // (b) the paragraph is the last content in the document and 513 // (c) the anchor character is an as-character anchored graphic. 514 bool lcl_HideObj( const SwTxtFrm& _rFrm, 515 const RndStdIds _eAnchorType, 516 const xub_StrLen _nObjAnchorPos, 517 SwAnchoredObject* _pAnchoredObj ) 518 { 519 bool bRet( true ); 520 521 if (_eAnchorType == FLY_AT_CHAR) 522 { 523 const IDocumentSettingAccess* pIDSA = _rFrm.GetTxtNode()->getIDocumentSettingAccess(); 524 if ( !pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) && 525 !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) && 526 !pIDSA->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) && 527 pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) && 528 _rFrm.IsInDocBody() && !_rFrm.FindNextCnt() ) 529 { 530 const xub_Unicode cAnchorChar = 531 _rFrm.GetTxtNode()->GetTxt().GetChar( _nObjAnchorPos ); 532 if ( cAnchorChar == CH_TXTATR_BREAKWORD ) 533 { 534 const SwTxtAttr* const pHint( 535 _rFrm.GetTxtNode()->GetTxtAttrForCharAt(_nObjAnchorPos, 536 RES_TXTATR_FLYCNT) ); 537 if ( pHint ) 538 { 539 const SwFrmFmt* pFrmFmt = 540 static_cast<const SwTxtFlyCnt*>(pHint)->GetFlyCnt().GetFrmFmt(); 541 if ( pFrmFmt->Which() == RES_FLYFRMFMT ) 542 { 543 SwNodeIndex nCntntIndex = *(pFrmFmt->GetCntnt().GetCntntIdx()); 544 nCntntIndex++; 545 if ( nCntntIndex.GetNode().IsNoTxtNode() ) 546 { 547 bRet = false; 548 // set needed data structure values for object positioning 549 SWRECTFN( (&_rFrm) ); 550 SwRect aLastCharRect( _rFrm.Frm() ); 551 (aLastCharRect.*fnRect->fnSetWidth)( 1 ); 552 _pAnchoredObj->maLastCharRect = aLastCharRect; 553 _pAnchoredObj->mnLastTopOfLine = (aLastCharRect.*fnRect->fnGetTop)(); 554 } 555 } 556 } 557 } 558 } 559 } 560 561 return bRet; 562 } 563 // <-- 564 /************************************************************************* 565 * SwTxtFrm::HideAndShowObjects() 566 *************************************************************************/ 567 /** method to hide/show objects 568 569 OD 2004-01-15 #110582# 570 method hides respectively shows objects, which are anchored at paragraph, 571 at/as a character of the paragraph, corresponding to the paragraph and 572 paragraph portion visibility. 573 574 - is called from HideHidden() - should hide objects in hidden paragraphs and 575 - from _Format() - should hide/show objects in partly visible paragraphs 576 577 @author OD 578 */ 579 void SwTxtFrm::HideAndShowObjects() 580 { 581 if ( GetDrawObjs() ) 582 { 583 if ( IsHiddenNow() ) 584 { 585 // complete paragraph is hidden. Thus, hide all objects 586 for ( sal_uInt32 i = 0; i < GetDrawObjs()->Count(); ++i ) 587 { 588 SdrObject* pObj = (*GetDrawObjs())[i]->DrawObj(); 589 SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall()); 590 // --> OD 2005-03-30 #120729# - hotfix: do not hide object 591 // under certain conditions 592 const RndStdIds eAnchorType( pContact->GetAnchorId() ); 593 const xub_StrLen nObjAnchorPos = pContact->GetCntntAnchorIndex().GetIndex(); 594 if ((eAnchorType != FLY_AT_CHAR) || 595 lcl_HideObj( *this, eAnchorType, nObjAnchorPos, 596 (*GetDrawObjs())[i] )) 597 { 598 pContact->MoveObjToInvisibleLayer( pObj ); 599 } 600 // <-- 601 } 602 } 603 else 604 { 605 // paragraph is visible, but can contain hidden text portion. 606 // first we check if objects are allowed to be hidden: 607 const SwTxtNode& rNode = *GetTxtNode(); 608 const ViewShell* pVsh = getRootFrm()->GetCurrShell(); 609 const bool bShouldBeHidden = !pVsh || !pVsh->GetWin() || 610 !pVsh->GetViewOptions()->IsShowHiddenChar(); 611 612 // Thus, show all objects, which are anchored at paragraph and 613 // hide/show objects, which are anchored at/as character, according 614 // to the visibility of the anchor character. 615 for ( sal_uInt32 i = 0; i < GetDrawObjs()->Count(); ++i ) 616 { 617 SdrObject* pObj = (*GetDrawObjs())[i]->DrawObj(); 618 SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall()); 619 // --> OD 2005-03-30 #120729# - determine anchor type only once 620 const RndStdIds eAnchorType( pContact->GetAnchorId() ); 621 // <-- 622 623 if (eAnchorType == FLY_AT_PARA) 624 { 625 pContact->MoveObjToVisibleLayer( pObj ); 626 } 627 else if ((eAnchorType == FLY_AT_CHAR) || 628 (eAnchorType == FLY_AS_CHAR)) 629 { 630 xub_StrLen nHiddenStart; 631 xub_StrLen nHiddenEnd; 632 xub_StrLen nObjAnchorPos = pContact->GetCntntAnchorIndex().GetIndex(); 633 SwScriptInfo::GetBoundsOfHiddenRange( rNode, nObjAnchorPos, nHiddenStart, nHiddenEnd, 0 ); 634 // --> OD 2005-03-30 #120729# - hotfix: do not hide object 635 // under certain conditions 636 if ( nHiddenStart != STRING_LEN && bShouldBeHidden && 637 lcl_HideObj( *this, eAnchorType, nObjAnchorPos, (*GetDrawObjs())[i] ) ) 638 // <-- 639 pContact->MoveObjToInvisibleLayer( pObj ); 640 else 641 pContact->MoveObjToVisibleLayer( pObj ); 642 } 643 else 644 { 645 ASSERT( false, 646 "<SwTxtFrm::HideAndShowObjects()> - object not anchored at/inside paragraph!?" ); 647 } 648 } 649 } 650 } 651 652 if ( IsFollow() ) 653 { 654 FindMaster()->HideAndShowObjects(); 655 } 656 } 657 658 /************************************************************************* 659 * SwTxtFrm::FindBrk() 660 * 661 * Liefert die erste Trennmoeglichkeit in der aktuellen Zeile zurueck. 662 * Die Methode wird in SwTxtFrm::Format() benutzt, um festzustellen, ob 663 * die Vorgaengerzeile mitformatiert werden muss. 664 * nFound ist <= nEndLine. 665 *************************************************************************/ 666 667 xub_StrLen SwTxtFrm::FindBrk( const XubString &rTxt, 668 const xub_StrLen nStart, 669 const xub_StrLen nEnd ) const 670 { 671 // --> OD 2009-12-28 #i104291# - applying patch to avoid overflow. 672 unsigned long nFound = nStart; 673 const xub_StrLen nEndLine = Min( nEnd, rTxt.Len() ); 674 675 // Wir ueberlesen erst alle Blanks am Anfang der Zeile (vgl. Bug 2235). 676 while( nFound <= nEndLine && 677 ' ' == rTxt.GetChar( static_cast<xub_StrLen>(nFound) ) ) 678 { 679 nFound++; 680 } 681 682 // Eine knifflige Sache mit den TxtAttr-Dummy-Zeichen (hier "$"): 683 // "Dr.$Meyer" am Anfang der zweiten Zeile. Dahinter ein Blank eingegeben 684 // und das Wort rutscht nicht in die erste Zeile, obwohl es ginge. 685 // Aus diesem Grund nehmen wir das Dummy-Zeichen noch mit. 686 while( nFound <= nEndLine && 687 ' ' != rTxt.GetChar( static_cast<xub_StrLen>(nFound) ) ) 688 { 689 nFound++; 690 } 691 692 return nFound <= STRING_LEN 693 ? static_cast<xub_StrLen>(nFound) 694 : STRING_LEN; 695 // <-- 696 } 697 698 /************************************************************************* 699 * SwTxtFrm::IsIdxInside() 700 *************************************************************************/ 701 702 sal_Bool SwTxtFrm::IsIdxInside( const xub_StrLen nPos, const xub_StrLen nLen ) const 703 { 704 if( GetOfst() > nPos + nLen ) // d.h., der Bereich liegt komplett vor uns. 705 return sal_False; 706 707 if( !GetFollow() ) // der Bereich liegt nicht komplett vor uns, 708 return sal_True; // nach uns kommt niemand mehr. 709 710 const xub_StrLen nMax = GetFollow()->GetOfst(); 711 712 // der Bereich liegt nicht komplett hinter uns bzw. 713 // unser Text ist geloescht worden. 714 if( nMax > nPos || nMax > GetTxt().Len() ) 715 return sal_True; 716 717 // changes made in the first line of a follow can modify the master 718 const SwParaPortion* pPara = GetFollow()->GetPara(); 719 return pPara && ( nPos <= nMax + pPara->GetLen() ); 720 } 721 722 /************************************************************************* 723 * SwTxtFrm::InvalidateRange() 724 *************************************************************************/ 725 inline void SwTxtFrm::InvalidateRange(const SwCharRange &aRange, const long nD) 726 { 727 if ( IsIdxInside( aRange.Start(), aRange.Len() ) ) 728 _InvalidateRange( aRange, nD ); 729 } 730 731 /************************************************************************* 732 * SwTxtFrm::_InvalidateRange() 733 *************************************************************************/ 734 735 void SwTxtFrm::_InvalidateRange( const SwCharRange &aRange, const long nD) 736 { 737 if ( !HasPara() ) 738 { InvalidateSize(); 739 return; 740 } 741 742 SetWidow( sal_False ); 743 SwParaPortion *pPara = GetPara(); 744 745 sal_Bool bInv = sal_False; 746 if( 0 != nD ) 747 { 748 //Auf nDelta werden die Differenzen zwischen alter und 749 //neuer Zeilenlaenge aufaddiert, deshalb ist es negativ, 750 //wenn Zeichen eingefuegt wurden, positiv, wenn Zeichen 751 //geloescht wurden. 752 *(pPara->GetDelta()) += nD; 753 bInv = sal_True; 754 } 755 SwCharRange &rReformat = *(pPara->GetReformat()); 756 if(aRange != rReformat) { 757 if( STRING_LEN == rReformat.Len() ) 758 rReformat = aRange; 759 else 760 rReformat += aRange; 761 bInv = sal_True; 762 } 763 if(bInv) 764 { 765 // 90365: nD is passed to a follow two times 766 // if( GetFollow() ) 767 // ((SwTxtFrm*)GetFollow())->InvalidateRange( aRange, nD ); 768 InvalidateSize(); 769 } 770 } 771 772 /************************************************************************* 773 * SwTxtFrm::CalcLineSpace() 774 *************************************************************************/ 775 776 void SwTxtFrm::CalcLineSpace() 777 { 778 ASSERT( ! IsVertical() || ! IsSwapped(), 779 "SwTxtFrm::CalcLineSpace with swapped frame!" ) 780 781 if( IsLocked() || !HasPara() ) 782 return; 783 784 SwParaPortion *pPara; 785 if( GetDrawObjs() || 786 GetTxtNode()->GetSwAttrSet().GetLRSpace().IsAutoFirst() || 787 ( pPara = GetPara() )->IsFixLineHeight() ) 788 { 789 Init(); 790 return; 791 } 792 793 Size aNewSize( Prt().SSize() ); 794 795 SwTxtFormatInfo aInf( this ); 796 SwTxtFormatter aLine( this, &aInf ); 797 if( aLine.GetDropLines() ) 798 { 799 Init(); 800 return; 801 } 802 803 aLine.Top(); 804 aLine.RecalcRealHeight(); 805 806 aNewSize.Height() = (aLine.Y() - Frm().Top()) + aLine.GetLineHeight(); 807 808 SwTwips nDelta = aNewSize.Height() - Prt().Height(); 809 // 4291: Unterlauf bei Flys 810 if( aInf.GetTxtFly()->IsOn() ) 811 { 812 SwRect aTmpFrm( Frm() ); 813 if( nDelta < 0 ) 814 aTmpFrm.Height( Prt().Height() ); 815 else 816 aTmpFrm.Height( aNewSize.Height() ); 817 if( aInf.GetTxtFly()->Relax( aTmpFrm ) ) 818 { 819 Init(); 820 return; 821 } 822 } 823 824 if( nDelta ) 825 { 826 SwTxtFrmBreak aBreak( this ); 827 if( GetFollow() || aBreak.IsBreakNow( aLine ) ) 828 { 829 // Wenn es einen Follow() gibt, oder wenn wir an dieser 830 // Stelle aufbrechen muessen, so wird neu formatiert. 831 Init(); 832 } 833 else 834 { 835 // Alles nimmt seinen gewohnten Gang ... 836 pPara->SetPrepAdjust(); 837 pPara->SetPrep(); 838 } 839 } 840 } 841 842 // 843 // SET_WRONG( nPos, nCnt, bMove ) 844 // 845 #define SET_WRONG( nPos, nCnt, bMove ) \ 846 { \ 847 lcl_SetWrong( *this, nPos, nCnt, bMove ); \ 848 } 849 850 void lcl_SetWrong( SwTxtFrm& rFrm, xub_StrLen nPos, long nCnt, bool bMove ) 851 { 852 if ( !rFrm.IsFollow() ) 853 { 854 SwTxtNode* pTxtNode = rFrm.GetTxtNode(); 855 IGrammarContact* pGrammarContact = getGrammarContact( *pTxtNode ); 856 SwGrammarMarkUp* pWrongGrammar = pGrammarContact ? 857 pGrammarContact->getGrammarCheck( *pTxtNode, false ) : 858 pTxtNode->GetGrammarCheck(); 859 bool bGrammarProxy = pWrongGrammar != pTxtNode->GetGrammarCheck(); 860 if( bMove ) 861 { 862 if( pTxtNode->GetWrong() ) 863 pTxtNode->GetWrong()->Move( nPos, nCnt ); 864 if( pWrongGrammar ) 865 pWrongGrammar->MoveGrammar( nPos, nCnt ); 866 if( bGrammarProxy && pTxtNode->GetGrammarCheck() ) 867 pTxtNode->GetGrammarCheck()->MoveGrammar( nPos, nCnt ); 868 if( pTxtNode->GetSmartTags() ) 869 pTxtNode->GetSmartTags()->Move( nPos, nCnt ); 870 } 871 else 872 { 873 xub_StrLen nLen = (xub_StrLen)nCnt; 874 if( pTxtNode->GetWrong() ) 875 pTxtNode->GetWrong()->Invalidate( nPos, nLen ); 876 if( pWrongGrammar ) 877 pWrongGrammar->Invalidate( nPos, nLen ); 878 if( pTxtNode->GetSmartTags() ) 879 pTxtNode->GetSmartTags()->Invalidate( nPos, nLen ); 880 } 881 if ( !pTxtNode->GetWrong() && !pTxtNode->IsWrongDirty() ) 882 { 883 pTxtNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) ); 884 pTxtNode->GetWrong()->SetInvalid( nPos, nPos + (sal_uInt16)( nCnt > 0 ? nCnt : 1 ) ); 885 } 886 if ( !pTxtNode->GetSmartTags() && !pTxtNode->IsSmartTagDirty() ) 887 { 888 // SMARTTAGS 889 pTxtNode->SetSmartTags( new SwWrongList( WRONGLIST_SMARTTAG ) ); 890 pTxtNode->GetSmartTags()->SetInvalid( nPos, nPos + (sal_uInt16)( nCnt > 0 ? nCnt : 1 ) ); 891 } 892 pTxtNode->SetWrongDirty( true ); 893 pTxtNode->SetGrammarCheckDirty( true ); 894 pTxtNode->SetWordCountDirty( true ); 895 pTxtNode->SetAutoCompleteWordDirty( true ); 896 // SMARTTAGS 897 pTxtNode->SetSmartTagDirty( true ); 898 } 899 900 SwRootFrm *pRootFrm = rFrm.getRootFrm(); 901 if (pRootFrm) 902 { 903 pRootFrm->SetNeedGrammarCheck( sal_True ); 904 } 905 906 SwPageFrm *pPage = rFrm.FindPageFrm(); 907 if( pPage ) 908 { 909 pPage->InvalidateSpelling(); 910 pPage->InvalidateAutoCompleteWords(); 911 pPage->InvalidateWordCount(); 912 pPage->InvalidateSmartTags(); 913 } 914 } 915 916 // 917 // SET_SCRIPT_INVAL( nPos ) 918 // 919 920 #define SET_SCRIPT_INVAL( nPos )\ 921 lcl_SetScriptInval( *this, nPos ); 922 923 void lcl_SetScriptInval( SwTxtFrm& rFrm, xub_StrLen nPos ) 924 { 925 if( rFrm.GetPara() ) 926 rFrm.GetPara()->GetScriptInfo().SetInvalidity( nPos ); 927 } 928 929 void lcl_ModifyOfst( SwTxtFrm* pFrm, xub_StrLen nPos, xub_StrLen nLen ) 930 { 931 while( pFrm && pFrm->GetOfst() <= nPos ) 932 pFrm = pFrm->GetFollow(); 933 while( pFrm ) 934 { 935 pFrm->ManipOfst( pFrm->GetOfst() + nLen ); 936 pFrm = pFrm->GetFollow(); 937 } 938 } 939 940 /************************************************************************* 941 * SwTxtFrm::Modify() 942 *************************************************************************/ 943 944 void SwTxtFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew ) 945 { 946 const MSHORT nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0; 947 948 //Wuensche die FrmAttribute betreffen werden von der Basisklasse 949 //verarbeitet. 950 if( IsInRange( aFrmFmtSetRange, nWhich ) || RES_FMT_CHG == nWhich ) 951 { 952 SwCntntFrm::Modify( pOld, pNew ); 953 if( nWhich == RES_FMT_CHG && getRootFrm()->GetCurrShell() ) 954 { 955 // Collection hat sich geaendert 956 Prepare( PREP_CLEAR ); 957 _InvalidatePrt(); 958 SET_WRONG( 0, STRING_LEN, false ); 959 SetDerivedR2L( sal_False ); 960 CheckDirChange(); 961 // OD 09.12.2002 #105576# - Force complete paint due to existing 962 // indents. 963 SetCompletePaint(); 964 InvalidateLineNum(); 965 } 966 return; 967 } 968 969 // Im gelockten Zustand werden keine Bestellungen angenommen. 970 if( IsLocked() ) 971 return; 972 973 // Dies spart Stack, man muss nur aufpassen, 974 // dass sie Variablen gesetzt werden. 975 xub_StrLen nPos, nLen; 976 sal_Bool bSetFldsDirty = sal_False; 977 sal_Bool bRecalcFtnFlag = sal_False; 978 979 switch( nWhich ) 980 { 981 case RES_LINENUMBER: 982 { 983 InvalidateLineNum(); 984 } 985 break; 986 case RES_INS_TXT: 987 { 988 nPos = ((SwInsTxt*)pNew)->nPos; 989 nLen = ((SwInsTxt*)pNew)->nLen; 990 if( IsIdxInside( nPos, nLen ) ) 991 { 992 if( !nLen ) 993 { 994 // 6969: Aktualisierung der NumPortions auch bei leeren Zeilen! 995 if( nPos ) 996 InvalidateSize(); 997 else 998 Prepare( PREP_CLEAR ); 999 } 1000 else 1001 _InvalidateRange( SwCharRange( nPos, nLen ), nLen ); 1002 } 1003 SET_WRONG( nPos, nLen, true ) 1004 SET_SCRIPT_INVAL( nPos ) 1005 bSetFldsDirty = sal_True; 1006 if( HasFollow() ) 1007 lcl_ModifyOfst( this, nPos, nLen ); 1008 } 1009 break; 1010 case RES_DEL_CHR: 1011 { 1012 nPos = ((SwDelChr*)pNew)->nPos; 1013 InvalidateRange( SwCharRange( nPos, 1 ), -1 ); 1014 SET_WRONG( nPos, -1, true ) 1015 SET_SCRIPT_INVAL( nPos ) 1016 bSetFldsDirty = bRecalcFtnFlag = sal_True; 1017 if( HasFollow() ) 1018 lcl_ModifyOfst( this, nPos, STRING_LEN ); 1019 } 1020 break; 1021 case RES_DEL_TXT: 1022 { 1023 nPos = ((SwDelTxt*)pNew)->nStart; 1024 nLen = ((SwDelTxt*)pNew)->nLen; 1025 long m = nLen; 1026 m *= -1; 1027 if( IsIdxInside( nPos, nLen ) ) 1028 { 1029 if( !nLen ) 1030 InvalidateSize(); 1031 else 1032 InvalidateRange( SwCharRange( nPos, 1 ), m ); 1033 } 1034 SET_WRONG( nPos, m, true ) 1035 SET_SCRIPT_INVAL( nPos ) 1036 bSetFldsDirty = bRecalcFtnFlag = sal_True; 1037 if( HasFollow() ) 1038 lcl_ModifyOfst( this, nPos, nLen ); 1039 } 1040 break; 1041 case RES_UPDATE_ATTR: 1042 { 1043 nPos = ((SwUpdateAttr*)pNew)->nStart; 1044 nLen = ((SwUpdateAttr*)pNew)->nEnd - nPos; 1045 if( IsIdxInside( nPos, nLen ) ) 1046 { 1047 // Es muss in jedem Fall neu formatiert werden, 1048 // auch wenn der invalidierte Bereich null ist. 1049 // Beispiel: leere Zeile, 14Pt einstellen ! 1050 // if( !nLen ) nLen = 1; 1051 1052 // 6680: FtnNummern muessen formatiert werden. 1053 if( !nLen ) 1054 nLen = 1; 1055 1056 _InvalidateRange( SwCharRange( nPos, nLen) ); 1057 MSHORT nTmp = ((SwUpdateAttr*)pNew)->nWhichAttr; 1058 1059 if( ! nTmp || RES_TXTATR_CHARFMT == nTmp || RES_TXTATR_AUTOFMT == nTmp || 1060 RES_FMT_CHG == nTmp || RES_ATTRSET_CHG == nTmp ) 1061 { 1062 SET_WRONG( nPos, nPos + nLen, false ) 1063 SET_SCRIPT_INVAL( nPos ) 1064 } 1065 } 1066 1067 // --> OD 2010-02-16 #i104008# 1068 ViewShell* pViewSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0; 1069 if ( pViewSh ) 1070 { 1071 pViewSh->InvalidateAccessibleParaAttrs( *this ); 1072 } 1073 // <-- 1074 } 1075 break; 1076 case RES_OBJECTDYING: 1077 break; 1078 1079 case RES_PARATR_LINESPACING: 1080 { 1081 CalcLineSpace(); 1082 InvalidateSize(); 1083 _InvalidatePrt(); 1084 if( IsInSct() && !GetPrev() ) 1085 { 1086 SwSectionFrm *pSect = FindSctFrm(); 1087 if( pSect->ContainsAny() == this ) 1088 pSect->InvalidatePrt(); 1089 } 1090 1091 // OD 09.01.2004 #i11859# - correction: 1092 // (1) Also invalidate next frame on next page/column. 1093 // (2) Skip empty sections and hidden paragraphs 1094 // Thus, use method <InvalidateNextPrtArea()> 1095 InvalidateNextPrtArea(); 1096 1097 SetCompletePaint(); 1098 } 1099 break; 1100 case RES_TXTATR_FIELD: 1101 { 1102 nPos = *((SwFmtFld*)pNew)->GetTxtFld()->GetStart(); 1103 if( IsIdxInside( nPos, 1 ) ) 1104 { 1105 if( pNew == pOld ) 1106 { 1107 // Nur repainten 1108 // opt: invalidate aufs Window ? 1109 InvalidatePage(); 1110 SetCompletePaint(); 1111 } 1112 else 1113 _InvalidateRange( SwCharRange( nPos, 1 ) ); 1114 } 1115 bSetFldsDirty = sal_True; 1116 // ST2 1117 if ( SwSmartTagMgr::Get().IsSmartTagsEnabled() ) 1118 SET_WRONG( nPos, nPos + 1, false ) 1119 } 1120 break; 1121 case RES_TXTATR_FTN : 1122 { 1123 nPos = *((SwFmtFtn*)pNew)->GetTxtFtn()->GetStart(); 1124 if( IsInFtn() || IsIdxInside( nPos, 1 ) ) 1125 Prepare( PREP_FTN, ((SwFmtFtn*)pNew)->GetTxtFtn() ); 1126 break; 1127 } 1128 1129 case RES_ATTRSET_CHG: 1130 { 1131 InvalidateLineNum(); 1132 1133 SwAttrSet& rNewSet = *((SwAttrSetChg*)pNew)->GetChgSet(); 1134 const SfxPoolItem* pItem; 1135 int nClear = 0; 1136 MSHORT nCount = rNewSet.Count(); 1137 1138 if( SFX_ITEM_SET == rNewSet.GetItemState( RES_TXTATR_FTN, 1139 sal_False, &pItem )) 1140 { 1141 nPos = *((SwFmtFtn*)pItem)->GetTxtFtn()->GetStart(); 1142 if( IsIdxInside( nPos, 1 ) ) 1143 Prepare( PREP_FTN, pNew ); 1144 nClear = 0x01; 1145 --nCount; 1146 } 1147 1148 if( SFX_ITEM_SET == rNewSet.GetItemState( RES_TXTATR_FIELD, 1149 sal_False, &pItem )) 1150 { 1151 nPos = *((SwFmtFld*)pItem)->GetTxtFld()->GetStart(); 1152 if( IsIdxInside( nPos, 1 ) ) 1153 { 1154 const SfxPoolItem& rOldItem = ((SwAttrSetChg*)pOld)-> 1155 GetChgSet()->Get( RES_TXTATR_FIELD ); 1156 if( pItem == &rOldItem ) 1157 { 1158 // Nur repainten 1159 // opt: invalidate aufs Window ? 1160 InvalidatePage(); 1161 SetCompletePaint(); 1162 } 1163 else 1164 _InvalidateRange( SwCharRange( nPos, 1 ) ); 1165 } 1166 nClear |= 0x02; 1167 --nCount; 1168 } 1169 sal_Bool bLineSpace = SFX_ITEM_SET == rNewSet.GetItemState( 1170 RES_PARATR_LINESPACING, sal_False ), 1171 bRegister = SFX_ITEM_SET == rNewSet.GetItemState( 1172 RES_PARATR_REGISTER, sal_False ); 1173 if ( bLineSpace || bRegister ) 1174 { 1175 Prepare( bRegister ? PREP_REGISTER : PREP_ADJUST_FRM ); 1176 CalcLineSpace(); 1177 InvalidateSize(); 1178 _InvalidatePrt(); 1179 1180 // OD 09.01.2004 #i11859# - correction: 1181 // (1) Also invalidate next frame on next page/column. 1182 // (2) Skip empty sections and hidden paragraphs 1183 // Thus, use method <InvalidateNextPrtArea()> 1184 InvalidateNextPrtArea(); 1185 1186 SetCompletePaint(); 1187 nClear |= 0x04; 1188 if ( bLineSpace ) 1189 { 1190 --nCount; 1191 if( IsInSct() && !GetPrev() ) 1192 { 1193 SwSectionFrm *pSect = FindSctFrm(); 1194 if( pSect->ContainsAny() == this ) 1195 pSect->InvalidatePrt(); 1196 } 1197 } 1198 if ( bRegister ) 1199 --nCount; 1200 } 1201 if ( SFX_ITEM_SET == rNewSet.GetItemState( RES_PARATR_SPLIT, 1202 sal_False )) 1203 { 1204 if ( GetPrev() ) 1205 CheckKeep(); 1206 Prepare( PREP_CLEAR ); 1207 InvalidateSize(); 1208 nClear |= 0x08; 1209 --nCount; 1210 } 1211 1212 if( SFX_ITEM_SET == rNewSet.GetItemState( RES_BACKGROUND, sal_False) 1213 && !IsFollow() && GetDrawObjs() ) 1214 { 1215 SwSortedObjs *pObjs = GetDrawObjs(); 1216 for ( int i = 0; GetDrawObjs() && i < int(pObjs->Count()); ++i ) 1217 { 1218 SwAnchoredObject* pAnchoredObj = (*pObjs)[MSHORT(i)]; 1219 if ( pAnchoredObj->ISA(SwFlyFrm) ) 1220 { 1221 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj); 1222 if( !pFly->IsFlyInCntFrm() ) 1223 { 1224 const SvxBrushItem &rBack = 1225 pFly->GetAttrSet()->GetBackground(); 1226 // OD 20.08.2002 #99657# #GetTransChg# 1227 // following condition determines, if the fly frame 1228 // "inherites" the background color of text frame. 1229 // This is the case, if fly frame background 1230 // color is "no fill"/"auto fill" and if the fly frame 1231 // has no background graphic. 1232 // Thus, check complete fly frame background 1233 // color and *not* only its transparency value 1234 if ( (rBack.GetColor() == COL_TRANSPARENT) && 1235 //if( rBack.GetColor().GetTransparency() && 1236 rBack.GetGraphicPos() == GPOS_NONE ) 1237 { 1238 pFly->SetCompletePaint(); 1239 pFly->InvalidatePage(); 1240 } 1241 } 1242 } 1243 } 1244 } 1245 1246 if ( SFX_ITEM_SET == 1247 rNewSet.GetItemState( RES_TXTATR_CHARFMT, sal_False ) ) 1248 { 1249 SET_WRONG( 0, STRING_LEN, false ) 1250 SET_SCRIPT_INVAL( 0 ) 1251 } 1252 else if ( SFX_ITEM_SET == 1253 rNewSet.GetItemState( RES_CHRATR_LANGUAGE, sal_False ) || 1254 SFX_ITEM_SET == 1255 rNewSet.GetItemState( RES_CHRATR_CJK_LANGUAGE, sal_False ) || 1256 SFX_ITEM_SET == 1257 rNewSet.GetItemState( RES_CHRATR_CTL_LANGUAGE, sal_False ) ) 1258 SET_WRONG( 0, STRING_LEN, false ) 1259 else if ( SFX_ITEM_SET == 1260 rNewSet.GetItemState( RES_CHRATR_FONT, sal_False ) || 1261 SFX_ITEM_SET == 1262 rNewSet.GetItemState( RES_CHRATR_CJK_FONT, sal_False ) || 1263 SFX_ITEM_SET == 1264 rNewSet.GetItemState( RES_CHRATR_CTL_FONT, sal_False ) ) 1265 SET_SCRIPT_INVAL( 0 ) 1266 else if ( SFX_ITEM_SET == 1267 rNewSet.GetItemState( RES_FRAMEDIR, sal_False ) ) 1268 { 1269 SetDerivedR2L( sal_False ); 1270 CheckDirChange(); 1271 // OD 09.12.2002 #105576# - Force complete paint due to existing 1272 // indents. 1273 SetCompletePaint(); 1274 } 1275 1276 1277 if( nCount ) 1278 { 1279 if( getRootFrm()->GetCurrShell() ) 1280 { 1281 Prepare( PREP_CLEAR ); 1282 _InvalidatePrt(); 1283 } 1284 1285 if( nClear ) 1286 { 1287 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld ); 1288 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew ); 1289 1290 if( 0x01 & nClear ) 1291 { 1292 aOldSet.ClearItem( RES_TXTATR_FTN ); 1293 aNewSet.ClearItem( RES_TXTATR_FTN ); 1294 } 1295 if( 0x02 & nClear ) 1296 { 1297 aOldSet.ClearItem( RES_TXTATR_FIELD ); 1298 aNewSet.ClearItem( RES_TXTATR_FIELD ); 1299 } 1300 if ( 0x04 & nClear ) 1301 { 1302 if ( bLineSpace ) 1303 { 1304 aOldSet.ClearItem( RES_PARATR_LINESPACING ); 1305 aNewSet.ClearItem( RES_PARATR_LINESPACING ); 1306 } 1307 if ( bRegister ) 1308 { 1309 aOldSet.ClearItem( RES_PARATR_REGISTER ); 1310 aNewSet.ClearItem( RES_PARATR_REGISTER ); 1311 } 1312 } 1313 if ( 0x08 & nClear ) 1314 { 1315 aOldSet.ClearItem( RES_PARATR_SPLIT ); 1316 aNewSet.ClearItem( RES_PARATR_SPLIT ); 1317 } 1318 SwCntntFrm::Modify( &aOldSet, &aNewSet ); 1319 } 1320 else 1321 SwCntntFrm::Modify( pOld, pNew ); 1322 } 1323 1324 // --> OD 2009-01-06 #i88069# 1325 ViewShell* pViewSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0; 1326 if ( pViewSh ) 1327 { 1328 pViewSh->InvalidateAccessibleParaAttrs( *this ); 1329 } 1330 // <-- 1331 } 1332 break; 1333 1334 /* Seit dem neuen Blocksatz muessen wir immer neu formatieren: 1335 case RES_PARATR_ADJUST: 1336 { 1337 if( GetShell() ) 1338 { 1339 Prepare( PREP_CLEAR ); 1340 } 1341 break; 1342 } 1343 */ 1344 // 6870: SwDocPosUpdate auswerten. 1345 case RES_DOCPOS_UPDATE: 1346 { 1347 if( pOld && pNew ) 1348 { 1349 const SwDocPosUpdate *pDocPos = (const SwDocPosUpdate*)pOld; 1350 if( pDocPos->nDocPos <= aFrm.Top() ) 1351 { 1352 const SwFmtFld *pFld = (const SwFmtFld *)pNew; 1353 InvalidateRange( 1354 SwCharRange( *pFld->GetTxtFld()->GetStart(), 1 ) ); 1355 } 1356 } 1357 break; 1358 } 1359 case RES_PARATR_SPLIT: 1360 if ( GetPrev() ) 1361 CheckKeep(); 1362 Prepare( PREP_CLEAR ); 1363 bSetFldsDirty = sal_True; 1364 break; 1365 case RES_FRAMEDIR : 1366 SetDerivedR2L( sal_False ); 1367 CheckDirChange(); 1368 break; 1369 default: 1370 { 1371 Prepare( PREP_CLEAR ); 1372 _InvalidatePrt(); 1373 if ( !nWhich ) 1374 { 1375 //Wird z.B. bei HiddenPara mit 0 gerufen. 1376 SwFrm *pNxt; 1377 if ( 0 != (pNxt = FindNext()) ) 1378 pNxt->InvalidatePrt(); 1379 } 1380 } 1381 } // switch 1382 1383 if( bSetFldsDirty ) 1384 GetNode()->getIDocumentFieldsAccess()->SetFieldsDirty( sal_True, GetNode(), 1 ); 1385 1386 if ( bRecalcFtnFlag ) 1387 CalcFtnFlag(); 1388 } 1389 1390 sal_Bool SwTxtFrm::GetInfo( SfxPoolItem &rHnt ) const 1391 { 1392 if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && ! IsFollow() ) 1393 { 1394 SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt; 1395 const SwPageFrm *pPage = FindPageFrm(); 1396 if ( pPage ) 1397 { 1398 if ( pPage == rInfo.GetOrigPage() && !GetPrev() ) 1399 { 1400 //Das sollte er sein (kann allenfalls temporaer anders sein, 1401 // sollte uns das beunruhigen?) 1402 rInfo.SetInfo( pPage, this ); 1403 return sal_False; 1404 } 1405 if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() && 1406 (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum())) 1407 { 1408 //Das koennte er sein. 1409 rInfo.SetInfo( pPage, this ); 1410 } 1411 } 1412 } 1413 return sal_True; 1414 } 1415 1416 /************************************************************************* 1417 * SwTxtFrm::PrepWidows() 1418 *************************************************************************/ 1419 1420 void SwTxtFrm::PrepWidows( const MSHORT nNeed, sal_Bool bNotify ) 1421 { 1422 ASSERT(GetFollow() && nNeed, "+SwTxtFrm::Prepare: lost all friends"); 1423 1424 SwParaPortion *pPara = GetPara(); 1425 if ( !pPara ) 1426 return; 1427 pPara->SetPrepWidows( sal_True ); 1428 1429 // These two lines of code have been deleted for #102340#. 1430 // Obviously the widow control does not work if we have a 1431 // pMaster->pFollow->pFollow situation: 1432 1433 // returnen oder nicht ist hier die Frage. 1434 // Ohne IsLocked() ist 5156 gefaehrlich, 1435 // ohne IsFollow() werden die Orphans unterdrueckt: 6968. 1436 // Abfrage auf IsLocked erst hier, weil das Flag gesetzt werden soll. 1437 // if( IsLocked() && IsFollow() ) 1438 // return; 1439 1440 MSHORT nHave = nNeed; 1441 1442 // Wir geben ein paar Zeilen ab und schrumpfen im CalcPreps() 1443 SWAP_IF_NOT_SWAPPED( this ) 1444 1445 SwTxtSizeInfo aInf( this ); 1446 SwTxtMargin aLine( this, &aInf ); 1447 aLine.Bottom(); 1448 xub_StrLen nTmpLen = aLine.GetCurr()->GetLen(); 1449 while( nHave && aLine.PrevLine() ) 1450 { 1451 if( nTmpLen ) 1452 --nHave; 1453 nTmpLen = aLine.GetCurr()->GetLen(); 1454 } 1455 // In dieser Ecke tummelten sich einige Bugs: 7513, 7606. 1456 // Wenn feststeht, dass Zeilen abgegeben werden koennen, 1457 // muss der Master darueber hinaus die Widow-Regel ueberpruefen. 1458 if( !nHave ) 1459 { 1460 sal_Bool bSplit; 1461 if( !IsFollow() ) //Nur ein Master entscheidet ueber Orphans 1462 { 1463 const WidowsAndOrphans aWidOrp( this ); 1464 bSplit = ( aLine.GetLineNr() >= aWidOrp.GetOrphansLines() && 1465 aLine.GetLineNr() >= aLine.GetDropLines() ); 1466 } 1467 else 1468 bSplit = sal_True; 1469 1470 if( bSplit ) 1471 { 1472 GetFollow()->SetOfst( aLine.GetEnd() ); 1473 aLine.TruncLines( sal_True ); 1474 if( pPara->IsFollowField() ) 1475 GetFollow()->SetFieldFollow( sal_True ); 1476 } 1477 } 1478 if ( bNotify ) 1479 { 1480 _InvalidateSize(); 1481 InvalidatePage(); 1482 } 1483 1484 UNDO_SWAP( this ) 1485 } 1486 1487 /************************************************************************* 1488 * SwTxtFrm::Prepare 1489 *************************************************************************/ 1490 1491 sal_Bool lcl_ErgoVadis( SwTxtFrm* pFrm, xub_StrLen &rPos, const PrepareHint ePrep ) 1492 { 1493 const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo(); 1494 if( ePrep == PREP_ERGOSUM ) 1495 { 1496 if( !rFtnInfo.aErgoSum.Len() ) 1497 return sal_False;; 1498 rPos = pFrm->GetOfst(); 1499 } 1500 else 1501 { 1502 if( !rFtnInfo.aQuoVadis.Len() ) 1503 return sal_False; 1504 if( pFrm->HasFollow() ) 1505 rPos = pFrm->GetFollow()->GetOfst(); 1506 else 1507 rPos = pFrm->GetTxt().Len(); 1508 if( rPos ) 1509 --rPos; // unser letztes Zeichen 1510 } 1511 return sal_True; 1512 } 1513 1514 void SwTxtFrm::Prepare( const PrepareHint ePrep, const void* pVoid, 1515 sal_Bool bNotify ) 1516 { 1517 SwFrmSwapper aSwapper( this, sal_False ); 1518 1519 #if OSL_DEBUG_LEVEL > 1 1520 const SwTwips nDbgY = Frm().Top(); 1521 (void)nDbgY; 1522 #endif 1523 1524 if ( IsEmpty() ) 1525 { 1526 switch ( ePrep ) 1527 { 1528 case PREP_BOSS_CHGD: 1529 SetInvalidVert( sal_True ); // Test 1530 case PREP_WIDOWS_ORPHANS: 1531 case PREP_WIDOWS: 1532 case PREP_FTN_GONE : return; 1533 1534 case PREP_POS_CHGD : 1535 { 1536 // Auch in (spaltigen) Bereichen ist ein InvalidateSize notwendig, 1537 // damit formatiert wird und ggf. das bUndersized gesetzt wird. 1538 if( IsInFly() || IsInSct() ) 1539 { 1540 SwTwips nTmpBottom = GetUpper()->Frm().Top() + 1541 GetUpper()->Prt().Bottom(); 1542 if( nTmpBottom < Frm().Bottom() ) 1543 break; 1544 } 1545 // Gibt es ueberhaupt Flys auf der Seite ? 1546 SwTxtFly aTxtFly( this ); 1547 if( aTxtFly.IsOn() ) 1548 { 1549 // Ueberlappt irgendein Fly ? 1550 aTxtFly.Relax(); 1551 if ( aTxtFly.IsOn() || IsUndersized() ) 1552 break; 1553 } 1554 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue()) 1555 break; 1556 1557 GETGRID( FindPageFrm() ) 1558 if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() ) 1559 break; 1560 1561 // --> OD 2004-07-16 #i28701# - consider anchored objects 1562 if ( GetDrawObjs() ) 1563 break; 1564 // <-- 1565 1566 return; 1567 } 1568 default: 1569 break; 1570 } 1571 } 1572 1573 if( !HasPara() && PREP_MUST_FIT != ePrep ) 1574 { 1575 SetInvalidVert( sal_True ); // Test 1576 ASSERT( !IsLocked(), "SwTxtFrm::Prepare: three of a perfect pair" ); 1577 if ( bNotify ) 1578 InvalidateSize(); 1579 else 1580 _InvalidateSize(); 1581 return; 1582 } 1583 1584 //Objekt mit Locking aus dem Cache holen. 1585 SwTxtLineAccess aAccess( this ); 1586 SwParaPortion *pPara = aAccess.GetPara(); 1587 1588 switch( ePrep ) 1589 { 1590 case PREP_MOVEFTN : Frm().Height(0); 1591 Prt().Height(0); 1592 _InvalidatePrt(); 1593 _InvalidateSize(); 1594 // KEIN break 1595 case PREP_ADJUST_FRM : pPara->SetPrepAdjust( sal_True ); 1596 if( IsFtnNumFrm() != pPara->IsFtnNum() || 1597 IsUndersized() ) 1598 { 1599 InvalidateRange( SwCharRange( 0, 1 ), 1); 1600 if( GetOfst() && !IsFollow() ) 1601 _SetOfst( 0 ); 1602 } 1603 break; 1604 case PREP_MUST_FIT : pPara->SetPrepMustFit( sal_True ); 1605 /* no break here */ 1606 case PREP_WIDOWS_ORPHANS : pPara->SetPrepAdjust( sal_True ); 1607 break; 1608 1609 case PREP_WIDOWS : 1610 // MustFit ist staerker als alles anderes 1611 if( pPara->IsPrepMustFit() ) 1612 return; 1613 // Siehe Kommentar in WidowsAndOrphans::FindOrphans und CalcPreps() 1614 PrepWidows( *(const MSHORT *)pVoid, bNotify ); 1615 break; 1616 1617 case PREP_FTN : 1618 { 1619 SwTxtFtn *pFtn = (SwTxtFtn *)pVoid; 1620 if( IsInFtn() ) 1621 { 1622 // Bin ich der erste TxtFrm einer Fussnote ? 1623 if( !GetPrev() ) 1624 // Wir sind also ein TxtFrm der Fussnote, die 1625 // die Fussnotenzahl zur Anzeige bringen muss. 1626 // Oder den ErgoSum-Text... 1627 InvalidateRange( SwCharRange( 0, 1 ), 1); 1628 1629 if( !GetNext() ) 1630 { 1631 // Wir sind der letzte Ftn, jetzt muessten die 1632 // QuoVadis-Texte geupdated werden. 1633 const SwFtnInfo &rFtnInfo = GetNode()->GetDoc()->GetFtnInfo(); 1634 if( !pPara->UpdateQuoVadis( rFtnInfo.aQuoVadis ) ) 1635 { 1636 xub_StrLen nPos = pPara->GetParLen(); 1637 if( nPos ) 1638 --nPos; 1639 InvalidateRange( SwCharRange( nPos, 1 ), 1); 1640 } 1641 } 1642 } 1643 else 1644 { 1645 // Wir sind also der TxtFrm _mit_ der Fussnote 1646 const xub_StrLen nPos = *pFtn->GetStart(); 1647 InvalidateRange( SwCharRange( nPos, 1 ), 1); 1648 } 1649 break; 1650 } 1651 case PREP_BOSS_CHGD : 1652 { 1653 // Test 1654 { 1655 SetInvalidVert( sal_False ); 1656 sal_Bool bOld = IsVertical(); 1657 SetInvalidVert( sal_True ); 1658 if( bOld != IsVertical() ) 1659 InvalidateRange( SwCharRange( GetOfst(), STRING_LEN ) ); 1660 } 1661 1662 if( HasFollow() ) 1663 { 1664 xub_StrLen nNxtOfst = GetFollow()->GetOfst(); 1665 if( nNxtOfst ) 1666 --nNxtOfst; 1667 InvalidateRange( SwCharRange( nNxtOfst, 1 ), 1); 1668 } 1669 if( IsInFtn() ) 1670 { 1671 xub_StrLen nPos; 1672 if( lcl_ErgoVadis( this, nPos, PREP_QUOVADIS ) ) 1673 InvalidateRange( SwCharRange( nPos, 1 ), 0 ); 1674 if( lcl_ErgoVadis( this, nPos, PREP_ERGOSUM ) ) 1675 InvalidateRange( SwCharRange( nPos, 1 ), 0 ); 1676 } 1677 // 4739: Wenn wir ein Seitennummernfeld besitzen, muessen wir 1678 // die Stellen invalidieren. 1679 SwpHints *pHints = GetTxtNode()->GetpSwpHints(); 1680 if( pHints ) 1681 { 1682 const sal_uInt16 nSize = pHints->Count(); 1683 const xub_StrLen nEnd = GetFollow() ? 1684 GetFollow()->GetOfst() : STRING_LEN; 1685 for ( sal_uInt16 i = 0; i < nSize; ++i ) 1686 { 1687 const SwTxtAttr *pHt = (*pHints)[i]; 1688 const xub_StrLen nStart = *pHt->GetStart(); 1689 if( nStart >= GetOfst() ) 1690 { 1691 if( nStart >= nEnd ) 1692 i = nSize; // fuehrt das Ende herbei 1693 else 1694 { 1695 // 4029: wenn wir zurueckfliessen und eine Ftn besitzen, so 1696 // fliesst die Ftn in jedem Fall auch mit. Damit sie nicht im 1697 // Weg steht, schicken wir uns ein ADJUST_FRM. 1698 // pVoid != 0 bedeutet MoveBwd() 1699 const MSHORT nWhich = pHt->Which(); 1700 if( RES_TXTATR_FIELD == nWhich || 1701 (HasFtn() && pVoid && RES_TXTATR_FTN == nWhich)) 1702 InvalidateRange( SwCharRange( nStart, 1 ), 1 ); 1703 } 1704 } 1705 } 1706 } 1707 // A new boss, a new chance for growing 1708 if( IsUndersized() ) 1709 { 1710 _InvalidateSize(); 1711 InvalidateRange( SwCharRange( GetOfst(), 1 ), 1); 1712 } 1713 break; 1714 } 1715 1716 case PREP_POS_CHGD : 1717 { 1718 if ( GetValidPrtAreaFlag() ) 1719 { 1720 GETGRID( FindPageFrm() ) 1721 if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() ) 1722 InvalidatePrt(); 1723 } 1724 1725 // Falls wir mit niemandem ueberlappen: 1726 // Ueberlappte irgendein Fly _vor_ der Positionsaenderung ? 1727 sal_Bool bFormat = pPara->HasFly(); 1728 if( !bFormat ) 1729 { 1730 if( IsInFly() ) 1731 { 1732 SwTwips nTmpBottom = GetUpper()->Frm().Top() + 1733 GetUpper()->Prt().Bottom(); 1734 if( nTmpBottom < Frm().Bottom() ) 1735 bFormat = sal_True; 1736 } 1737 if( !bFormat ) 1738 { 1739 if ( GetDrawObjs() ) 1740 { 1741 const sal_uInt32 nCnt = GetDrawObjs()->Count(); 1742 for ( MSHORT i = 0; i < nCnt; ++i ) 1743 { 1744 SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i]; 1745 // --> OD 2004-07-16 #i28701# - consider all 1746 // to-character anchored objects 1747 if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId() 1748 == FLY_AT_CHAR ) 1749 { 1750 bFormat = sal_True; 1751 break; 1752 } 1753 } 1754 } 1755 if( !bFormat ) 1756 { 1757 // Gibt es ueberhaupt Flys auf der Seite ? 1758 SwTxtFly aTxtFly( this ); 1759 if( aTxtFly.IsOn() ) 1760 { 1761 // Ueberlappt irgendein Fly ? 1762 aTxtFly.Relax(); 1763 bFormat = aTxtFly.IsOn() || IsUndersized(); 1764 } 1765 } 1766 } 1767 } 1768 1769 if( bFormat ) 1770 { 1771 if( !IsLocked() ) 1772 { 1773 if( pPara->GetRepaint()->HasArea() ) 1774 SetCompletePaint(); 1775 Init(); 1776 pPara = 0; 1777 _InvalidateSize(); 1778 } 1779 } 1780 else 1781 { 1782 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() ) 1783 Prepare( PREP_REGISTER, 0, bNotify ); 1784 // Durch Positionsverschiebungen mit Ftns muessen die 1785 // Frames neu adjustiert werden. 1786 else if( HasFtn() ) 1787 { 1788 Prepare( PREP_ADJUST_FRM, 0, bNotify ); 1789 _InvalidateSize(); 1790 } 1791 else 1792 return; // damit kein SetPrep() erfolgt. 1793 } 1794 break; 1795 } 1796 case PREP_REGISTER: 1797 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() ) 1798 { 1799 pPara->SetPrepAdjust( sal_True ); 1800 CalcLineSpace(); 1801 InvalidateSize(); 1802 _InvalidatePrt(); 1803 SwFrm* pNxt; 1804 if ( 0 != ( pNxt = GetIndNext() ) ) 1805 { 1806 pNxt->_InvalidatePrt(); 1807 if ( pNxt->IsLayoutFrm() ) 1808 pNxt->InvalidatePage(); 1809 } 1810 SetCompletePaint(); 1811 } 1812 break; 1813 case PREP_FTN_GONE : 1814 { 1815 // Wenn ein Follow uns ruft, weil eine Fussnote geloescht wird, muss unsere 1816 // letzte Zeile formatiert werden, damit ggf. die erste Zeile des Follows 1817 // hochrutschen kann, die extra auf die naechste Seite gerutscht war, um mit 1818 // der Fussnote zusammen zu sein, insbesondere bei spaltigen Bereichen. 1819 ASSERT( GetFollow(), "PREP_FTN_GONE darf nur vom Follow gerufen werden" ); 1820 xub_StrLen nPos = GetFollow()->GetOfst(); 1821 if( IsFollow() && GetOfst() == nPos ) // falls wir gar keine Textmasse besitzen, 1822 FindMaster()->Prepare( PREP_FTN_GONE ); // rufen wir das Prepare unseres Masters 1823 if( nPos ) 1824 --nPos; // das Zeichen vor unserem Follow 1825 InvalidateRange( SwCharRange( nPos, 1 ), 0 ); 1826 return; 1827 } 1828 case PREP_ERGOSUM: 1829 case PREP_QUOVADIS: 1830 { 1831 xub_StrLen nPos; 1832 if( lcl_ErgoVadis( this, nPos, ePrep ) ) 1833 InvalidateRange( SwCharRange( nPos, 1 ), 0 ); 1834 } 1835 break; 1836 case PREP_FLY_ATTR_CHG: 1837 { 1838 if( pVoid ) 1839 { 1840 xub_StrLen nWhere = CalcFlyPos( (SwFrmFmt*)pVoid ); 1841 ASSERT( STRING_LEN != nWhere, "Prepare: Why me?" ); 1842 InvalidateRange( SwCharRange( nWhere, 1 ) ); 1843 return; 1844 } 1845 // else ... Laufe in den Default-Switch 1846 } 1847 case PREP_CLEAR: 1848 default: 1849 { 1850 if( IsLocked() ) 1851 { 1852 if( PREP_FLY_ARRIVE == ePrep || PREP_FLY_LEAVE == ePrep ) 1853 { 1854 xub_StrLen nLen = ( GetFollow() ? GetFollow()->GetOfst() : 1855 STRING_LEN ) - GetOfst(); 1856 InvalidateRange( SwCharRange( GetOfst(), nLen ), 0 ); 1857 } 1858 } 1859 else 1860 { 1861 if( pPara->GetRepaint()->HasArea() ) 1862 SetCompletePaint(); 1863 Init(); 1864 pPara = 0; 1865 if( GetOfst() && !IsFollow() ) 1866 _SetOfst( 0 ); 1867 if ( bNotify ) 1868 InvalidateSize(); 1869 else 1870 _InvalidateSize(); 1871 } 1872 return; // damit kein SetPrep() erfolgt. 1873 } 1874 } 1875 if( pPara ) 1876 pPara->SetPrep( sal_True ); 1877 } 1878 1879 /* -----------------11.02.99 17:56------------------- 1880 * Kleine Hilfsklasse mit folgender Funktion: 1881 * Sie soll eine Probeformatierung vorbereiten. 1882 * Der Frame wird in Groesse und Position angepasst, sein SwParaPortion zur Seite 1883 * gestellt und eine neue erzeugt, dazu wird formatiert mit gesetztem bTestFormat. 1884 * Im Dtor wird der TxtFrm wieder in seinen alten Zustand zurueckversetzt. 1885 * 1886 * --------------------------------------------------*/ 1887 1888 class SwTestFormat 1889 { 1890 SwTxtFrm *pFrm; 1891 SwParaPortion *pOldPara; 1892 SwRect aOldFrm, aOldPrt; 1893 public: 1894 SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPrv, SwTwips nMaxHeight ); 1895 ~SwTestFormat(); 1896 }; 1897 1898 SwTestFormat::SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPre, SwTwips nMaxHeight ) 1899 : pFrm( pTxtFrm ) 1900 { 1901 aOldFrm = pFrm->Frm(); 1902 aOldPrt = pFrm->Prt(); 1903 1904 SWRECTFN( pFrm ) 1905 SwTwips nLower = (pFrm->*fnRect->fnGetBottomMargin)(); 1906 1907 pFrm->Frm() = pFrm->GetUpper()->Prt(); 1908 pFrm->Frm() += pFrm->GetUpper()->Frm().Pos(); 1909 1910 (pFrm->Frm().*fnRect->fnSetHeight)( nMaxHeight ); 1911 if( pFrm->GetPrev() ) 1912 (pFrm->Frm().*fnRect->fnSetPosY)( 1913 (pFrm->GetPrev()->Frm().*fnRect->fnGetBottom)() - 1914 ( bVert ? nMaxHeight + 1 : 0 ) ); 1915 1916 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm ); 1917 const SwBorderAttrs &rAttrs = *aAccess.Get(); 1918 (pFrm->Prt().*fnRect->fnSetPosX)( rAttrs.CalcLeft( pFrm ) ); 1919 1920 if( pPre ) 1921 { 1922 SwTwips nUpper = pFrm->CalcUpperSpace( &rAttrs, pPre ); 1923 (pFrm->Prt().*fnRect->fnSetPosY)( nUpper ); 1924 } 1925 (pFrm->Prt().*fnRect->fnSetHeight)( 1926 Max( 0L , (pFrm->Frm().*fnRect->fnGetHeight)() - 1927 (pFrm->Prt().*fnRect->fnGetTop)() - nLower ) ); 1928 (pFrm->Prt().*fnRect->fnSetWidth)( 1929 (pFrm->Frm().*fnRect->fnGetWidth)() - 1930 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)> 1931 ( rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm ) ) ); 1932 pOldPara = pFrm->HasPara() ? pFrm->GetPara() : NULL; 1933 pFrm->SetPara( new SwParaPortion(), sal_False ); 1934 1935 ASSERT( ! pFrm->IsSwapped(), "A frame is swapped before _Format" ); 1936 1937 if ( pFrm->IsVertical() ) 1938 pFrm->SwapWidthAndHeight(); 1939 1940 SwTxtFormatInfo aInf( pFrm, sal_False, sal_True, sal_True ); 1941 SwTxtFormatter aLine( pFrm, &aInf ); 1942 1943 pFrm->_Format( aLine, aInf ); 1944 1945 if ( pFrm->IsVertical() ) 1946 pFrm->SwapWidthAndHeight(); 1947 1948 ASSERT( ! pFrm->IsSwapped(), "A frame is swapped after _Format" ); 1949 } 1950 1951 SwTestFormat::~SwTestFormat() 1952 { 1953 pFrm->Frm() = aOldFrm; 1954 pFrm->Prt() = aOldPrt; 1955 pFrm->SetPara( pOldPara ); 1956 } 1957 1958 sal_Bool SwTxtFrm::TestFormat( const SwFrm* pPrv, SwTwips &rMaxHeight, sal_Bool &bSplit ) 1959 { 1960 PROTOCOL_ENTER( this, PROT_TESTFORMAT, 0, 0 ) 1961 1962 if( IsLocked() && GetUpper()->Prt().Width() <= 0 ) 1963 return sal_False; 1964 1965 SwTestFormat aSave( this, pPrv, rMaxHeight ); 1966 1967 return SwTxtFrm::WouldFit( rMaxHeight, bSplit, sal_True ); 1968 } 1969 1970 1971 /************************************************************************* 1972 * SwTxtFrm::WouldFit() 1973 *************************************************************************/ 1974 1975 /* SwTxtFrm::WouldFit() 1976 * sal_True: wenn ich aufspalten kann. 1977 * Es soll und braucht nicht neu formatiert werden. 1978 * Wir gehen davon aus, dass bereits formatiert wurde und dass 1979 * die Formatierungsdaten noch aktuell sind. 1980 * Wir gehen davon aus, dass die Framebreiten des evtl. Masters und 1981 * Follows gleich sind. Deswegen wird kein FindBreak() mit FindOrphans() 1982 * gerufen. 1983 * Die benoetigte Hoehe wird von nMaxHeight abgezogen! 1984 */ 1985 1986 sal_Bool SwTxtFrm::WouldFit( SwTwips &rMaxHeight, sal_Bool &bSplit, sal_Bool bTst ) 1987 { 1988 ASSERT( ! IsVertical() || ! IsSwapped(), 1989 "SwTxtFrm::WouldFit with swapped frame" ); 1990 SWRECTFN( this ); 1991 1992 if( IsLocked() ) 1993 return sal_False; 1994 1995 //Kann gut sein, dass mir der IdleCollector mir die gecachten 1996 //Informationen entzogen hat. 1997 if( !IsEmpty() ) 1998 GetFormatted(); 1999 2000 // OD 2004-05-24 #i27801# - correction: 'short cut' for empty paragraph 2001 // can *not* be applied, if test format is in progress. The test format doesn't 2002 // adjust the frame and the printing area - see method <SwTxtFrm::_Format(..)>, 2003 // which is called in <SwTxtFrm::TestFormat(..)> 2004 if ( IsEmpty() && !bTst ) 2005 { 2006 bSplit = sal_False; 2007 SwTwips nHeight = bVert ? Prt().SSize().Width() : Prt().SSize().Height(); 2008 if( rMaxHeight < nHeight ) 2009 return sal_False; 2010 else 2011 { 2012 rMaxHeight -= nHeight; 2013 return sal_True; 2014 } 2015 } 2016 2017 // In sehr unguenstigen Faellen kann GetPara immer noch 0 sein. 2018 // Dann returnen wir sal_True, um auf der neuen Seite noch einmal 2019 // anformatiert zu werden. 2020 ASSERT( HasPara() || IsHiddenNow(), "WouldFit: GetFormatted() and then !HasPara()" ); 2021 if( !HasPara() || ( !(Frm().*fnRect->fnGetHeight)() && IsHiddenNow() ) ) 2022 return sal_True; 2023 2024 // Da das Orphan-Flag nur sehr fluechtig existiert, wird als zweite 2025 // Bedingung ueberprueft, ob die Rahmengroesse durch CalcPreps 2026 // auf riesengross gesetzt wird, um ein MoveFwd zu erzwingen. 2027 if( IsWidow() || ( bVert ? 2028 ( 0 == Frm().Left() ) : 2029 ( LONG_MAX - 20000 < Frm().Bottom() ) ) ) 2030 { 2031 SetWidow(sal_False); 2032 if ( GetFollow() ) 2033 { 2034 // Wenn wir hier durch eine Widow-Anforderung unseres Follows gelandet 2035 // sind, wird ueberprueft, ob es ueberhaupt einen Follow mit einer 2036 // echten Hoehe gibt, andernfalls (z.B. in neu angelegten SctFrms) 2037 // ignorieren wir das IsWidow() und pruefen doch noch, ob wir 2038 // genung Platz finden. 2039 if( ( ( ! bVert && LONG_MAX - 20000 >= Frm().Bottom() ) || 2040 ( bVert && 0 < Frm().Left() ) ) && 2041 ( GetFollow()->IsVertical() ? 2042 !GetFollow()->Frm().Width() : 2043 !GetFollow()->Frm().Height() ) ) 2044 { 2045 SwTxtFrm* pFoll = GetFollow()->GetFollow(); 2046 while( pFoll && 2047 ( pFoll->IsVertical() ? 2048 !pFoll->Frm().Width() : 2049 !pFoll->Frm().Height() ) ) 2050 pFoll = pFoll->GetFollow(); 2051 if( pFoll ) 2052 return sal_False; 2053 } 2054 else 2055 return sal_False; 2056 } 2057 } 2058 2059 SWAP_IF_NOT_SWAPPED( this ); 2060 2061 SwTxtSizeInfo aInf( this ); 2062 SwTxtMargin aLine( this, &aInf ); 2063 2064 WidowsAndOrphans aFrmBreak( this, rMaxHeight, bSplit ); 2065 2066 sal_Bool bRet = sal_True; 2067 2068 aLine.Bottom(); 2069 // Ist Aufspalten ueberhaupt notwendig? 2070 if ( 0 != ( bSplit = !aFrmBreak.IsInside( aLine ) ) ) 2071 bRet = !aFrmBreak.IsKeepAlways() && aFrmBreak.WouldFit( aLine, rMaxHeight, bTst ); 2072 else 2073 { 2074 //Wir brauchen die Gesamthoehe inklusive der aktuellen Zeile 2075 aLine.Top(); 2076 do 2077 { 2078 rMaxHeight -= aLine.GetLineHeight(); 2079 } while ( aLine.Next() ); 2080 } 2081 2082 UNDO_SWAP( this ) 2083 2084 return bRet; 2085 } 2086 2087 2088 /************************************************************************* 2089 * SwTxtFrm::GetParHeight() 2090 *************************************************************************/ 2091 2092 KSHORT SwTxtFrm::GetParHeight() const 2093 { 2094 ASSERT( ! IsVertical() || ! IsSwapped(), 2095 "SwTxtFrm::GetParHeight with swapped frame" ) 2096 2097 if( !HasPara() ) 2098 { // Fuer nichtleere Absaetze ist dies ein Sonderfall, da koennen wir 2099 // bei UnderSized ruhig nur 1 Twip mehr anfordern. 2100 KSHORT nRet = (KSHORT)Prt().SSize().Height(); 2101 if( IsUndersized() ) 2102 { 2103 if( IsEmpty() ) 2104 nRet = (KSHORT)EmptyHeight(); 2105 else 2106 ++nRet; 2107 } 2108 return nRet; 2109 } 2110 2111 // FME, OD 08.01.2004 #i11859# - refactoring and improve code 2112 const SwLineLayout* pLineLayout = GetPara(); 2113 KSHORT nHeight = pLineLayout->GetRealHeight(); 2114 if( GetOfst() && !IsFollow() ) // Ist dieser Absatz gescrollt? Dann ist unsere 2115 nHeight *= 2; // bisherige Hoehe mind. eine Zeilenhoehe zu gering 2116 // OD 2004-03-04 #115793# 2117 while ( pLineLayout && pLineLayout->GetNext() ) 2118 { 2119 pLineLayout = pLineLayout->GetNext(); 2120 nHeight = nHeight + pLineLayout->GetRealHeight(); 2121 } 2122 2123 return nHeight; 2124 } 2125 2126 2127 /************************************************************************* 2128 * SwTxtFrm::GetFormatted() 2129 *************************************************************************/ 2130 2131 // returnt this _immer_ im formatierten Zustand! 2132 SwTxtFrm* SwTxtFrm::GetFormatted( bool bForceQuickFormat ) 2133 { 2134 SWAP_IF_SWAPPED( this ) 2135 2136 //Kann gut sein, dass mir der IdleCollector mir die gecachten 2137 //Informationen entzogen hat. Calc() ruft unser Format. 2138 //Nicht bei leeren Absaetzen! 2139 if( !HasPara() && !(IsValid() && IsEmpty()) ) 2140 { 2141 // Calc() muss gerufen werden, weil unsere Frameposition 2142 // nicht stimmen muss. 2143 const sal_Bool bFormat = GetValidSizeFlag(); 2144 Calc(); 2145 // Es kann durchaus sein, dass Calc() das Format() 2146 // nicht anstiess (weil wir einst vom Idle-Zerstoerer 2147 // aufgefordert wurden unsere Formatinformationen wegzuschmeissen). 2148 // 6995: Optimierung mit FormatQuick() 2149 if( bFormat && !FormatQuick( bForceQuickFormat ) ) 2150 Format(); 2151 } 2152 2153 UNDO_SWAP( this ) 2154 2155 return this; 2156 } 2157 2158 /************************************************************************* 2159 * SwTxtFrm::CalcFitToContent() 2160 *************************************************************************/ 2161 2162 SwTwips SwTxtFrm::CalcFitToContent() 2163 { 2164 // --> FME 2004-07-16 #i31490# 2165 // If we are currently locked, we better return with a 2166 // fairly reasonable value: 2167 if ( IsLocked() ) 2168 return Prt().Width(); 2169 // <-- 2170 2171 SwParaPortion* pOldPara = GetPara(); 2172 SwParaPortion *pDummy = new SwParaPortion(); 2173 SetPara( pDummy, false ); 2174 const SwPageFrm* pPage = FindPageFrm(); 2175 2176 const Point aOldFrmPos = Frm().Pos(); 2177 const SwTwips nOldFrmWidth = Frm().Width(); 2178 const SwTwips nOldPrtWidth = Prt().Width(); 2179 const SwTwips nPageWidth = GetUpper()->IsVertical() ? 2180 pPage->Prt().Height() : 2181 pPage->Prt().Width(); 2182 2183 Frm().Width( nPageWidth ); 2184 Prt().Width( nPageWidth ); 2185 2186 // --> FME 2004-07-19 #i25422# objects anchored as character in RTL 2187 if ( IsRightToLeft() ) 2188 Frm().Pos().X() += nOldFrmWidth - nPageWidth; 2189 2190 // --> FME 2004-07-16 #i31490# 2191 SwTxtFrmLocker aLock( this ); 2192 // <-- 2193 2194 SwTxtFormatInfo aInf( this, sal_False, sal_True, sal_True ); 2195 aInf.SetIgnoreFly( sal_True ); 2196 SwTxtFormatter aLine( this, &aInf ); 2197 SwHookOut aHook( aInf ); 2198 2199 // --> OD 2005-09-06 #i54031# - assure mininum of MINLAY twips. 2200 const SwTwips nMax = Max( (SwTwips)MINLAY, 2201 aLine._CalcFitToContent() + 1 ); 2202 // <-- 2203 2204 Frm().Width( nOldFrmWidth ); 2205 Prt().Width( nOldPrtWidth ); 2206 2207 // --> FME 2004-07-19 #i25422# objects anchored as character in RTL 2208 if ( IsRightToLeft() ) 2209 Frm().Pos() = aOldFrmPos; 2210 2211 2212 SetPara( pOldPara ); 2213 2214 return nMax; 2215 } 2216 2217 /** simulate format for a list item paragraph, whose list level attributes 2218 are in LABEL_ALIGNMENT mode, in order to determine additional first 2219 line offset for the real text formatting due to the value of label 2220 adjustment attribute of the list level. 2221 2222 OD 2008-01-31 #newlistlevelattrs# 2223 2224 @author OD 2225 */ 2226 void SwTxtFrm::CalcAdditionalFirstLineOffset() 2227 { 2228 if ( IsLocked() ) 2229 return; 2230 2231 // reset additional first line offset 2232 mnAdditionalFirstLineOffset = 0; 2233 2234 const SwTxtNode* pTxtNode( GetTxtNode() ); 2235 if ( pTxtNode && pTxtNode->IsNumbered() && pTxtNode->IsCountedInList() && 2236 pTxtNode->GetNumRule() ) 2237 { 2238 const SwNumFmt& rNumFmt = 2239 pTxtNode->GetNumRule()->Get( static_cast<sal_uInt16>(pTxtNode->GetActualListLevel()) ); 2240 if ( rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 2241 { 2242 // keep current paragraph portion and apply dummy paragraph portion 2243 SwParaPortion* pOldPara = GetPara(); 2244 SwParaPortion *pDummy = new SwParaPortion(); 2245 SetPara( pDummy, false ); 2246 2247 // lock paragraph 2248 SwTxtFrmLocker aLock( this ); 2249 2250 // simulate text formatting 2251 SwTxtFormatInfo aInf( this, sal_False, sal_True, sal_True ); 2252 aInf.SetIgnoreFly( sal_True ); 2253 SwTxtFormatter aLine( this, &aInf ); 2254 SwHookOut aHook( aInf ); 2255 aLine._CalcFitToContent(); 2256 2257 // determine additional first line offset 2258 const SwLinePortion* pFirstPortion = aLine.GetCurr()->GetFirstPortion(); 2259 if ( pFirstPortion->InNumberGrp() && !pFirstPortion->IsFtnNumPortion() ) 2260 { 2261 SwTwips nNumberPortionWidth( pFirstPortion->Width() ); 2262 2263 const SwLinePortion* pPortion = pFirstPortion->GetPortion(); 2264 while ( pPortion && 2265 pPortion->InNumberGrp() && !pPortion->IsFtnNumPortion()) 2266 { 2267 nNumberPortionWidth += pPortion->Width(); 2268 pPortion = pPortion->GetPortion(); 2269 } 2270 2271 if ( ( IsRightToLeft() && 2272 rNumFmt.GetNumAdjust() == SVX_ADJUST_LEFT ) || 2273 ( !IsRightToLeft() && 2274 rNumFmt.GetNumAdjust() == SVX_ADJUST_RIGHT ) ) 2275 { 2276 mnAdditionalFirstLineOffset = -nNumberPortionWidth; 2277 } 2278 else if ( rNumFmt.GetNumAdjust() == SVX_ADJUST_CENTER ) 2279 { 2280 mnAdditionalFirstLineOffset = -(nNumberPortionWidth/2); 2281 } 2282 } 2283 2284 // restore paragraph portion 2285 SetPara( pOldPara ); 2286 } 2287 } 2288 } 2289 2290 /** determine height of last line for the calculation of the proportional line 2291 spacing 2292 2293 OD 08.01.2004 #i11859# 2294 OD 2004-03-17 #i11860# - method <GetHeightOfLastLineForPropLineSpacing()> 2295 replace by method <_CalcHeightOfLastLine()>. Height of last line will be 2296 stored in new member <mnHeightOfLastLine> and can be accessed via method 2297 <GetHeightOfLastLine()> 2298 OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont> 2299 in order to force the usage of the former algorithm to determine the 2300 height of the last line, which uses the font. 2301 2302 @author OD 2303 */ 2304 void SwTxtFrm::_CalcHeightOfLastLine( const bool _bUseFont ) 2305 { 2306 // --> OD 2006-11-13 #i71281# 2307 // invalidate printing area, if height of last line changes 2308 const SwTwips mnOldHeightOfLastLine( mnHeightOfLastLine ); 2309 // <-- 2310 // determine output device 2311 ViewShell* pVsh = getRootFrm()->GetCurrShell(); 2312 ASSERT( pVsh, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no ViewShell" ); 2313 // --> OD 2007-07-02 #i78921# - make code robust, according to provided patch 2314 // There could be no <ViewShell> instance in the case of loading a binary 2315 // StarOffice file format containing an embedded Writer document. 2316 if ( !pVsh ) 2317 { 2318 return; 2319 } 2320 OutputDevice* pOut = pVsh->GetOut(); 2321 const IDocumentSettingAccess* pIDSA = GetTxtNode()->getIDocumentSettingAccess(); 2322 if ( !pVsh->GetViewOptions()->getBrowseMode() || 2323 pVsh->GetViewOptions()->IsPrtFormat() ) 2324 { 2325 pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true ); 2326 } 2327 ASSERT( pOut, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no OutputDevice" ); 2328 // --> OD 2007-07-02 #i78921# - make code robust, according to provided patch 2329 if ( !pOut ) 2330 { 2331 return; 2332 } 2333 // <-- 2334 2335 // determine height of last line 2336 2337 if ( _bUseFont || pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING ) ) 2338 { 2339 // former determination of last line height for proprotional line 2340 // spacing - take height of font set at the paragraph 2341 SwFont aFont( GetAttrSet(), pIDSA ); 2342 2343 // Wir muessen dafuer sorgen, dass am OutputDevice der Font 2344 // korrekt restauriert wird, sonst droht ein Last!=Owner. 2345 if ( pLastFont ) 2346 { 2347 SwFntObj *pOldFont = pLastFont; 2348 pLastFont = NULL; 2349 aFont.SetFntChg( sal_True ); 2350 aFont.ChgPhysFnt( pVsh, *pOut ); 2351 mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut ); 2352 pLastFont->Unlock(); 2353 pLastFont = pOldFont; 2354 pLastFont->SetDevFont( pVsh, *pOut ); 2355 } 2356 else 2357 { 2358 Font aOldFont = pOut->GetFont(); 2359 aFont.SetFntChg( sal_True ); 2360 aFont.ChgPhysFnt( pVsh, *pOut ); 2361 mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut ); 2362 pLastFont->Unlock(); 2363 pLastFont = NULL; 2364 pOut->SetFont( aOldFont ); 2365 } 2366 } 2367 else 2368 { 2369 // new determination of last line height - take actually height of last line 2370 // --> OD 2008-05-06 #i89000# 2371 // assure same results, if paragraph is undersized 2372 if ( IsUndersized() ) 2373 { 2374 mnHeightOfLastLine = 0; 2375 } 2376 else 2377 { 2378 bool bCalcHeightOfLastLine = true; 2379 if ( !HasPara() ) 2380 { 2381 if ( IsEmpty() ) 2382 { 2383 mnHeightOfLastLine = EmptyHeight(); 2384 bCalcHeightOfLastLine = false; 2385 } 2386 } 2387 2388 if ( bCalcHeightOfLastLine ) 2389 { 2390 ASSERT( HasPara(), 2391 "<SwTxtFrm::_CalcHeightOfLastLine()> - missing paragraph portions." ); 2392 const SwLineLayout* pLineLayout = GetPara(); 2393 while ( pLineLayout && pLineLayout->GetNext() ) 2394 { 2395 // iteration to last line 2396 pLineLayout = pLineLayout->GetNext(); 2397 } 2398 if ( pLineLayout ) 2399 { 2400 SwTwips nAscent, nDescent, nDummy1, nDummy2; 2401 // --> OD 2005-05-20 #i47162# - suppress consideration of 2402 // fly content portions and the line portion. 2403 pLineLayout->MaxAscentDescent( nAscent, nDescent, 2404 nDummy1, nDummy2, 2405 0, true ); 2406 // <-- 2407 // --> OD 2006-11-22 #i71281# 2408 // Suppress wrong invalidation of printing area, if method is 2409 // called recursive. 2410 // Thus, member <mnHeightOfLastLine> is only set directly, if 2411 // no recursive call is needed. 2412 // mnHeightOfLastLine = nAscent + nDescent; 2413 const SwTwips nNewHeightOfLastLine = nAscent + nDescent; 2414 // --> OD 2005-05-20 #i47162# - if last line only contains 2415 // fly content portions, <mnHeightOfLastLine> is zero. 2416 // In this case determine height of last line by the font 2417 if ( nNewHeightOfLastLine == 0 ) 2418 { 2419 _CalcHeightOfLastLine( true ); 2420 } 2421 else 2422 { 2423 mnHeightOfLastLine = nNewHeightOfLastLine; 2424 } 2425 // <-- 2426 // <-- 2427 } 2428 } 2429 } 2430 // <-- 2431 } 2432 // --> OD 2006-11-13 #i71281# 2433 // invalidate printing area, if height of last line changes 2434 if ( mnHeightOfLastLine != mnOldHeightOfLastLine ) 2435 { 2436 InvalidatePrt(); 2437 } 2438 // <-- 2439 } 2440 2441 /************************************************************************* 2442 * SwTxtFrm::GetLineSpace() 2443 *************************************************************************/ 2444 // OD 07.01.2004 #i11859# - change return data type 2445 // add default parameter <_bNoPropLineSpacing> to control, if the 2446 // value of a proportional line spacing is returned or not 2447 // OD 07.01.2004 - trying to describe purpose of method: 2448 // Method returns the value of the inter line spacing for a text frame. 2449 // Such a value exists for proportional line spacings ("1,5 Lines", 2450 // "Double", "Proportional" and for leading line spacing ("Leading"). 2451 // By parameter <_bNoPropLineSpace> (default value false) it can be 2452 // controlled, if the value of a proportional line spacing is returned. 2453 long SwTxtFrm::GetLineSpace( const bool _bNoPropLineSpace ) const 2454 { 2455 long nRet = 0; 2456 2457 const SwAttrSet* pSet = GetAttrSet(); 2458 const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing(); 2459 2460 switch( rSpace.GetInterLineSpaceRule() ) 2461 { 2462 case SVX_INTER_LINE_SPACE_PROP: 2463 { 2464 // OD 07.01.2004 #i11859# 2465 if ( _bNoPropLineSpace ) 2466 { 2467 break; 2468 } 2469 2470 // OD 2004-03-17 #i11860# - use method <GetHeightOfLastLine()> 2471 nRet = GetHeightOfLastLine(); 2472 2473 long nTmp = nRet; 2474 nTmp *= rSpace.GetPropLineSpace(); 2475 nTmp /= 100; 2476 nTmp -= nRet; 2477 if ( nTmp > 0 ) 2478 nRet = nTmp; 2479 else 2480 nRet = 0; 2481 } 2482 break; 2483 case SVX_INTER_LINE_SPACE_FIX: 2484 { 2485 if ( rSpace.GetInterLineSpace() > 0 ) 2486 nRet = rSpace.GetInterLineSpace(); 2487 } 2488 break; 2489 default: 2490 break; 2491 } 2492 return nRet; 2493 } 2494 2495 /************************************************************************* 2496 * SwTxtFrm::FirstLineHeight() 2497 *************************************************************************/ 2498 2499 KSHORT SwTxtFrm::FirstLineHeight() const 2500 { 2501 if ( !HasPara() ) 2502 { 2503 if( IsEmpty() && IsValid() ) 2504 return IsVertical() ? (KSHORT)Prt().Width() : (KSHORT)Prt().Height(); 2505 return KSHRT_MAX; 2506 } 2507 const SwParaPortion *pPara = GetPara(); 2508 if ( !pPara ) 2509 return KSHRT_MAX; 2510 2511 return pPara->Height(); 2512 } 2513 2514 MSHORT SwTxtFrm::GetLineCount( xub_StrLen nPos ) 2515 { 2516 MSHORT nRet = 0; 2517 SwTxtFrm *pFrm = this; 2518 do 2519 { 2520 pFrm->GetFormatted(); 2521 if( !pFrm->HasPara() ) 2522 break; 2523 SwTxtSizeInfo aInf( pFrm ); 2524 SwTxtMargin aLine( pFrm, &aInf ); 2525 if( STRING_LEN == nPos ) 2526 aLine.Bottom(); 2527 else 2528 aLine.CharToLine( nPos ); 2529 nRet = nRet + aLine.GetLineNr(); 2530 pFrm = pFrm->GetFollow(); 2531 } while ( pFrm && pFrm->GetOfst() <= nPos ); 2532 return nRet; 2533 } 2534 2535 void SwTxtFrm::ChgThisLines() 2536 { 2537 //not necassary to format here (GerFormatted etc.), because we have to come from there! 2538 2539 sal_uLong nNew = 0; 2540 const SwLineNumberInfo &rInf = GetNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo(); 2541 if ( GetTxt().Len() && HasPara() ) 2542 { 2543 SwTxtSizeInfo aInf( this ); 2544 SwTxtMargin aLine( this, &aInf ); 2545 if ( rInf.IsCountBlankLines() ) 2546 { 2547 aLine.Bottom(); 2548 nNew = (sal_uLong)aLine.GetLineNr(); 2549 } 2550 else 2551 { 2552 do 2553 { 2554 if( aLine.GetCurr()->HasCntnt() ) 2555 ++nNew; 2556 } while ( aLine.NextLine() ); 2557 } 2558 } 2559 else if ( rInf.IsCountBlankLines() ) 2560 nNew = 1; 2561 2562 if ( nNew != nThisLines ) 2563 { 2564 if ( !IsInTab() && GetAttrSet()->GetLineNumber().IsCount() ) 2565 { 2566 nAllLines -= nThisLines; 2567 nThisLines = nNew; 2568 nAllLines += nThisLines; 2569 SwFrm *pNxt = GetNextCntntFrm(); 2570 while( pNxt && pNxt->IsInTab() ) 2571 { 2572 if( 0 != (pNxt = pNxt->FindTabFrm()) ) 2573 pNxt = pNxt->FindNextCnt(); 2574 } 2575 if( pNxt ) 2576 pNxt->InvalidateLineNum(); 2577 2578 //Extend repaint to the bottom. 2579 if ( HasPara() ) 2580 { 2581 SwRepaint *pRepaint = GetPara()->GetRepaint(); 2582 pRepaint->Bottom( Max( pRepaint->Bottom(), 2583 Frm().Top()+Prt().Bottom())); 2584 } 2585 } 2586 else //Paragraphs which are not counted should not manipulate the AllLines. 2587 nThisLines = nNew; 2588 } 2589 2590 //mba: invalidating is not necessary; if mongolian script has a problem, it should be fixed at the ritgh place 2591 //with invalidating we probably get too much flickering 2592 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 2593 //Ugly. How can we hack if better? 2594 //InvalidatePage(); 2595 } 2596 2597 2598 void SwTxtFrm::RecalcAllLines() 2599 { 2600 ValidateLineNum(); 2601 2602 const SwAttrSet *pAttrSet = GetAttrSet(); 2603 2604 if ( !IsInTab() ) 2605 { 2606 const sal_uLong nOld = GetAllLines(); 2607 const SwFmtLineNumber &rLineNum = pAttrSet->GetLineNumber(); 2608 sal_uLong nNewNum; 2609 const bool bRestart = GetTxtNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo().IsRestartEachPage(); 2610 2611 if ( !IsFollow() && rLineNum.GetStartValue() && rLineNum.IsCount() ) 2612 nNewNum = rLineNum.GetStartValue() - 1; 2613 //If it is a follow or not has not be considered if it is a restart at each page; the 2614 //restart should also take affekt at follows. 2615 else if ( bRestart && FindPageFrm()->FindFirstBodyCntnt() == this ) 2616 { 2617 nNewNum = 0; 2618 } 2619 else 2620 { 2621 SwCntntFrm *pPrv = GetPrevCntntFrm(); 2622 while ( pPrv && 2623 (pPrv->IsInTab() || pPrv->IsInDocBody() != IsInDocBody()) ) 2624 pPrv = pPrv->GetPrevCntntFrm(); 2625 2626 // --> FME 2007-06-22 #i78254# Restart line numbering at page change: 2627 // First body content may be in table! 2628 if ( bRestart && pPrv && pPrv->FindPageFrm() != FindPageFrm() ) 2629 pPrv = 0; 2630 // <-- 2631 2632 nNewNum = pPrv ? ((SwTxtFrm*)pPrv)->GetAllLines() : 0; 2633 } 2634 if ( rLineNum.IsCount() ) 2635 nNewNum += GetThisLines(); 2636 2637 if ( nOld != nNewNum ) 2638 { 2639 nAllLines = nNewNum; 2640 SwCntntFrm *pNxt = GetNextCntntFrm(); 2641 while ( pNxt && 2642 (pNxt->IsInTab() || pNxt->IsInDocBody() != IsInDocBody()) ) 2643 pNxt = pNxt->GetNextCntntFrm(); 2644 if ( pNxt ) 2645 { 2646 if ( pNxt->GetUpper() != GetUpper() ) 2647 pNxt->InvalidateLineNum(); 2648 else 2649 pNxt->_InvalidateLineNum(); 2650 } 2651 } 2652 } 2653 } 2654 2655 void SwTxtFrm::VisitPortions( SwPortionHandler& rPH ) const 2656 { 2657 const SwParaPortion* pPara = GetPara(); 2658 2659 if( pPara ) 2660 { 2661 if ( IsFollow() ) 2662 rPH.Skip( GetOfst() ); 2663 2664 const SwLineLayout* pLine = pPara; 2665 while ( pLine ) 2666 { 2667 const SwLinePortion* pPor = pLine->GetFirstPortion(); 2668 while ( pPor ) 2669 { 2670 pPor->HandlePortion( rPH ); 2671 pPor = pPor->GetPortion(); 2672 } 2673 2674 rPH.LineBreak(); 2675 pLine = pLine->GetNext(); 2676 } 2677 } 2678 2679 rPH.Finish(); 2680 } 2681 2682 2683 /************************************************************************* 2684 * SwTxtFrm::GetScriptInfo() 2685 *************************************************************************/ 2686 2687 const SwScriptInfo* SwTxtFrm::GetScriptInfo() const 2688 { 2689 const SwParaPortion* pPara = GetPara(); 2690 return pPara ? &pPara->GetScriptInfo() : 0; 2691 } 2692 2693 /************************************************************************* 2694 * lcl_CalcFlyBasePos() 2695 * Helper function for SwTxtFrm::CalcBasePosForFly() 2696 *************************************************************************/ 2697 2698 SwTwips lcl_CalcFlyBasePos( const SwTxtFrm& rFrm, SwRect aFlyRect, 2699 SwTxtFly& rTxtFly ) 2700 { 2701 SWRECTFN( (&rFrm) ) 2702 SwTwips nRet = rFrm.IsRightToLeft() ? 2703 (rFrm.Frm().*fnRect->fnGetRight)() : 2704 (rFrm.Frm().*fnRect->fnGetLeft)(); 2705 2706 do 2707 { 2708 SwRect aRect = rTxtFly.GetFrm( aFlyRect ); 2709 if ( 0 != (aRect.*fnRect->fnGetWidth)() ) 2710 { 2711 if ( rFrm.IsRightToLeft() ) 2712 { 2713 if ( (aRect.*fnRect->fnGetRight)() - 2714 (aFlyRect.*fnRect->fnGetRight)() >= 0 ) 2715 { 2716 (aFlyRect.*fnRect->fnSetRight)( 2717 (aRect.*fnRect->fnGetLeft)() ); 2718 nRet = (aRect.*fnRect->fnGetLeft)(); 2719 } 2720 else 2721 break; 2722 } 2723 else 2724 { 2725 if ( (aFlyRect.*fnRect->fnGetLeft)() - 2726 (aRect.*fnRect->fnGetLeft)() >= 0 ) 2727 { 2728 (aFlyRect.*fnRect->fnSetLeft)( 2729 (aRect.*fnRect->fnGetRight)() + 1 ); 2730 nRet = (aRect.*fnRect->fnGetRight)(); 2731 } 2732 else 2733 break; 2734 } 2735 } 2736 else 2737 break; 2738 } 2739 while ( (aFlyRect.*fnRect->fnGetWidth)() > 0 ); 2740 2741 return nRet; 2742 } 2743 2744 /************************************************************************* 2745 * SwTxtFrm::CalcBasePosForFly() 2746 *************************************************************************/ 2747 2748 void SwTxtFrm::CalcBaseOfstForFly() 2749 { 2750 ASSERT( !IsVertical() || !IsSwapped(), 2751 "SwTxtFrm::CalcBasePosForFly with swapped frame!" ) 2752 2753 const SwNode* pNode = GetTxtNode(); 2754 if ( !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_FLY_OFFSETS) ) 2755 return; 2756 2757 SWRECTFN( this ) 2758 2759 SwRect aFlyRect( Frm().Pos() + Prt().Pos(), Prt().SSize() ); 2760 2761 // Get first 'real' line and adjust position and height of line rectangle 2762 // OD 08.09.2003 #110978#, #108749#, #110354# - correct behaviour, 2763 // if no 'real' line exists (empty paragraph with and without a dummy portion) 2764 { 2765 SwTwips nTop = (aFlyRect.*fnRect->fnGetTop)(); 2766 const SwLineLayout* pLay = GetPara(); 2767 SwTwips nLineHeight = 200; 2768 while( pLay && pLay->IsDummy() && pLay->GetNext() ) 2769 { 2770 nTop += pLay->Height(); 2771 pLay = pLay->GetNext(); 2772 } 2773 if ( pLay ) 2774 { 2775 nLineHeight = pLay->Height(); 2776 } 2777 (aFlyRect.*fnRect->fnSetTopAndHeight)( nTop, nLineHeight ); 2778 } 2779 2780 SwTxtFly aTxtFly( this ); 2781 aTxtFly.SetIgnoreCurrentFrame( sal_True ); 2782 aTxtFly.SetIgnoreContour( sal_True ); 2783 // --> OD 2004-12-17 #118809# - ignore objects in page header|footer for 2784 // text frames not in page header|footer 2785 aTxtFly.SetIgnoreObjsInHeaderFooter( sal_True ); 2786 // <-- 2787 SwTwips nRet1 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly ); 2788 aTxtFly.SetIgnoreCurrentFrame( sal_False ); 2789 SwTwips nRet2 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly ); 2790 2791 // make values relative to frame start position 2792 SwTwips nLeft = IsRightToLeft() ? 2793 (Frm().*fnRect->fnGetRight)() : 2794 (Frm().*fnRect->fnGetLeft)(); 2795 2796 mnFlyAnchorOfst = nRet1 - nLeft; 2797 mnFlyAnchorOfstNoWrap = nRet2 - nLeft; 2798 } 2799 2800 /* repaint all text frames of the given text node */ 2801 void SwTxtFrm::repaintTextFrames( const SwTxtNode& rNode ) 2802 { 2803 SwIterator<SwTxtFrm,SwTxtNode> aIter( rNode ); 2804 for( const SwTxtFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() ) 2805 { 2806 SwRect aRec( pFrm->PaintArea() ); 2807 const SwRootFrm *pRootFrm = pFrm->getRootFrm(); 2808 ViewShell *pCurShell = pRootFrm ? pRootFrm->GetCurrShell() : NULL; 2809 if( pCurShell ) 2810 pCurShell->InvalidateWindows( aRec ); 2811 } 2812 } 2813 2814