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 27 28 #include <com/sun/star/uno/Sequence.h> 29 #include <unotools/linguprops.hxx> 30 #include <unotools/lingucfg.hxx> 31 #include <hintids.hxx> 32 #include <sfx2/printer.hxx> 33 #include <editeng/hyznitem.hxx> 34 #include <editeng/escpitem.hxx> 35 #include <editeng/hngpnctitem.hxx> 36 #include <editeng/scriptspaceitem.hxx> 37 #include <editeng/brshitem.hxx> 38 #include <editeng/splwrap.hxx> 39 #include <editeng/pgrditem.hxx> 40 #include <editeng/tstpitem.hxx> 41 42 #include <SwSmartTagMgr.hxx> 43 #include <linguistic/lngprops.hxx> 44 #include <editeng/unolingu.hxx> 45 #include <breakit.hxx> 46 #include <editeng/forbiddenruleitem.hxx> 47 #include <txatbase.hxx> 48 #include <fmtinfmt.hxx> 49 #include <swmodule.hxx> 50 #include <vcl/svapp.hxx> 51 #include <vcl/wrkwin.hxx> 52 #include <viewsh.hxx> // ViewShell 53 #include <viewopt.hxx> // SwViewOptions 54 #include <frmtool.hxx> // DrawGraphic 55 #include <IDocumentSettingAccess.hxx> 56 #include <IDocumentDeviceAccess.hxx> 57 #include <paratr.hxx> // SwFmtDrop 58 #include <rootfrm.hxx> // SwRootFrm 59 #include <inftxt.hxx> // SwTxtInfo 60 #include <blink.hxx> // SwBlink 61 #include <noteurl.hxx> // SwNoteURL 62 #include <porftn.hxx> // SwFtnPortion 63 #include <porrst.hxx> // SwHangingPortion 64 #include <itratr.hxx> 65 #include <accessibilityoptions.hxx> 66 #include <wrong.hxx> 67 #include <doc.hxx> 68 #include <pam.hxx> 69 #include <SwGrammarMarkUp.hxx> 70 #include <cstdio> 71 #include <EnhancedPDFExportHelper.hxx> 72 73 #include <unomid.h> 74 75 using namespace ::com::sun::star; 76 using namespace ::com::sun::star::linguistic2; 77 using namespace ::com::sun::star::uno; 78 using namespace ::com::sun::star::beans; 79 80 81 #define CHAR_UNDERSCORE ((sal_Unicode)0x005F) 82 #define CHAR_LEFT_ARROW ((sal_Unicode)0x25C0) 83 #define CHAR_RIGHT_ARROW ((sal_Unicode)0x25B6) 84 #define CHAR_TAB ((sal_Unicode)0x2192) 85 #define CHAR_TAB_RTL ((sal_Unicode)0x2190) 86 #define CHAR_LINEBREAK ((sal_Unicode)0x21B5) 87 #define CHAR_LINEBREAK_RTL ((sal_Unicode)0x21B3) 88 89 #define DRAW_SPECIAL_OPTIONS_CENTER 1 90 #define DRAW_SPECIAL_OPTIONS_ROTATE 2 91 92 // --> OD 2006-06-27 #b6440955# 93 // variable moved to class <numfunc:GetDefBulletConfig> 94 //extern const sal_Char __FAR_DATA sBulletFntName[]; 95 namespace numfunc 96 { 97 extern const String& GetDefBulletFontname(); 98 extern bool IsDefBulletFontUserDefined(); 99 } 100 // <-- 101 102 #ifdef DBG_UTIL 103 // Test2: WYSIWYG++ 104 // Test4: WYSIWYG debug 105 static sal_Bool bDbgLow = sal_False; 106 #endif 107 108 #ifdef DBG_UTIL 109 110 sal_Bool SwTxtSizeInfo::IsOptCalm() const { return !GetOpt().IsTest3(); } 111 112 sal_Bool SwTxtSizeInfo::IsOptLow() const { return bDbgLow; } 113 114 sal_Bool SwTxtSizeInfo::IsOptDbg() const { return GetOpt().IsTest4(); } 115 116 sal_Bool SwTxtSizeInfo::IsOptTest1() const { return GetOpt().IsTest1(); } 117 118 sal_Bool SwTxtSizeInfo::IsOptTest2() const { return GetOpt().IsTest2(); } 119 120 sal_Bool SwTxtSizeInfo::IsOptTest3() const { return GetOpt().IsTest3(); } 121 122 sal_Bool SwTxtSizeInfo::IsOptTest4() const { return GetOpt().IsTest4(); } 123 124 sal_Bool SwTxtSizeInfo::IsOptTest5() const { return GetOpt().IsTest5(); } 125 126 sal_Bool SwTxtSizeInfo::IsOptTest6() const { return GetOpt().IsTest6(); } 127 128 sal_Bool SwTxtSizeInfo::IsOptTest7() const { return GetOpt().IsTest7(); } 129 130 sal_Bool SwTxtSizeInfo::IsOptTest8() const { return GetOpt().IsTest8(); } 131 132 #endif 133 134 /************************************************************************* 135 * SwLineInfo::SwLineInfo() 136 *************************************************************************/ 137 138 // --> OD 2008-01-17 #newlistlevelattrs# 139 SwLineInfo::SwLineInfo() 140 : pRuler( 0 ), 141 pSpace( 0 ), 142 nVertAlign( 0 ), 143 nDefTabStop( 0 ), 144 bListTabStopIncluded( false ), 145 nListTabStopPosition( 0 ) 146 { 147 } 148 149 SwLineInfo::~SwLineInfo() 150 { 151 delete pRuler; 152 } 153 void SwLineInfo::CtorInitLineInfo( const SwAttrSet& rAttrSet, 154 const SwTxtNode& rTxtNode ) 155 // <-- 156 { 157 // --> OD 2008-01-17 #newlistlevelattrs# 158 // pRuler = &rAttrSet.GetTabStops(); 159 delete pRuler; 160 pRuler = new SvxTabStopItem( rAttrSet.GetTabStops() ); 161 if ( rTxtNode.GetListTabStopPosition( nListTabStopPosition ) ) 162 { 163 bListTabStopIncluded = true; 164 165 // insert the list tab stop into SvxTabItem instance <pRuler> 166 const SvxTabStop aListTabStop( nListTabStopPosition, 167 SVX_TAB_ADJUST_LEFT ); 168 pRuler->Insert( aListTabStop ); 169 170 // remove default tab stops, which are before the inserted list tab stop 171 for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ ) 172 { 173 if ( (*pRuler)[i].GetTabPos() < nListTabStopPosition && 174 (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT ) 175 { 176 pRuler->Remove(i); 177 continue; 178 } 179 } 180 } 181 // <-- 182 // --> OD 2008-02-15 #newlistlevelattrs# 183 if ( !rTxtNode.getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) ) 184 { 185 // remove default tab stop at position 0 186 for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ ) 187 { 188 if ( (*pRuler)[i].GetTabPos() == 0 && 189 (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT ) 190 { 191 pRuler->Remove(i); 192 break; 193 } 194 } 195 } 196 // <-- 197 pSpace = &rAttrSet.GetLineSpacing(); 198 nVertAlign = rAttrSet.GetParaVertAlign().GetValue(); 199 nDefTabStop = MSHRT_MAX; 200 } 201 202 /************************************************************************* 203 * SwTxtInfo::CtorInitTxtInfo() 204 *************************************************************************/ 205 206 void SwTxtInfo::CtorInitTxtInfo( SwTxtFrm *pFrm ) 207 { 208 pPara = pFrm->GetPara(); 209 nTxtStart = pFrm->GetOfst(); 210 if( !pPara ) 211 { 212 ASSERT( pPara, "+SwTxtInfo::CTOR: missing paragraph information" ); 213 pFrm->Format(); 214 pPara = pFrm->GetPara(); 215 } 216 } 217 218 SwTxtInfo::SwTxtInfo( const SwTxtInfo &rInf ) 219 : pPara( ((SwTxtInfo&)rInf).GetParaPortion() ), 220 nTxtStart( rInf.GetTxtStart() ) 221 { } 222 223 224 #ifdef DBG_UTIL 225 /************************************************************************* 226 * ChkOutDev() 227 *************************************************************************/ 228 229 void ChkOutDev( const SwTxtSizeInfo &rInf ) 230 { 231 if ( !rInf.GetVsh() ) 232 return; 233 234 const OutputDevice* pOut = rInf.GetOut(); 235 const OutputDevice* pRef = rInf.GetRefDev(); 236 ASSERT( pOut && pRef, "ChkOutDev: invalid output devices" ) 237 } 238 #endif // PRODUCT 239 240 241 inline xub_StrLen GetMinLen( const SwTxtSizeInfo &rInf ) 242 { 243 const xub_StrLen nInfLen = rInf.GetIdx() + rInf.GetLen(); 244 return Min( rInf.GetTxt().Len(), nInfLen ); 245 } 246 247 248 SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew ) 249 : SwTxtInfo( rNew ), 250 pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()), 251 pVsh(((SwTxtSizeInfo&)rNew).GetVsh()), 252 pOut(((SwTxtSizeInfo&)rNew).GetOut()), 253 pRef(((SwTxtSizeInfo&)rNew).GetRefDev()), 254 pFnt(((SwTxtSizeInfo&)rNew).GetFont()), 255 pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()), 256 pFrm(rNew.pFrm), 257 pOpt(&rNew.GetOpt()), 258 pTxt(&rNew.GetTxt()), 259 nIdx(rNew.GetIdx()), 260 nLen(rNew.GetLen()), 261 nKanaIdx( rNew.GetKanaIdx() ), 262 bOnWin( rNew.OnWin() ), 263 bNotEOL( rNew.NotEOL() ), 264 bURLNotify( rNew.URLNotify() ), 265 bStopUnderFlow( rNew.StopUnderFlow() ), 266 bFtnInside( rNew.IsFtnInside() ), 267 bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ), 268 bMulti( rNew.IsMulti() ), 269 bFirstMulti( rNew.IsFirstMulti() ), 270 bRuby( rNew.IsRuby() ), 271 bHanging( rNew.IsHanging() ), 272 bScriptSpace( rNew.HasScriptSpace() ), 273 bForbiddenChars( rNew.HasForbiddenChars() ), 274 bSnapToGrid( rNew.SnapToGrid() ), 275 nDirection( rNew.GetDirection() ) 276 { 277 #ifdef DBG_UTIL 278 ChkOutDev( *this ); 279 #endif 280 } 281 282 void SwTxtSizeInfo::CtorInitTxtSizeInfo( SwTxtFrm *pFrame, SwFont *pNewFnt, 283 const xub_StrLen nNewIdx, const xub_StrLen nNewLen ) 284 { 285 pKanaComp = NULL; 286 nKanaIdx = 0; 287 pFrm = pFrame; 288 CtorInitTxtInfo( pFrm ); 289 const SwTxtNode *pNd = pFrm->GetTxtNode(); 290 pVsh = pFrm->getRootFrm()->GetCurrShell(); 291 292 // Get the output and reference device 293 if ( pVsh ) 294 { 295 pOut = pVsh->GetOut(); 296 pRef = &pVsh->GetRefDev(); 297 bOnWin = pVsh->GetWin() || OUTDEV_WINDOW == pOut->GetOutDevType(); 298 } 299 else 300 { 301 //Zugriff ueber StarONE, es muss keine Shell existieren oder aktiv sein. 302 if ( pNd->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) ) 303 { 304 //in Ermangelung eines Besseren kann hier ja wohl nur noch das 305 //AppWin genommen werden? 306 pOut = GetpApp()->GetDefaultDevice(); 307 } 308 else 309 pOut = pNd->getIDocumentDeviceAccess()->getPrinter( false ); 310 311 pRef = pOut; 312 } 313 314 #ifdef DBG_UTIL 315 ChkOutDev( *this ); 316 #endif 317 318 // Set default layout mode ( LTR or RTL ). 319 if ( pFrm->IsRightToLeft() ) 320 { 321 pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL ); 322 pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL ); 323 nDirection = DIR_RIGHT2LEFT; 324 } 325 else 326 { 327 pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG ); 328 pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG ); 329 nDirection = DIR_LEFT2RIGHT; 330 } 331 332 /* LanguageType eLang; 333 const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions(); 334 if ( SvtCTLOptions::NUMERALS_HINDI == rCTLOptions.GetCTLTextNumerals() ) 335 eLang = LANGUAGE_ARABIC_SAUDI_ARABIA; 336 else if ( SvtCTLOptions::NUMERALS_ARABIC == rCTLOptions.GetCTLTextNumerals() ) 337 eLang = LANGUAGE_ENGLISH; 338 else 339 eLang = (LanguageType)::GetAppLanguage(); 340 341 pOut->SetDigitLanguage( eLang ); 342 pRef->SetDigitLanguage( eLang );*/ 343 344 // 345 // The Options 346 // 347 pOpt = pVsh ? 348 pVsh->GetViewOptions() : 349 SW_MOD()->GetViewOption( pNd->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) ); //Options vom Module wg. StarONE 350 351 // bURLNotify wird gesetzt, wenn MakeGraphic dies vorbereitet 352 // TODO: Aufdr?seln 353 bURLNotify = pNoteURL && !bOnWin; 354 355 SetSnapToGrid( pNd->GetSwAttrSet().GetParaGrid().GetValue() && 356 pFrm->IsInDocBody() ); 357 358 pFnt = pNewFnt; 359 pUnderFnt = 0; 360 pTxt = &pNd->GetTxt(); 361 362 nIdx = nNewIdx; 363 nLen = nNewLen; 364 bNotEOL = sal_False; 365 bStopUnderFlow = bFtnInside = bOtherThanFtnInside = sal_False; 366 bMulti = bFirstMulti = bRuby = bHanging = bScriptSpace = 367 bForbiddenChars = sal_False; 368 369 SetLen( GetMinLen( *this ) ); 370 } 371 372 SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew, const XubString &rTxt, 373 const xub_StrLen nIndex, const xub_StrLen nLength ) 374 : SwTxtInfo( rNew ), 375 pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()), 376 pVsh(((SwTxtSizeInfo&)rNew).GetVsh()), 377 pOut(((SwTxtSizeInfo&)rNew).GetOut()), 378 pRef(((SwTxtSizeInfo&)rNew).GetRefDev()), 379 pFnt(((SwTxtSizeInfo&)rNew).GetFont()), 380 pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()), 381 pFrm( rNew.pFrm ), 382 pOpt(&rNew.GetOpt()), 383 pTxt(&rTxt), 384 nIdx(nIndex), 385 nLen(nLength), 386 nKanaIdx( rNew.GetKanaIdx() ), 387 bOnWin( rNew.OnWin() ), 388 bNotEOL( rNew.NotEOL() ), 389 bURLNotify( rNew.URLNotify() ), 390 bStopUnderFlow( rNew.StopUnderFlow() ), 391 bFtnInside( rNew.IsFtnInside() ), 392 bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ), 393 bMulti( rNew.IsMulti() ), 394 bFirstMulti( rNew.IsFirstMulti() ), 395 bRuby( rNew.IsRuby() ), 396 bHanging( rNew.IsHanging() ), 397 bScriptSpace( rNew.HasScriptSpace() ), 398 bForbiddenChars( rNew.HasForbiddenChars() ), 399 bSnapToGrid( rNew.SnapToGrid() ), 400 nDirection( rNew.GetDirection() ) 401 { 402 #ifdef DBG_UTIL 403 ChkOutDev( *this ); 404 #endif 405 SetLen( GetMinLen( *this ) ); 406 } 407 408 /************************************************************************* 409 * SwTxtSizeInfo::SelectFont() 410 *************************************************************************/ 411 412 void SwTxtSizeInfo::SelectFont() 413 { 414 // 8731: Der Weg muss ueber ChgPhysFnt gehen, sonst geraet 415 // der FontMetricCache durcheinander. In diesem Fall steht pLastMet 416 // auf dem alten Wert. 417 // Falsch: GetOut()->SetFont( GetFont()->GetFnt() ); 418 GetFont()->Invalidate(); 419 GetFont()->ChgPhysFnt( pVsh, *GetOut() ); 420 } 421 422 /************************************************************************* 423 * SwTxtSizeInfo::NoteAnimation() 424 *************************************************************************/ 425 426 void SwTxtSizeInfo::NoteAnimation() const 427 { 428 if( OnWin() ) 429 SwRootFrm::FlushVout(); 430 431 ASSERT( pOut == pVsh->GetOut(), 432 "SwTxtSizeInfo::NoteAnimation() changed pOut" ) 433 } 434 435 /************************************************************************* 436 * SwTxtSizeInfo::GetTxtSize() 437 *************************************************************************/ 438 439 SwPosSize SwTxtSizeInfo::GetTxtSize( OutputDevice* pOutDev, 440 const SwScriptInfo* pSI, 441 const XubString& rTxt, 442 const xub_StrLen nIndex, 443 const xub_StrLen nLength, 444 const sal_uInt16 nComp ) const 445 { 446 SwDrawTextInfo aDrawInf( pVsh, *pOutDev, pSI, rTxt, nIndex, nLength ); 447 aDrawInf.SetFrm( pFrm ); 448 aDrawInf.SetFont( pFnt ); 449 aDrawInf.SetSnapToGrid( SnapToGrid() ); 450 aDrawInf.SetKanaComp( nComp ); 451 SwPosSize aSize = pFnt->_GetTxtSize( aDrawInf ); 452 return aSize; 453 } 454 455 /************************************************************************* 456 * SwTxtSizeInfo::GetTxtSize() 457 *************************************************************************/ 458 459 SwPosSize SwTxtSizeInfo::GetTxtSize() const 460 { 461 const SwScriptInfo& rSI = 462 ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo(); 463 464 // in some cases, compression is not allowed or surpressed for 465 // performance reasons 466 sal_uInt16 nComp =( SW_CJK == GetFont()->GetActual() && 467 rSI.CountCompChg() && 468 ! IsMulti() ) ? 469 GetKanaComp() : 470 0 ; 471 472 SwDrawTextInfo aDrawInf( pVsh, *pOut, &rSI, *pTxt, nIdx, nLen ); 473 aDrawInf.SetFrm( pFrm ); 474 aDrawInf.SetFont( pFnt ); 475 aDrawInf.SetSnapToGrid( SnapToGrid() ); 476 aDrawInf.SetKanaComp( nComp ); 477 return pFnt->_GetTxtSize( aDrawInf ); 478 } 479 480 /************************************************************************* 481 * SwTxtSizeInfo::GetTxtSize() 482 *************************************************************************/ 483 484 void SwTxtSizeInfo::GetTxtSize( const SwScriptInfo* pSI, const xub_StrLen nIndex, 485 const xub_StrLen nLength, const sal_uInt16 nComp, 486 sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff ) const 487 { 488 SwDrawTextInfo aDrawInf( pVsh, *pOut, pSI, *pTxt, nIndex, nLength ); 489 aDrawInf.SetFrm( pFrm ); 490 aDrawInf.SetFont( pFnt ); 491 aDrawInf.SetSnapToGrid( SnapToGrid() ); 492 aDrawInf.SetKanaComp( nComp ); 493 SwPosSize aSize = pFnt->_GetTxtSize( aDrawInf ); 494 nMaxSizeDiff = (sal_uInt16)aDrawInf.GetKanaDiff(); 495 nMinSize = aSize.Width(); 496 } 497 498 /************************************************************************* 499 * SwTxtSizeInfo::GetTxtBreak() 500 *************************************************************************/ 501 502 xub_StrLen SwTxtSizeInfo::GetTxtBreak( const long nLineWidth, 503 const xub_StrLen nMaxLen, 504 const sal_uInt16 nComp ) const 505 { 506 const SwScriptInfo& rScriptInfo = 507 ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo(); 508 509 ASSERT( pRef == pOut, "GetTxtBreak is supposed to use the RefDev" ) 510 SwDrawTextInfo aDrawInf( pVsh, *pOut, &rScriptInfo, 511 *pTxt, GetIdx(), nMaxLen ); 512 aDrawInf.SetFrm( pFrm ); 513 aDrawInf.SetFont( pFnt ); 514 aDrawInf.SetSnapToGrid( SnapToGrid() ); 515 aDrawInf.SetKanaComp( nComp ); 516 aDrawInf.SetHyphPos( 0 ); 517 518 return pFnt->GetTxtBreak( aDrawInf, nLineWidth ); 519 } 520 521 /************************************************************************* 522 * SwTxtSizeInfo::GetTxtBreak() 523 *************************************************************************/ 524 525 xub_StrLen SwTxtSizeInfo::GetTxtBreak( const long nLineWidth, 526 const xub_StrLen nMaxLen, 527 const sal_uInt16 nComp, 528 xub_StrLen& rExtraCharPos ) const 529 { 530 const SwScriptInfo& rScriptInfo = 531 ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo(); 532 533 ASSERT( pRef == pOut, "GetTxtBreak is supposed to use the RefDev" ) 534 SwDrawTextInfo aDrawInf( pVsh, *pOut, &rScriptInfo, 535 *pTxt, GetIdx(), nMaxLen ); 536 aDrawInf.SetFrm( pFrm ); 537 aDrawInf.SetFont( pFnt ); 538 aDrawInf.SetSnapToGrid( SnapToGrid() ); 539 aDrawInf.SetKanaComp( nComp ); 540 aDrawInf.SetHyphPos( &rExtraCharPos ); 541 542 return pFnt->GetTxtBreak( aDrawInf, nLineWidth ); 543 } 544 545 /************************************************************************* 546 * SwTxtPaintInfo::CtorInitTxtPaintInfo() 547 *************************************************************************/ 548 549 void SwTxtPaintInfo::CtorInitTxtPaintInfo( SwTxtFrm *pFrame, const SwRect &rPaint ) 550 { 551 CtorInitTxtSizeInfo( pFrame ); 552 aTxtFly.CtorInitTxtFly( pFrame ), 553 aPaintRect = rPaint; 554 nSpaceIdx = 0; 555 pSpaceAdd = NULL; 556 pWrongList = NULL; 557 pGrammarCheckList = NULL; 558 pSmartTags = NULL; // SMARTTAGS 559 560 #ifndef DBG_UTIL 561 pBrushItem = 0; 562 #else 563 pBrushItem = ((SvxBrushItem*)-1); 564 #endif 565 } 566 567 SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf, const XubString &rTxt ) 568 : SwTxtSizeInfo( rInf, rTxt ), 569 pWrongList( rInf.GetpWrongList() ), 570 pGrammarCheckList( rInf.GetGrammarCheckList() ), 571 pSmartTags( rInf.GetSmartTags() ), // SMARTTAGS 572 pSpaceAdd( rInf.GetpSpaceAdd() ), 573 pBrushItem( rInf.GetBrushItem() ), 574 aTxtFly( *rInf.GetTxtFly() ), 575 aPos( rInf.GetPos() ), 576 aPaintRect( rInf.GetPaintRect() ), 577 nSpaceIdx( rInf.GetSpaceIdx() ) 578 { } 579 580 SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf ) 581 : SwTxtSizeInfo( rInf ), 582 pWrongList( rInf.GetpWrongList() ), 583 pGrammarCheckList( rInf.GetGrammarCheckList() ), 584 pSmartTags( rInf.GetSmartTags() ), // SMARTTAGS 585 pSpaceAdd( rInf.GetpSpaceAdd() ), 586 pBrushItem( rInf.GetBrushItem() ), 587 aTxtFly( *rInf.GetTxtFly() ), 588 aPos( rInf.GetPos() ), 589 aPaintRect( rInf.GetPaintRect() ), 590 nSpaceIdx( rInf.GetSpaceIdx() ) 591 { } 592 593 extern Color aGlobalRetoucheColor; 594 595 /************************************************************************* 596 * lcl_IsDarkBackground 597 * 598 * Returns if the current background color is dark. 599 *************************************************************************/ 600 601 sal_Bool lcl_IsDarkBackground( const SwTxtPaintInfo& rInf ) 602 { 603 const Color* pCol = rInf.GetFont()->GetBackColor(); 604 if( ! pCol || COL_TRANSPARENT == pCol->GetColor() ) 605 { 606 const SvxBrushItem* pItem; 607 SwRect aOrigBackRect; 608 609 /// OD 21.08.2002 610 /// consider, that [GetBackgroundBrush(...)] can set <pCol> 611 /// - see implementation in /core/layout/paintfrm.cxx 612 /// OD 21.08.2002 #99657# 613 /// There is a background color, if there is a background brush and 614 /// its color is *not* "no fill"/"auto fill". 615 if( rInf.GetTxtFrm()->GetBackgroundBrush( pItem, pCol, aOrigBackRect, sal_False ) ) 616 { 617 if ( !pCol ) 618 pCol = &pItem->GetColor(); 619 620 /// OD 30.08.2002 #99657# 621 /// determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it. 622 if ( pCol->GetColor() == COL_TRANSPARENT) 623 pCol = NULL; 624 } 625 else 626 pCol = NULL; 627 } 628 629 630 if( !pCol ) 631 pCol = &aGlobalRetoucheColor; 632 633 return pCol->IsDark(); 634 } 635 636 /************************************************************************* 637 * SwTxtPaintInfo::_DrawText() 638 *************************************************************************/ 639 640 void SwTxtPaintInfo::_DrawText( const XubString &rText, const SwLinePortion &rPor, 641 const xub_StrLen nStart, const xub_StrLen nLength, 642 const sal_Bool bKern, const sal_Bool bWrong, 643 const sal_Bool bSmartTag, 644 const sal_Bool bGrammarCheck ) // SMARTTAGS 645 { 646 if( !nLength ) 647 return; 648 649 if( GetFont()->IsBlink() && OnWin() && rPor.Width() ) 650 { 651 // check if accessibility options allow blinking portions: 652 const ViewShell* pSh = GetTxtFrm()->getRootFrm()->GetCurrShell(); 653 if ( pSh && ! pSh->GetAccessibilityOptions()->IsStopAnimatedText() && 654 ! pSh->IsPreView() ) 655 { 656 if( !pBlink ) 657 pBlink = new SwBlink(); 658 659 Point aPoint( aPos ); 660 661 if ( GetTxtFrm()->IsRightToLeft() ) 662 GetTxtFrm()->SwitchLTRtoRTL( aPoint ); 663 664 if ( TEXT_LAYOUT_BIDI_STRONG != GetOut()->GetLayoutMode() ) 665 aPoint.X() -= rPor.Width(); 666 667 if ( GetTxtFrm()->IsVertical() ) 668 GetTxtFrm()->SwitchHorizontalToVertical( aPoint ); 669 670 pBlink->Insert( aPoint, &rPor, GetTxtFrm(), pFnt->GetOrientation() ); 671 672 if( !pBlink->IsVisible() ) 673 return; 674 } 675 else 676 { 677 delete pBlink; 678 pBlink = NULL; 679 } 680 } 681 682 // The SwScriptInfo is useless if we are inside a field portion 683 SwScriptInfo* pSI = 0; 684 if ( ! rPor.InFldGrp() ) 685 pSI = &GetParaPortion()->GetScriptInfo(); 686 687 // in some cases, kana compression is not allowed or surpressed for 688 // performance reasons 689 sal_uInt16 nComp = 0; 690 if ( ! IsMulti() ) 691 nComp = GetKanaComp(); 692 693 sal_Bool bCfgIsAutoGrammar = sal_False; 694 SvtLinguConfig().GetProperty( C2U( UPN_IS_GRAMMAR_AUTO ) ) >>= bCfgIsAutoGrammar; 695 const sal_Bool bBullet = OnWin() && GetOpt().IsBlank() && IsNoSymbol(); 696 const sal_Bool bTmpWrong = bWrong && OnWin() && GetOpt().IsOnlineSpell(); 697 const sal_Bool bTmpGrammarCheck = bGrammarCheck && OnWin() && bCfgIsAutoGrammar && GetOpt().IsOnlineSpell(); 698 const sal_Bool bTmpSmart = bSmartTag && OnWin() && !GetOpt().IsPagePreview() && SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS 699 700 ASSERT( GetParaPortion(), "No paragraph!"); 701 SwDrawTextInfo aDrawInf( pFrm->getRootFrm()->GetCurrShell(), *pOut, pSI, rText, nStart, nLength, 702 rPor.Width(), bBullet ); 703 704 aDrawInf.SetLeft( GetPaintRect().Left() ); 705 aDrawInf.SetRight( GetPaintRect().Right() ); 706 aDrawInf.SetUnderFnt( pUnderFnt ); 707 708 const long nSpaceAdd = ( rPor.IsBlankPortion() || rPor.IsDropPortion() || 709 rPor.InNumberGrp() ) ? 0 : GetSpaceAdd(); 710 if ( nSpaceAdd ) 711 { 712 xub_StrLen nCharCnt; 713 // --> FME 2005-04-04 #i41860# Thai justified alignemt needs some 714 // additional information: 715 aDrawInf.SetNumberOfBlanks( rPor.InTxtGrp() ? 716 static_cast<const SwTxtPortion&>(rPor).GetSpaceCnt( *this, nCharCnt ) : 717 0 ); 718 // <-- 719 } 720 721 aDrawInf.SetSpace( nSpaceAdd ); 722 aDrawInf.SetKanaComp( nComp ); 723 724 // the font is used to identify the current script via nActual 725 aDrawInf.SetFont( pFnt ); 726 // the frame is used to identify the orientation 727 aDrawInf.SetFrm( GetTxtFrm() ); 728 // we have to know if the paragraph should snap to grid 729 aDrawInf.SetSnapToGrid( SnapToGrid() ); 730 // for underlining we must know when not to add extra space behind 731 // a character in justified mode 732 aDrawInf.SetSpaceStop( ! rPor.GetPortion() || 733 rPor.GetPortion()->InFixMargGrp() || 734 rPor.GetPortion()->IsHolePortion() ); 735 736 if( GetTxtFly()->IsOn() ) 737 { 738 // aPos muss als TopLeft vorliegen, weil die ClipRects sonst 739 // nicht berechnet werden koennen. 740 const Point aPoint( aPos.X(), aPos.Y() - rPor.GetAscent() ); 741 const Size aSize( rPor.Width(), rPor.Height() ); 742 aDrawInf.SetPos( aPoint ); 743 aDrawInf.SetSize( aSize ); 744 aDrawInf.SetAscent( rPor.GetAscent() ); 745 aDrawInf.SetKern( bKern ? rPor.Width() : 0 ); 746 aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL ); 747 aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL ); 748 aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL ); // SMARTTAGS 749 GetTxtFly()->DrawTextOpaque( aDrawInf ); 750 } 751 else 752 { 753 aDrawInf.SetPos( aPos ); 754 if( bKern ) 755 pFnt->_DrawStretchText( aDrawInf ); 756 else 757 { 758 aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL ); 759 aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL ); 760 aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL ); // SMARTTAGS 761 pFnt->_DrawText( aDrawInf ); 762 } 763 } 764 } 765 766 /************************************************************************* 767 * SwTxtPaintInfo::CalcRect() 768 *************************************************************************/ 769 770 void SwTxtPaintInfo::CalcRect( const SwLinePortion& rPor, 771 SwRect* pRect, SwRect* pIntersect ) const 772 { 773 Size aSize( rPor.Width(), rPor.Height() ); 774 if( rPor.IsHangingPortion() ) 775 aSize.Width() = ((SwHangingPortion&)rPor).GetInnerWidth(); 776 if( rPor.InSpaceGrp() && GetSpaceAdd() ) 777 { 778 SwTwips nAdd = rPor.CalcSpacing( GetSpaceAdd(), *this ); 779 if( rPor.InFldGrp() && GetSpaceAdd() < 0 && nAdd ) 780 nAdd += GetSpaceAdd() / SPACING_PRECISION_FACTOR; 781 aSize.Width() += nAdd; 782 } 783 784 Point aPoint; 785 786 if( IsRotated() ) 787 { 788 long nTmp = aSize.Width(); 789 aSize.Width() = aSize.Height(); 790 aSize.Height() = nTmp; 791 if ( 1 == GetDirection() ) 792 { 793 aPoint.A() = X() - rPor.GetAscent(); 794 aPoint.B() = Y() - aSize.Height(); 795 } 796 else 797 { 798 aPoint.A() = X() - rPor.Height() + rPor.GetAscent(); 799 aPoint.B() = Y(); 800 } 801 } 802 else 803 { 804 aPoint.A() = X(); 805 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 806 if ( GetTxtFrm()->IsVertLR() ) 807 aPoint.B() = Y() - rPor.Height() + rPor.GetAscent(); 808 else 809 aPoint.B() = Y() - rPor.GetAscent(); 810 } 811 812 // Adjust x coordinate if we are inside a bidi portion 813 const sal_Bool bFrmDir = GetTxtFrm()->IsRightToLeft(); 814 sal_Bool bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == GetDirection() ) || 815 ( bFrmDir && DIR_LEFT2RIGHT == GetDirection() ); 816 817 if ( bCounterDir ) 818 aPoint.A() -= aSize.Width(); 819 820 SwRect aRect( aPoint, aSize ); 821 822 if ( GetTxtFrm()->IsRightToLeft() ) 823 GetTxtFrm()->SwitchLTRtoRTL( aRect ); 824 825 if ( GetTxtFrm()->IsVertical() ) 826 GetTxtFrm()->SwitchHorizontalToVertical( aRect ); 827 828 if ( pRect ) 829 *pRect = aRect; 830 831 if( aRect.HasArea() && pIntersect ) 832 { 833 ::SwAlignRect( aRect, (ViewShell*)GetVsh() ); 834 835 if ( GetOut()->IsClipRegion() ) 836 { 837 SwRect aClip( GetOut()->GetClipRegion().GetBoundRect() ); 838 aRect.Intersection( aClip ); 839 } 840 841 *pIntersect = aRect; 842 } 843 } 844 845 /************************************************************************* 846 * lcl_DrawSpecial 847 * 848 * Draws a special portion, e.g., line break portion, tab portion. 849 * rPor - The portion 850 * rRect - The rectangle surrounding the character 851 * pCol - Specify a color for the character 852 * bCenter - Draw the character centered, otherwise left aligned 853 * bRotate - Rotate the character if character rotation is set 854 *************************************************************************/ 855 856 static void lcl_DrawSpecial( const SwTxtPaintInfo& rInf, const SwLinePortion& rPor, 857 SwRect& rRect, const Color* pCol, sal_Unicode cChar, 858 sal_uInt8 nOptions ) 859 { 860 sal_Bool bCenter = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_CENTER ); 861 sal_Bool bRotate = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_ROTATE ); 862 863 // rRect is given in absolute coordinates 864 if ( rInf.GetTxtFrm()->IsRightToLeft() ) 865 rInf.GetTxtFrm()->SwitchRTLtoLTR( rRect ); 866 if ( rInf.GetTxtFrm()->IsVertical() ) 867 rInf.GetTxtFrm()->SwitchVerticalToHorizontal( rRect ); 868 869 const SwFont* pOldFnt = rInf.GetFont(); 870 871 // Font is generated only once: 872 static SwFont* pFnt = 0; 873 if ( ! pFnt ) 874 { 875 pFnt = new SwFont( *pOldFnt ); 876 pFnt->SetFamily( FAMILY_DONTKNOW, pFnt->GetActual() ); 877 pFnt->SetName( numfunc::GetDefBulletFontname(), pFnt->GetActual() ); 878 pFnt->SetStyleName( aEmptyStr, pFnt->GetActual() ); 879 pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, pFnt->GetActual() ); 880 } 881 882 // Some of the current values are set at the font: 883 if ( ! bRotate ) 884 pFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() ); 885 else 886 pFnt->SetVertical( pOldFnt->GetOrientation() ); 887 888 if ( pCol ) 889 pFnt->SetColor( *pCol ); 890 else 891 pFnt->SetColor( pOldFnt->GetColor() ); 892 893 Size aFontSize( 0, SPECIAL_FONT_HEIGHT ); 894 pFnt->SetSize( aFontSize, pFnt->GetActual() ); 895 896 ((SwTxtPaintInfo&)rInf).SetFont( pFnt ); 897 898 // The maximum width depends on the current orientation 899 const sal_uInt16 nDir = pFnt->GetOrientation( rInf.GetTxtFrm()->IsVertical() ); 900 SwTwips nMaxWidth = 0; 901 switch ( nDir ) 902 { 903 case 0 : 904 nMaxWidth = rRect.Width(); 905 break; 906 case 900 : 907 case 2700 : 908 nMaxWidth = rRect.Height(); 909 break; 910 default: 911 ASSERT( sal_False, "Unknown direction set at font" ) 912 break; 913 } 914 915 // check if char fits into rectangle 916 const XubString aTmp( cChar ); 917 aFontSize = rInf.GetTxtSize( aTmp ).SvLSize(); 918 while ( aFontSize.Width() > nMaxWidth ) 919 { 920 SwTwips nFactor = ( 100 * aFontSize.Width() ) / nMaxWidth; 921 const SwTwips nOldWidth = aFontSize.Width(); 922 923 // new height for font 924 const sal_uInt8 nAct = pFnt->GetActual(); 925 aFontSize.Height() = ( 100 * pFnt->GetSize( nAct ).Height() ) / nFactor; 926 aFontSize.Width() = ( 100 * pFnt->GetSize( nAct).Width() ) / nFactor; 927 928 if ( !aFontSize.Width() && !aFontSize.Height() ) 929 break; 930 931 pFnt->SetSize( aFontSize, nAct ); 932 933 aFontSize = rInf.GetTxtSize( aTmp ).SvLSize(); 934 935 if ( aFontSize.Width() >= nOldWidth ) 936 break; 937 } 938 939 const Point aOldPos( rInf.GetPos() ); 940 941 // adjust values so that tab is vertically and horizontally centered 942 SwTwips nX = rRect.Left(); 943 SwTwips nY = rRect.Top(); 944 switch ( nDir ) 945 { 946 case 0 : 947 if ( bCenter ) 948 nX += ( rRect.Width() - aFontSize.Width() ) / 2; 949 nY += ( rRect.Height() - aFontSize.Height() ) / 2 + rInf.GetAscent(); 950 break; 951 case 900 : 952 if ( bCenter ) 953 nX += ( rRect.Width() - aFontSize.Height() ) / 2 + rInf.GetAscent(); 954 nY += ( rRect.Height() + aFontSize.Width() ) / 2; 955 break; 956 case 2700 : 957 if ( bCenter ) 958 nX += ( rRect.Width() + aFontSize.Height() ) / 2 - rInf.GetAscent(); 959 nY += ( rRect.Height() - aFontSize.Width() ) / 2; 960 break; 961 } 962 963 Point aTmpPos( nX, nY ); 964 ((SwTxtPaintInfo&)rInf).SetPos( aTmpPos ); 965 sal_uInt16 nOldWidth = rPor.Width(); 966 ((SwLinePortion&)rPor).Width( (sal_uInt16)aFontSize.Width() ); 967 rInf.DrawText( aTmp, rPor ); 968 ((SwLinePortion&)rPor).Width( nOldWidth ); 969 ((SwTxtPaintInfo&)rInf).SetFont( (SwFont*)pOldFnt ); 970 ((SwTxtPaintInfo&)rInf).SetPos( aOldPos ); 971 } 972 973 /************************************************************************* 974 * SwTxtPaintInfo::DrawRect() 975 *************************************************************************/ 976 977 void SwTxtPaintInfo::DrawRect( const SwRect &rRect, sal_Bool bNoGraphic, 978 sal_Bool bRetouche ) const 979 { 980 if ( OnWin() || !bRetouche ) 981 { 982 if( aTxtFly.IsOn() ) 983 ((SwTxtPaintInfo*)this)->GetTxtFly()-> 984 DrawFlyRect( pOut, rRect, *this, bNoGraphic ); 985 else if ( bNoGraphic ) 986 pOut->DrawRect( rRect.SVRect() ); 987 else 988 { 989 ASSERT( ((SvxBrushItem*)-1) != pBrushItem, "DrawRect: Uninitialized BrushItem!" ); 990 ::DrawGraphic( pBrushItem, pOut, aItemRect, rRect ); 991 } 992 } 993 } 994 995 /************************************************************************* 996 * SwTxtPaintInfo::DrawTab() 997 *************************************************************************/ 998 999 void SwTxtPaintInfo::DrawTab( const SwLinePortion &rPor ) const 1000 { 1001 if( OnWin() ) 1002 { 1003 SwRect aRect; 1004 CalcRect( rPor, &aRect ); 1005 1006 if ( ! aRect.HasArea() ) 1007 return; 1008 1009 const sal_Unicode cChar = GetTxtFrm()->IsRightToLeft() ? 1010 CHAR_TAB_RTL : CHAR_TAB; 1011 const sal_uInt8 nOptions = DRAW_SPECIAL_OPTIONS_CENTER | 1012 DRAW_SPECIAL_OPTIONS_ROTATE; 1013 lcl_DrawSpecial( *this, rPor, aRect, 0, cChar, nOptions ); 1014 } 1015 } 1016 1017 /************************************************************************* 1018 * SwTxtPaintInfo::DrawLineBreak() 1019 *************************************************************************/ 1020 1021 void SwTxtPaintInfo::DrawLineBreak( const SwLinePortion &rPor ) const 1022 { 1023 if( OnWin() ) 1024 { 1025 KSHORT nOldWidth = rPor.Width(); 1026 ((SwLinePortion&)rPor).Width( LINE_BREAK_WIDTH ); 1027 1028 SwRect aRect; 1029 CalcRect( rPor, &aRect ); 1030 1031 if( aRect.HasArea() ) 1032 { 1033 const sal_Unicode cChar = GetTxtFrm()->IsRightToLeft() ? 1034 CHAR_LINEBREAK_RTL : CHAR_LINEBREAK; 1035 const sal_uInt8 nOptions = 0; 1036 lcl_DrawSpecial( *this, rPor, aRect, 0, cChar, nOptions ); 1037 } 1038 1039 ((SwLinePortion&)rPor).Width( nOldWidth ); 1040 } 1041 } 1042 1043 1044 /************************************************************************* 1045 * SwTxtPaintInfo::DrawRedArrow() 1046 *************************************************************************/ 1047 1048 void SwTxtPaintInfo::DrawRedArrow( const SwLinePortion &rPor ) const 1049 { 1050 Size aSize( SPECIAL_FONT_HEIGHT, SPECIAL_FONT_HEIGHT ); 1051 SwRect aRect( ((SwArrowPortion&)rPor).GetPos(), aSize ); 1052 sal_Unicode cChar; 1053 if( ((SwArrowPortion&)rPor).IsLeft() ) 1054 { 1055 aRect.Pos().Y() += 20 - GetAscent(); 1056 aRect.Pos().X() += 20; 1057 if( aSize.Height() > rPor.Height() ) 1058 aRect.Height( rPor.Height() ); 1059 cChar = CHAR_LEFT_ARROW; 1060 } 1061 else 1062 { 1063 if( aSize.Height() > rPor.Height() ) 1064 aRect.Height( rPor.Height() ); 1065 aRect.Pos().Y() -= aRect.Height() + 20; 1066 aRect.Pos().X() -= aRect.Width() + 20; 1067 cChar = CHAR_RIGHT_ARROW; 1068 } 1069 1070 if ( GetTxtFrm()->IsVertical() ) 1071 GetTxtFrm()->SwitchHorizontalToVertical( aRect ); 1072 1073 Color aCol( COL_LIGHTRED ); 1074 1075 if( aRect.HasArea() ) 1076 { 1077 const sal_uInt8 nOptions = 0; 1078 lcl_DrawSpecial( *this, rPor, aRect, &aCol, cChar, nOptions ); 1079 } 1080 } 1081 1082 1083 /************************************************************************* 1084 * SwTxtPaintInfo::DrawPostIts() 1085 *************************************************************************/ 1086 1087 void SwTxtPaintInfo::DrawPostIts( const SwLinePortion&, sal_Bool bScript ) const 1088 { 1089 if( OnWin() && pOpt->IsPostIts() ) 1090 { 1091 Size aSize; 1092 Point aTmp; 1093 1094 const sal_uInt16 nPostItsWidth = pOpt->GetPostItsWidth( GetOut() ); 1095 const sal_uInt16 nFontHeight = pFnt->GetHeight( pVsh, *GetOut() ); 1096 const sal_uInt16 nFontAscent = pFnt->GetAscent( pVsh, *GetOut() ); 1097 1098 switch ( pFnt->GetOrientation( GetTxtFrm()->IsVertical() ) ) 1099 { 1100 case 0 : 1101 aSize.Width() = nPostItsWidth; 1102 aSize.Height() = nFontHeight; 1103 aTmp.X() = aPos.X(); 1104 aTmp.Y() = aPos.Y() - nFontAscent; 1105 break; 1106 case 900 : 1107 aSize.Height() = nPostItsWidth; 1108 aSize.Width() = nFontHeight; 1109 aTmp.X() = aPos.X() - nFontAscent; 1110 aTmp.Y() = aPos.Y(); 1111 break; 1112 case 2700 : 1113 aSize.Height() = nPostItsWidth; 1114 aSize.Width() = nFontHeight; 1115 aTmp.X() = aPos.X() - nFontHeight + 1116 nFontAscent; 1117 aTmp.Y() = aPos.Y(); 1118 break; 1119 } 1120 1121 SwRect aTmpRect( aTmp, aSize ); 1122 1123 if ( GetTxtFrm()->IsRightToLeft() ) 1124 GetTxtFrm()->SwitchLTRtoRTL( aTmpRect ); 1125 1126 if ( GetTxtFrm()->IsVertical() ) 1127 GetTxtFrm()->SwitchHorizontalToVertical( aTmpRect ); 1128 1129 const Rectangle aRect( aTmpRect.SVRect() ); 1130 pOpt->PaintPostIts( (OutputDevice*)GetOut(), aRect, bScript ); 1131 } 1132 } 1133 1134 void SwTxtPaintInfo::DrawCheckBox( const SwFieldFormPortion &rPor, bool checked) const 1135 { 1136 SwRect aIntersect; 1137 CalcRect( rPor, &aIntersect, 0 ); 1138 if ( aIntersect.HasArea() ) 1139 { 1140 if (OnWin() && SwViewOption::IsFieldShadings() && 1141 !GetOpt().IsPagePreview()) 1142 { 1143 OutputDevice* pOut_ = (OutputDevice*)GetOut(); 1144 pOut_->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 1145 pOut_->SetFillColor( SwViewOption::GetFieldShadingsColor() ); 1146 pOut_->SetLineColor(); 1147 pOut_->DrawRect( aIntersect.SVRect() ); 1148 pOut_->Pop(); 1149 } 1150 const int delta=10; 1151 Rectangle r(aIntersect.Left()+delta, aIntersect.Top()+delta, aIntersect.Right()-delta, aIntersect.Bottom()-delta); 1152 pOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 1153 pOut->SetLineColor( Color(0, 0, 0)); 1154 pOut->SetFillColor(); 1155 pOut->DrawRect( r ); 1156 if (checked) { 1157 pOut->DrawLine(r.TopLeft(), r.BottomRight()); 1158 pOut->DrawLine(r.TopRight(), r.BottomLeft()); 1159 } 1160 pOut->Pop(); 1161 } 1162 } 1163 /************************************************************************* 1164 * SwTxtPaintInfo::DrawBackGround() 1165 *************************************************************************/ 1166 void SwTxtPaintInfo::DrawBackground( const SwLinePortion &rPor ) const 1167 { 1168 ASSERT( OnWin(), "SwTxtPaintInfo::DrawBackground: printer polution ?" ); 1169 1170 SwRect aIntersect; 1171 CalcRect( rPor, 0, &aIntersect ); 1172 1173 if ( aIntersect.HasArea() ) 1174 { 1175 OutputDevice* pTmpOut = (OutputDevice*)GetOut(); 1176 pTmpOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 1177 1178 // For dark background we do not want to have a filled rectangle 1179 if ( GetVsh() && GetVsh()->GetWin() && lcl_IsDarkBackground( *this ) ) 1180 { 1181 pTmpOut->SetLineColor( SwViewOption::GetFontColor().GetColor() ); 1182 } 1183 else 1184 { 1185 pTmpOut->SetFillColor( SwViewOption::GetFieldShadingsColor() ); 1186 pTmpOut->SetLineColor(); 1187 } 1188 1189 DrawRect( aIntersect, sal_True ); 1190 pTmpOut->Pop(); 1191 } 1192 } 1193 1194 void SwTxtPaintInfo::_DrawBackBrush( const SwLinePortion &rPor ) const 1195 { 1196 { 1197 SwRect aIntersect; 1198 CalcRect( rPor, &aIntersect, 0 ); 1199 if(aIntersect.HasArea()) 1200 { 1201 SwTxtNode *pNd = pFrm->GetTxtNode(); 1202 const ::sw::mark::IMark* pFieldmark = NULL; 1203 if(pNd) 1204 { 1205 const SwDoc *doc=pNd->GetDoc(); 1206 if(doc) 1207 { 1208 SwIndex aIndex(pNd, GetIdx()); 1209 SwPosition aPosition(*pNd, aIndex); 1210 pFieldmark=doc->getIDocumentMarkAccess()->getFieldmarkFor(aPosition); 1211 } 1212 } 1213 bool bIsStartMark=(1==GetLen() && CH_TXT_ATR_FIELDSTART==GetTxt().GetChar(GetIdx())); 1214 if(pFieldmark) { 1215 OSL_TRACE("Found Fieldmark"); 1216 #if DEBUG 1217 rtl::OUString str = pFieldmark->ToString( ); 1218 fprintf( stderr, "%s\n", rtl::OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr( ) ); 1219 #endif 1220 } 1221 if(bIsStartMark) OSL_TRACE("Found StartMark"); 1222 if (OnWin() && (pFieldmark!=NULL || bIsStartMark) && 1223 SwViewOption::IsFieldShadings() && 1224 !GetOpt().IsPagePreview()) 1225 { 1226 OutputDevice* pOutDev = (OutputDevice*)GetOut(); 1227 pOutDev->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 1228 pOutDev->SetFillColor( SwViewOption::GetFieldShadingsColor() ); 1229 pOutDev->SetLineColor( ); 1230 pOutDev->DrawRect( aIntersect.SVRect() ); 1231 pOutDev->Pop(); 1232 } 1233 } 1234 } 1235 if( !pFnt->GetBackColor() ) return; 1236 1237 ASSERT( pFnt->GetBackColor(), "DrawBackBrush: Lost Color" ); 1238 1239 SwRect aIntersect; 1240 CalcRect( rPor, 0, &aIntersect ); 1241 1242 if ( aIntersect.HasArea() ) 1243 { 1244 OutputDevice* pTmpOut = (OutputDevice*)GetOut(); 1245 1246 // --> FME 2004-06-24 #i16816# tagged pdf support 1247 SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pTmpOut ); 1248 // <-- 1249 1250 pTmpOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 1251 1252 pTmpOut->SetFillColor( *pFnt->GetBackColor() ); 1253 pTmpOut->SetLineColor(); 1254 1255 DrawRect( aIntersect, sal_True, sal_False ); 1256 1257 pTmpOut->Pop(); 1258 } 1259 } 1260 1261 /************************************************************************* 1262 * SwTxtPaintInfo::DrawViewOpt() 1263 *************************************************************************/ 1264 1265 void SwTxtPaintInfo::DrawViewOpt( const SwLinePortion &rPor, 1266 const MSHORT nWhich ) const 1267 { 1268 if( OnWin() && !IsMulti() ) 1269 { 1270 sal_Bool bDraw = sal_False; 1271 switch( nWhich ) 1272 { 1273 case POR_FTN: 1274 case POR_QUOVADIS: 1275 case POR_NUMBER: 1276 case POR_FLD: 1277 case POR_URL: 1278 case POR_HIDDEN: 1279 case POR_TOX: 1280 case POR_REF: 1281 case POR_META: 1282 case POR_CONTROLCHAR: 1283 if ( !GetOpt().IsPagePreview() 1284 && !GetOpt().IsReadonly() 1285 && SwViewOption::IsFieldShadings() 1286 && ( POR_NUMBER != nWhich 1287 || pFrm->GetTxtNode()->HasMarkedLabel())) // #i27615# 1288 { 1289 bDraw = sal_True; 1290 } 1291 break; 1292 case POR_INPUTFLD: 1293 // input field shading also in read-only mode 1294 if ( !GetOpt().IsPagePreview() 1295 && SwViewOption::IsFieldShadings() ) 1296 { 1297 bDraw = sal_True; 1298 } 1299 break; 1300 case POR_TAB: if ( GetOpt().IsTab() ) bDraw = sal_True; break; 1301 case POR_SOFTHYPH: if ( GetOpt().IsSoftHyph() )bDraw = sal_True; break; 1302 case POR_BLANK: if ( GetOpt().IsHardBlank())bDraw = sal_True; break; 1303 default: 1304 { 1305 ASSERT( !this, "SwTxtPaintInfo::DrawViewOpt: don't know how to draw this" ); 1306 break; 1307 } 1308 } 1309 if ( bDraw ) 1310 DrawBackground( rPor ); 1311 } 1312 } 1313 1314 /************************************************************************* 1315 * SwTxtPaintInfo::_NotifyURL() 1316 *************************************************************************/ 1317 1318 void SwTxtPaintInfo::_NotifyURL( const SwLinePortion &rPor ) const 1319 { 1320 ASSERT( pNoteURL, "NotifyURL: pNoteURL gone with the wind!" ); 1321 1322 SwRect aIntersect; 1323 CalcRect( rPor, 0, &aIntersect ); 1324 1325 if( aIntersect.HasArea() ) 1326 { 1327 SwTxtNode *pNd = (SwTxtNode*)GetTxtFrm()->GetTxtNode(); 1328 SwTxtAttr *const pAttr = 1329 pNd->GetTxtAttrAt(GetIdx(), RES_TXTATR_INETFMT); 1330 if( pAttr ) 1331 { 1332 const SwFmtINetFmt& rFmt = pAttr->GetINetFmt(); 1333 pNoteURL->InsertURLNote( rFmt.GetValue(), rFmt.GetTargetFrame(), 1334 aIntersect ); 1335 } 1336 } 1337 } 1338 1339 /************************************************************************* 1340 * lcl_InitHyphValues() 1341 *************************************************************************/ 1342 1343 static void lcl_InitHyphValues( PropertyValues &rVals, 1344 sal_Int16 nMinLeading, sal_Int16 nMinTrailing ) 1345 { 1346 sal_Int32 nLen = rVals.getLength(); 1347 1348 if (0 == nLen) // yet to be initialized? 1349 { 1350 rVals.realloc( 2 ); 1351 PropertyValue *pVal = rVals.getArray(); 1352 1353 pVal[0].Name = C2U( UPN_HYPH_MIN_LEADING ); 1354 pVal[0].Handle = UPH_HYPH_MIN_LEADING; 1355 pVal[0].Value <<= nMinLeading; 1356 1357 pVal[1].Name = C2U( UPN_HYPH_MIN_TRAILING ); 1358 pVal[1].Handle = UPH_HYPH_MIN_TRAILING; 1359 pVal[1].Value <<= nMinTrailing; 1360 } 1361 else if (2 == nLen) // already initialized once? 1362 { 1363 PropertyValue *pVal = rVals.getArray(); 1364 pVal[0].Value <<= nMinLeading; 1365 pVal[1].Value <<= nMinTrailing; 1366 } 1367 else { 1368 DBG_ERROR( "unxpected size of sequence" ); 1369 } 1370 } 1371 1372 /************************************************************************* 1373 * SwTxtFormatInfo::GetHyphValues() 1374 *************************************************************************/ 1375 1376 const PropertyValues & SwTxtFormatInfo::GetHyphValues() const 1377 { 1378 DBG_ASSERT( 2 == aHyphVals.getLength(), 1379 "hyphenation values not yet initialized" ); 1380 return aHyphVals; 1381 } 1382 1383 /************************************************************************* 1384 * SwTxtFormatInfo::InitHyph() 1385 *************************************************************************/ 1386 1387 sal_Bool SwTxtFormatInfo::InitHyph( const sal_Bool bAutoHyphen ) 1388 { 1389 const SwAttrSet& rAttrSet = GetTxtFrm()->GetTxtNode()->GetSwAttrSet(); 1390 SetHanging( rAttrSet.GetHangingPunctuation().GetValue() ); 1391 SetScriptSpace( rAttrSet.GetScriptSpace().GetValue() ); 1392 SetForbiddenChars( rAttrSet.GetForbiddenRule().GetValue() ); 1393 const SvxHyphenZoneItem &rAttr = rAttrSet.GetHyphenZone(); 1394 MaxHyph() = rAttr.GetMaxHyphens(); 1395 sal_Bool bAuto = bAutoHyphen || rAttr.IsHyphen(); 1396 if( bAuto || bInterHyph ) 1397 { 1398 nHyphStart = nHyphWrdStart = STRING_LEN; 1399 nHyphWrdLen = 0; 1400 1401 const sal_Int16 nMinimalLeading = Max(rAttr.GetMinLead(), sal_uInt8(2)); 1402 const sal_Int16 nMinimalTrailing = rAttr.GetMinTrail(); 1403 lcl_InitHyphValues( aHyphVals, nMinimalLeading, nMinimalTrailing); 1404 } 1405 return bAuto; 1406 } 1407 1408 /************************************************************************* 1409 * SwTxtFormatInfo::CtorInitTxtFormatInfo() 1410 *************************************************************************/ 1411 1412 void SwTxtFormatInfo::CtorInitTxtFormatInfo( SwTxtFrm *pNewFrm, const sal_Bool bNewInterHyph, 1413 const sal_Bool bNewQuick, const sal_Bool bTst ) 1414 { 1415 CtorInitTxtPaintInfo( pNewFrm, SwRect() ); 1416 1417 bQuick = bNewQuick; 1418 bInterHyph = bNewInterHyph; 1419 1420 //! needs to be done in this order 1421 nMinLeading = 2; 1422 nMinTrailing = 2; 1423 nMinWordLength = 0; 1424 bAutoHyph = InitHyph(); 1425 1426 bIgnoreFly = sal_False; 1427 bFakeLineStart = sal_False; 1428 bShift = sal_False; 1429 bDropInit = sal_False; 1430 bTestFormat = bTst; 1431 nLeft = 0; 1432 nRight = 0; 1433 nFirst = 0; 1434 nRealWidth = 0; 1435 nForcedLeftMargin = 0; 1436 pRest = 0; 1437 nLineHeight = 0; 1438 nLineNettoHeight = 0; 1439 SetLineStart(0); 1440 Init(); 1441 } 1442 1443 /************************************************************************* 1444 * SwTxtFormatInfo::IsHyphenate() 1445 *************************************************************************/ 1446 // Trennen oder nicht trennen, das ist hier die Frage: 1447 // - in keinem Fall trennen, wenn der Hyphenator ERROR zurueckliefert, 1448 // oder wenn als Sprache NOLANGUAGE eingestellt ist. 1449 // - ansonsten immer trennen, wenn interaktive Trennung vorliegt 1450 // - wenn keine interakt. Trennung, dann nur trennen, wenn im ParaFmt 1451 // automatische Trennung eingestellt ist. 1452 1453 sal_Bool SwTxtFormatInfo::IsHyphenate() const 1454 { 1455 if( !bInterHyph && !bAutoHyph ) 1456 return sal_False; 1457 1458 LanguageType eTmp = GetFont()->GetLanguage(); 1459 if( LANGUAGE_DONTKNOW == eTmp || LANGUAGE_NONE == eTmp ) 1460 return sal_False; 1461 1462 uno::Reference< XHyphenator > xHyph = ::GetHyphenator(); 1463 if (bInterHyph && xHyph.is()) 1464 SvxSpellWrapper::CheckHyphLang( xHyph, eTmp ); 1465 1466 if( !xHyph.is() || !xHyph->hasLocale( pBreakIt->GetLocale(eTmp) ) ) 1467 return sal_False; 1468 return sal_True; 1469 } 1470 1471 /************************************************************************* 1472 * SwTxtFormatInfo::GetDropFmt() 1473 *************************************************************************/ 1474 1475 // Dropcaps vom SwTxtFormatter::CTOR gerufen. 1476 const SwFmtDrop *SwTxtFormatInfo::GetDropFmt() const 1477 { 1478 const SwFmtDrop *pDrop = &GetTxtFrm()->GetTxtNode()->GetSwAttrSet().GetDrop(); 1479 if( 1 >= pDrop->GetLines() || 1480 ( !pDrop->GetChars() && !pDrop->GetWholeWord() ) ) 1481 pDrop = 0; 1482 return pDrop; 1483 } 1484 1485 /************************************************************************* 1486 * SwTxtFormatInfo::Init() 1487 *************************************************************************/ 1488 1489 void SwTxtFormatInfo::Init() 1490 { 1491 // Nicht initialisieren: pRest, nLeft, nRight, nFirst, nRealWidth 1492 X(0); 1493 bArrowDone = bFull = bFtnDone = bErgoDone = bNumDone = bNoEndHyph = 1494 bNoMidHyph = bStop = bNewLine = bUnderFlow = sal_False; 1495 1496 // generally we do not allow number portions in follows, except... 1497 if ( GetTxtFrm()->IsFollow() ) 1498 { 1499 const SwTxtFrm* pMaster = GetTxtFrm()->FindMaster(); 1500 const SwLinePortion* pTmpPara = pMaster->GetPara(); 1501 1502 // there is a master for this follow and the master does not have 1503 // any contents (especially it does not have a number portion) 1504 bNumDone = ! pTmpPara || 1505 ! ((SwParaPortion*)pTmpPara)->GetFirstPortion()->IsFlyPortion(); 1506 } 1507 1508 pRoot = 0; 1509 pLast = 0; 1510 pFly = 0; 1511 pLastFld = 0; 1512 pLastTab = 0; 1513 pUnderFlow = 0; 1514 cTabDecimal = 0; 1515 nWidth = nRealWidth; 1516 nForcedLeftMargin = 0; 1517 nSoftHyphPos = 0; 1518 nUnderScorePos = STRING_LEN; 1519 cHookChar = 0; 1520 SetIdx(0); 1521 SetLen( GetTxt().Len() ); 1522 SetPaintOfst(0); 1523 } 1524 1525 /*-----------------16.10.00 11:39------------------- 1526 * There are a few differences between a copy constructor 1527 * and the following constructor for multi-line formatting. 1528 * The root is the first line inside the multi-portion, 1529 * the line start is the actual position in the text, 1530 * the line width is the rest width from the surrounding line 1531 * and the bMulti and bFirstMulti-flag has to be set correctly. 1532 * --------------------------------------------------*/ 1533 1534 SwTxtFormatInfo::SwTxtFormatInfo( const SwTxtFormatInfo& rInf, 1535 SwLineLayout& rLay, SwTwips nActWidth ) : SwTxtPaintInfo( rInf ) 1536 { 1537 pRoot = &rLay; 1538 pLast = &rLay; 1539 pFly = NULL; 1540 pLastFld = NULL; 1541 pUnderFlow = NULL; 1542 pRest = NULL; 1543 pLastTab = NULL; 1544 1545 nSoftHyphPos = 0; 1546 nUnderScorePos = STRING_LEN; 1547 nHyphStart = 0; 1548 nHyphWrdStart = 0; 1549 nHyphWrdLen = 0; 1550 nLineStart = rInf.GetIdx(); 1551 nLeft = rInf.nLeft; 1552 nRight = rInf.nRight; 1553 nFirst = rInf.nLeft; 1554 nRealWidth = KSHORT(nActWidth); 1555 nWidth = nRealWidth; 1556 nLineHeight = 0; 1557 nLineNettoHeight = 0; 1558 nForcedLeftMargin = 0; 1559 1560 nMinLeading = 0; 1561 nMinTrailing = 0; 1562 nMinWordLength = 0; 1563 bFull = sal_False; 1564 bFtnDone = sal_True; 1565 bErgoDone = sal_True; 1566 bNumDone = sal_True; 1567 bArrowDone = sal_True; 1568 bStop = sal_False; 1569 bNewLine = sal_True; 1570 bShift = sal_False; 1571 bUnderFlow = sal_False; 1572 bInterHyph = sal_False; 1573 bAutoHyph = sal_False; 1574 bDropInit = sal_False; 1575 bQuick = rInf.bQuick; 1576 bNoEndHyph = sal_False; 1577 bNoMidHyph = sal_False; 1578 bIgnoreFly = sal_False; 1579 bFakeLineStart = sal_False; 1580 1581 cTabDecimal = 0; 1582 cHookChar = 0; 1583 nMaxHyph = 0; 1584 bTestFormat = rInf.bTestFormat; 1585 SetMulti( sal_True ); 1586 SetFirstMulti( rInf.IsFirstMulti() ); 1587 } 1588 1589 /************************************************************************* 1590 * SwTxtFormatInfo::_CheckFtnPortion() 1591 *************************************************************************/ 1592 1593 sal_Bool SwTxtFormatInfo::_CheckFtnPortion( SwLineLayout* pCurr ) 1594 { 1595 KSHORT nHeight = pCurr->GetRealHeight(); 1596 SwLinePortion *pPor = pCurr->GetPortion(); 1597 sal_Bool bRet = sal_False; 1598 while( pPor ) 1599 { 1600 if( pPor->IsFtnPortion() && nHeight > ((SwFtnPortion*)pPor)->Orig() ) 1601 { 1602 bRet = sal_True; 1603 SetLineHeight( nHeight ); 1604 SetLineNettoHeight( pCurr->Height() ); 1605 break; 1606 } 1607 pPor = pPor->GetPortion(); 1608 } 1609 return bRet; 1610 } 1611 1612 1613 1614 1615 /************************************************************************* 1616 * SwTxtFormatInfo::ScanPortionEnd() 1617 *************************************************************************/ 1618 xub_StrLen SwTxtFormatInfo::ScanPortionEnd( const xub_StrLen nStart, 1619 const xub_StrLen nEnd ) 1620 { 1621 cHookChar = 0; 1622 xub_StrLen i = nStart; 1623 1624 // 1625 // Used for decimal tab handling: 1626 // 1627 const xub_Unicode cTabDec = GetLastTab() ? (sal_Unicode)GetTabDecimal() : 0; 1628 const xub_Unicode cThousandSep = ',' == cTabDec ? '.' : ','; 1629 // --> FME 2006-01-23 #i45951# German (Switzerland) uses ' as thousand separator: 1630 const xub_Unicode cThousandSep2 = ',' == cTabDec ? '.' : '\''; 1631 // <-- 1632 1633 bool bNumFound = false; 1634 const bool bTabCompat = GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT); 1635 1636 // Removed for i7288. bSkip used to be passed from SwFldPortion::Format 1637 // as IsFollow(). Therefore more than one special character was not 1638 // handled correctly at the beginning of follow fields. 1639 // if ( bSkip && i < nEnd ) 1640 // ++i; 1641 1642 for( ; i < nEnd; ++i ) 1643 { 1644 const xub_Unicode cPos = GetChar( i ); 1645 switch( cPos ) 1646 { 1647 case CH_TXTATR_BREAKWORD: 1648 case CH_TXTATR_INWORD: 1649 if( !HasHint( i )) 1650 break; 1651 // no break; 1652 1653 case CHAR_SOFTHYPHEN: 1654 case CHAR_HARDHYPHEN: 1655 case CHAR_HARDBLANK: 1656 case CH_TAB: 1657 case CH_BREAK: 1658 case CHAR_ZWSP : 1659 case CHAR_ZWNBSP : 1660 // case CHAR_RLM : 1661 // case CHAR_LRM : 1662 cHookChar = cPos; 1663 return i; 1664 1665 case CHAR_UNDERSCORE: 1666 if ( STRING_LEN == nUnderScorePos ) 1667 nUnderScorePos = i; 1668 break; 1669 1670 default: 1671 if ( cTabDec ) 1672 { 1673 if( cTabDec == cPos ) 1674 { 1675 ASSERT( cPos, "Unexpected end of string" ); 1676 if( cPos ) // robust 1677 { 1678 cHookChar = cPos; 1679 return i; 1680 } 1681 } 1682 1683 // 1684 // Compatibility: First non-digit character behind a 1685 // a digit character becomes the hook character 1686 // 1687 if ( bTabCompat ) 1688 { 1689 if ( ( 0x2F < cPos && cPos < 0x3A ) || 1690 ( bNumFound && ( cPos == cThousandSep || cPos == cThousandSep2 ) ) ) 1691 { 1692 bNumFound = true; 1693 } 1694 else 1695 { 1696 if ( bNumFound ) 1697 { 1698 cHookChar = cPos; 1699 SetTabDecimal( cPos ); 1700 return i; 1701 } 1702 } 1703 } 1704 } 1705 } 1706 } 1707 1708 // --> FME 2006-01-13 #130210# Check if character *behind* the portion has 1709 // to become the hook: 1710 if ( i == nEnd && i < GetTxt().Len() && bNumFound ) 1711 { 1712 const xub_Unicode cPos = GetChar( i ); 1713 if ( cPos != cTabDec && cPos != cThousandSep && cPos !=cThousandSep2 && ( 0x2F >= cPos || cPos >= 0x3A ) ) 1714 { 1715 cHookChar = GetChar( i ); 1716 SetTabDecimal( cHookChar ); 1717 } 1718 } 1719 1720 return i; 1721 } 1722 1723 sal_Bool SwTxtFormatInfo::LastKernPortion() 1724 { 1725 if( GetLast() ) 1726 { 1727 if( GetLast()->IsKernPortion() ) 1728 return sal_True; 1729 if( GetLast()->Width() || ( GetLast()->GetLen() && 1730 !GetLast()->IsHolePortion() ) ) 1731 return sal_False; 1732 } 1733 SwLinePortion* pPor = GetRoot(); 1734 SwLinePortion *pKern = NULL; 1735 while( pPor ) 1736 { 1737 if( pPor->IsKernPortion() ) 1738 pKern = pPor; 1739 else if( pPor->Width() || ( pPor->GetLen() && !pPor->IsHolePortion() ) ) 1740 pKern = NULL; 1741 pPor = pPor->GetPortion(); 1742 } 1743 if( pKern ) 1744 { 1745 SetLast( pKern ); 1746 return sal_True; 1747 } 1748 return sal_False; 1749 } 1750 1751 /************************************************************************* 1752 * class SwTxtSlot 1753 *************************************************************************/ 1754 1755 SwTxtSlot::SwTxtSlot( 1756 const SwTxtSizeInfo *pNew, 1757 const SwLinePortion *pPor, 1758 bool bTxtLen, 1759 bool bExgLists, 1760 const sal_Char *pCh ) 1761 : pOldTxt( 0 ), 1762 pOldSmartTagList( 0 ), 1763 pOldGrammarCheckList( 0 ), 1764 pTempList( 0 ) 1765 { 1766 if( pCh ) 1767 { 1768 aTxt = XubString( pCh, RTL_TEXTENCODING_MS_1252 ); 1769 bOn = sal_True; 1770 } 1771 else 1772 bOn = pPor->GetExpTxt( *pNew, aTxt ); 1773 1774 // Der Text wird ausgetauscht... 1775 if( bOn ) 1776 { 1777 pInf = (SwTxtSizeInfo*)pNew; 1778 nIdx = pInf->GetIdx(); 1779 nLen = pInf->GetLen(); 1780 pOldTxt = &(pInf->GetTxt()); 1781 pInf->SetTxt( aTxt ); 1782 pInf->SetIdx( 0 ); 1783 pInf->SetLen( bTxtLen ? pInf->GetTxt().Len() : pPor->GetLen() ); 1784 1785 // ST2 1786 if ( bExgLists ) 1787 { 1788 pOldSmartTagList = static_cast<SwTxtPaintInfo*>(pInf)->GetSmartTags(); 1789 if ( pOldSmartTagList ) 1790 { 1791 const sal_uInt16 nPos = pOldSmartTagList->GetWrongPos(nIdx); 1792 const xub_StrLen nListPos = pOldSmartTagList->Pos(nPos); 1793 if( nListPos == nIdx ) 1794 ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList->SubList( nPos ) ); 1795 else if( !pTempList && nPos < pOldSmartTagList->Count() && nListPos < nIdx && aTxt.Len() ) 1796 { 1797 pTempList = new SwWrongList( WRONGLIST_SMARTTAG ); 1798 pTempList->Insert( rtl::OUString(), 0, 0, aTxt.Len(), 0 ); 1799 ((SwTxtPaintInfo*)pInf)->SetSmartTags( pTempList ); 1800 } 1801 else 1802 ((SwTxtPaintInfo*)pInf)->SetSmartTags( 0); 1803 } 1804 pOldGrammarCheckList = static_cast<SwTxtPaintInfo*>(pInf)->GetGrammarCheckList(); 1805 if ( pOldGrammarCheckList ) 1806 { 1807 const sal_uInt16 nPos = pOldGrammarCheckList->GetWrongPos(nIdx); 1808 const xub_StrLen nListPos = pOldGrammarCheckList->Pos(nPos); 1809 if( nListPos == nIdx ) 1810 ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList->SubList( nPos ) ); 1811 else if( !pTempList && nPos < pOldGrammarCheckList->Count() && nListPos < nIdx && aTxt.Len() ) 1812 { 1813 pTempList = new SwWrongList( WRONGLIST_GRAMMAR ); 1814 pTempList->Insert( rtl::OUString(), 0, 0, aTxt.Len(), 0 ); 1815 ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pTempList ); 1816 } 1817 else 1818 ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( 0); 1819 } 1820 } 1821 } 1822 } 1823 1824 /************************************************************************* 1825 * SwTxtSlot::~SwTxtSlot() 1826 *************************************************************************/ 1827 1828 SwTxtSlot::~SwTxtSlot() 1829 { 1830 if( bOn ) 1831 { 1832 pInf->SetTxt( *pOldTxt ); 1833 pInf->SetIdx( nIdx ); 1834 pInf->SetLen( nLen ); 1835 1836 // ST2 1837 // Restore old smart tag list 1838 if ( pOldSmartTagList ) 1839 ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList ); 1840 if ( pOldGrammarCheckList ) 1841 ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList ); 1842 delete pTempList; 1843 } 1844 } 1845 1846 /************************************************************************* 1847 * SwFontSave::SwFontSave() 1848 *************************************************************************/ 1849 1850 SwFontSave::SwFontSave( const SwTxtSizeInfo &rInf, SwFont *pNew, 1851 SwAttrIter* pItr ) 1852 : pFnt( pNew ? ((SwTxtSizeInfo&)rInf).GetFont() : 0 ) 1853 { 1854 if( pFnt ) 1855 { 1856 pInf = &((SwTxtSizeInfo&)rInf); 1857 // In these cases we temporarily switch to the new font: 1858 // 1. the fonts have a different magic number 1859 // 2. they have different script types 1860 // 3. their background colors differ (this is not covered by 1.) 1861 if( pFnt->DifferentMagic( pNew, pFnt->GetActual() ) || 1862 pNew->GetActual() != pFnt->GetActual() || 1863 ( ! pNew->GetBackColor() && pFnt->GetBackColor() ) || 1864 ( pNew->GetBackColor() && ! pFnt->GetBackColor() ) || 1865 ( pNew->GetBackColor() && pFnt->GetBackColor() && 1866 ( *pNew->GetBackColor() != *pFnt->GetBackColor() ) ) ) 1867 { 1868 pNew->SetTransparent( sal_True ); 1869 pNew->SetAlign( ALIGN_BASELINE ); 1870 pInf->SetFont( pNew ); 1871 } 1872 else 1873 pFnt = 0; 1874 pNew->Invalidate(); 1875 pNew->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() ); 1876 if( pItr && pItr->GetFnt() == pFnt ) 1877 { 1878 pIter = pItr; 1879 pIter->SetFnt( pNew ); 1880 } 1881 else 1882 pIter = NULL; 1883 } 1884 } 1885 1886 /************************************************************************* 1887 * SwFontSave::~SwFontSave() 1888 *************************************************************************/ 1889 1890 SwFontSave::~SwFontSave() 1891 { 1892 if( pFnt ) 1893 { 1894 // SwFont zurueckstellen 1895 pFnt->Invalidate(); 1896 pInf->SetFont( pFnt ); 1897 if( pIter ) 1898 { 1899 pIter->SetFnt( pFnt ); 1900 pIter->nPos = STRING_LEN; 1901 } 1902 } 1903 } 1904 1905 /************************************************************************* 1906 * SwDefFontSave::SwDefFontSave() 1907 *************************************************************************/ 1908 1909 SwDefFontSave::SwDefFontSave( const SwTxtSizeInfo &rInf ) 1910 : pFnt( ((SwTxtSizeInfo&)rInf).GetFont() ) 1911 { 1912 const sal_Bool bTmpAlter = pFnt->GetFixKerning() || 1913 ( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet(pFnt->GetActual()) ) 1914 ; 1915 1916 const sal_Bool bFamily = bTmpAlter && 1917 pFnt->GetName( pFnt->GetActual() ) != numfunc::GetDefBulletFontname(); 1918 const sal_Bool bRotation = (sal_Bool)pFnt->GetOrientation() && 1919 ! rInf.GetTxtFrm()->IsVertical(); 1920 1921 if( bFamily || bRotation ) 1922 { 1923 pNewFnt = new SwFont( *pFnt ); 1924 1925 if ( bFamily ) 1926 { 1927 pNewFnt->SetFamily( FAMILY_DONTKNOW, pFnt->GetActual() ); 1928 pNewFnt->SetName( numfunc::GetDefBulletFontname(), pFnt->GetActual() ); 1929 pNewFnt->SetStyleName( aEmptyStr, pFnt->GetActual() ); 1930 pNewFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, pFnt->GetActual() ); 1931 pNewFnt->SetFixKerning( 0 ); 1932 } 1933 1934 if ( bRotation ) 1935 pNewFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() ); 1936 1937 pInf = &((SwTxtSizeInfo&)rInf); 1938 pNewFnt->Invalidate(); 1939 pInf->SetFont( pNewFnt ); 1940 } 1941 else 1942 { 1943 pFnt = 0; 1944 pNewFnt = 0; 1945 } 1946 } 1947 1948 /************************************************************************* 1949 * SwDefFontSave::~SwDefFontSave() 1950 *************************************************************************/ 1951 1952 SwDefFontSave::~SwDefFontSave() 1953 { 1954 if( pFnt ) 1955 { 1956 delete pNewFnt; 1957 // SwFont zurueckstellen 1958 pFnt->Invalidate(); 1959 pInf->SetFont( pFnt ); 1960 } 1961 } 1962 1963 /************************************************************************* 1964 * SwTxtFormatInfo::ChgHyph() 1965 *************************************************************************/ 1966 1967 sal_Bool SwTxtFormatInfo::ChgHyph( const sal_Bool bNew ) 1968 { 1969 const sal_Bool bOld = bAutoHyph; 1970 if( bAutoHyph != bNew ) 1971 { 1972 bAutoHyph = bNew; 1973 InitHyph( bNew ); 1974 // 5744: Sprache am Hyphenator einstellen. 1975 if( pFnt ) 1976 pFnt->ChgPhysFnt( pVsh, *pOut ); 1977 } 1978 return bOld; 1979 } 1980 1981 1982