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