xref: /aoo41x/main/sw/source/core/text/inftxt.cxx (revision 69a74367)
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             {
1297                 bDraw = sal_True;
1298             }
1299             break;
1300         case POR_INPUTFLD:
1301             // input field shading also in read-only mode
1302             if ( !GetOpt().IsPagePreview()
1303                  && SwViewOption::IsFieldShadings() )
1304             {
1305                 bDraw = sal_True;
1306             }
1307             break;
1308         case POR_TAB:		if ( GetOpt().IsTab() )		bDraw = sal_True; break;
1309         case POR_SOFTHYPH:	if ( GetOpt().IsSoftHyph() )bDraw = sal_True; break;
1310         case POR_BLANK:     if ( GetOpt().IsHardBlank())bDraw = sal_True; break;
1311         default:
1312             {
1313                 ASSERT( !this, "SwTxtPaintInfo::DrawViewOpt: don't know how to draw this" );
1314                 break;
1315             }
1316         }
1317         if ( bDraw )
1318             DrawBackground( rPor );
1319     }
1320 }
1321 
1322 /*************************************************************************
1323  *					   SwTxtPaintInfo::_NotifyURL()
1324  *************************************************************************/
1325 
1326 void SwTxtPaintInfo::_NotifyURL( const SwLinePortion &rPor ) const
1327 {
1328 	ASSERT( pNoteURL, "NotifyURL: pNoteURL gone with the wind!" );
1329 
1330     SwRect aIntersect;
1331     CalcRect( rPor, 0, &aIntersect );
1332 
1333     if( aIntersect.HasArea() )
1334 	{
1335 		SwTxtNode *pNd = (SwTxtNode*)GetTxtFrm()->GetTxtNode();
1336         SwTxtAttr *const pAttr =
1337             pNd->GetTxtAttrAt(GetIdx(), RES_TXTATR_INETFMT);
1338 		if( pAttr )
1339 		{
1340 			const SwFmtINetFmt& rFmt = pAttr->GetINetFmt();
1341 			pNoteURL->InsertURLNote( rFmt.GetValue(), rFmt.GetTargetFrame(),
1342                 aIntersect );
1343 		}
1344 	}
1345 }
1346 
1347 /*************************************************************************
1348  *					lcl_InitHyphValues()
1349  *************************************************************************/
1350 
1351 static void lcl_InitHyphValues( PropertyValues &rVals,
1352 			sal_Int16 nMinLeading, sal_Int16 nMinTrailing )
1353 {
1354 	sal_Int32 nLen = rVals.getLength();
1355 
1356 	if (0 == nLen)	// yet to be initialized?
1357 	{
1358 		rVals.realloc( 2 );
1359 		PropertyValue *pVal = rVals.getArray();
1360 
1361 		pVal[0].Name	= C2U( UPN_HYPH_MIN_LEADING );
1362 		pVal[0].Handle	= UPH_HYPH_MIN_LEADING;
1363 		pVal[0].Value	<<= nMinLeading;
1364 
1365 		pVal[1].Name	= C2U( UPN_HYPH_MIN_TRAILING );
1366 		pVal[1].Handle	= UPH_HYPH_MIN_TRAILING;
1367 		pVal[1].Value	<<= nMinTrailing;
1368 	}
1369 	else if (2 == nLen)	// already initialized once?
1370 	{
1371 		PropertyValue *pVal = rVals.getArray();
1372 		pVal[0].Value <<= nMinLeading;
1373 		pVal[1].Value <<= nMinTrailing;
1374 	}
1375 	else {
1376 		DBG_ERROR( "unxpected size of sequence" );
1377     }
1378 }
1379 
1380 /*************************************************************************
1381  *					SwTxtFormatInfo::GetHyphValues()
1382  *************************************************************************/
1383 
1384 const PropertyValues & SwTxtFormatInfo::GetHyphValues() const
1385 {
1386 	DBG_ASSERT( 2 == aHyphVals.getLength(),
1387 			"hyphenation values not yet initialized" );
1388 	return aHyphVals;
1389 }
1390 
1391 /*************************************************************************
1392  *					SwTxtFormatInfo::InitHyph()
1393  *************************************************************************/
1394 
1395 sal_Bool SwTxtFormatInfo::InitHyph( const sal_Bool bAutoHyphen )
1396 {
1397 	const SwAttrSet& rAttrSet = GetTxtFrm()->GetTxtNode()->GetSwAttrSet();
1398 	SetHanging( rAttrSet.GetHangingPunctuation().GetValue() );
1399 	SetScriptSpace( rAttrSet.GetScriptSpace().GetValue() );
1400 	SetForbiddenChars( rAttrSet.GetForbiddenRule().GetValue() );
1401 	const SvxHyphenZoneItem &rAttr = rAttrSet.GetHyphenZone();
1402 	MaxHyph() = rAttr.GetMaxHyphens();
1403     sal_Bool bAuto = bAutoHyphen || rAttr.IsHyphen();
1404 	if( bAuto || bInterHyph )
1405 	{
1406 		nHyphStart = nHyphWrdStart = STRING_LEN;
1407 		nHyphWrdLen = 0;
1408 
1409         const sal_Int16 nMinimalLeading  = Max(rAttr.GetMinLead(), sal_uInt8(2));
1410         const sal_Int16 nMinimalTrailing = rAttr.GetMinTrail();
1411         lcl_InitHyphValues( aHyphVals, nMinimalLeading, nMinimalTrailing);
1412 	}
1413 	return bAuto;
1414 }
1415 
1416 /*************************************************************************
1417  *					SwTxtFormatInfo::CtorInitTxtFormatInfo()
1418  *************************************************************************/
1419 
1420 void SwTxtFormatInfo::CtorInitTxtFormatInfo( SwTxtFrm *pNewFrm, const sal_Bool bNewInterHyph,
1421 								const sal_Bool bNewQuick, const sal_Bool bTst )
1422 {
1423 	CtorInitTxtPaintInfo( pNewFrm, SwRect() );
1424 
1425 	bQuick = bNewQuick;
1426 	bInterHyph = bNewInterHyph;
1427 
1428 	//! needs to be done in this order
1429 	nMinLeading		= 2;
1430 	nMinTrailing	= 2;
1431 	nMinWordLength	= 0;
1432 	bAutoHyph = InitHyph();
1433 
1434 	bIgnoreFly = sal_False;
1435     bFakeLineStart = sal_False;
1436 	bShift = sal_False;
1437 	bDropInit = sal_False;
1438 	bTestFormat = bTst;
1439 	nLeft = 0;
1440 	nRight = 0;
1441 	nFirst = 0;
1442 	nRealWidth = 0;
1443 	nForcedLeftMargin = 0;
1444 	pRest = 0;
1445 	nLineHeight = 0;
1446     nLineNettoHeight = 0;
1447 	SetLineStart(0);
1448 	Init();
1449 }
1450 
1451 /*************************************************************************
1452  *					SwTxtFormatInfo::IsHyphenate()
1453  *************************************************************************/
1454 // Trennen oder nicht trennen, das ist hier die Frage:
1455 // - in keinem Fall trennen, wenn der Hyphenator ERROR zurueckliefert,
1456 //	 oder wenn als Sprache NOLANGUAGE eingestellt ist.
1457 // - ansonsten immer trennen, wenn interaktive Trennung vorliegt
1458 // - wenn keine interakt. Trennung, dann nur trennen, wenn im ParaFmt
1459 //	 automatische Trennung eingestellt ist.
1460 
1461 sal_Bool SwTxtFormatInfo::IsHyphenate() const
1462 {
1463 	if( !bInterHyph && !bAutoHyph )
1464 		return sal_False;
1465 
1466 	LanguageType eTmp = GetFont()->GetLanguage();
1467 	if( LANGUAGE_DONTKNOW == eTmp || LANGUAGE_NONE == eTmp )
1468 		return sal_False;
1469 
1470 	uno::Reference< XHyphenator > xHyph = ::GetHyphenator();
1471 	if (bInterHyph && xHyph.is())
1472 		SvxSpellWrapper::CheckHyphLang( xHyph, eTmp );
1473 
1474 	if( !xHyph.is() || !xHyph->hasLocale( pBreakIt->GetLocale(eTmp) ) )
1475 		return sal_False;
1476 	return sal_True;
1477 }
1478 
1479 /*************************************************************************
1480  *					SwTxtFormatInfo::GetDropFmt()
1481  *************************************************************************/
1482 
1483 // Dropcaps vom SwTxtFormatter::CTOR gerufen.
1484 const SwFmtDrop *SwTxtFormatInfo::GetDropFmt() const
1485 {
1486 	const SwFmtDrop *pDrop = &GetTxtFrm()->GetTxtNode()->GetSwAttrSet().GetDrop();
1487 	if( 1 >= pDrop->GetLines() ||
1488 		( !pDrop->GetChars() && !pDrop->GetWholeWord() ) )
1489 		pDrop = 0;
1490 	return pDrop;
1491 }
1492 
1493 /*************************************************************************
1494  *						SwTxtFormatInfo::Init()
1495  *************************************************************************/
1496 
1497 void SwTxtFormatInfo::Init()
1498 {
1499 	// Nicht initialisieren: pRest, nLeft, nRight, nFirst, nRealWidth
1500 	X(0);
1501 	bArrowDone = bFull = bFtnDone = bErgoDone = bNumDone = bNoEndHyph =
1502 		bNoMidHyph = bStop = bNewLine = bUnderFlow = sal_False;
1503 
1504     // generally we do not allow number portions in follows, except...
1505     if ( GetTxtFrm()->IsFollow() )
1506     {
1507         const SwTxtFrm* pMaster = GetTxtFrm()->FindMaster();
1508         const SwLinePortion* pTmpPara = pMaster->GetPara();
1509 
1510         // there is a master for this follow and the master does not have
1511         // any contents (especially it does not have a number portion)
1512         bNumDone = ! pTmpPara ||
1513                    ! ((SwParaPortion*)pTmpPara)->GetFirstPortion()->IsFlyPortion();
1514     }
1515 
1516 	pRoot = 0;
1517 	pLast = 0;
1518 	pFly = 0;
1519 	pLastFld = 0;
1520 	pLastTab = 0;
1521 	pUnderFlow = 0;
1522 	cTabDecimal = 0;
1523 	nWidth = nRealWidth;
1524 	nForcedLeftMargin = 0;
1525 	nSoftHyphPos = 0;
1526     nUnderScorePos = STRING_LEN;
1527 	cHookChar = 0;
1528 	SetIdx(0);
1529 	SetLen( GetTxt().Len() );
1530 	SetPaintOfst(0);
1531 }
1532 
1533 /*-----------------16.10.00 11:39-------------------
1534  * There are a few differences between a copy constructor
1535  * and the following constructor for multi-line formatting.
1536  * The root is the first line inside the multi-portion,
1537  * the line start is the actual position in the text,
1538  * the line width is the rest width from the surrounding line
1539  * and the bMulti and bFirstMulti-flag has to be set correctly.
1540  * --------------------------------------------------*/
1541 
1542 SwTxtFormatInfo::SwTxtFormatInfo( const SwTxtFormatInfo& rInf,
1543 	SwLineLayout& rLay, SwTwips nActWidth ) : SwTxtPaintInfo( rInf )
1544 {
1545 	pRoot = &rLay;
1546 	pLast = &rLay;
1547 	pFly = NULL;
1548 	pLastFld = NULL;
1549 	pUnderFlow = NULL;
1550 	pRest = NULL;
1551 	pLastTab = NULL;
1552 
1553 	nSoftHyphPos = 0;
1554     nUnderScorePos = STRING_LEN;
1555     nHyphStart = 0;
1556 	nHyphWrdStart = 0;
1557 	nHyphWrdLen = 0;
1558 	nLineStart = rInf.GetIdx();
1559 	nLeft = rInf.nLeft;
1560 	nRight = rInf.nRight;
1561 	nFirst = rInf.nLeft;
1562 	nRealWidth = KSHORT(nActWidth);
1563 	nWidth = nRealWidth;
1564 	nLineHeight = 0;
1565     nLineNettoHeight = 0;
1566 	nForcedLeftMargin = 0;
1567 
1568 	nMinLeading = 0;
1569 	nMinTrailing = 0;
1570 	nMinWordLength = 0;
1571 	bFull = sal_False;
1572 	bFtnDone = sal_True;
1573 	bErgoDone = sal_True;
1574 	bNumDone = sal_True;
1575     bArrowDone = sal_True;
1576     bStop = sal_False;
1577 	bNewLine = sal_True;
1578 	bShift	= sal_False;
1579 	bUnderFlow = sal_False;
1580 	bInterHyph = sal_False;
1581 	bAutoHyph = sal_False;
1582 	bDropInit = sal_False;
1583 	bQuick	= rInf.bQuick;
1584 	bNoEndHyph	= sal_False;
1585 	bNoMidHyph	= sal_False;
1586 	bIgnoreFly = sal_False;
1587     bFakeLineStart = sal_False;
1588 
1589 	cTabDecimal = 0;
1590 	cHookChar = 0;
1591 	nMaxHyph = 0;
1592 	bTestFormat = rInf.bTestFormat;
1593 	SetMulti( sal_True );
1594     SetFirstMulti( rInf.IsFirstMulti() );
1595 }
1596 
1597 /*************************************************************************
1598  *				   SwTxtFormatInfo::_CheckFtnPortion()
1599  *************************************************************************/
1600 
1601 sal_Bool SwTxtFormatInfo::_CheckFtnPortion( SwLineLayout* pCurr )
1602 {
1603 	KSHORT nHeight = pCurr->GetRealHeight();
1604 	SwLinePortion *pPor = pCurr->GetPortion();
1605 	sal_Bool bRet = sal_False;
1606 	while( pPor )
1607 	{
1608 		if( pPor->IsFtnPortion() && nHeight > ((SwFtnPortion*)pPor)->Orig() )
1609 		{
1610 			bRet = sal_True;
1611 			SetLineHeight( nHeight );
1612             SetLineNettoHeight( pCurr->Height() );
1613 			break;
1614 		}
1615 		pPor = pPor->GetPortion();
1616 	}
1617 	return bRet;
1618 }
1619 
1620 
1621 
1622 
1623 /*************************************************************************
1624  *				   SwTxtFormatInfo::ScanPortionEnd()
1625  *************************************************************************/
1626 xub_StrLen SwTxtFormatInfo::ScanPortionEnd( const xub_StrLen nStart,
1627                                             const xub_StrLen nEnd )
1628 {
1629 	cHookChar = 0;
1630     xub_StrLen i = nStart;
1631 
1632     //
1633     // Used for decimal tab handling:
1634     //
1635     const xub_Unicode cTabDec = GetLastTab() ? (sal_Unicode)GetTabDecimal() : 0;
1636     const xub_Unicode cThousandSep  = ',' == cTabDec ? '.' : ',';
1637     // --> FME 2006-01-23 #i45951# German (Switzerland) uses ' as thousand separator:
1638     const xub_Unicode cThousandSep2 = ',' == cTabDec ? '.' : '\'';
1639     // <--
1640 
1641     bool bNumFound = false;
1642     const bool bTabCompat = GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
1643 
1644     // Removed for i7288. bSkip used to be passed from SwFldPortion::Format
1645     // as IsFollow(). Therefore more than one special character was not
1646     // handled correctly at the beginning of follow fields.
1647 //    if ( bSkip && i < nEnd )
1648 //       ++i;
1649 
1650 	for( ; i < nEnd; ++i )
1651 	{
1652 		const xub_Unicode cPos = GetChar( i );
1653 		switch( cPos )
1654 		{
1655 		case CH_TXTATR_BREAKWORD:
1656 		case CH_TXTATR_INWORD:
1657 			if( !HasHint( i ))
1658 				break;
1659 			// no break;
1660 
1661 		case CHAR_SOFTHYPHEN:
1662 		case CHAR_HARDHYPHEN:
1663 		case CHAR_HARDBLANK:
1664 		case CH_TAB:
1665 		case CH_BREAK:
1666         case CHAR_ZWSP :
1667         case CHAR_ZWNBSP :
1668 //        case CHAR_RLM :
1669 //        case CHAR_LRM :
1670 			cHookChar = cPos;
1671 			return i;
1672 
1673         case CHAR_UNDERSCORE:
1674             if ( STRING_LEN == nUnderScorePos )
1675                 nUnderScorePos = i;
1676             break;
1677 
1678         default:
1679             if ( cTabDec )
1680             {
1681 			    if( cTabDec == cPos )
1682 			    {
1683     				ASSERT( cPos, "Unexpected end of string" );
1684 				    if( cPos ) // robust
1685 				    {
1686     					cHookChar = cPos;
1687 					    return i;
1688 				    }
1689 			    }
1690 
1691                 //
1692                 // Compatibility: First non-digit character behind a
1693                 // a digit character becomes the hook character
1694                 //
1695                 if ( bTabCompat )
1696                 {
1697                     if ( ( 0x2F < cPos && cPos < 0x3A ) ||
1698                          ( bNumFound && ( cPos == cThousandSep || cPos == cThousandSep2 ) ) )
1699                     {
1700                         bNumFound = true;
1701                     }
1702                     else
1703                     {
1704                         if ( bNumFound )
1705                         {
1706     				    	cHookChar = cPos;
1707                             SetTabDecimal( cPos );
1708     					    return i;
1709                         }
1710                     }
1711 		        }
1712             }
1713         }
1714 	}
1715 
1716     // --> FME 2006-01-13 #130210# Check if character *behind* the portion has
1717     // to become the hook:
1718     if ( i == nEnd && i < GetTxt().Len() && bNumFound )
1719     {
1720 		const xub_Unicode cPos = GetChar( i );
1721         if ( cPos != cTabDec && cPos != cThousandSep && cPos !=cThousandSep2 && ( 0x2F >= cPos || cPos >= 0x3A ) )
1722         {
1723             cHookChar = GetChar( i );
1724             SetTabDecimal( cHookChar );
1725         }
1726     }
1727 
1728 	return i;
1729 }
1730 
1731 sal_Bool SwTxtFormatInfo::LastKernPortion()
1732 {
1733 	if( GetLast() )
1734 	{
1735 	 	if( GetLast()->IsKernPortion() )
1736 			return sal_True;
1737 		if( GetLast()->Width() || ( GetLast()->GetLen() &&
1738 			!GetLast()->IsHolePortion() ) )
1739 			return sal_False;
1740 	}
1741 	SwLinePortion* pPor = GetRoot();
1742 	SwLinePortion *pKern = NULL;
1743 	while( pPor )
1744 	{
1745 		if( pPor->IsKernPortion() )
1746 			pKern = pPor;
1747 		else if( pPor->Width() || ( pPor->GetLen() && !pPor->IsHolePortion() ) )
1748 			pKern = NULL;
1749 		pPor = pPor->GetPortion();
1750 	}
1751 	if( pKern )
1752 	{
1753 		SetLast( pKern );
1754 		return sal_True;
1755 	}
1756 	return sal_False;
1757 }
1758 
1759 /*************************************************************************
1760  *                      class SwTxtSlot
1761  *************************************************************************/
1762 
1763 SwTxtSlot::SwTxtSlot(
1764     const SwTxtSizeInfo *pNew,
1765     const SwLinePortion *pPor,
1766     bool bTxtLen,
1767     bool bExgLists,
1768     const sal_Char *pCh )
1769     : pOldTxt( 0 ),
1770       pOldSmartTagList( 0 ),
1771       pOldGrammarCheckList( 0 ),
1772       pTempList( 0 )
1773 {
1774 	if( pCh )
1775 	{
1776 		aTxt = XubString( pCh, RTL_TEXTENCODING_MS_1252 );
1777 		bOn = sal_True;
1778 	}
1779 	else
1780 		bOn = pPor->GetExpTxt( *pNew, aTxt );
1781 
1782 	// Der Text wird ausgetauscht...
1783 	if( bOn )
1784 	{
1785 		pInf = (SwTxtSizeInfo*)pNew;
1786 		nIdx = pInf->GetIdx();
1787 		nLen = pInf->GetLen();
1788 		pOldTxt = &(pInf->GetTxt());
1789 		pInf->SetTxt( aTxt );
1790 		pInf->SetIdx( 0 );
1791         pInf->SetLen( bTxtLen ? pInf->GetTxt().Len() : pPor->GetLen() );
1792 
1793         // ST2
1794         if ( bExgLists )
1795         {
1796             pOldSmartTagList = static_cast<SwTxtPaintInfo*>(pInf)->GetSmartTags();
1797             if ( pOldSmartTagList )
1798             {
1799                 const sal_uInt16 nPos = pOldSmartTagList->GetWrongPos(nIdx);
1800                 const xub_StrLen nListPos = pOldSmartTagList->Pos(nPos);
1801                 if( nListPos == nIdx )
1802                     ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList->SubList( nPos ) );
1803                 else if( !pTempList && nPos < pOldSmartTagList->Count() && nListPos < nIdx && aTxt.Len() )
1804                 {
1805                     pTempList = new SwWrongList( WRONGLIST_SMARTTAG );
1806                     pTempList->Insert( rtl::OUString(), 0, 0, aTxt.Len(), 0 );
1807                     ((SwTxtPaintInfo*)pInf)->SetSmartTags( pTempList );
1808                 }
1809                 else
1810                     ((SwTxtPaintInfo*)pInf)->SetSmartTags( 0);
1811             }
1812             pOldGrammarCheckList = static_cast<SwTxtPaintInfo*>(pInf)->GetGrammarCheckList();
1813             if ( pOldGrammarCheckList )
1814             {
1815                 const sal_uInt16 nPos = pOldGrammarCheckList->GetWrongPos(nIdx);
1816                 const xub_StrLen nListPos = pOldGrammarCheckList->Pos(nPos);
1817                 if( nListPos == nIdx )
1818                     ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList->SubList( nPos ) );
1819                 else if( !pTempList && nPos < pOldGrammarCheckList->Count() && nListPos < nIdx && aTxt.Len() )
1820                 {
1821                     pTempList = new SwWrongList( WRONGLIST_GRAMMAR );
1822                     pTempList->Insert( rtl::OUString(), 0, 0, aTxt.Len(), 0 );
1823                     ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pTempList );
1824                 }
1825                 else
1826                     ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( 0);
1827             }
1828         }
1829     }
1830 }
1831 
1832 /*************************************************************************
1833  *                       SwTxtSlot::~SwTxtSlot()
1834  *************************************************************************/
1835 
1836 SwTxtSlot::~SwTxtSlot()
1837 {
1838 	if( bOn )
1839 	{
1840 		pInf->SetTxt( *pOldTxt );
1841 		pInf->SetIdx( nIdx );
1842 		pInf->SetLen( nLen );
1843 
1844         // ST2
1845         // Restore old smart tag list
1846         if ( pOldSmartTagList )
1847             ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList );
1848         if ( pOldGrammarCheckList )
1849             ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList );
1850         delete pTempList;
1851     }
1852 }
1853 
1854 /*************************************************************************
1855  *					   SwFontSave::SwFontSave()
1856  *************************************************************************/
1857 
1858 SwFontSave::SwFontSave( const SwTxtSizeInfo &rInf, SwFont *pNew,
1859 		SwAttrIter* pItr )
1860 		: pFnt( pNew ? ((SwTxtSizeInfo&)rInf).GetFont() : 0 )
1861 {
1862 	if( pFnt )
1863 	{
1864 		pInf = &((SwTxtSizeInfo&)rInf);
1865         // In these cases we temporarily switch to the new font:
1866         // 1. the fonts have a different magic number
1867         // 2. they have different script types
1868         // 3. their background colors differ (this is not covered by 1.)
1869 		if( pFnt->DifferentMagic( pNew, pFnt->GetActual() ) ||
1870             pNew->GetActual() != pFnt->GetActual() ||
1871             ( ! pNew->GetBackColor() && pFnt->GetBackColor() ) ||
1872             ( pNew->GetBackColor() && ! pFnt->GetBackColor() ) ||
1873             ( pNew->GetBackColor() && pFnt->GetBackColor() &&
1874               ( *pNew->GetBackColor() != *pFnt->GetBackColor() ) ) )
1875 		{
1876 			pNew->SetTransparent( sal_True );
1877 			pNew->SetAlign( ALIGN_BASELINE );
1878 			pInf->SetFont( pNew );
1879 		}
1880 		else
1881 			pFnt = 0;
1882 		pNew->Invalidate();
1883         pNew->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
1884 		if( pItr && pItr->GetFnt() == pFnt )
1885 		{
1886 			pIter = pItr;
1887 			pIter->SetFnt( pNew );
1888 		}
1889 		else
1890 			pIter = NULL;
1891 	}
1892 }
1893 
1894 /*************************************************************************
1895  *					   SwFontSave::~SwFontSave()
1896  *************************************************************************/
1897 
1898 SwFontSave::~SwFontSave()
1899 {
1900 	if( pFnt )
1901 	{
1902 		// SwFont zurueckstellen
1903 		pFnt->Invalidate();
1904 		pInf->SetFont( pFnt );
1905 		if( pIter )
1906 		{
1907 			pIter->SetFnt( pFnt );
1908 			pIter->nPos = STRING_LEN;
1909 		}
1910 	}
1911 }
1912 
1913 /*************************************************************************
1914  *					   SwDefFontSave::SwDefFontSave()
1915  *************************************************************************/
1916 
1917 SwDefFontSave::SwDefFontSave( const SwTxtSizeInfo &rInf )
1918 		: pFnt( ((SwTxtSizeInfo&)rInf).GetFont()  )
1919 {
1920     const sal_Bool bTmpAlter = pFnt->GetFixKerning() ||
1921 		 ( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet(pFnt->GetActual()) )
1922 		;
1923 
1924     const sal_Bool bFamily = bTmpAlter &&
1925           pFnt->GetName( pFnt->GetActual() ) != numfunc::GetDefBulletFontname();
1926     const sal_Bool bRotation = (sal_Bool)pFnt->GetOrientation() &&
1927                                 ! rInf.GetTxtFrm()->IsVertical();
1928 
1929     if( bFamily || bRotation )
1930 	{
1931 		pNewFnt = new SwFont( *pFnt );
1932 
1933         if ( bFamily )
1934         {
1935             pNewFnt->SetFamily( FAMILY_DONTKNOW, pFnt->GetActual() );
1936             pNewFnt->SetName( numfunc::GetDefBulletFontname(), pFnt->GetActual() );
1937             pNewFnt->SetStyleName( aEmptyStr, pFnt->GetActual() );
1938             pNewFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, pFnt->GetActual() );
1939             pNewFnt->SetFixKerning( 0 );
1940         }
1941 
1942         if ( bRotation )
1943             pNewFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
1944 
1945         pInf = &((SwTxtSizeInfo&)rInf);
1946 		pNewFnt->Invalidate();
1947 		pInf->SetFont( pNewFnt );
1948 	}
1949 	else
1950 	{
1951 		pFnt = 0;
1952 		pNewFnt = 0;
1953 	}
1954 }
1955 
1956 /*************************************************************************
1957  *					   SwDefFontSave::~SwDefFontSave()
1958  *************************************************************************/
1959 
1960 SwDefFontSave::~SwDefFontSave()
1961 {
1962 	if( pFnt )
1963 	{
1964 		delete pNewFnt;
1965 		// SwFont zurueckstellen
1966 		pFnt->Invalidate();
1967 		pInf->SetFont( pFnt );
1968 	}
1969 }
1970 
1971 /*************************************************************************
1972  *					SwTxtFormatInfo::ChgHyph()
1973  *************************************************************************/
1974 
1975 sal_Bool SwTxtFormatInfo::ChgHyph( const sal_Bool bNew )
1976 {
1977 	const sal_Bool bOld = bAutoHyph;
1978 	if( bAutoHyph != bNew )
1979 	{
1980 		bAutoHyph = bNew;
1981 		InitHyph( bNew );
1982 		// 5744: Sprache am Hyphenator einstellen.
1983 		if( pFnt )
1984             pFnt->ChgPhysFnt( pVsh, *pOut );
1985 	}
1986 	return bOld;
1987 }
1988 
1989 
1990