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