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