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