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