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 <sfx2/printer.hxx> 32 #include <editeng/lspcitem.hxx> 33 #include <editeng/adjitem.hxx> 34 #include <editeng/escpitem.hxx> 35 #include <editeng/lrspitem.hxx> 36 #include <editeng/pgrditem.hxx> 37 #include <vcl/window.hxx> 38 #include <vcl/svapp.hxx> 39 #include <viewsh.hxx> // ViewShell 40 #include <viewopt.hxx> 41 #include <ndtxt.hxx> // SwTxtNode 42 #include <pagefrm.hxx> // SwPageFrm 43 #include <paratr.hxx> 44 #include <SwPortionHandler.hxx> 45 #include <txtcfg.hxx> 46 #include <porrst.hxx> 47 #include <inftxt.hxx> 48 #include <txtpaint.hxx> // ClipVout 49 #include <swfntcch.hxx> // SwFontAccess 50 #include <tgrditem.hxx> 51 #include <pagedesc.hxx> // SwPageDesc 52 #include <frmatr.hxx> 53 #include <redlnitr.hxx> // SwRedlineItr 54 #include <porfly.hxx> // SwFlyPortion 55 #include <atrhndl.hxx> 56 #include "rootfrm.hxx" 57 58 #include <IDocumentRedlineAccess.hxx> 59 #include <IDocumentSettingAccess.hxx> 60 #include <IDocumentDeviceAccess.hxx> 61 62 /************************************************************************* 63 * class SwTmpEndPortion 64 *************************************************************************/ 65 66 SwTmpEndPortion::SwTmpEndPortion( const SwLinePortion &rPortion ) 67 { 68 Height( rPortion.Height() ); 69 SetAscent( rPortion.GetAscent() ); 70 SetWhichPor( POR_TMPEND ); 71 } 72 73 /************************************************************************* 74 * virtual SwTmpEndPortion::Paint() 75 *************************************************************************/ 76 77 void SwTmpEndPortion::Paint( const SwTxtPaintInfo &rInf ) const 78 { 79 if( rInf.OnWin() && rInf.GetOpt().IsParagraph() ) 80 { 81 SwDefFontSave aSave( rInf ); 82 const XubString aTmp( CH_PAR ); 83 rInf.DrawText( aTmp, *this ); 84 } 85 } 86 87 /************************************************************************* 88 * class SwBreakPortion 89 *************************************************************************/ 90 SwBreakPortion::SwBreakPortion( const SwLinePortion &rPortion ) 91 : SwLinePortion( rPortion ) 92 { 93 nLineLength = 1; 94 SetWhichPor( POR_BRK ); 95 } 96 97 xub_StrLen SwBreakPortion::GetCrsrOfst( const KSHORT ) const 98 { return 0; } 99 100 KSHORT SwBreakPortion::GetViewWidth( const SwTxtSizeInfo & ) const 101 { return 0; } 102 103 SwLinePortion *SwBreakPortion::Compress() 104 { return (GetPortion() && GetPortion()->InTxtGrp() ? 0 : this); } 105 106 void SwBreakPortion::Paint( const SwTxtPaintInfo &rInf ) const 107 { 108 if( rInf.OnWin() && rInf.GetOpt().IsLineBreak() ) 109 rInf.DrawLineBreak( *this ); 110 } 111 112 /************************************************************************* 113 * virtual SwBreakPortion::Format() 114 *************************************************************************/ 115 116 sal_Bool SwBreakPortion::Format( SwTxtFormatInfo &rInf ) 117 { 118 const SwLinePortion *pRoot = rInf.GetRoot(); 119 Width( 0 ); 120 Height( pRoot->Height() ); 121 SetAscent( pRoot->GetAscent() ); 122 if ( rInf.GetIdx()+1 == rInf.GetTxt().Len() ) 123 rInf.SetNewLine( sal_True ); 124 return sal_True; 125 } 126 127 /************************************************************************* 128 * virtual SwBreakPortion::HandlePortion() 129 *************************************************************************/ 130 131 void SwBreakPortion::HandlePortion( SwPortionHandler& rPH ) const 132 { 133 rPH.Text( GetLen(), GetWhichPor() ); 134 } 135 136 137 SwKernPortion::SwKernPortion( SwLinePortion &rPortion, short nKrn, 138 sal_Bool bBG, sal_Bool bGK ) : 139 nKern( nKrn ), bBackground( bBG ), bGridKern( bGK ) 140 { 141 Height( rPortion.Height() ); 142 SetAscent( rPortion.GetAscent() ); 143 nLineLength = 0; 144 SetWhichPor( POR_KERN ); 145 if( nKern > 0 ) 146 Width( nKern ); 147 rPortion.Insert( this ); 148 } 149 150 SwKernPortion::SwKernPortion( const SwLinePortion& rPortion ) : 151 nKern( 0 ), bBackground( sal_False ), bGridKern( sal_True ) 152 { 153 Height( rPortion.Height() ); 154 SetAscent( rPortion.GetAscent() ); 155 156 nLineLength = 0; 157 SetWhichPor( POR_KERN ); 158 } 159 160 void SwKernPortion::Paint( const SwTxtPaintInfo &rInf ) const 161 { 162 if( Width() ) 163 { 164 // bBackground is set for Kerning Portions between two fields 165 if ( bBackground ) 166 rInf.DrawViewOpt( *this, POR_FLD ); 167 168 rInf.DrawBackBrush( *this ); 169 170 // do we have to repaint a post it portion? 171 if( rInf.OnWin() && pPortion && !pPortion->Width() ) 172 pPortion->PrePaint( rInf, this ); 173 174 if( rInf.GetFont()->IsPaintBlank() ) 175 { 176 static sal_Char __READONLY_DATA sDoubleSpace[] = " "; 177 XubString aTxtDouble( sDoubleSpace, RTL_TEXTENCODING_MS_1252 ); 178 // --> FME 2006-07-12 #b6439097# 179 SwRect aClipRect; 180 rInf.CalcRect( *this, &aClipRect, 0 ); 181 SwSaveClip aClip( (OutputDevice*)rInf.GetOut() ); 182 aClip.ChgClip( aClipRect, 0 ); 183 // <-- 184 rInf.DrawText( aTxtDouble, *this, 0, 2, sal_True ); 185 } 186 } 187 } 188 189 void SwKernPortion::FormatEOL( SwTxtFormatInfo &rInf ) 190 { 191 if ( bGridKern ) 192 return; 193 194 if( rInf.GetLast() == this ) 195 rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) ); 196 if( nKern < 0 ) 197 Width( -nKern ); 198 else 199 Width( 0 ); 200 rInf.GetLast()->FormatEOL( rInf ); 201 } 202 203 SwArrowPortion::SwArrowPortion( const SwLinePortion &rPortion ) : 204 bLeft( sal_True ) 205 { 206 Height( rPortion.Height() ); 207 SetAscent( rPortion.GetAscent() ); 208 nLineLength = 0; 209 SetWhichPor( POR_ARROW ); 210 } 211 212 SwArrowPortion::SwArrowPortion( const SwTxtPaintInfo &rInf ) 213 : bLeft( sal_False ) 214 { 215 Height( (sal_uInt16)(rInf.GetTxtFrm()->Prt().Height()) ); 216 aPos.X() = rInf.GetTxtFrm()->Frm().Left() + 217 rInf.GetTxtFrm()->Prt().Right(); 218 aPos.Y() = rInf.GetTxtFrm()->Frm().Top() + 219 rInf.GetTxtFrm()->Prt().Bottom(); 220 SetWhichPor( POR_ARROW ); 221 } 222 223 void SwArrowPortion::Paint( const SwTxtPaintInfo &rInf ) const 224 { 225 ((SwArrowPortion*)this)->aPos = rInf.GetPos(); 226 } 227 228 SwLinePortion *SwArrowPortion::Compress() { return this; } 229 230 SwTwips SwTxtFrm::EmptyHeight() const 231 { 232 ASSERT( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::EmptyHeight with swapped frame" ); 233 234 SwFont *pFnt; 235 const SwTxtNode& rTxtNode = *GetTxtNode(); 236 const IDocumentSettingAccess* pIDSA = rTxtNode.getIDocumentSettingAccess(); 237 ViewShell *pSh = getRootFrm()->GetCurrShell(); 238 if ( rTxtNode.HasSwAttrSet() ) 239 { 240 const SwAttrSet *pAttrSet = &( rTxtNode.GetSwAttrSet() ); 241 pFnt = new SwFont( pAttrSet, pIDSA ); 242 } 243 else 244 { 245 SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pSh); 246 pFnt = new SwFont( *aFontAccess.Get()->GetFont() ); 247 pFnt->ChkMagic( pSh, pFnt->GetActual() ); 248 } 249 250 if ( IsVertical() ) 251 pFnt->SetVertical( 2700 ); 252 253 OutputDevice* pOut = pSh ? pSh->GetOut() : 0; 254 if ( !pOut || !pSh->GetViewOptions()->getBrowseMode() || 255 pSh->GetViewOptions()->IsPrtFormat() ) 256 { 257 pOut = rTxtNode.getIDocumentDeviceAccess()->getReferenceDevice(true); 258 } 259 260 const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess(); 261 if( IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) ) 262 { 263 MSHORT nRedlPos = pIDRA->GetRedlinePos( rTxtNode, USHRT_MAX ); 264 if( MSHRT_MAX != nRedlPos ) 265 { 266 SwAttrHandler aAttrHandler; 267 aAttrHandler.Init( GetTxtNode()->GetSwAttrSet(), 268 *GetTxtNode()->getIDocumentSettingAccess(), NULL ); 269 SwRedlineItr aRedln( rTxtNode, *pFnt, aAttrHandler, 270 nRedlPos, sal_True ); 271 } 272 } 273 274 SwTwips nRet; 275 if( !pOut ) 276 nRet = IsVertical() ? 277 Prt().SSize().Width() + 1 : 278 Prt().SSize().Height() + 1; 279 else 280 { 281 pFnt->SetFntChg( sal_True ); 282 pFnt->ChgPhysFnt( pSh, *pOut ); 283 nRet = pFnt->GetHeight( pSh, *pOut ); 284 } 285 delete pFnt; 286 return nRet; 287 } 288 289 /************************************************************************* 290 * SwTxtFrm::FormatEmpty() 291 *************************************************************************/ 292 293 sal_Bool SwTxtFrm::FormatEmpty() 294 { 295 ASSERT( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::FormatEmpty with swapped frame" ); 296 297 if ( HasFollow() || GetTxtNode()->GetpSwpHints() || 298 0 != GetTxtNode()->GetNumRule() || 299 GetTxtNode()->HasHiddenCharAttribute( true ) || 300 IsInFtn() || ( HasPara() && GetPara()->IsPrepMustFit() ) ) 301 return sal_False; 302 const SwAttrSet& aSet = GetTxtNode()->GetSwAttrSet(); 303 const SvxAdjust nAdjust = aSet.GetAdjust().GetAdjust(); 304 if( ( ( ! IsRightToLeft() && ( SVX_ADJUST_LEFT != nAdjust ) ) || 305 ( IsRightToLeft() && ( SVX_ADJUST_RIGHT != nAdjust ) ) ) || 306 aSet.GetRegister().GetValue() ) 307 return sal_False; 308 const SvxLineSpacingItem &rSpacing = aSet.GetLineSpacing(); 309 if( SVX_LINE_SPACE_MIN == rSpacing.GetLineSpaceRule() || 310 SVX_LINE_SPACE_FIX == rSpacing.GetLineSpaceRule() || 311 aSet.GetLRSpace().IsAutoFirst() ) 312 return sal_False; 313 else 314 { 315 SwTxtFly aTxtFly( this ); 316 SwRect aRect; 317 sal_Bool bFirstFlyCheck = 0 != Prt().Height(); 318 if ( bFirstFlyCheck && 319 aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) ) 320 return sal_False; 321 else 322 { 323 SwTwips nHeight = EmptyHeight(); 324 325 if ( GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() && 326 IsInDocBody() ) 327 { 328 GETGRID( FindPageFrm() ) 329 if ( pGrid ) 330 nHeight = pGrid->GetBaseHeight() + pGrid->GetRubyHeight(); 331 } 332 333 SWRECTFN( this ) 334 const SwTwips nChg = nHeight - (Prt().*fnRect->fnGetHeight)(); 335 336 if( !nChg ) 337 SetUndersized( sal_False ); 338 AdjustFrm( nChg ); 339 340 if( HasBlinkPor() ) 341 { 342 ClearPara(); 343 ResetBlinkPor(); 344 } 345 SetCacheIdx( MSHRT_MAX ); 346 if( !IsEmpty() ) 347 { 348 SetEmpty( sal_True ); 349 SetCompletePaint(); 350 } 351 if( !bFirstFlyCheck && 352 aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) ) 353 return sal_False; 354 355 // --> OD 2004-11-17 #i35635# - call method <HideAndShowObjects()> 356 // to assure that objects anchored at the empty paragraph are 357 // correctly visible resp. invisible. 358 HideAndShowObjects(); 359 // <-- 360 return sal_True; 361 } 362 } 363 } 364 365 sal_Bool SwTxtFrm::FillRegister( SwTwips& rRegStart, KSHORT& rRegDiff ) 366 { 367 const SwFrm *pFrm = this; 368 rRegDiff = 0; 369 while( !( ( FRM_BODY | FRM_FLY ) 370 & pFrm->GetType() ) && pFrm->GetUpper() ) 371 pFrm = pFrm->GetUpper(); 372 if( ( FRM_BODY| FRM_FLY ) & pFrm->GetType() ) 373 { 374 SWRECTFN( pFrm ) 375 rRegStart = (pFrm->*fnRect->fnGetPrtTop)(); 376 pFrm = pFrm->FindPageFrm(); 377 if( pFrm->IsPageFrm() ) 378 { 379 SwPageDesc* pDesc = ((SwPageFrm*)pFrm)->FindPageDesc(); 380 if( pDesc ) 381 { 382 rRegDiff = pDesc->GetRegHeight(); 383 if( !rRegDiff ) 384 { 385 const SwTxtFmtColl *pFmt = pDesc->GetRegisterFmtColl(); 386 if( pFmt ) 387 { 388 const SvxLineSpacingItem &rSpace = pFmt->GetLineSpacing(); 389 if( SVX_LINE_SPACE_FIX == rSpace.GetLineSpaceRule() ) 390 { 391 rRegDiff = rSpace.GetLineHeight(); 392 pDesc->SetRegHeight( rRegDiff ); 393 pDesc->SetRegAscent( ( 4 * rRegDiff ) / 5 ); 394 } 395 else 396 { 397 ViewShell *pSh = getRootFrm()->GetCurrShell(); 398 SwFontAccess aFontAccess( pFmt, pSh ); 399 SwFont aFnt( *aFontAccess.Get()->GetFont() ); 400 401 OutputDevice *pOut = 0; 402 if( !pSh || !pSh->GetViewOptions()->getBrowseMode() || 403 pSh->GetViewOptions()->IsPrtFormat() ) 404 pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true ); 405 406 if( pSh && !pOut ) 407 pOut = pSh->GetWin(); 408 409 if( !pOut ) 410 pOut = GetpApp()->GetDefaultDevice(); 411 412 MapMode aOldMap( pOut->GetMapMode() ); 413 pOut->SetMapMode( MapMode( MAP_TWIP ) ); 414 415 aFnt.ChgFnt( pSh, *pOut ); 416 rRegDiff = aFnt.GetHeight( pSh, *pOut ); 417 KSHORT nNettoHeight = rRegDiff; 418 419 switch( rSpace.GetLineSpaceRule() ) 420 { 421 case SVX_LINE_SPACE_AUTO: 422 break; 423 case SVX_LINE_SPACE_MIN: 424 { 425 if( rRegDiff < KSHORT( rSpace.GetLineHeight() ) ) 426 rRegDiff = rSpace.GetLineHeight(); 427 break; 428 } 429 default: ASSERT( 430 sal_False, ": unknown LineSpaceRule" ); 431 } 432 switch( rSpace.GetInterLineSpaceRule() ) 433 { 434 case SVX_INTER_LINE_SPACE_OFF: 435 break; 436 case SVX_INTER_LINE_SPACE_PROP: 437 { 438 long nTmp = rSpace.GetPropLineSpace(); 439 if( nTmp < 50 ) 440 nTmp = nTmp ? 50 : 100; 441 nTmp *= rRegDiff; 442 nTmp /= 100; 443 if( !nTmp ) 444 ++nTmp; 445 rRegDiff = (KSHORT)nTmp; 446 nNettoHeight = rRegDiff; 447 break; 448 } 449 case SVX_INTER_LINE_SPACE_FIX: 450 { 451 rRegDiff = rRegDiff + rSpace.GetInterLineSpace(); 452 nNettoHeight = rRegDiff; 453 break; 454 } 455 default: ASSERT( sal_False, ": unknown InterLineSpaceRule" ); 456 } 457 pDesc->SetRegHeight( rRegDiff ); 458 pDesc->SetRegAscent( rRegDiff - nNettoHeight + 459 aFnt.GetAscent( pSh, *pOut ) ); 460 pOut->SetMapMode( aOldMap ); 461 } 462 } 463 } 464 const long nTmpDiff = pDesc->GetRegAscent() - rRegDiff; 465 if ( bVert ) 466 rRegStart -= nTmpDiff; 467 else 468 rRegStart += nTmpDiff; 469 } 470 } 471 } 472 return ( 0 != rRegDiff ); 473 } 474 475 /************************************************************************* 476 * virtual SwHiddenTextPortion::Paint() 477 *************************************************************************/ 478 479 void SwHiddenTextPortion::Paint( const SwTxtPaintInfo & rInf) const 480 { 481 (void)rInf; 482 #if OSL_DEBUG_LEVEL > 1 483 OutputDevice* pOut = (OutputDevice*)rInf.GetOut(); 484 Color aCol( SwViewOption::GetFieldShadingsColor() ); 485 Color aOldColor( pOut->GetFillColor() ); 486 pOut->SetFillColor( aCol ); 487 Point aPos( rInf.GetPos() ); 488 aPos.Y() -= 150; 489 aPos.X() -= 25; 490 SwRect aRect( aPos, Size( 100, 200 ) ); 491 ((OutputDevice*)pOut)->DrawRect( aRect.SVRect() ); 492 pOut->SetFillColor( aOldColor ); 493 #endif 494 } 495 496 /************************************************************************* 497 * virtual SwHiddenTextPortion::Format() 498 *************************************************************************/ 499 500 sal_Bool SwHiddenTextPortion::Format( SwTxtFormatInfo &rInf ) 501 { 502 Width( 0 ); 503 rInf.GetTxtFrm()->HideFootnotes( rInf.GetIdx(), rInf.GetIdx() + GetLen() ); 504 505 return sal_False; 506 }; 507 508 /************************************************************************* 509 * virtual SwControlCharPortion::Paint() 510 *************************************************************************/ 511 512 void SwControlCharPortion::Paint( const SwTxtPaintInfo &rInf ) const 513 { 514 if ( Width() ) // is only set during prepaint mode 515 { 516 rInf.DrawViewOpt( *this, POR_CONTROLCHAR ); 517 518 if ( !rInf.GetOpt().IsPagePreview() && 519 !rInf.GetOpt().IsReadonly() && 520 SwViewOption::IsFieldShadings() && 521 CHAR_ZWNBSP != mcChar ) 522 { 523 SwFont aTmpFont( *rInf.GetFont() ); 524 aTmpFont.SetEscapement( CHAR_ZWSP == mcChar ? DFLT_ESC_AUTO_SUB : -25 ); 525 const sal_uInt16 nProp = 40; 526 aTmpFont.SetProportion( nProp ); // a smaller font 527 SwFontSave aFontSave( rInf, &aTmpFont ); 528 529 String aOutString; 530 531 switch ( mcChar ) 532 { 533 case CHAR_ZWSP : 534 aOutString = '/'; break; 535 // case CHAR_LRM : 536 // rTxt = sal_Unicode(0x2514); break; 537 // case CHAR_RLM : 538 // rTxt = sal_Unicode(0x2518); break; 539 } 540 541 if ( !mnHalfCharWidth ) 542 mnHalfCharWidth = rInf.GetTxtSize( aOutString ).Width() / 2; 543 544 Point aOldPos = rInf.GetPos(); 545 Point aNewPos( aOldPos ); 546 aNewPos.X() = aNewPos.X() + ( Width() / 2 ) - mnHalfCharWidth; 547 const_cast< SwTxtPaintInfo& >( rInf ).SetPos( aNewPos ); 548 549 rInf.DrawText( aOutString, *this ); 550 551 const_cast< SwTxtPaintInfo& >( rInf ).SetPos( aOldPos ); 552 } 553 } 554 } 555 556 /************************************************************************* 557 * virtual SwControlCharPortion::Format() 558 *************************************************************************/ 559 560 sal_Bool SwControlCharPortion::Format( SwTxtFormatInfo &rInf ) 561 { 562 const SwLinePortion* pRoot = rInf.GetRoot(); 563 Width( 0 ); 564 Height( pRoot->Height() ); 565 SetAscent( pRoot->GetAscent() ); 566 567 return sal_False; 568 } 569 570 /************************************************************************* 571 * virtual SwControlCharPortion::GetViewWidth() 572 *************************************************************************/ 573 574 KSHORT SwControlCharPortion::GetViewWidth( const SwTxtSizeInfo& rInf ) const 575 { 576 if( !mnViewWidth ) 577 mnViewWidth = rInf.GetTxtSize( ' ' ).Width(); 578 579 return mnViewWidth; 580 } 581