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