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