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