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