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