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