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 // 6870: SwDocPosUpdate auswerten. 1335 case RES_DOCPOS_UPDATE: 1336 { 1337 if( pOld && pNew ) 1338 { 1339 const SwDocPosUpdate *pDocPos = (const SwDocPosUpdate*)pOld; 1340 if( pDocPos->nDocPos <= aFrm.Top() ) 1341 { 1342 const SwFmtFld *pFld = (const SwFmtFld *)pNew; 1343 InvalidateRange( 1344 SwCharRange( *pFld->GetTxtFld()->GetStart(), 1 ) ); 1345 } 1346 } 1347 break; 1348 } 1349 case RES_PARATR_SPLIT: 1350 if ( GetPrev() ) 1351 CheckKeep(); 1352 Prepare( PREP_CLEAR ); 1353 bSetFldsDirty = sal_True; 1354 break; 1355 case RES_FRAMEDIR : 1356 SetDerivedR2L( sal_False ); 1357 CheckDirChange(); 1358 break; 1359 default: 1360 { 1361 Prepare( PREP_CLEAR ); 1362 _InvalidatePrt(); 1363 if ( !nWhich ) 1364 { 1365 //Wird z.B. bei HiddenPara mit 0 gerufen. 1366 SwFrm *pNxt; 1367 if ( 0 != (pNxt = FindNext()) ) 1368 pNxt->InvalidatePrt(); 1369 } 1370 } 1371 } // switch 1372 1373 if( bSetFldsDirty ) 1374 GetNode()->getIDocumentFieldsAccess()->SetFieldsDirty( sal_True, GetNode(), 1 ); 1375 1376 if ( bRecalcFtnFlag ) 1377 CalcFtnFlag(); 1378 } 1379 1380 sal_Bool SwTxtFrm::GetInfo( SfxPoolItem &rHnt ) const 1381 { 1382 if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && ! IsFollow() ) 1383 { 1384 SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt; 1385 const SwPageFrm *pPage = FindPageFrm(); 1386 if ( pPage ) 1387 { 1388 if ( pPage == rInfo.GetOrigPage() && !GetPrev() ) 1389 { 1390 //Das sollte er sein (kann allenfalls temporaer anders sein, 1391 // sollte uns das beunruhigen?) 1392 rInfo.SetInfo( pPage, this ); 1393 return sal_False; 1394 } 1395 if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() && 1396 (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum())) 1397 { 1398 //Das koennte er sein. 1399 rInfo.SetInfo( pPage, this ); 1400 } 1401 } 1402 } 1403 return sal_True; 1404 } 1405 1406 /************************************************************************* 1407 * SwTxtFrm::PrepWidows() 1408 *************************************************************************/ 1409 1410 void SwTxtFrm::PrepWidows( const MSHORT nNeed, sal_Bool bNotify ) 1411 { 1412 ASSERT(GetFollow() && nNeed, "+SwTxtFrm::Prepare: lost all friends"); 1413 1414 SwParaPortion *pPara = GetPara(); 1415 if ( !pPara ) 1416 return; 1417 pPara->SetPrepWidows( sal_True ); 1418 1419 // These two lines of code have been deleted for #102340#. 1420 // Obviously the widow control does not work if we have a 1421 // pMaster->pFollow->pFollow situation: 1422 1423 // returnen oder nicht ist hier die Frage. 1424 // Ohne IsLocked() ist 5156 gefaehrlich, 1425 // ohne IsFollow() werden die Orphans unterdrueckt: 6968. 1426 // Abfrage auf IsLocked erst hier, weil das Flag gesetzt werden soll. 1427 // if( IsLocked() && IsFollow() ) 1428 // return; 1429 1430 MSHORT nHave = nNeed; 1431 1432 // Wir geben ein paar Zeilen ab und schrumpfen im CalcPreps() 1433 SWAP_IF_NOT_SWAPPED( this ) 1434 1435 SwTxtSizeInfo aInf( this ); 1436 SwTxtMargin aLine( this, &aInf ); 1437 aLine.Bottom(); 1438 xub_StrLen nTmpLen = aLine.GetCurr()->GetLen(); 1439 while( nHave && aLine.PrevLine() ) 1440 { 1441 if( nTmpLen ) 1442 --nHave; 1443 nTmpLen = aLine.GetCurr()->GetLen(); 1444 } 1445 // In dieser Ecke tummelten sich einige Bugs: 7513, 7606. 1446 // Wenn feststeht, dass Zeilen abgegeben werden koennen, 1447 // muss der Master darueber hinaus die Widow-Regel ueberpruefen. 1448 if( !nHave ) 1449 { 1450 sal_Bool bSplit; 1451 if( !IsFollow() ) //Nur ein Master entscheidet ueber Orphans 1452 { 1453 const WidowsAndOrphans aWidOrp( this ); 1454 bSplit = ( aLine.GetLineNr() >= aWidOrp.GetOrphansLines() && 1455 aLine.GetLineNr() >= aLine.GetDropLines() ); 1456 } 1457 else 1458 bSplit = sal_True; 1459 1460 if( bSplit ) 1461 { 1462 GetFollow()->SetOfst( aLine.GetEnd() ); 1463 aLine.TruncLines( sal_True ); 1464 if( pPara->IsFollowField() ) 1465 GetFollow()->SetFieldFollow( sal_True ); 1466 } 1467 } 1468 if ( bNotify ) 1469 { 1470 _InvalidateSize(); 1471 InvalidatePage(); 1472 } 1473 1474 UNDO_SWAP( this ) 1475 } 1476 1477 /************************************************************************* 1478 * SwTxtFrm::Prepare 1479 *************************************************************************/ 1480 1481 sal_Bool lcl_ErgoVadis( SwTxtFrm* pFrm, xub_StrLen &rPos, const PrepareHint ePrep ) 1482 { 1483 const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo(); 1484 if( ePrep == PREP_ERGOSUM ) 1485 { 1486 if( !rFtnInfo.aErgoSum.Len() ) 1487 return sal_False;; 1488 rPos = pFrm->GetOfst(); 1489 } 1490 else 1491 { 1492 if( !rFtnInfo.aQuoVadis.Len() ) 1493 return sal_False; 1494 if( pFrm->HasFollow() ) 1495 rPos = pFrm->GetFollow()->GetOfst(); 1496 else 1497 rPos = pFrm->GetTxt().Len(); 1498 if( rPos ) 1499 --rPos; // unser letztes Zeichen 1500 } 1501 return sal_True; 1502 } 1503 1504 void SwTxtFrm::Prepare( const PrepareHint ePrep, const void* pVoid, 1505 sal_Bool bNotify ) 1506 { 1507 SwFrmSwapper aSwapper( this, sal_False ); 1508 1509 #if OSL_DEBUG_LEVEL > 1 1510 const SwTwips nDbgY = Frm().Top(); 1511 (void)nDbgY; 1512 #endif 1513 1514 if ( IsEmpty() ) 1515 { 1516 switch ( ePrep ) 1517 { 1518 case PREP_BOSS_CHGD: 1519 SetInvalidVert( sal_True ); // Test 1520 case PREP_WIDOWS_ORPHANS: 1521 case PREP_WIDOWS: 1522 case PREP_FTN_GONE : return; 1523 1524 case PREP_POS_CHGD : 1525 { 1526 // Auch in (spaltigen) Bereichen ist ein InvalidateSize notwendig, 1527 // damit formatiert wird und ggf. das bUndersized gesetzt wird. 1528 if( IsInFly() || IsInSct() ) 1529 { 1530 SwTwips nTmpBottom = GetUpper()->Frm().Top() + 1531 GetUpper()->Prt().Bottom(); 1532 if( nTmpBottom < Frm().Bottom() ) 1533 break; 1534 } 1535 // Gibt es ueberhaupt Flys auf der Seite ? 1536 SwTxtFly aTxtFly( this ); 1537 if( aTxtFly.IsOn() ) 1538 { 1539 // Ueberlappt irgendein Fly ? 1540 aTxtFly.Relax(); 1541 if ( aTxtFly.IsOn() || IsUndersized() ) 1542 break; 1543 } 1544 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue()) 1545 break; 1546 1547 GETGRID( FindPageFrm() ) 1548 if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() ) 1549 break; 1550 1551 // --> OD 2004-07-16 #i28701# - consider anchored objects 1552 if ( GetDrawObjs() ) 1553 break; 1554 // <-- 1555 1556 return; 1557 } 1558 default: 1559 break; 1560 } 1561 } 1562 1563 if( !HasPara() && PREP_MUST_FIT != ePrep ) 1564 { 1565 SetInvalidVert( sal_True ); // Test 1566 ASSERT( !IsLocked(), "SwTxtFrm::Prepare: three of a perfect pair" ); 1567 if ( bNotify ) 1568 InvalidateSize(); 1569 else 1570 _InvalidateSize(); 1571 return; 1572 } 1573 1574 //Objekt mit Locking aus dem Cache holen. 1575 SwTxtLineAccess aAccess( this ); 1576 SwParaPortion *pPara = aAccess.GetPara(); 1577 1578 switch( ePrep ) 1579 { 1580 case PREP_MOVEFTN : Frm().Height(0); 1581 Prt().Height(0); 1582 _InvalidatePrt(); 1583 _InvalidateSize(); 1584 // KEIN break 1585 case PREP_ADJUST_FRM : pPara->SetPrepAdjust( sal_True ); 1586 if( IsFtnNumFrm() != pPara->IsFtnNum() || 1587 IsUndersized() ) 1588 { 1589 InvalidateRange( SwCharRange( 0, 1 ), 1); 1590 if( GetOfst() && !IsFollow() ) 1591 _SetOfst( 0 ); 1592 } 1593 break; 1594 case PREP_MUST_FIT : pPara->SetPrepMustFit( sal_True ); 1595 /* no break here */ 1596 case PREP_WIDOWS_ORPHANS : pPara->SetPrepAdjust( sal_True ); 1597 break; 1598 1599 case PREP_WIDOWS : 1600 // MustFit ist staerker als alles anderes 1601 if( pPara->IsPrepMustFit() ) 1602 return; 1603 // Siehe Kommentar in WidowsAndOrphans::FindOrphans und CalcPreps() 1604 PrepWidows( *(const MSHORT *)pVoid, bNotify ); 1605 break; 1606 1607 case PREP_FTN : 1608 { 1609 SwTxtFtn *pFtn = (SwTxtFtn *)pVoid; 1610 if( IsInFtn() ) 1611 { 1612 // Bin ich der erste TxtFrm einer Fussnote ? 1613 if( !GetPrev() ) 1614 // Wir sind also ein TxtFrm der Fussnote, die 1615 // die Fussnotenzahl zur Anzeige bringen muss. 1616 // Oder den ErgoSum-Text... 1617 InvalidateRange( SwCharRange( 0, 1 ), 1); 1618 1619 if( !GetNext() ) 1620 { 1621 // Wir sind der letzte Ftn, jetzt muessten die 1622 // QuoVadis-Texte geupdated werden. 1623 const SwFtnInfo &rFtnInfo = GetNode()->GetDoc()->GetFtnInfo(); 1624 if( !pPara->UpdateQuoVadis( rFtnInfo.aQuoVadis ) ) 1625 { 1626 xub_StrLen nPos = pPara->GetParLen(); 1627 if( nPos ) 1628 --nPos; 1629 InvalidateRange( SwCharRange( nPos, 1 ), 1); 1630 } 1631 } 1632 } 1633 else 1634 { 1635 // Wir sind also der TxtFrm _mit_ der Fussnote 1636 const xub_StrLen nPos = *pFtn->GetStart(); 1637 InvalidateRange( SwCharRange( nPos, 1 ), 1); 1638 } 1639 break; 1640 } 1641 case PREP_BOSS_CHGD : 1642 { 1643 // Test 1644 { 1645 SetInvalidVert( sal_False ); 1646 sal_Bool bOld = IsVertical(); 1647 SetInvalidVert( sal_True ); 1648 if( bOld != IsVertical() ) 1649 InvalidateRange( SwCharRange( GetOfst(), STRING_LEN ) ); 1650 } 1651 1652 if( HasFollow() ) 1653 { 1654 xub_StrLen nNxtOfst = GetFollow()->GetOfst(); 1655 if( nNxtOfst ) 1656 --nNxtOfst; 1657 InvalidateRange( SwCharRange( nNxtOfst, 1 ), 1); 1658 } 1659 if( IsInFtn() ) 1660 { 1661 xub_StrLen nPos; 1662 if( lcl_ErgoVadis( this, nPos, PREP_QUOVADIS ) ) 1663 InvalidateRange( SwCharRange( nPos, 1 ), 0 ); 1664 if( lcl_ErgoVadis( this, nPos, PREP_ERGOSUM ) ) 1665 InvalidateRange( SwCharRange( nPos, 1 ), 0 ); 1666 } 1667 // 4739: Wenn wir ein Seitennummernfeld besitzen, muessen wir 1668 // die Stellen invalidieren. 1669 SwpHints *pHints = GetTxtNode()->GetpSwpHints(); 1670 if( pHints ) 1671 { 1672 const sal_uInt16 nSize = pHints->Count(); 1673 const xub_StrLen nEnd = GetFollow() ? 1674 GetFollow()->GetOfst() : STRING_LEN; 1675 for ( sal_uInt16 i = 0; i < nSize; ++i ) 1676 { 1677 const SwTxtAttr *pHt = (*pHints)[i]; 1678 const xub_StrLen nStart = *pHt->GetStart(); 1679 if( nStart >= GetOfst() ) 1680 { 1681 if( nStart >= nEnd ) 1682 i = nSize; // fuehrt das Ende herbei 1683 else 1684 { 1685 // 4029: wenn wir zurueckfliessen und eine Ftn besitzen, so 1686 // fliesst die Ftn in jedem Fall auch mit. Damit sie nicht im 1687 // Weg steht, schicken wir uns ein ADJUST_FRM. 1688 // pVoid != 0 bedeutet MoveBwd() 1689 const MSHORT nWhich = pHt->Which(); 1690 if( RES_TXTATR_FIELD == nWhich || 1691 (HasFtn() && pVoid && RES_TXTATR_FTN == nWhich)) 1692 InvalidateRange( SwCharRange( nStart, 1 ), 1 ); 1693 } 1694 } 1695 } 1696 } 1697 // A new boss, a new chance for growing 1698 if( IsUndersized() ) 1699 { 1700 _InvalidateSize(); 1701 InvalidateRange( SwCharRange( GetOfst(), 1 ), 1); 1702 } 1703 break; 1704 } 1705 1706 case PREP_POS_CHGD : 1707 { 1708 if ( GetValidPrtAreaFlag() ) 1709 { 1710 GETGRID( FindPageFrm() ) 1711 if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() ) 1712 InvalidatePrt(); 1713 } 1714 1715 // Falls wir mit niemandem ueberlappen: 1716 // Ueberlappte irgendein Fly _vor_ der Positionsaenderung ? 1717 sal_Bool bFormat = pPara->HasFly(); 1718 if( !bFormat ) 1719 { 1720 if( IsInFly() ) 1721 { 1722 SwTwips nTmpBottom = GetUpper()->Frm().Top() + 1723 GetUpper()->Prt().Bottom(); 1724 if( nTmpBottom < Frm().Bottom() ) 1725 bFormat = sal_True; 1726 } 1727 if( !bFormat ) 1728 { 1729 if ( GetDrawObjs() ) 1730 { 1731 const sal_uInt32 nCnt = GetDrawObjs()->Count(); 1732 for ( MSHORT i = 0; i < nCnt; ++i ) 1733 { 1734 SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i]; 1735 // --> OD 2004-07-16 #i28701# - consider all 1736 // to-character anchored objects 1737 if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId() 1738 == FLY_AT_CHAR ) 1739 { 1740 bFormat = sal_True; 1741 break; 1742 } 1743 } 1744 } 1745 if( !bFormat ) 1746 { 1747 // Gibt es ueberhaupt Flys auf der Seite ? 1748 SwTxtFly aTxtFly( this ); 1749 if( aTxtFly.IsOn() ) 1750 { 1751 // Ueberlappt irgendein Fly ? 1752 aTxtFly.Relax(); 1753 bFormat = aTxtFly.IsOn() || IsUndersized(); 1754 } 1755 } 1756 } 1757 } 1758 1759 if( bFormat ) 1760 { 1761 if( !IsLocked() ) 1762 { 1763 if( pPara->GetRepaint()->HasArea() ) 1764 SetCompletePaint(); 1765 Init(); 1766 pPara = 0; 1767 _InvalidateSize(); 1768 } 1769 } 1770 else 1771 { 1772 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() ) 1773 Prepare( PREP_REGISTER, 0, bNotify ); 1774 // Durch Positionsverschiebungen mit Ftns muessen die 1775 // Frames neu adjustiert werden. 1776 else if( HasFtn() ) 1777 { 1778 Prepare( PREP_ADJUST_FRM, 0, bNotify ); 1779 _InvalidateSize(); 1780 } 1781 else 1782 return; // damit kein SetPrep() erfolgt. 1783 } 1784 break; 1785 } 1786 case PREP_REGISTER: 1787 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() ) 1788 { 1789 pPara->SetPrepAdjust( sal_True ); 1790 CalcLineSpace(); 1791 InvalidateSize(); 1792 _InvalidatePrt(); 1793 SwFrm* pNxt; 1794 if ( 0 != ( pNxt = GetIndNext() ) ) 1795 { 1796 pNxt->_InvalidatePrt(); 1797 if ( pNxt->IsLayoutFrm() ) 1798 pNxt->InvalidatePage(); 1799 } 1800 SetCompletePaint(); 1801 } 1802 break; 1803 case PREP_FTN_GONE : 1804 { 1805 // Wenn ein Follow uns ruft, weil eine Fussnote geloescht wird, muss unsere 1806 // letzte Zeile formatiert werden, damit ggf. die erste Zeile des Follows 1807 // hochrutschen kann, die extra auf die naechste Seite gerutscht war, um mit 1808 // der Fussnote zusammen zu sein, insbesondere bei spaltigen Bereichen. 1809 ASSERT( GetFollow(), "PREP_FTN_GONE darf nur vom Follow gerufen werden" ); 1810 xub_StrLen nPos = GetFollow()->GetOfst(); 1811 if( IsFollow() && GetOfst() == nPos ) // falls wir gar keine Textmasse besitzen, 1812 FindMaster()->Prepare( PREP_FTN_GONE ); // rufen wir das Prepare unseres Masters 1813 if( nPos ) 1814 --nPos; // das Zeichen vor unserem Follow 1815 InvalidateRange( SwCharRange( nPos, 1 ), 0 ); 1816 return; 1817 } 1818 case PREP_ERGOSUM: 1819 case PREP_QUOVADIS: 1820 { 1821 xub_StrLen nPos; 1822 if( lcl_ErgoVadis( this, nPos, ePrep ) ) 1823 InvalidateRange( SwCharRange( nPos, 1 ), 0 ); 1824 } 1825 break; 1826 case PREP_FLY_ATTR_CHG: 1827 { 1828 if( pVoid ) 1829 { 1830 xub_StrLen nWhere = CalcFlyPos( (SwFrmFmt*)pVoid ); 1831 ASSERT( STRING_LEN != nWhere, "Prepare: Why me?" ); 1832 InvalidateRange( SwCharRange( nWhere, 1 ) ); 1833 return; 1834 } 1835 // else ... Laufe in den Default-Switch 1836 } 1837 case PREP_CLEAR: 1838 default: 1839 { 1840 if( IsLocked() ) 1841 { 1842 if( PREP_FLY_ARRIVE == ePrep || PREP_FLY_LEAVE == ePrep ) 1843 { 1844 xub_StrLen nLen = ( GetFollow() ? GetFollow()->GetOfst() : 1845 STRING_LEN ) - GetOfst(); 1846 InvalidateRange( SwCharRange( GetOfst(), nLen ), 0 ); 1847 } 1848 } 1849 else 1850 { 1851 if( pPara->GetRepaint()->HasArea() ) 1852 SetCompletePaint(); 1853 Init(); 1854 pPara = 0; 1855 if( GetOfst() && !IsFollow() ) 1856 _SetOfst( 0 ); 1857 if ( bNotify ) 1858 InvalidateSize(); 1859 else 1860 _InvalidateSize(); 1861 } 1862 return; // damit kein SetPrep() erfolgt. 1863 } 1864 } 1865 if( pPara ) 1866 pPara->SetPrep( sal_True ); 1867 } 1868 1869 /* -----------------11.02.99 17:56------------------- 1870 * Kleine Hilfsklasse mit folgender Funktion: 1871 * Sie soll eine Probeformatierung vorbereiten. 1872 * Der Frame wird in Groesse und Position angepasst, sein SwParaPortion zur Seite 1873 * gestellt und eine neue erzeugt, dazu wird formatiert mit gesetztem bTestFormat. 1874 * Im Dtor wird der TxtFrm wieder in seinen alten Zustand zurueckversetzt. 1875 * 1876 * --------------------------------------------------*/ 1877 1878 class SwTestFormat 1879 { 1880 SwTxtFrm *pFrm; 1881 SwParaPortion *pOldPara; 1882 SwRect aOldFrm, aOldPrt; 1883 public: 1884 SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPrv, SwTwips nMaxHeight ); 1885 ~SwTestFormat(); 1886 }; 1887 1888 SwTestFormat::SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPre, SwTwips nMaxHeight ) 1889 : pFrm( pTxtFrm ) 1890 { 1891 aOldFrm = pFrm->Frm(); 1892 aOldPrt = pFrm->Prt(); 1893 1894 SWRECTFN( pFrm ) 1895 SwTwips nLower = (pFrm->*fnRect->fnGetBottomMargin)(); 1896 1897 pFrm->Frm() = pFrm->GetUpper()->Prt(); 1898 pFrm->Frm() += pFrm->GetUpper()->Frm().Pos(); 1899 1900 (pFrm->Frm().*fnRect->fnSetHeight)( nMaxHeight ); 1901 if( pFrm->GetPrev() ) 1902 (pFrm->Frm().*fnRect->fnSetPosY)( 1903 (pFrm->GetPrev()->Frm().*fnRect->fnGetBottom)() - 1904 ( bVert ? nMaxHeight + 1 : 0 ) ); 1905 1906 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm ); 1907 const SwBorderAttrs &rAttrs = *aAccess.Get(); 1908 (pFrm->Prt().*fnRect->fnSetPosX)( rAttrs.CalcLeft( pFrm ) ); 1909 1910 if( pPre ) 1911 { 1912 SwTwips nUpper = pFrm->CalcUpperSpace( &rAttrs, pPre ); 1913 (pFrm->Prt().*fnRect->fnSetPosY)( nUpper ); 1914 } 1915 (pFrm->Prt().*fnRect->fnSetHeight)( 1916 Max( 0L , (pFrm->Frm().*fnRect->fnGetHeight)() - 1917 (pFrm->Prt().*fnRect->fnGetTop)() - nLower ) ); 1918 (pFrm->Prt().*fnRect->fnSetWidth)( 1919 (pFrm->Frm().*fnRect->fnGetWidth)() - 1920 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)> 1921 ( rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm ) ) ); 1922 pOldPara = pFrm->HasPara() ? pFrm->GetPara() : NULL; 1923 pFrm->SetPara( new SwParaPortion(), sal_False ); 1924 1925 ASSERT( ! pFrm->IsSwapped(), "A frame is swapped before _Format" ); 1926 1927 if ( pFrm->IsVertical() ) 1928 pFrm->SwapWidthAndHeight(); 1929 1930 SwTxtFormatInfo aInf( pFrm, sal_False, sal_True, sal_True ); 1931 SwTxtFormatter aLine( pFrm, &aInf ); 1932 1933 pFrm->_Format( aLine, aInf ); 1934 1935 if ( pFrm->IsVertical() ) 1936 pFrm->SwapWidthAndHeight(); 1937 1938 ASSERT( ! pFrm->IsSwapped(), "A frame is swapped after _Format" ); 1939 } 1940 1941 SwTestFormat::~SwTestFormat() 1942 { 1943 pFrm->Frm() = aOldFrm; 1944 pFrm->Prt() = aOldPrt; 1945 pFrm->SetPara( pOldPara ); 1946 } 1947 1948 sal_Bool SwTxtFrm::TestFormat( const SwFrm* pPrv, SwTwips &rMaxHeight, sal_Bool &bSplit ) 1949 { 1950 PROTOCOL_ENTER( this, PROT_TESTFORMAT, 0, 0 ) 1951 1952 if( IsLocked() && GetUpper()->Prt().Width() <= 0 ) 1953 return sal_False; 1954 1955 SwTestFormat aSave( this, pPrv, rMaxHeight ); 1956 1957 return SwTxtFrm::WouldFit( rMaxHeight, bSplit, sal_True ); 1958 } 1959 1960 1961 /************************************************************************* 1962 * SwTxtFrm::WouldFit() 1963 *************************************************************************/ 1964 1965 /* SwTxtFrm::WouldFit() 1966 * sal_True: wenn ich aufspalten kann. 1967 * Es soll und braucht nicht neu formatiert werden. 1968 * Wir gehen davon aus, dass bereits formatiert wurde und dass 1969 * die Formatierungsdaten noch aktuell sind. 1970 * Wir gehen davon aus, dass die Framebreiten des evtl. Masters und 1971 * Follows gleich sind. Deswegen wird kein FindBreak() mit FindOrphans() 1972 * gerufen. 1973 * Die benoetigte Hoehe wird von nMaxHeight abgezogen! 1974 */ 1975 1976 sal_Bool SwTxtFrm::WouldFit( SwTwips &rMaxHeight, sal_Bool &bSplit, sal_Bool bTst ) 1977 { 1978 ASSERT( ! IsVertical() || ! IsSwapped(), 1979 "SwTxtFrm::WouldFit with swapped frame" ); 1980 SWRECTFN( this ); 1981 1982 if( IsLocked() ) 1983 return sal_False; 1984 1985 //Kann gut sein, dass mir der IdleCollector mir die gecachten 1986 //Informationen entzogen hat. 1987 if( !IsEmpty() ) 1988 GetFormatted(); 1989 1990 // OD 2004-05-24 #i27801# - correction: 'short cut' for empty paragraph 1991 // can *not* be applied, if test format is in progress. The test format doesn't 1992 // adjust the frame and the printing area - see method <SwTxtFrm::_Format(..)>, 1993 // which is called in <SwTxtFrm::TestFormat(..)> 1994 if ( IsEmpty() && !bTst ) 1995 { 1996 bSplit = sal_False; 1997 SwTwips nHeight = bVert ? Prt().SSize().Width() : Prt().SSize().Height(); 1998 if( rMaxHeight < nHeight ) 1999 return sal_False; 2000 else 2001 { 2002 rMaxHeight -= nHeight; 2003 return sal_True; 2004 } 2005 } 2006 2007 // In sehr unguenstigen Faellen kann GetPara immer noch 0 sein. 2008 // Dann returnen wir sal_True, um auf der neuen Seite noch einmal 2009 // anformatiert zu werden. 2010 ASSERT( HasPara() || IsHiddenNow(), "WouldFit: GetFormatted() and then !HasPara()" ); 2011 if( !HasPara() || ( !(Frm().*fnRect->fnGetHeight)() && IsHiddenNow() ) ) 2012 return sal_True; 2013 2014 // Da das Orphan-Flag nur sehr fluechtig existiert, wird als zweite 2015 // Bedingung ueberprueft, ob die Rahmengroesse durch CalcPreps 2016 // auf riesengross gesetzt wird, um ein MoveFwd zu erzwingen. 2017 if( IsWidow() || ( bVert ? 2018 ( 0 == Frm().Left() ) : 2019 ( LONG_MAX - 20000 < Frm().Bottom() ) ) ) 2020 { 2021 SetWidow(sal_False); 2022 if ( GetFollow() ) 2023 { 2024 // Wenn wir hier durch eine Widow-Anforderung unseres Follows gelandet 2025 // sind, wird ueberprueft, ob es ueberhaupt einen Follow mit einer 2026 // echten Hoehe gibt, andernfalls (z.B. in neu angelegten SctFrms) 2027 // ignorieren wir das IsWidow() und pruefen doch noch, ob wir 2028 // genung Platz finden. 2029 if( ( ( ! bVert && LONG_MAX - 20000 >= Frm().Bottom() ) || 2030 ( bVert && 0 < Frm().Left() ) ) && 2031 ( GetFollow()->IsVertical() ? 2032 !GetFollow()->Frm().Width() : 2033 !GetFollow()->Frm().Height() ) ) 2034 { 2035 SwTxtFrm* pFoll = GetFollow()->GetFollow(); 2036 while( pFoll && 2037 ( pFoll->IsVertical() ? 2038 !pFoll->Frm().Width() : 2039 !pFoll->Frm().Height() ) ) 2040 pFoll = pFoll->GetFollow(); 2041 if( pFoll ) 2042 return sal_False; 2043 } 2044 else 2045 return sal_False; 2046 } 2047 } 2048 2049 SWAP_IF_NOT_SWAPPED( this ); 2050 2051 SwTxtSizeInfo aInf( this ); 2052 SwTxtMargin aLine( this, &aInf ); 2053 2054 WidowsAndOrphans aFrmBreak( this, rMaxHeight, bSplit ); 2055 2056 sal_Bool bRet = sal_True; 2057 2058 aLine.Bottom(); 2059 // Ist Aufspalten ueberhaupt notwendig? 2060 if ( 0 != ( bSplit = !aFrmBreak.IsInside( aLine ) ) ) 2061 bRet = !aFrmBreak.IsKeepAlways() && aFrmBreak.WouldFit( aLine, rMaxHeight, bTst ); 2062 else 2063 { 2064 //Wir brauchen die Gesamthoehe inklusive der aktuellen Zeile 2065 aLine.Top(); 2066 do 2067 { 2068 rMaxHeight -= aLine.GetLineHeight(); 2069 } while ( aLine.Next() ); 2070 } 2071 2072 UNDO_SWAP( this ) 2073 2074 return bRet; 2075 } 2076 2077 2078 /************************************************************************* 2079 * SwTxtFrm::GetParHeight() 2080 *************************************************************************/ 2081 2082 KSHORT SwTxtFrm::GetParHeight() const 2083 { 2084 ASSERT( ! IsVertical() || ! IsSwapped(), 2085 "SwTxtFrm::GetParHeight with swapped frame" ) 2086 2087 if( !HasPara() ) 2088 { // Fuer nichtleere Absaetze ist dies ein Sonderfall, da koennen wir 2089 // bei UnderSized ruhig nur 1 Twip mehr anfordern. 2090 KSHORT nRet = (KSHORT)Prt().SSize().Height(); 2091 if( IsUndersized() ) 2092 { 2093 if( IsEmpty() ) 2094 nRet = (KSHORT)EmptyHeight(); 2095 else 2096 ++nRet; 2097 } 2098 return nRet; 2099 } 2100 2101 // FME, OD 08.01.2004 #i11859# - refactoring and improve code 2102 const SwLineLayout* pLineLayout = GetPara(); 2103 KSHORT nHeight = pLineLayout->GetRealHeight(); 2104 if( GetOfst() && !IsFollow() ) // Ist dieser Absatz gescrollt? Dann ist unsere 2105 nHeight *= 2; // bisherige Hoehe mind. eine Zeilenhoehe zu gering 2106 // OD 2004-03-04 #115793# 2107 while ( pLineLayout && pLineLayout->GetNext() ) 2108 { 2109 pLineLayout = pLineLayout->GetNext(); 2110 nHeight = nHeight + pLineLayout->GetRealHeight(); 2111 } 2112 2113 return nHeight; 2114 } 2115 2116 2117 /************************************************************************* 2118 * SwTxtFrm::GetFormatted() 2119 *************************************************************************/ 2120 2121 // returnt this _immer_ im formatierten Zustand! 2122 SwTxtFrm* SwTxtFrm::GetFormatted( bool bForceQuickFormat ) 2123 { 2124 SWAP_IF_SWAPPED( this ) 2125 2126 //Kann gut sein, dass mir der IdleCollector mir die gecachten 2127 //Informationen entzogen hat. Calc() ruft unser Format. 2128 //Nicht bei leeren Absaetzen! 2129 if( !HasPara() && !(IsValid() && IsEmpty()) ) 2130 { 2131 // Calc() muss gerufen werden, weil unsere Frameposition 2132 // nicht stimmen muss. 2133 const sal_Bool bFormat = GetValidSizeFlag(); 2134 Calc(); 2135 // Es kann durchaus sein, dass Calc() das Format() 2136 // nicht anstiess (weil wir einst vom Idle-Zerstoerer 2137 // aufgefordert wurden unsere Formatinformationen wegzuschmeissen). 2138 // 6995: Optimierung mit FormatQuick() 2139 if( bFormat && !FormatQuick( bForceQuickFormat ) ) 2140 Format(); 2141 } 2142 2143 UNDO_SWAP( this ) 2144 2145 return this; 2146 } 2147 2148 /************************************************************************* 2149 * SwTxtFrm::CalcFitToContent() 2150 *************************************************************************/ 2151 2152 SwTwips SwTxtFrm::CalcFitToContent() 2153 { 2154 // --> FME 2004-07-16 #i31490# 2155 // If we are currently locked, we better return with a 2156 // fairly reasonable value: 2157 if ( IsLocked() ) 2158 return Prt().Width(); 2159 // <-- 2160 2161 SwParaPortion* pOldPara = GetPara(); 2162 SwParaPortion *pDummy = new SwParaPortion(); 2163 SetPara( pDummy, false ); 2164 const SwPageFrm* pPage = FindPageFrm(); 2165 2166 const Point aOldFrmPos = Frm().Pos(); 2167 const SwTwips nOldFrmWidth = Frm().Width(); 2168 const SwTwips nOldPrtWidth = Prt().Width(); 2169 const SwTwips nPageWidth = GetUpper()->IsVertical() ? 2170 pPage->Prt().Height() : 2171 pPage->Prt().Width(); 2172 2173 Frm().Width( nPageWidth ); 2174 Prt().Width( nPageWidth ); 2175 2176 // --> FME 2004-07-19 #i25422# objects anchored as character in RTL 2177 if ( IsRightToLeft() ) 2178 Frm().Pos().X() += nOldFrmWidth - nPageWidth; 2179 2180 // --> FME 2004-07-16 #i31490# 2181 SwTxtFrmLocker aLock( this ); 2182 // <-- 2183 2184 SwTxtFormatInfo aInf( this, sal_False, sal_True, sal_True ); 2185 aInf.SetIgnoreFly( sal_True ); 2186 SwTxtFormatter aLine( this, &aInf ); 2187 SwHookOut aHook( aInf ); 2188 2189 // --> OD 2005-09-06 #i54031# - assure mininum of MINLAY twips. 2190 const SwTwips nMax = Max( (SwTwips)MINLAY, 2191 aLine._CalcFitToContent() + 1 ); 2192 // <-- 2193 2194 Frm().Width( nOldFrmWidth ); 2195 Prt().Width( nOldPrtWidth ); 2196 2197 // --> FME 2004-07-19 #i25422# objects anchored as character in RTL 2198 if ( IsRightToLeft() ) 2199 Frm().Pos() = aOldFrmPos; 2200 2201 2202 SetPara( pOldPara ); 2203 2204 return nMax; 2205 } 2206 2207 /** simulate format for a list item paragraph, whose list level attributes 2208 are in LABEL_ALIGNMENT mode, in order to determine additional first 2209 line offset for the real text formatting due to the value of label 2210 adjustment attribute of the list level. 2211 2212 OD 2008-01-31 #newlistlevelattrs# 2213 2214 @author OD 2215 */ 2216 void SwTxtFrm::CalcAdditionalFirstLineOffset() 2217 { 2218 if ( IsLocked() ) 2219 return; 2220 2221 // reset additional first line offset 2222 mnAdditionalFirstLineOffset = 0; 2223 2224 const SwTxtNode* pTxtNode( GetTxtNode() ); 2225 if ( pTxtNode && pTxtNode->IsNumbered() && pTxtNode->IsCountedInList() && 2226 pTxtNode->GetNumRule() ) 2227 { 2228 const SwNumFmt& rNumFmt = 2229 pTxtNode->GetNumRule()->Get( static_cast<sal_uInt16>(pTxtNode->GetActualListLevel()) ); 2230 if ( rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 2231 { 2232 // keep current paragraph portion and apply dummy paragraph portion 2233 SwParaPortion* pOldPara = GetPara(); 2234 SwParaPortion *pDummy = new SwParaPortion(); 2235 SetPara( pDummy, false ); 2236 2237 // lock paragraph 2238 SwTxtFrmLocker aLock( this ); 2239 2240 // simulate text formatting 2241 SwTxtFormatInfo aInf( this, sal_False, sal_True, sal_True ); 2242 aInf.SetIgnoreFly( sal_True ); 2243 SwTxtFormatter aLine( this, &aInf ); 2244 SwHookOut aHook( aInf ); 2245 aLine._CalcFitToContent(); 2246 2247 // determine additional first line offset 2248 const SwLinePortion* pFirstPortion = aLine.GetCurr()->GetFirstPortion(); 2249 if ( pFirstPortion->InNumberGrp() && !pFirstPortion->IsFtnNumPortion() ) 2250 { 2251 SwTwips nNumberPortionWidth( pFirstPortion->Width() ); 2252 2253 const SwLinePortion* pPortion = pFirstPortion->GetPortion(); 2254 while ( pPortion && 2255 pPortion->InNumberGrp() && !pPortion->IsFtnNumPortion()) 2256 { 2257 nNumberPortionWidth += pPortion->Width(); 2258 pPortion = pPortion->GetPortion(); 2259 } 2260 2261 if ( ( IsRightToLeft() && 2262 rNumFmt.GetNumAdjust() == SVX_ADJUST_LEFT ) || 2263 ( !IsRightToLeft() && 2264 rNumFmt.GetNumAdjust() == SVX_ADJUST_RIGHT ) ) 2265 { 2266 mnAdditionalFirstLineOffset = -nNumberPortionWidth; 2267 } 2268 else if ( rNumFmt.GetNumAdjust() == SVX_ADJUST_CENTER ) 2269 { 2270 mnAdditionalFirstLineOffset = -(nNumberPortionWidth/2); 2271 } 2272 } 2273 2274 // restore paragraph portion 2275 SetPara( pOldPara ); 2276 } 2277 } 2278 } 2279 2280 /** determine height of last line for the calculation of the proportional line 2281 spacing 2282 2283 OD 08.01.2004 #i11859# 2284 OD 2004-03-17 #i11860# - method <GetHeightOfLastLineForPropLineSpacing()> 2285 replace by method <_CalcHeightOfLastLine()>. Height of last line will be 2286 stored in new member <mnHeightOfLastLine> and can be accessed via method 2287 <GetHeightOfLastLine()> 2288 OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont> 2289 in order to force the usage of the former algorithm to determine the 2290 height of the last line, which uses the font. 2291 2292 @author OD 2293 */ 2294 void SwTxtFrm::_CalcHeightOfLastLine( const bool _bUseFont ) 2295 { 2296 // --> OD 2006-11-13 #i71281# 2297 // invalidate printing area, if height of last line changes 2298 const SwTwips mnOldHeightOfLastLine( mnHeightOfLastLine ); 2299 // <-- 2300 // determine output device 2301 ViewShell* pVsh = getRootFrm()->GetCurrShell(); 2302 ASSERT( pVsh, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no ViewShell" ); 2303 // --> OD 2007-07-02 #i78921# - make code robust, according to provided patch 2304 // There could be no <ViewShell> instance in the case of loading a binary 2305 // StarOffice file format containing an embedded Writer document. 2306 if ( !pVsh ) 2307 { 2308 return; 2309 } 2310 OutputDevice* pOut = pVsh->GetOut(); 2311 const IDocumentSettingAccess* pIDSA = GetTxtNode()->getIDocumentSettingAccess(); 2312 if ( !pVsh->GetViewOptions()->getBrowseMode() || 2313 pVsh->GetViewOptions()->IsPrtFormat() ) 2314 { 2315 pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true ); 2316 } 2317 ASSERT( pOut, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no OutputDevice" ); 2318 // --> OD 2007-07-02 #i78921# - make code robust, according to provided patch 2319 if ( !pOut ) 2320 { 2321 return; 2322 } 2323 // <-- 2324 2325 // determine height of last line 2326 2327 if ( _bUseFont || pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING ) ) 2328 { 2329 // former determination of last line height for proprotional line 2330 // spacing - take height of font set at the paragraph 2331 SwFont aFont( GetAttrSet(), pIDSA ); 2332 2333 // Wir muessen dafuer sorgen, dass am OutputDevice der Font 2334 // korrekt restauriert wird, sonst droht ein Last!=Owner. 2335 if ( pLastFont ) 2336 { 2337 SwFntObj *pOldFont = pLastFont; 2338 pLastFont = NULL; 2339 aFont.SetFntChg( sal_True ); 2340 aFont.ChgPhysFnt( pVsh, *pOut ); 2341 mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut ); 2342 pLastFont->Unlock(); 2343 pLastFont = pOldFont; 2344 pLastFont->SetDevFont( pVsh, *pOut ); 2345 } 2346 else 2347 { 2348 Font aOldFont = pOut->GetFont(); 2349 aFont.SetFntChg( sal_True ); 2350 aFont.ChgPhysFnt( pVsh, *pOut ); 2351 mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut ); 2352 pLastFont->Unlock(); 2353 pLastFont = NULL; 2354 pOut->SetFont( aOldFont ); 2355 } 2356 } 2357 else 2358 { 2359 // new determination of last line height - take actually height of last line 2360 // --> OD 2008-05-06 #i89000# 2361 // assure same results, if paragraph is undersized 2362 if ( IsUndersized() ) 2363 { 2364 mnHeightOfLastLine = 0; 2365 } 2366 else 2367 { 2368 bool bCalcHeightOfLastLine = true; 2369 if ( !HasPara() ) 2370 { 2371 if ( IsEmpty() ) 2372 { 2373 mnHeightOfLastLine = EmptyHeight(); 2374 bCalcHeightOfLastLine = false; 2375 } 2376 } 2377 2378 if ( bCalcHeightOfLastLine ) 2379 { 2380 ASSERT( HasPara(), 2381 "<SwTxtFrm::_CalcHeightOfLastLine()> - missing paragraph portions." ); 2382 const SwLineLayout* pLineLayout = GetPara(); 2383 while ( pLineLayout && pLineLayout->GetNext() ) 2384 { 2385 // iteration to last line 2386 pLineLayout = pLineLayout->GetNext(); 2387 } 2388 if ( pLineLayout ) 2389 { 2390 SwTwips nAscent, nDescent, nDummy1, nDummy2; 2391 // --> OD 2005-05-20 #i47162# - suppress consideration of 2392 // fly content portions and the line portion. 2393 pLineLayout->MaxAscentDescent( nAscent, nDescent, 2394 nDummy1, nDummy2, 2395 0, true ); 2396 // <-- 2397 // --> OD 2006-11-22 #i71281# 2398 // Suppress wrong invalidation of printing area, if method is 2399 // called recursive. 2400 // Thus, member <mnHeightOfLastLine> is only set directly, if 2401 // no recursive call is needed. 2402 // mnHeightOfLastLine = nAscent + nDescent; 2403 const SwTwips nNewHeightOfLastLine = nAscent + nDescent; 2404 // --> OD 2005-05-20 #i47162# - if last line only contains 2405 // fly content portions, <mnHeightOfLastLine> is zero. 2406 // In this case determine height of last line by the font 2407 if ( nNewHeightOfLastLine == 0 ) 2408 { 2409 _CalcHeightOfLastLine( true ); 2410 } 2411 else 2412 { 2413 mnHeightOfLastLine = nNewHeightOfLastLine; 2414 } 2415 // <-- 2416 // <-- 2417 } 2418 } 2419 } 2420 // <-- 2421 } 2422 // --> OD 2006-11-13 #i71281# 2423 // invalidate printing area, if height of last line changes 2424 if ( mnHeightOfLastLine != mnOldHeightOfLastLine ) 2425 { 2426 InvalidatePrt(); 2427 } 2428 // <-- 2429 } 2430 2431 /************************************************************************* 2432 * SwTxtFrm::GetLineSpace() 2433 *************************************************************************/ 2434 // OD 07.01.2004 #i11859# - change return data type 2435 // add default parameter <_bNoPropLineSpacing> to control, if the 2436 // value of a proportional line spacing is returned or not 2437 // OD 07.01.2004 - trying to describe purpose of method: 2438 // Method returns the value of the inter line spacing for a text frame. 2439 // Such a value exists for proportional line spacings ("1,5 Lines", 2440 // "Double", "Proportional" and for leading line spacing ("Leading"). 2441 // By parameter <_bNoPropLineSpace> (default value false) it can be 2442 // controlled, if the value of a proportional line spacing is returned. 2443 long SwTxtFrm::GetLineSpace( const bool _bNoPropLineSpace ) const 2444 { 2445 long nRet = 0; 2446 2447 const SwAttrSet* pSet = GetAttrSet(); 2448 const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing(); 2449 2450 switch( rSpace.GetInterLineSpaceRule() ) 2451 { 2452 case SVX_INTER_LINE_SPACE_PROP: 2453 { 2454 // OD 07.01.2004 #i11859# 2455 if ( _bNoPropLineSpace ) 2456 { 2457 break; 2458 } 2459 2460 // OD 2004-03-17 #i11860# - use method <GetHeightOfLastLine()> 2461 nRet = GetHeightOfLastLine(); 2462 2463 long nTmp = nRet; 2464 nTmp *= rSpace.GetPropLineSpace(); 2465 nTmp /= 100; 2466 nTmp -= nRet; 2467 if ( nTmp > 0 ) 2468 nRet = nTmp; 2469 else 2470 nRet = 0; 2471 } 2472 break; 2473 case SVX_INTER_LINE_SPACE_FIX: 2474 { 2475 if ( rSpace.GetInterLineSpace() > 0 ) 2476 nRet = rSpace.GetInterLineSpace(); 2477 } 2478 break; 2479 default: 2480 break; 2481 } 2482 return nRet; 2483 } 2484 2485 /************************************************************************* 2486 * SwTxtFrm::FirstLineHeight() 2487 *************************************************************************/ 2488 2489 KSHORT SwTxtFrm::FirstLineHeight() const 2490 { 2491 if ( !HasPara() ) 2492 { 2493 if( IsEmpty() && IsValid() ) 2494 return IsVertical() ? (KSHORT)Prt().Width() : (KSHORT)Prt().Height(); 2495 return KSHRT_MAX; 2496 } 2497 const SwParaPortion *pPara = GetPara(); 2498 if ( !pPara ) 2499 return KSHRT_MAX; 2500 2501 return pPara->Height(); 2502 } 2503 2504 MSHORT SwTxtFrm::GetLineCount( xub_StrLen nPos ) 2505 { 2506 MSHORT nRet = 0; 2507 SwTxtFrm *pFrm = this; 2508 do 2509 { 2510 pFrm->GetFormatted(); 2511 if( !pFrm->HasPara() ) 2512 break; 2513 SwTxtSizeInfo aInf( pFrm ); 2514 SwTxtMargin aLine( pFrm, &aInf ); 2515 if( STRING_LEN == nPos ) 2516 aLine.Bottom(); 2517 else 2518 aLine.CharToLine( nPos ); 2519 nRet = nRet + aLine.GetLineNr(); 2520 pFrm = pFrm->GetFollow(); 2521 } while ( pFrm && pFrm->GetOfst() <= nPos ); 2522 return nRet; 2523 } 2524 2525 void SwTxtFrm::ChgThisLines() 2526 { 2527 //not necassary to format here (GerFormatted etc.), because we have to come from there! 2528 2529 sal_uLong nNew = 0; 2530 const SwLineNumberInfo &rInf = GetNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo(); 2531 if ( GetTxt().Len() && HasPara() ) 2532 { 2533 SwTxtSizeInfo aInf( this ); 2534 SwTxtMargin aLine( this, &aInf ); 2535 if ( rInf.IsCountBlankLines() ) 2536 { 2537 aLine.Bottom(); 2538 nNew = (sal_uLong)aLine.GetLineNr(); 2539 } 2540 else 2541 { 2542 do 2543 { 2544 if( aLine.GetCurr()->HasCntnt() ) 2545 ++nNew; 2546 } while ( aLine.NextLine() ); 2547 } 2548 } 2549 else if ( rInf.IsCountBlankLines() ) 2550 nNew = 1; 2551 2552 if ( nNew != nThisLines ) 2553 { 2554 if ( !IsInTab() && GetAttrSet()->GetLineNumber().IsCount() ) 2555 { 2556 nAllLines -= nThisLines; 2557 nThisLines = nNew; 2558 nAllLines += nThisLines; 2559 SwFrm *pNxt = GetNextCntntFrm(); 2560 while( pNxt && pNxt->IsInTab() ) 2561 { 2562 if( 0 != (pNxt = pNxt->FindTabFrm()) ) 2563 pNxt = pNxt->FindNextCnt(); 2564 } 2565 if( pNxt ) 2566 pNxt->InvalidateLineNum(); 2567 2568 //Extend repaint to the bottom. 2569 if ( HasPara() ) 2570 { 2571 SwRepaint *pRepaint = GetPara()->GetRepaint(); 2572 pRepaint->Bottom( Max( pRepaint->Bottom(), 2573 Frm().Top()+Prt().Bottom())); 2574 } 2575 } 2576 else //Paragraphs which are not counted should not manipulate the AllLines. 2577 nThisLines = nNew; 2578 } 2579 2580 //mba: invalidating is not necessary; if mongolian script has a problem, it should be fixed at the ritgh place 2581 //with invalidating we probably get too much flickering 2582 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 2583 //Ugly. How can we hack if better? 2584 //InvalidatePage(); 2585 } 2586 2587 2588 void SwTxtFrm::RecalcAllLines() 2589 { 2590 ValidateLineNum(); 2591 2592 const SwAttrSet *pAttrSet = GetAttrSet(); 2593 2594 if ( !IsInTab() ) 2595 { 2596 const sal_uLong nOld = GetAllLines(); 2597 const SwFmtLineNumber &rLineNum = pAttrSet->GetLineNumber(); 2598 sal_uLong nNewNum; 2599 const bool bRestart = GetTxtNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo().IsRestartEachPage(); 2600 2601 if ( !IsFollow() && rLineNum.GetStartValue() && rLineNum.IsCount() ) 2602 nNewNum = rLineNum.GetStartValue() - 1; 2603 //If it is a follow or not has not be considered if it is a restart at each page; the 2604 //restart should also take affekt at follows. 2605 else if ( bRestart && FindPageFrm()->FindFirstBodyCntnt() == this ) 2606 { 2607 nNewNum = 0; 2608 } 2609 else 2610 { 2611 SwCntntFrm *pPrv = GetPrevCntntFrm(); 2612 while ( pPrv && 2613 (pPrv->IsInTab() || pPrv->IsInDocBody() != IsInDocBody()) ) 2614 pPrv = pPrv->GetPrevCntntFrm(); 2615 2616 // --> FME 2007-06-22 #i78254# Restart line numbering at page change: 2617 // First body content may be in table! 2618 if ( bRestart && pPrv && pPrv->FindPageFrm() != FindPageFrm() ) 2619 pPrv = 0; 2620 // <-- 2621 2622 nNewNum = pPrv ? ((SwTxtFrm*)pPrv)->GetAllLines() : 0; 2623 } 2624 if ( rLineNum.IsCount() ) 2625 nNewNum += GetThisLines(); 2626 2627 if ( nOld != nNewNum ) 2628 { 2629 nAllLines = nNewNum; 2630 SwCntntFrm *pNxt = GetNextCntntFrm(); 2631 while ( pNxt && 2632 (pNxt->IsInTab() || pNxt->IsInDocBody() != IsInDocBody()) ) 2633 pNxt = pNxt->GetNextCntntFrm(); 2634 if ( pNxt ) 2635 { 2636 if ( pNxt->GetUpper() != GetUpper() ) 2637 pNxt->InvalidateLineNum(); 2638 else 2639 pNxt->_InvalidateLineNum(); 2640 } 2641 } 2642 } 2643 } 2644 2645 void SwTxtFrm::VisitPortions( SwPortionHandler& rPH ) const 2646 { 2647 const SwParaPortion* pPara = GetPara(); 2648 2649 if( pPara ) 2650 { 2651 if ( IsFollow() ) 2652 rPH.Skip( GetOfst() ); 2653 2654 const SwLineLayout* pLine = pPara; 2655 while ( pLine ) 2656 { 2657 const SwLinePortion* pPor = pLine->GetFirstPortion(); 2658 while ( pPor ) 2659 { 2660 pPor->HandlePortion( rPH ); 2661 pPor = pPor->GetPortion(); 2662 } 2663 2664 rPH.LineBreak(); 2665 pLine = pLine->GetNext(); 2666 } 2667 } 2668 2669 rPH.Finish(); 2670 } 2671 2672 2673 /************************************************************************* 2674 * SwTxtFrm::GetScriptInfo() 2675 *************************************************************************/ 2676 2677 const SwScriptInfo* SwTxtFrm::GetScriptInfo() const 2678 { 2679 const SwParaPortion* pPara = GetPara(); 2680 return pPara ? &pPara->GetScriptInfo() : 0; 2681 } 2682 2683 /************************************************************************* 2684 * lcl_CalcFlyBasePos() 2685 * Helper function for SwTxtFrm::CalcBasePosForFly() 2686 *************************************************************************/ 2687 2688 SwTwips lcl_CalcFlyBasePos( const SwTxtFrm& rFrm, SwRect aFlyRect, 2689 SwTxtFly& rTxtFly ) 2690 { 2691 SWRECTFN( (&rFrm) ) 2692 SwTwips nRet = rFrm.IsRightToLeft() ? 2693 (rFrm.Frm().*fnRect->fnGetRight)() : 2694 (rFrm.Frm().*fnRect->fnGetLeft)(); 2695 2696 do 2697 { 2698 SwRect aRect = rTxtFly.GetFrm( aFlyRect ); 2699 if ( 0 != (aRect.*fnRect->fnGetWidth)() ) 2700 { 2701 if ( rFrm.IsRightToLeft() ) 2702 { 2703 if ( (aRect.*fnRect->fnGetRight)() - 2704 (aFlyRect.*fnRect->fnGetRight)() >= 0 ) 2705 { 2706 (aFlyRect.*fnRect->fnSetRight)( 2707 (aRect.*fnRect->fnGetLeft)() ); 2708 nRet = (aRect.*fnRect->fnGetLeft)(); 2709 } 2710 else 2711 break; 2712 } 2713 else 2714 { 2715 if ( (aFlyRect.*fnRect->fnGetLeft)() - 2716 (aRect.*fnRect->fnGetLeft)() >= 0 ) 2717 { 2718 (aFlyRect.*fnRect->fnSetLeft)( 2719 (aRect.*fnRect->fnGetRight)() + 1 ); 2720 nRet = (aRect.*fnRect->fnGetRight)(); 2721 } 2722 else 2723 break; 2724 } 2725 } 2726 else 2727 break; 2728 } 2729 while ( (aFlyRect.*fnRect->fnGetWidth)() > 0 ); 2730 2731 return nRet; 2732 } 2733 2734 /************************************************************************* 2735 * SwTxtFrm::CalcBasePosForFly() 2736 *************************************************************************/ 2737 2738 void SwTxtFrm::CalcBaseOfstForFly() 2739 { 2740 ASSERT( !IsVertical() || !IsSwapped(), 2741 "SwTxtFrm::CalcBasePosForFly with swapped frame!" ) 2742 2743 const SwNode* pNode = GetTxtNode(); 2744 if ( !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_FLY_OFFSETS) ) 2745 return; 2746 2747 SWRECTFN( this ) 2748 2749 SwRect aFlyRect( Frm().Pos() + Prt().Pos(), Prt().SSize() ); 2750 2751 // Get first 'real' line and adjust position and height of line rectangle 2752 // OD 08.09.2003 #110978#, #108749#, #110354# - correct behaviour, 2753 // if no 'real' line exists (empty paragraph with and without a dummy portion) 2754 { 2755 SwTwips nTop = (aFlyRect.*fnRect->fnGetTop)(); 2756 const SwLineLayout* pLay = GetPara(); 2757 SwTwips nLineHeight = 200; 2758 while( pLay && pLay->IsDummy() && pLay->GetNext() ) 2759 { 2760 nTop += pLay->Height(); 2761 pLay = pLay->GetNext(); 2762 } 2763 if ( pLay ) 2764 { 2765 nLineHeight = pLay->Height(); 2766 } 2767 (aFlyRect.*fnRect->fnSetTopAndHeight)( nTop, nLineHeight ); 2768 } 2769 2770 SwTxtFly aTxtFly( this ); 2771 aTxtFly.SetIgnoreCurrentFrame( sal_True ); 2772 aTxtFly.SetIgnoreContour( sal_True ); 2773 // --> OD 2004-12-17 #118809# - ignore objects in page header|footer for 2774 // text frames not in page header|footer 2775 aTxtFly.SetIgnoreObjsInHeaderFooter( sal_True ); 2776 // <-- 2777 SwTwips nRet1 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly ); 2778 aTxtFly.SetIgnoreCurrentFrame( sal_False ); 2779 SwTwips nRet2 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly ); 2780 2781 // make values relative to frame start position 2782 SwTwips nLeft = IsRightToLeft() ? 2783 (Frm().*fnRect->fnGetRight)() : 2784 (Frm().*fnRect->fnGetLeft)(); 2785 2786 mnFlyAnchorOfst = nRet1 - nLeft; 2787 mnFlyAnchorOfstNoWrap = nRet2 - nLeft; 2788 } 2789 2790 /* repaint all text frames of the given text node */ 2791 void SwTxtFrm::repaintTextFrames( const SwTxtNode& rNode ) 2792 { 2793 SwIterator<SwTxtFrm,SwTxtNode> aIter( rNode ); 2794 for( const SwTxtFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() ) 2795 { 2796 SwRect aRec( pFrm->PaintArea() ); 2797 const SwRootFrm *pRootFrm = pFrm->getRootFrm(); 2798 ViewShell *pCurShell = pRootFrm ? pRootFrm->GetCurrShell() : NULL; 2799 if( pCurShell ) 2800 pCurShell->InvalidateWindows( aRec ); 2801 } 2802 } 2803 2804