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 bDraw = sal_True; 1297 break; 1298 case POR_TAB: if ( GetOpt().IsTab() ) bDraw = sal_True; break; 1299 case POR_SOFTHYPH: if ( GetOpt().IsSoftHyph() )bDraw = sal_True; break; 1300 case POR_BLANK: if ( GetOpt().IsHardBlank())bDraw = sal_True; break; 1301 default: 1302 { 1303 ASSERT( !this, "SwTxtPaintInfo::DrawViewOpt: don't know how to draw this" ); 1304 break; 1305 } 1306 } 1307 if ( bDraw ) 1308 DrawBackground( rPor ); 1309 } 1310 } 1311 1312 /************************************************************************* 1313 * SwTxtPaintInfo::_NotifyURL() 1314 *************************************************************************/ 1315 1316 void SwTxtPaintInfo::_NotifyURL( const SwLinePortion &rPor ) const 1317 { 1318 ASSERT( pNoteURL, "NotifyURL: pNoteURL gone with the wind!" ); 1319 1320 SwRect aIntersect; 1321 CalcRect( rPor, 0, &aIntersect ); 1322 1323 if( aIntersect.HasArea() ) 1324 { 1325 SwTxtNode *pNd = (SwTxtNode*)GetTxtFrm()->GetTxtNode(); 1326 SwTxtAttr *const pAttr = 1327 pNd->GetTxtAttrAt(GetIdx(), RES_TXTATR_INETFMT); 1328 if( pAttr ) 1329 { 1330 const SwFmtINetFmt& rFmt = pAttr->GetINetFmt(); 1331 pNoteURL->InsertURLNote( rFmt.GetValue(), rFmt.GetTargetFrame(), 1332 aIntersect ); 1333 } 1334 } 1335 } 1336 1337 /************************************************************************* 1338 * lcl_InitHyphValues() 1339 *************************************************************************/ 1340 1341 static void lcl_InitHyphValues( PropertyValues &rVals, 1342 sal_Int16 nMinLeading, sal_Int16 nMinTrailing ) 1343 { 1344 sal_Int32 nLen = rVals.getLength(); 1345 1346 if (0 == nLen) // yet to be initialized? 1347 { 1348 rVals.realloc( 2 ); 1349 PropertyValue *pVal = rVals.getArray(); 1350 1351 pVal[0].Name = C2U( UPN_HYPH_MIN_LEADING ); 1352 pVal[0].Handle = UPH_HYPH_MIN_LEADING; 1353 pVal[0].Value <<= nMinLeading; 1354 1355 pVal[1].Name = C2U( UPN_HYPH_MIN_TRAILING ); 1356 pVal[1].Handle = UPH_HYPH_MIN_TRAILING; 1357 pVal[1].Value <<= nMinTrailing; 1358 } 1359 else if (2 == nLen) // already initialized once? 1360 { 1361 PropertyValue *pVal = rVals.getArray(); 1362 pVal[0].Value <<= nMinLeading; 1363 pVal[1].Value <<= nMinTrailing; 1364 } 1365 else { 1366 DBG_ERROR( "unxpected size of sequence" ); 1367 } 1368 } 1369 1370 /************************************************************************* 1371 * SwTxtFormatInfo::GetHyphValues() 1372 *************************************************************************/ 1373 1374 const PropertyValues & SwTxtFormatInfo::GetHyphValues() const 1375 { 1376 DBG_ASSERT( 2 == aHyphVals.getLength(), 1377 "hyphenation values not yet initialized" ); 1378 return aHyphVals; 1379 } 1380 1381 /************************************************************************* 1382 * SwTxtFormatInfo::InitHyph() 1383 *************************************************************************/ 1384 1385 sal_Bool SwTxtFormatInfo::InitHyph( const sal_Bool bAutoHyphen ) 1386 { 1387 const SwAttrSet& rAttrSet = GetTxtFrm()->GetTxtNode()->GetSwAttrSet(); 1388 SetHanging( rAttrSet.GetHangingPunctuation().GetValue() ); 1389 SetScriptSpace( rAttrSet.GetScriptSpace().GetValue() ); 1390 SetForbiddenChars( rAttrSet.GetForbiddenRule().GetValue() ); 1391 const SvxHyphenZoneItem &rAttr = rAttrSet.GetHyphenZone(); 1392 MaxHyph() = rAttr.GetMaxHyphens(); 1393 sal_Bool bAuto = bAutoHyphen || rAttr.IsHyphen(); 1394 if( bAuto || bInterHyph ) 1395 { 1396 nHyphStart = nHyphWrdStart = STRING_LEN; 1397 nHyphWrdLen = 0; 1398 1399 const sal_Int16 nMinimalLeading = Max(rAttr.GetMinLead(), sal_uInt8(2)); 1400 const sal_Int16 nMinimalTrailing = rAttr.GetMinTrail(); 1401 lcl_InitHyphValues( aHyphVals, nMinimalLeading, nMinimalTrailing); 1402 } 1403 return bAuto; 1404 } 1405 1406 /************************************************************************* 1407 * SwTxtFormatInfo::CtorInitTxtFormatInfo() 1408 *************************************************************************/ 1409 1410 void SwTxtFormatInfo::CtorInitTxtFormatInfo( SwTxtFrm *pNewFrm, const sal_Bool bNewInterHyph, 1411 const sal_Bool bNewQuick, const sal_Bool bTst ) 1412 { 1413 CtorInitTxtPaintInfo( pNewFrm, SwRect() ); 1414 1415 bQuick = bNewQuick; 1416 bInterHyph = bNewInterHyph; 1417 1418 //! needs to be done in this order 1419 nMinLeading = 2; 1420 nMinTrailing = 2; 1421 nMinWordLength = 0; 1422 bAutoHyph = InitHyph(); 1423 1424 bIgnoreFly = sal_False; 1425 bFakeLineStart = sal_False; 1426 bShift = sal_False; 1427 bDropInit = sal_False; 1428 bTestFormat = bTst; 1429 nLeft = 0; 1430 nRight = 0; 1431 nFirst = 0; 1432 nRealWidth = 0; 1433 nForcedLeftMargin = 0; 1434 pRest = 0; 1435 nLineHeight = 0; 1436 nLineNettoHeight = 0; 1437 SetLineStart(0); 1438 Init(); 1439 } 1440 1441 /************************************************************************* 1442 * SwTxtFormatInfo::IsHyphenate() 1443 *************************************************************************/ 1444 // Trennen oder nicht trennen, das ist hier die Frage: 1445 // - in keinem Fall trennen, wenn der Hyphenator ERROR zurueckliefert, 1446 // oder wenn als Sprache NOLANGUAGE eingestellt ist. 1447 // - ansonsten immer trennen, wenn interaktive Trennung vorliegt 1448 // - wenn keine interakt. Trennung, dann nur trennen, wenn im ParaFmt 1449 // automatische Trennung eingestellt ist. 1450 1451 sal_Bool SwTxtFormatInfo::IsHyphenate() const 1452 { 1453 if( !bInterHyph && !bAutoHyph ) 1454 return sal_False; 1455 1456 LanguageType eTmp = GetFont()->GetLanguage(); 1457 if( LANGUAGE_DONTKNOW == eTmp || LANGUAGE_NONE == eTmp ) 1458 return sal_False; 1459 1460 uno::Reference< XHyphenator > xHyph = ::GetHyphenator(); 1461 if (bInterHyph && xHyph.is()) 1462 SvxSpellWrapper::CheckHyphLang( xHyph, eTmp ); 1463 1464 if( !xHyph.is() || !xHyph->hasLocale( pBreakIt->GetLocale(eTmp) ) ) 1465 return sal_False; 1466 return sal_True; 1467 } 1468 1469 /************************************************************************* 1470 * SwTxtFormatInfo::GetDropFmt() 1471 *************************************************************************/ 1472 1473 // Dropcaps vom SwTxtFormatter::CTOR gerufen. 1474 const SwFmtDrop *SwTxtFormatInfo::GetDropFmt() const 1475 { 1476 const SwFmtDrop *pDrop = &GetTxtFrm()->GetTxtNode()->GetSwAttrSet().GetDrop(); 1477 if( 1 >= pDrop->GetLines() || 1478 ( !pDrop->GetChars() && !pDrop->GetWholeWord() ) ) 1479 pDrop = 0; 1480 return pDrop; 1481 } 1482 1483 /************************************************************************* 1484 * SwTxtFormatInfo::Init() 1485 *************************************************************************/ 1486 1487 void SwTxtFormatInfo::Init() 1488 { 1489 // Nicht initialisieren: pRest, nLeft, nRight, nFirst, nRealWidth 1490 X(0); 1491 bArrowDone = bFull = bFtnDone = bErgoDone = bNumDone = bNoEndHyph = 1492 bNoMidHyph = bStop = bNewLine = bUnderFlow = sal_False; 1493 1494 // generally we do not allow number portions in follows, except... 1495 if ( GetTxtFrm()->IsFollow() ) 1496 { 1497 const SwTxtFrm* pMaster = GetTxtFrm()->FindMaster(); 1498 const SwLinePortion* pTmpPara = pMaster->GetPara(); 1499 1500 // there is a master for this follow and the master does not have 1501 // any contents (especially it does not have a number portion) 1502 bNumDone = ! pTmpPara || 1503 ! ((SwParaPortion*)pTmpPara)->GetFirstPortion()->IsFlyPortion(); 1504 } 1505 1506 pRoot = 0; 1507 pLast = 0; 1508 pFly = 0; 1509 pLastFld = 0; 1510 pLastTab = 0; 1511 pUnderFlow = 0; 1512 cTabDecimal = 0; 1513 nWidth = nRealWidth; 1514 nForcedLeftMargin = 0; 1515 nSoftHyphPos = 0; 1516 nUnderScorePos = STRING_LEN; 1517 cHookChar = 0; 1518 SetIdx(0); 1519 SetLen( GetTxt().Len() ); 1520 SetPaintOfst(0); 1521 } 1522 1523 /*-----------------16.10.00 11:39------------------- 1524 * There are a few differences between a copy constructor 1525 * and the following constructor for multi-line formatting. 1526 * The root is the first line inside the multi-portion, 1527 * the line start is the actual position in the text, 1528 * the line width is the rest width from the surrounding line 1529 * and the bMulti and bFirstMulti-flag has to be set correctly. 1530 * --------------------------------------------------*/ 1531 1532 SwTxtFormatInfo::SwTxtFormatInfo( const SwTxtFormatInfo& rInf, 1533 SwLineLayout& rLay, SwTwips nActWidth ) : SwTxtPaintInfo( rInf ) 1534 { 1535 pRoot = &rLay; 1536 pLast = &rLay; 1537 pFly = NULL; 1538 pLastFld = NULL; 1539 pUnderFlow = NULL; 1540 pRest = NULL; 1541 pLastTab = NULL; 1542 1543 nSoftHyphPos = 0; 1544 nUnderScorePos = STRING_LEN; 1545 nHyphStart = 0; 1546 nHyphWrdStart = 0; 1547 nHyphWrdLen = 0; 1548 nLineStart = rInf.GetIdx(); 1549 nLeft = rInf.nLeft; 1550 nRight = rInf.nRight; 1551 nFirst = rInf.nLeft; 1552 nRealWidth = KSHORT(nActWidth); 1553 nWidth = nRealWidth; 1554 nLineHeight = 0; 1555 nLineNettoHeight = 0; 1556 nForcedLeftMargin = 0; 1557 1558 nMinLeading = 0; 1559 nMinTrailing = 0; 1560 nMinWordLength = 0; 1561 bFull = sal_False; 1562 bFtnDone = sal_True; 1563 bErgoDone = sal_True; 1564 bNumDone = sal_True; 1565 bArrowDone = sal_True; 1566 bStop = sal_False; 1567 bNewLine = sal_True; 1568 bShift = sal_False; 1569 bUnderFlow = sal_False; 1570 bInterHyph = sal_False; 1571 bAutoHyph = sal_False; 1572 bDropInit = sal_False; 1573 bQuick = rInf.bQuick; 1574 bNoEndHyph = sal_False; 1575 bNoMidHyph = sal_False; 1576 bIgnoreFly = sal_False; 1577 bFakeLineStart = sal_False; 1578 1579 cTabDecimal = 0; 1580 cHookChar = 0; 1581 nMaxHyph = 0; 1582 bTestFormat = rInf.bTestFormat; 1583 SetMulti( sal_True ); 1584 SetFirstMulti( rInf.IsFirstMulti() ); 1585 } 1586 1587 /************************************************************************* 1588 * SwTxtFormatInfo::_CheckFtnPortion() 1589 *************************************************************************/ 1590 1591 sal_Bool SwTxtFormatInfo::_CheckFtnPortion( SwLineLayout* pCurr ) 1592 { 1593 KSHORT nHeight = pCurr->GetRealHeight(); 1594 SwLinePortion *pPor = pCurr->GetPortion(); 1595 sal_Bool bRet = sal_False; 1596 while( pPor ) 1597 { 1598 if( pPor->IsFtnPortion() && nHeight > ((SwFtnPortion*)pPor)->Orig() ) 1599 { 1600 bRet = sal_True; 1601 SetLineHeight( nHeight ); 1602 SetLineNettoHeight( pCurr->Height() ); 1603 break; 1604 } 1605 pPor = pPor->GetPortion(); 1606 } 1607 return bRet; 1608 } 1609 1610 1611 1612 1613 /************************************************************************* 1614 * SwTxtFormatInfo::ScanPortionEnd() 1615 *************************************************************************/ 1616 xub_StrLen SwTxtFormatInfo::ScanPortionEnd( const xub_StrLen nStart, 1617 const xub_StrLen nEnd ) 1618 { 1619 cHookChar = 0; 1620 xub_StrLen i = nStart; 1621 1622 // 1623 // Used for decimal tab handling: 1624 // 1625 const xub_Unicode cTabDec = GetLastTab() ? (sal_Unicode)GetTabDecimal() : 0; 1626 const xub_Unicode cThousandSep = ',' == cTabDec ? '.' : ','; 1627 // --> FME 2006-01-23 #i45951# German (Switzerland) uses ' as thousand separator: 1628 const xub_Unicode cThousandSep2 = ',' == cTabDec ? '.' : '\''; 1629 // <-- 1630 1631 bool bNumFound = false; 1632 const bool bTabCompat = GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT); 1633 1634 // Removed for i7288. bSkip used to be passed from SwFldPortion::Format 1635 // as IsFollow(). Therefore more than one special character was not 1636 // handled correctly at the beginning of follow fields. 1637 // if ( bSkip && i < nEnd ) 1638 // ++i; 1639 1640 for( ; i < nEnd; ++i ) 1641 { 1642 const xub_Unicode cPos = GetChar( i ); 1643 switch( cPos ) 1644 { 1645 case CH_TXTATR_BREAKWORD: 1646 case CH_TXTATR_INWORD: 1647 if( !HasHint( i )) 1648 break; 1649 // no break; 1650 1651 case CHAR_SOFTHYPHEN: 1652 case CHAR_HARDHYPHEN: 1653 case CHAR_HARDBLANK: 1654 case CH_TAB: 1655 case CH_BREAK: 1656 case CHAR_ZWSP : 1657 case CHAR_ZWNBSP : 1658 // case CHAR_RLM : 1659 // case CHAR_LRM : 1660 cHookChar = cPos; 1661 return i; 1662 1663 case CHAR_UNDERSCORE: 1664 if ( STRING_LEN == nUnderScorePos ) 1665 nUnderScorePos = i; 1666 break; 1667 1668 default: 1669 if ( cTabDec ) 1670 { 1671 if( cTabDec == cPos ) 1672 { 1673 ASSERT( cPos, "Unexpected end of string" ); 1674 if( cPos ) // robust 1675 { 1676 cHookChar = cPos; 1677 return i; 1678 } 1679 } 1680 1681 // 1682 // Compatibility: First non-digit character behind a 1683 // a digit character becomes the hook character 1684 // 1685 if ( bTabCompat ) 1686 { 1687 if ( ( 0x2F < cPos && cPos < 0x3A ) || 1688 ( bNumFound && ( cPos == cThousandSep || cPos == cThousandSep2 ) ) ) 1689 { 1690 bNumFound = true; 1691 } 1692 else 1693 { 1694 if ( bNumFound ) 1695 { 1696 cHookChar = cPos; 1697 SetTabDecimal( cPos ); 1698 return i; 1699 } 1700 } 1701 } 1702 } 1703 } 1704 } 1705 1706 // --> FME 2006-01-13 #130210# Check if character *behind* the portion has 1707 // to become the hook: 1708 if ( i == nEnd && i < GetTxt().Len() && bNumFound ) 1709 { 1710 const xub_Unicode cPos = GetChar( i ); 1711 if ( cPos != cTabDec && cPos != cThousandSep && cPos !=cThousandSep2 && ( 0x2F >= cPos || cPos >= 0x3A ) ) 1712 { 1713 cHookChar = GetChar( i ); 1714 SetTabDecimal( cHookChar ); 1715 } 1716 } 1717 1718 return i; 1719 } 1720 1721 sal_Bool SwTxtFormatInfo::LastKernPortion() 1722 { 1723 if( GetLast() ) 1724 { 1725 if( GetLast()->IsKernPortion() ) 1726 return sal_True; 1727 if( GetLast()->Width() || ( GetLast()->GetLen() && 1728 !GetLast()->IsHolePortion() ) ) 1729 return sal_False; 1730 } 1731 SwLinePortion* pPor = GetRoot(); 1732 SwLinePortion *pKern = NULL; 1733 while( pPor ) 1734 { 1735 if( pPor->IsKernPortion() ) 1736 pKern = pPor; 1737 else if( pPor->Width() || ( pPor->GetLen() && !pPor->IsHolePortion() ) ) 1738 pKern = NULL; 1739 pPor = pPor->GetPortion(); 1740 } 1741 if( pKern ) 1742 { 1743 SetLast( pKern ); 1744 return sal_True; 1745 } 1746 return sal_False; 1747 } 1748 1749 /************************************************************************* 1750 * class SwTxtSlot 1751 *************************************************************************/ 1752 1753 SwTxtSlot::SwTxtSlot( const SwTxtSizeInfo *pNew, const SwLinePortion *pPor, 1754 bool bTxtLen, bool bExgLists, const sal_Char *pCh ) 1755 : pOldTxt( 0 ), 1756 pOldSmartTagList( 0 ), 1757 pOldGrammarCheckList( 0 ), 1758 pTempList( 0 ) 1759 { 1760 if( pCh ) 1761 { 1762 aTxt = XubString( pCh, RTL_TEXTENCODING_MS_1252 ); 1763 bOn = sal_True; 1764 } 1765 else 1766 bOn = pPor->GetExpTxt( *pNew, aTxt ); 1767 1768 // Der Text wird ausgetauscht... 1769 if( bOn ) 1770 { 1771 pInf = (SwTxtSizeInfo*)pNew; 1772 nIdx = pInf->GetIdx(); 1773 nLen = pInf->GetLen(); 1774 pOldTxt = &(pInf->GetTxt()); 1775 pInf->SetTxt( aTxt ); 1776 pInf->SetIdx( 0 ); 1777 pInf->SetLen( bTxtLen ? pInf->GetTxt().Len() : pPor->GetLen() ); 1778 1779 // ST2 1780 if ( bExgLists ) 1781 { 1782 pOldSmartTagList = static_cast<SwTxtPaintInfo*>(pInf)->GetSmartTags(); 1783 if ( pOldSmartTagList ) 1784 { 1785 const sal_uInt16 nPos = pOldSmartTagList->GetWrongPos(nIdx); 1786 const xub_StrLen nListPos = pOldSmartTagList->Pos(nPos); 1787 if( nListPos == nIdx ) 1788 ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList->SubList( nPos ) ); 1789 else if( !pTempList && nPos < pOldSmartTagList->Count() && nListPos < nIdx && aTxt.Len() ) 1790 { 1791 pTempList = new SwWrongList( WRONGLIST_SMARTTAG ); 1792 pTempList->Insert( rtl::OUString(), 0, 0, aTxt.Len(), 0 ); 1793 ((SwTxtPaintInfo*)pInf)->SetSmartTags( pTempList ); 1794 } 1795 else 1796 ((SwTxtPaintInfo*)pInf)->SetSmartTags( 0); 1797 } 1798 pOldGrammarCheckList = static_cast<SwTxtPaintInfo*>(pInf)->GetGrammarCheckList(); 1799 if ( pOldGrammarCheckList ) 1800 { 1801 const sal_uInt16 nPos = pOldGrammarCheckList->GetWrongPos(nIdx); 1802 const xub_StrLen nListPos = pOldGrammarCheckList->Pos(nPos); 1803 if( nListPos == nIdx ) 1804 ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList->SubList( nPos ) ); 1805 else if( !pTempList && nPos < pOldGrammarCheckList->Count() && nListPos < nIdx && aTxt.Len() ) 1806 { 1807 pTempList = new SwWrongList( WRONGLIST_GRAMMAR ); 1808 pTempList->Insert( rtl::OUString(), 0, 0, aTxt.Len(), 0 ); 1809 ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pTempList ); 1810 } 1811 else 1812 ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( 0); 1813 } 1814 } 1815 } 1816 } 1817 1818 /************************************************************************* 1819 * SwTxtSlot::~SwTxtSlot() 1820 *************************************************************************/ 1821 1822 SwTxtSlot::~SwTxtSlot() 1823 { 1824 if( bOn ) 1825 { 1826 pInf->SetTxt( *pOldTxt ); 1827 pInf->SetIdx( nIdx ); 1828 pInf->SetLen( nLen ); 1829 1830 // ST2 1831 // Restore old smart tag list 1832 if ( pOldSmartTagList ) 1833 ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList ); 1834 if ( pOldGrammarCheckList ) 1835 ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList ); 1836 delete pTempList; 1837 } 1838 } 1839 1840 /************************************************************************* 1841 * SwFontSave::SwFontSave() 1842 *************************************************************************/ 1843 1844 SwFontSave::SwFontSave( const SwTxtSizeInfo &rInf, SwFont *pNew, 1845 SwAttrIter* pItr ) 1846 : pFnt( pNew ? ((SwTxtSizeInfo&)rInf).GetFont() : 0 ) 1847 { 1848 if( pFnt ) 1849 { 1850 pInf = &((SwTxtSizeInfo&)rInf); 1851 // In these cases we temporarily switch to the new font: 1852 // 1. the fonts have a different magic number 1853 // 2. they have different script types 1854 // 3. their background colors differ (this is not covered by 1.) 1855 if( pFnt->DifferentMagic( pNew, pFnt->GetActual() ) || 1856 pNew->GetActual() != pFnt->GetActual() || 1857 ( ! pNew->GetBackColor() && pFnt->GetBackColor() ) || 1858 ( pNew->GetBackColor() && ! pFnt->GetBackColor() ) || 1859 ( pNew->GetBackColor() && pFnt->GetBackColor() && 1860 ( *pNew->GetBackColor() != *pFnt->GetBackColor() ) ) ) 1861 { 1862 pNew->SetTransparent( sal_True ); 1863 pNew->SetAlign( ALIGN_BASELINE ); 1864 pInf->SetFont( pNew ); 1865 } 1866 else 1867 pFnt = 0; 1868 pNew->Invalidate(); 1869 pNew->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() ); 1870 if( pItr && pItr->GetFnt() == pFnt ) 1871 { 1872 pIter = pItr; 1873 pIter->SetFnt( pNew ); 1874 } 1875 else 1876 pIter = NULL; 1877 } 1878 } 1879 1880 /************************************************************************* 1881 * SwFontSave::~SwFontSave() 1882 *************************************************************************/ 1883 1884 SwFontSave::~SwFontSave() 1885 { 1886 if( pFnt ) 1887 { 1888 // SwFont zurueckstellen 1889 pFnt->Invalidate(); 1890 pInf->SetFont( pFnt ); 1891 if( pIter ) 1892 { 1893 pIter->SetFnt( pFnt ); 1894 pIter->nPos = STRING_LEN; 1895 } 1896 } 1897 } 1898 1899 /************************************************************************* 1900 * SwDefFontSave::SwDefFontSave() 1901 *************************************************************************/ 1902 1903 SwDefFontSave::SwDefFontSave( const SwTxtSizeInfo &rInf ) 1904 : pFnt( ((SwTxtSizeInfo&)rInf).GetFont() ) 1905 { 1906 const sal_Bool bTmpAlter = pFnt->GetFixKerning() || 1907 ( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet(pFnt->GetActual()) ) 1908 ; 1909 1910 const sal_Bool bFamily = bTmpAlter && 1911 pFnt->GetName( pFnt->GetActual() ) != numfunc::GetDefBulletFontname(); 1912 const sal_Bool bRotation = (sal_Bool)pFnt->GetOrientation() && 1913 ! rInf.GetTxtFrm()->IsVertical(); 1914 1915 if( bFamily || bRotation ) 1916 { 1917 pNewFnt = new SwFont( *pFnt ); 1918 1919 if ( bFamily ) 1920 { 1921 pNewFnt->SetFamily( FAMILY_DONTKNOW, pFnt->GetActual() ); 1922 pNewFnt->SetName( numfunc::GetDefBulletFontname(), pFnt->GetActual() ); 1923 pNewFnt->SetStyleName( aEmptyStr, pFnt->GetActual() ); 1924 pNewFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, pFnt->GetActual() ); 1925 pNewFnt->SetFixKerning( 0 ); 1926 } 1927 1928 if ( bRotation ) 1929 pNewFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() ); 1930 1931 pInf = &((SwTxtSizeInfo&)rInf); 1932 pNewFnt->Invalidate(); 1933 pInf->SetFont( pNewFnt ); 1934 } 1935 else 1936 { 1937 pFnt = 0; 1938 pNewFnt = 0; 1939 } 1940 } 1941 1942 /************************************************************************* 1943 * SwDefFontSave::~SwDefFontSave() 1944 *************************************************************************/ 1945 1946 SwDefFontSave::~SwDefFontSave() 1947 { 1948 if( pFnt ) 1949 { 1950 delete pNewFnt; 1951 // SwFont zurueckstellen 1952 pFnt->Invalidate(); 1953 pInf->SetFont( pFnt ); 1954 } 1955 } 1956 1957 /************************************************************************* 1958 * SwTxtFormatInfo::ChgHyph() 1959 *************************************************************************/ 1960 1961 sal_Bool SwTxtFormatInfo::ChgHyph( const sal_Bool bNew ) 1962 { 1963 const sal_Bool bOld = bAutoHyph; 1964 if( bAutoHyph != bNew ) 1965 { 1966 bAutoHyph = bNew; 1967 InitHyph( bNew ); 1968 // 5744: Sprache am Hyphenator einstellen. 1969 if( pFnt ) 1970 pFnt->ChgPhysFnt( pVsh, *pOut ); 1971 } 1972 return bOld; 1973 } 1974 1975 1976