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