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