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