xref: /aoo41x/main/sw/source/core/text/inftxt.cxx (revision cdf0e10c)
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