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