Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <com/sun/star/uno/Sequence.h>
21 : #include <unotools/linguprops.hxx>
22 : #include <unotools/lingucfg.hxx>
23 : #include <hintids.hxx>
24 : #include <sfx2/printer.hxx>
25 : #include <editeng/hyphenzoneitem.hxx>
26 : #include <editeng/escapementitem.hxx>
27 : #include <editeng/hngpnctitem.hxx>
28 : #include <editeng/scriptspaceitem.hxx>
29 : #include <editeng/brushitem.hxx>
30 : #include <editeng/splwrap.hxx>
31 : #include <editeng/pgrditem.hxx>
32 : #include <editeng/tstpitem.hxx>
33 : #include <editeng/shaditem.hxx>
34 :
35 : #include <SwSmartTagMgr.hxx>
36 : #include <linguistic/lngprops.hxx>
37 : #include <editeng/unolingu.hxx>
38 : #include <breakit.hxx>
39 : #include <editeng/forbiddenruleitem.hxx>
40 : #include <txatbase.hxx>
41 : #include <fmtinfmt.hxx>
42 : #include <swmodule.hxx>
43 : #include <vcl/svapp.hxx>
44 : #include <vcl/wrkwin.hxx>
45 : #include <viewsh.hxx>
46 : #include <viewopt.hxx>
47 : #include <frmtool.hxx>
48 : #include <IDocumentSettingAccess.hxx>
49 : #include <IDocumentDeviceAccess.hxx>
50 : #include <paratr.hxx>
51 : #include <rootfrm.hxx>
52 : #include <inftxt.hxx>
53 : #include <blink.hxx>
54 : #include <noteurl.hxx>
55 : #include <porftn.hxx>
56 : #include <porrst.hxx>
57 : #include <itratr.hxx>
58 : #include <accessibilityoptions.hxx>
59 : #include <wrong.hxx>
60 : #include <doc.hxx>
61 : #include <pam.hxx>
62 : #include <SwGrammarMarkUp.hxx>
63 : #include "numrule.hxx"
64 : #include <EnhancedPDFExportHelper.hxx>
65 : #include <docufld.hxx>
66 :
67 : //UUUU
68 : #include <frmfmt.hxx>
69 :
70 : #include <unomid.h>
71 :
72 : #if OSL_DEBUG_LEVEL > 1
73 : #include <stdio.h>
74 : #endif
75 :
76 : using namespace ::com::sun::star;
77 : using namespace ::com::sun::star::linguistic2;
78 : using namespace ::com::sun::star::uno;
79 : using namespace ::com::sun::star::beans;
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 : #ifdef DBG_UTIL
93 : bool SwTxtSizeInfo::IsOptDbg() const { return GetOpt().IsTest4(); }
94 : #endif
95 :
96 318182 : SwLineInfo::SwLineInfo()
97 : : pRuler( 0 ),
98 : pSpace( 0 ),
99 : nVertAlign( 0 ),
100 : nDefTabStop( 0 ),
101 : bListTabStopIncluded( false ),
102 318182 : nListTabStopPosition( 0 )
103 : {
104 318182 : }
105 :
106 318182 : SwLineInfo::~SwLineInfo()
107 : {
108 318182 : delete pRuler;
109 318182 : }
110 318182 : void SwLineInfo::CtorInitLineInfo( const SwAttrSet& rAttrSet,
111 : const SwTxtNode& rTxtNode )
112 : {
113 318182 : delete pRuler;
114 318182 : pRuler = new SvxTabStopItem( rAttrSet.GetTabStops() );
115 318182 : if ( rTxtNode.GetListTabStopPosition( nListTabStopPosition ) )
116 : {
117 12310 : bListTabStopIncluded = true;
118 :
119 : // insert the list tab stop into SvxTabItem instance <pRuler>
120 : const SvxTabStop aListTabStop( nListTabStopPosition,
121 12310 : SVX_TAB_ADJUST_LEFT );
122 12310 : pRuler->Insert( aListTabStop );
123 :
124 : // remove default tab stops, which are before the inserted list tab stop
125 39392 : for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
126 : {
127 27544 : if ( (*pRuler)[i].GetTabPos() < nListTabStopPosition &&
128 462 : (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
129 : {
130 150 : pRuler->Remove(i);
131 150 : continue;
132 : }
133 : }
134 : }
135 :
136 318182 : if ( !rTxtNode.getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
137 : {
138 : // remove default tab stop at position 0
139 492380 : for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
140 : {
141 281342 : if ( (*pRuler)[i].GetTabPos() == 0 &&
142 9874 : (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
143 : {
144 0 : pRuler->Remove(i);
145 0 : break;
146 : }
147 : }
148 : }
149 :
150 318182 : pSpace = &rAttrSet.GetLineSpacing();
151 318182 : nVertAlign = rAttrSet.GetParaVertAlign().GetValue();
152 318182 : nDefTabStop = USHRT_MAX;
153 318182 : }
154 :
155 318182 : void SwTxtInfo::CtorInitTxtInfo( SwTxtFrm *pFrm )
156 : {
157 318182 : m_pPara = pFrm->GetPara();
158 318182 : m_nTxtStart = pFrm->GetOfst();
159 318182 : if (!m_pPara)
160 : {
161 : SAL_WARN("sw.core", "+SwTxtInfo::CTOR: missing paragraph information");
162 0 : pFrm->Format();
163 0 : m_pPara = pFrm->GetPara();
164 : }
165 318182 : }
166 :
167 224728 : SwTxtInfo::SwTxtInfo( const SwTxtInfo &rInf )
168 224728 : : m_pPara( const_cast<SwTxtInfo&>(rInf).GetParaPortion() )
169 224728 : , m_nTxtStart( rInf.GetTxtStart() )
170 224728 : { }
171 :
172 : #if OSL_DEBUG_LEVEL > 0
173 :
174 : void ChkOutDev( const SwTxtSizeInfo &rInf )
175 : {
176 : if ( !rInf.GetVsh() )
177 : return;
178 :
179 : const OutputDevice* pOut = rInf.GetOut();
180 : const OutputDevice* pRef = rInf.GetRefDev();
181 : OSL_ENSURE( pOut && pRef, "ChkOutDev: invalid output devices" );
182 : }
183 : #endif
184 :
185 436989 : inline sal_Int32 GetMinLen( const SwTxtSizeInfo &rInf )
186 : {
187 436989 : const sal_Int32 nTxtLen = rInf.GetTxt().getLength();
188 436989 : if (rInf.GetLen() == COMPLETE_STRING)
189 436989 : return nTxtLen;
190 0 : const sal_Int32 nInfLen = rInf.GetIdx() + rInf.GetLen();
191 0 : return std::min(nTxtLen, nInfLen);
192 : }
193 :
194 105677 : SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew )
195 : : SwTxtInfo( rNew ),
196 105677 : m_pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()),
197 105677 : m_pVsh(((SwTxtSizeInfo&)rNew).GetVsh()),
198 105677 : m_pOut(((SwTxtSizeInfo&)rNew).GetOut()),
199 105677 : m_pRef(((SwTxtSizeInfo&)rNew).GetRefDev()),
200 105677 : m_pFnt(((SwTxtSizeInfo&)rNew).GetFont()),
201 105677 : m_pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()),
202 : m_pFrm(rNew.m_pFrm),
203 105677 : m_pOpt(&rNew.GetOpt()),
204 105677 : m_pTxt(&rNew.GetTxt()),
205 105677 : m_nIdx(rNew.GetIdx()),
206 105677 : m_nLen(rNew.GetLen()),
207 105677 : m_nKanaIdx( rNew.GetKanaIdx() ),
208 105677 : m_bOnWin( rNew.OnWin() ),
209 105677 : m_bNotEOL( rNew.NotEOL() ),
210 105677 : m_bURLNotify( rNew.URLNotify() ),
211 105677 : m_bStopUnderflow( rNew.StopUnderflow() ),
212 105677 : m_bFtnInside( rNew.IsFtnInside() ),
213 105677 : m_bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ),
214 105677 : m_bMulti( rNew.IsMulti() ),
215 105677 : m_bFirstMulti( rNew.IsFirstMulti() ),
216 105677 : m_bRuby( rNew.IsRuby() ),
217 105677 : m_bHanging( rNew.IsHanging() ),
218 105677 : m_bScriptSpace( rNew.HasScriptSpace() ),
219 105677 : m_bForbiddenChars( rNew.HasForbiddenChars() ),
220 105677 : m_bSnapToGrid( rNew.SnapToGrid() ),
221 2641925 : m_nDirection( rNew.GetDirection() )
222 : {
223 : #if OSL_DEBUG_LEVEL > 0
224 : ChkOutDev( *this );
225 : #endif
226 105677 : }
227 :
228 317938 : void SwTxtSizeInfo::CtorInitTxtSizeInfo( SwTxtFrm *pFrame, SwFont *pNewFnt,
229 : const sal_Int32 nNewIdx, const sal_Int32 nNewLen )
230 : {
231 317938 : m_pKanaComp = NULL;
232 317938 : m_nKanaIdx = 0;
233 317938 : m_pFrm = pFrame;
234 317938 : CtorInitTxtInfo( m_pFrm );
235 317938 : const SwTxtNode *pNd = m_pFrm->GetTxtNode();
236 317938 : m_pVsh = m_pFrm->getRootFrm()->GetCurrShell();
237 :
238 : // Get the output and reference device
239 317938 : if ( m_pVsh )
240 : {
241 317938 : m_pOut = m_pVsh->GetOut();
242 317938 : m_pRef = &m_pVsh->GetRefDev();
243 317938 : m_bOnWin = m_pVsh->GetWin() || OUTDEV_WINDOW == m_pOut->GetOutDevType();
244 : }
245 : else
246 : {
247 : // Access via StarONE. We do not need a Shell or an active one.
248 0 : if ( pNd->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) )
249 : {
250 : // We can only pick the AppWin here? (there's nothing better to pick?)
251 0 : m_pOut = Application::GetDefaultDevice();
252 : }
253 : else
254 0 : m_pOut = pNd->getIDocumentDeviceAccess()->getPrinter( false );
255 :
256 0 : m_pRef = m_pOut;
257 : }
258 :
259 : #if OSL_DEBUG_LEVEL > 0
260 : ChkOutDev( *this );
261 : #endif
262 :
263 : // Set default layout mode ( LTR or RTL ).
264 317938 : if ( m_pFrm->IsRightToLeft() )
265 : {
266 388 : m_pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
267 388 : m_pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
268 388 : m_nDirection = DIR_RIGHT2LEFT;
269 : }
270 : else
271 : {
272 317550 : m_pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
273 317550 : m_pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
274 317550 : m_nDirection = DIR_LEFT2RIGHT;
275 : }
276 :
277 : // The Options
278 :
279 : m_pOpt = m_pVsh ?
280 317938 : m_pVsh->GetViewOptions() :
281 635876 : SW_MOD()->GetViewOption( pNd->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) ); // Options from Module, due to StarONE
282 :
283 : // bURLNotify is set if MakeGraphic prepares it
284 : // TODO: Unwind
285 317938 : m_bURLNotify = pNoteURL && !m_bOnWin;
286 :
287 635736 : SetSnapToGrid( pNd->GetSwAttrSet().GetParaGrid().GetValue() &&
288 635736 : m_pFrm->IsInDocBody() );
289 :
290 317938 : m_pFnt = pNewFnt;
291 317938 : m_pUnderFnt = 0;
292 317938 : m_pTxt = &pNd->GetTxt();
293 :
294 317938 : m_nIdx = nNewIdx;
295 317938 : m_nLen = nNewLen;
296 317938 : m_bNotEOL = false;
297 317938 : m_bStopUnderflow = m_bFtnInside = m_bOtherThanFtnInside = false;
298 : m_bMulti = m_bFirstMulti = m_bRuby = m_bHanging = m_bScriptSpace =
299 317938 : m_bForbiddenChars = false;
300 :
301 317938 : SetLen( GetMinLen( *this ) );
302 317938 : }
303 :
304 119051 : SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew, const OUString* pTxt,
305 : const sal_Int32 nIndex, const sal_Int32 nLength )
306 : : SwTxtInfo( rNew ),
307 119051 : m_pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()),
308 119051 : m_pVsh(((SwTxtSizeInfo&)rNew).GetVsh()),
309 119051 : m_pOut(((SwTxtSizeInfo&)rNew).GetOut()),
310 119051 : m_pRef(((SwTxtSizeInfo&)rNew).GetRefDev()),
311 119051 : m_pFnt(((SwTxtSizeInfo&)rNew).GetFont()),
312 119051 : m_pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()),
313 : m_pFrm( rNew.m_pFrm ),
314 119051 : m_pOpt(&rNew.GetOpt()),
315 : m_pTxt(pTxt),
316 : m_nIdx(nIndex),
317 : m_nLen(nLength),
318 119051 : m_nKanaIdx( rNew.GetKanaIdx() ),
319 119051 : m_bOnWin( rNew.OnWin() ),
320 119051 : m_bNotEOL( rNew.NotEOL() ),
321 119051 : m_bURLNotify( rNew.URLNotify() ),
322 119051 : m_bStopUnderflow( rNew.StopUnderflow() ),
323 119051 : m_bFtnInside( rNew.IsFtnInside() ),
324 119051 : m_bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ),
325 119051 : m_bMulti( rNew.IsMulti() ),
326 119051 : m_bFirstMulti( rNew.IsFirstMulti() ),
327 119051 : m_bRuby( rNew.IsRuby() ),
328 119051 : m_bHanging( rNew.IsHanging() ),
329 119051 : m_bScriptSpace( rNew.HasScriptSpace() ),
330 119051 : m_bForbiddenChars( rNew.HasForbiddenChars() ),
331 119051 : m_bSnapToGrid( rNew.SnapToGrid() ),
332 2619122 : m_nDirection( rNew.GetDirection() )
333 : {
334 : #if OSL_DEBUG_LEVEL > 0
335 : ChkOutDev( *this );
336 : #endif
337 119051 : SetLen( GetMinLen( *this ) );
338 119051 : }
339 :
340 2752 : void SwTxtSizeInfo::SelectFont()
341 : {
342 : // The path needs to go via ChgPhysFnt or the FontMetricCache gets confused.
343 : // In this case pLastMet has it's old value.
344 : // Wrong: GetOut()->SetFont( GetFont()->GetFnt() );
345 2752 : GetFont()->Invalidate();
346 2752 : GetFont()->ChgPhysFnt( m_pVsh, *GetOut() );
347 2752 : }
348 :
349 0 : void SwTxtSizeInfo::NoteAnimation() const
350 : {
351 0 : if( OnWin() )
352 0 : SwRootFrm::FlushVout();
353 :
354 : OSL_ENSURE( m_pOut == m_pVsh->GetOut(),
355 : "SwTxtSizeInfo::NoteAnimation() changed m_pOut" );
356 0 : }
357 :
358 1210 : SwPosSize SwTxtSizeInfo::GetTxtSize( OutputDevice* pOutDev,
359 : const SwScriptInfo* pSI,
360 : const OUString& rTxt,
361 : const sal_Int32 nIndex,
362 : const sal_Int32 nLength,
363 : const sal_uInt16 nComp ) const
364 : {
365 1210 : SwDrawTextInfo aDrawInf( m_pVsh, *pOutDev, pSI, rTxt, nIndex, nLength );
366 1210 : aDrawInf.SetFrm( m_pFrm );
367 1210 : aDrawInf.SetFont( m_pFnt );
368 1210 : aDrawInf.SetSnapToGrid( SnapToGrid() );
369 1210 : aDrawInf.SetKanaComp( nComp );
370 1210 : return m_pFnt->_GetTxtSize( aDrawInf );
371 : }
372 :
373 6395 : SwPosSize SwTxtSizeInfo::GetTxtSize() const
374 : {
375 : const SwScriptInfo& rSI =
376 6395 : ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
377 :
378 : // in some cases, compression is not allowed or suppressed for
379 : // performance reasons
380 6395 : sal_uInt16 nComp =( SW_CJK == GetFont()->GetActual() &&
381 0 : rSI.CountCompChg() &&
382 0 : ! IsMulti() ) ?
383 : GetKanaComp() :
384 6395 : 0 ;
385 :
386 6395 : SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rSI, *m_pTxt, m_nIdx, m_nLen );
387 6395 : aDrawInf.SetFrm( m_pFrm );
388 6395 : aDrawInf.SetFont( m_pFnt );
389 6395 : aDrawInf.SetSnapToGrid( SnapToGrid() );
390 6395 : aDrawInf.SetKanaComp( nComp );
391 6395 : return m_pFnt->_GetTxtSize( aDrawInf );
392 : }
393 :
394 155839 : void SwTxtSizeInfo::GetTxtSize( const SwScriptInfo* pSI, const sal_Int32 nIndex,
395 : const sal_Int32 nLength, const sal_uInt16 nComp,
396 : sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff ) const
397 : {
398 155839 : SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, pSI, *m_pTxt, nIndex, nLength );
399 155839 : aDrawInf.SetFrm( m_pFrm );
400 155839 : aDrawInf.SetFont( m_pFnt );
401 155839 : aDrawInf.SetSnapToGrid( SnapToGrid() );
402 155839 : aDrawInf.SetKanaComp( nComp );
403 155839 : SwPosSize aSize = m_pFnt->_GetTxtSize( aDrawInf );
404 155839 : nMaxSizeDiff = (sal_uInt16)aDrawInf.GetKanaDiff();
405 155839 : nMinSize = aSize.Width();
406 155839 : }
407 :
408 66609 : sal_Int32 SwTxtSizeInfo::GetTxtBreak( const long nLineWidth,
409 : const sal_Int32 nMaxLen,
410 : const sal_uInt16 nComp ) const
411 : {
412 : const SwScriptInfo& rScriptInfo =
413 66609 : ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
414 :
415 : OSL_ENSURE( m_pRef == m_pOut, "GetTxtBreak is supposed to use the RefDev" );
416 : SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rScriptInfo,
417 66609 : *m_pTxt, GetIdx(), nMaxLen );
418 66609 : aDrawInf.SetFrm( m_pFrm );
419 66609 : aDrawInf.SetFont( m_pFnt );
420 66609 : aDrawInf.SetSnapToGrid( SnapToGrid() );
421 66609 : aDrawInf.SetKanaComp( nComp );
422 66609 : aDrawInf.SetHyphPos( 0 );
423 :
424 66609 : return m_pFnt->GetTxtBreak( aDrawInf, nLineWidth );
425 : }
426 :
427 0 : sal_Int32 SwTxtSizeInfo::GetTxtBreak( const long nLineWidth,
428 : const sal_Int32 nMaxLen,
429 : const sal_uInt16 nComp,
430 : sal_Int32& rExtraCharPos ) const
431 : {
432 : const SwScriptInfo& rScriptInfo =
433 0 : ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
434 :
435 : OSL_ENSURE( m_pRef == m_pOut, "GetTxtBreak is supposed to use the RefDev" );
436 : SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rScriptInfo,
437 0 : *m_pTxt, GetIdx(), nMaxLen );
438 0 : aDrawInf.SetFrm( m_pFrm );
439 0 : aDrawInf.SetFont( m_pFnt );
440 0 : aDrawInf.SetSnapToGrid( SnapToGrid() );
441 0 : aDrawInf.SetKanaComp( nComp );
442 0 : aDrawInf.SetHyphPos( &rExtraCharPos );
443 :
444 0 : return m_pFnt->GetTxtBreak( aDrawInf, nLineWidth );
445 : }
446 :
447 11760 : bool SwTxtSizeInfo::_HasHint( const SwTxtNode* pTxtNode, sal_Int32 nPos )
448 : {
449 11760 : return pTxtNode->GetTxtAttrForCharAt(nPos);
450 : }
451 :
452 119602 : void SwTxtPaintInfo::CtorInitTxtPaintInfo( SwTxtFrm *pFrame, const SwRect &rPaint )
453 : {
454 119602 : CtorInitTxtSizeInfo( pFrame );
455 119602 : aTxtFly.CtorInitTxtFly( pFrame ),
456 119602 : aPaintRect = rPaint;
457 119602 : nSpaceIdx = 0;
458 119602 : pSpaceAdd = NULL;
459 119602 : pWrongList = NULL;
460 119602 : pGrammarCheckList = NULL;
461 119602 : pSmartTags = NULL;
462 :
463 : #if OSL_DEBUG_LEVEL > 1
464 : pBrushItem = ((SvxBrushItem*)-1);
465 : #else
466 119602 : pBrushItem = 0;
467 : #endif
468 119602 : }
469 :
470 0 : SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf, const OUString* pTxt )
471 : : SwTxtSizeInfo( rInf, pTxt ),
472 0 : pWrongList( rInf.GetpWrongList() ),
473 0 : pGrammarCheckList( rInf.GetGrammarCheckList() ),
474 0 : pSmartTags( rInf.GetSmartTags() ),
475 0 : pSpaceAdd( rInf.GetpSpaceAdd() ),
476 0 : pBrushItem( rInf.GetBrushItem() ),
477 0 : aTxtFly( rInf.GetTxtFly() ),
478 0 : aPos( rInf.GetPos() ),
479 0 : aPaintRect( rInf.GetPaintRect() ),
480 0 : nSpaceIdx( rInf.GetSpaceIdx() )
481 0 : { }
482 :
483 105677 : SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf )
484 : : SwTxtSizeInfo( rInf ),
485 105677 : pWrongList( rInf.GetpWrongList() ),
486 105677 : pGrammarCheckList( rInf.GetGrammarCheckList() ),
487 105677 : pSmartTags( rInf.GetSmartTags() ),
488 105677 : pSpaceAdd( rInf.GetpSpaceAdd() ),
489 105677 : pBrushItem( rInf.GetBrushItem() ),
490 105677 : aTxtFly( rInf.GetTxtFly() ),
491 105677 : aPos( rInf.GetPos() ),
492 105677 : aPaintRect( rInf.GetPaintRect() ),
493 951093 : nSpaceIdx( rInf.GetSpaceIdx() )
494 105677 : { }
495 :
496 : extern Color aGlobalRetoucheColor;
497 :
498 : /// Returns if the current background color is dark.
499 3114 : static bool lcl_IsDarkBackground( const SwTxtPaintInfo& rInf )
500 : {
501 3114 : const Color* pCol = rInf.GetFont()->GetBackColor();
502 3114 : if( ! pCol || COL_TRANSPARENT == pCol->GetColor() )
503 : {
504 : const SvxBrushItem* pItem;
505 3114 : SwRect aOrigBackRect;
506 :
507 : //UUUU
508 3114 : drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes;
509 :
510 : // Consider, that [GetBackgroundBrush(...)] can set <pCol>
511 : // See implementation in /core/layout/paintfrm.cxx
512 : // There is a background color, if there is a background brush and
513 : // its color is *not* "no fill"/"auto fill".
514 3114 : if( rInf.GetTxtFrm()->GetBackgroundBrush( aFillAttributes, pItem, pCol, aOrigBackRect, false ) )
515 : {
516 14 : if ( !pCol )
517 14 : pCol = &pItem->GetColor();
518 :
519 : // Determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
520 14 : if ( pCol->GetColor() == COL_TRANSPARENT)
521 6 : pCol = NULL;
522 : }
523 : else
524 3100 : pCol = NULL;
525 : }
526 :
527 3114 : if( !pCol )
528 3106 : pCol = &aGlobalRetoucheColor;
529 :
530 3114 : return pCol->IsDark();
531 : }
532 :
533 43941 : void SwTxtPaintInfo::_DrawText( const OUString &rText, const SwLinePortion &rPor,
534 : const sal_Int32 nStart, const sal_Int32 nLength,
535 : const bool bKern, const bool bWrong,
536 : const bool bSmartTag,
537 : const bool bGrammarCheck )
538 : {
539 43941 : if( !nLength )
540 108 : return;
541 :
542 43941 : if( GetFont()->IsBlink() && OnWin() && rPor.Width() )
543 : {
544 : // check if accessibility options allow blinking portions:
545 216 : const SwViewShell* pSh = GetTxtFrm()->getRootFrm()->GetCurrShell();
546 432 : if ( pSh && ! pSh->GetAccessibilityOptions()->IsStopAnimatedText() &&
547 216 : ! pSh->IsPreview() )
548 : {
549 216 : if( !pBlink )
550 2 : pBlink = new SwBlink();
551 :
552 216 : Point aPoint( aPos );
553 :
554 216 : if ( GetTxtFrm()->IsRightToLeft() )
555 0 : GetTxtFrm()->SwitchLTRtoRTL( aPoint );
556 :
557 216 : if ( TEXT_LAYOUT_BIDI_STRONG != GetOut()->GetLayoutMode() )
558 96 : aPoint.X() -= rPor.Width();
559 :
560 216 : if ( GetTxtFrm()->IsVertical() )
561 0 : GetTxtFrm()->SwitchHorizontalToVertical( aPoint );
562 :
563 216 : pBlink->Insert( aPoint, &rPor, GetTxtFrm(), m_pFnt->GetOrientation() );
564 :
565 216 : if( !pBlink->IsVisible() )
566 108 : return;
567 : }
568 : else
569 : {
570 0 : delete pBlink;
571 0 : pBlink = NULL;
572 : }
573 : }
574 :
575 : // The SwScriptInfo is useless if we are inside a field portion
576 43833 : SwScriptInfo* pSI = 0;
577 43833 : if ( ! rPor.InFldGrp() )
578 41105 : pSI = &GetParaPortion()->GetScriptInfo();
579 :
580 : // in some cases, kana compression is not allowed or suppressed for
581 : // performance reasons
582 43833 : sal_uInt16 nComp = 0;
583 43833 : if ( ! IsMulti() )
584 43833 : nComp = GetKanaComp();
585 :
586 43833 : bool bCfgIsAutoGrammar = false;
587 43833 : SvtLinguConfig().GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bCfgIsAutoGrammar;
588 43833 : const bool bBullet = OnWin() && GetOpt().IsBlank() && IsNoSymbol();
589 43833 : const bool bTmpWrong = bWrong && OnWin() && GetOpt().IsOnlineSpell();
590 43833 : const bool bTmpGrammarCheck = bGrammarCheck && OnWin() && bCfgIsAutoGrammar && GetOpt().IsOnlineSpell();
591 43833 : const bool bTmpSmart = bSmartTag && OnWin() && !GetOpt().IsPagePreview() && SwSmartTagMgr::Get().IsSmartTagsEnabled();
592 :
593 : OSL_ENSURE( GetParaPortion(), "No paragraph!");
594 43833 : SwDrawTextInfo aDrawInf( m_pFrm->getRootFrm()->GetCurrShell(), *m_pOut, pSI, rText, nStart, nLength,
595 87666 : rPor.Width(), bBullet );
596 :
597 43833 : aDrawInf.SetLeft( GetPaintRect().Left() );
598 43833 : aDrawInf.SetRight( GetPaintRect().Right());
599 :
600 43833 : aDrawInf.SetUnderFnt( m_pUnderFnt );
601 :
602 131371 : const long nSpaceAdd = ( rPor.IsBlankPortion() || rPor.IsDropPortion() ||
603 130713 : rPor.InNumberGrp() ) ? 0 : GetSpaceAdd();
604 43833 : if ( nSpaceAdd )
605 : {
606 1514 : sal_Int32 nCharCnt = 0;
607 : // #i41860# Thai justified alignment needs some
608 : // additional information:
609 1514 : aDrawInf.SetNumberOfBlanks( rPor.InTxtGrp() ?
610 1514 : static_cast<const SwTxtPortion&>(rPor).GetSpaceCnt( *this, nCharCnt ) :
611 3028 : 0 );
612 : }
613 :
614 43833 : aDrawInf.SetSpace( nSpaceAdd );
615 43833 : aDrawInf.SetKanaComp( nComp );
616 :
617 : // the font is used to identify the current script via nActual
618 43833 : aDrawInf.SetFont( m_pFnt );
619 : // the frame is used to identify the orientation
620 43833 : aDrawInf.SetFrm( GetTxtFrm() );
621 : // we have to know if the paragraph should snap to grid
622 43833 : aDrawInf.SetSnapToGrid( SnapToGrid() );
623 : // for underlining we must know when not to add extra space behind
624 : // a character in justified mode
625 53513 : aDrawInf.SetSpaceStop( ! rPor.GetPortion() ||
626 52343 : rPor.GetPortion()->InFixMargGrp() ||
627 52343 : rPor.GetPortion()->IsHolePortion() );
628 :
629 : // Draw text next to the left border
630 43833 : Point aFontPos(aPos);
631 43833 : if( m_pFnt->GetLeftBorder() && !static_cast<const SwTxtPortion&>(rPor).GetJoinBorderWithPrev() )
632 : {
633 16 : const sal_uInt16 nLeftBorderSpace = m_pFnt->GetLeftBorderSpace();
634 16 : if ( GetTxtFrm()->IsRightToLeft() )
635 : {
636 0 : aFontPos.X() -= nLeftBorderSpace;
637 : }
638 : else
639 : {
640 16 : switch( m_pFnt->GetOrientation(GetTxtFrm()->IsVertical()) )
641 : {
642 : case 0 :
643 16 : aFontPos.X() += nLeftBorderSpace;
644 16 : break;
645 : case 900 :
646 0 : aFontPos.Y() -= nLeftBorderSpace;
647 0 : break;
648 : case 1800 :
649 0 : aFontPos.X() -= nLeftBorderSpace;
650 0 : break;
651 : case 2700 :
652 0 : aFontPos.Y() += nLeftBorderSpace;
653 0 : break;
654 : }
655 : }
656 16 : if( aFontPos.X() < 0 )
657 0 : aFontPos.X() = 0;
658 16 : if( aFontPos.X() < 0 )
659 0 : aFontPos.X() = 0;
660 : }
661 :
662 43833 : if( GetTxtFly().IsOn() )
663 : {
664 : // aPos needs to be the TopLeft, because we cannot calculate the
665 : // ClipRects otherwise
666 459 : const Point aPoint( aFontPos.X(), aFontPos.Y() - rPor.GetAscent() );
667 459 : const Size aSize( rPor.Width(), rPor.Height() );
668 459 : aDrawInf.SetPos( aPoint );
669 459 : aDrawInf.SetSize( aSize );
670 459 : aDrawInf.SetAscent( rPor.GetAscent() );
671 459 : aDrawInf.SetKern( bKern ? rPor.Width() : 0 );
672 459 : aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
673 459 : aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
674 459 : aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL );
675 459 : GetTxtFly().DrawTextOpaque( aDrawInf );
676 : }
677 : else
678 : {
679 43374 : aDrawInf.SetPos( aFontPos );
680 43374 : if( bKern )
681 140 : m_pFnt->_DrawStretchText( aDrawInf );
682 : else
683 : {
684 43234 : aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
685 43234 : aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
686 43234 : aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL );
687 43234 : m_pFnt->_DrawText( aDrawInf );
688 : }
689 43833 : }
690 : }
691 :
692 136893 : void SwTxtPaintInfo::CalcRect( const SwLinePortion& rPor,
693 : SwRect* pRect, SwRect* pIntersect,
694 : const bool bInsideBox ) const
695 : {
696 136893 : Size aSize( rPor.Width(), rPor.Height() );
697 136893 : if( rPor.IsHangingPortion() )
698 0 : aSize.Width() = ((SwHangingPortion&)rPor).GetInnerWidth();
699 136893 : if( rPor.InSpaceGrp() && GetSpaceAdd() )
700 : {
701 4566 : SwTwips nAdd = rPor.CalcSpacing( GetSpaceAdd(), *this );
702 4566 : if( rPor.InFldGrp() && GetSpaceAdd() < 0 && nAdd )
703 0 : nAdd += GetSpaceAdd() / SPACING_PRECISION_FACTOR;
704 4566 : aSize.Width() += nAdd;
705 : }
706 :
707 136893 : Point aPoint;
708 :
709 136893 : if( IsRotated() )
710 : {
711 6 : long nTmp = aSize.Width();
712 6 : aSize.Width() = aSize.Height();
713 6 : aSize.Height() = nTmp;
714 6 : if ( 1 == GetDirection() )
715 : {
716 6 : aPoint.A() = X() - rPor.GetAscent();
717 6 : aPoint.B() = Y() - aSize.Height();
718 : }
719 : else
720 : {
721 0 : aPoint.A() = X() - rPor.Height() + rPor.GetAscent();
722 0 : aPoint.B() = Y();
723 : }
724 : }
725 : else
726 : {
727 136887 : aPoint.A() = X();
728 136887 : if ( GetTxtFrm()->IsVertLR() )
729 0 : aPoint.B() = Y() - rPor.Height() + rPor.GetAscent();
730 : else
731 136887 : aPoint.B() = Y() - rPor.GetAscent();
732 : }
733 :
734 : // Adjust x coordinate if we are inside a bidi portion
735 136893 : const bool bFrmDir = GetTxtFrm()->IsRightToLeft();
736 136959 : const bool bCounterDir = ( !bFrmDir && DIR_RIGHT2LEFT == GetDirection() ) ||
737 136971 : ( bFrmDir && DIR_LEFT2RIGHT == GetDirection() );
738 :
739 136893 : if ( bCounterDir )
740 66 : aPoint.A() -= aSize.Width();
741 :
742 136893 : SwRect aRect( aPoint, aSize );
743 :
744 136893 : if ( GetTxtFrm()->IsRightToLeft() )
745 78 : GetTxtFrm()->SwitchLTRtoRTL( aRect );
746 :
747 136893 : if ( GetTxtFrm()->IsVertical() )
748 0 : GetTxtFrm()->SwitchHorizontalToVertical( aRect );
749 :
750 136893 : if( bInsideBox && rPor.InTxtGrp() )
751 : {
752 : const bool bJoinWithPrev =
753 90698 : static_cast<const SwTxtPortion&>(rPor).GetJoinBorderWithPrev();
754 : const bool bJoinWithNext =
755 90698 : static_cast<const SwTxtPortion&>(rPor).GetJoinBorderWithNext();
756 90698 : const bool bIsVert = GetTxtFrm()->IsVertical();
757 90698 : aRect.Top(aRect.Top() + GetFont()->CalcShadowSpace(SHADOW_TOP, bIsVert, bJoinWithPrev, bJoinWithNext ));
758 90698 : aRect.Bottom(aRect.Bottom() - GetFont()->CalcShadowSpace(SHADOW_BOTTOM, bIsVert, bJoinWithPrev, bJoinWithNext ));
759 90698 : aRect.Left(aRect.Left() + GetFont()->CalcShadowSpace(SHADOW_LEFT, bIsVert, bJoinWithPrev, bJoinWithNext ));
760 90698 : aRect.Right(aRect.Right() - GetFont()->CalcShadowSpace(SHADOW_RIGHT, bIsVert, bJoinWithPrev, bJoinWithNext ));
761 : }
762 :
763 136893 : if ( pRect )
764 89114 : *pRect = aRect;
765 :
766 136893 : if( aRect.HasArea() && pIntersect )
767 : {
768 47779 : ::SwAlignRect( aRect, (SwViewShell*)GetVsh() );
769 :
770 47779 : if ( GetOut()->IsClipRegion() )
771 : {
772 33237 : SwRect aClip( GetOut()->GetClipRegion().GetBoundRect() );
773 33237 : aRect.Intersection( aClip );
774 : }
775 :
776 47779 : *pIntersect = aRect;
777 : }
778 136893 : }
779 :
780 : /**
781 : * Draws a special portion
782 : * E.g.: line break portion, tab portion
783 : *
784 : * @param rPor The portion
785 : * @param rRect The rectangle surrounding the character
786 : * @param rCol Specify a color for the character
787 : * @param bCenter Draw the character centered, otherwise left aligned
788 : * @param bRotate Rotate the character if character rotation is set
789 : */
790 24 : static void lcl_DrawSpecial( const SwTxtPaintInfo& rInf, const SwLinePortion& rPor,
791 : SwRect& rRect, const Color& rCol, sal_Unicode cChar,
792 : sal_uInt8 nOptions )
793 : {
794 24 : bool bCenter = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_CENTER );
795 24 : bool bRotate = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_ROTATE );
796 :
797 : // rRect is given in absolute coordinates
798 24 : if ( rInf.GetTxtFrm()->IsRightToLeft() )
799 0 : rInf.GetTxtFrm()->SwitchRTLtoLTR( rRect );
800 24 : if ( rInf.GetTxtFrm()->IsVertical() )
801 0 : rInf.GetTxtFrm()->SwitchVerticalToHorizontal( rRect );
802 :
803 24 : const SwFont* pOldFnt = rInf.GetFont();
804 :
805 : // Font is generated only once:
806 : static SwFont* m_pFnt = 0;
807 24 : if ( ! m_pFnt )
808 : {
809 6 : m_pFnt = new SwFont( *pOldFnt );
810 6 : m_pFnt->SetFamily( FAMILY_DONTKNOW, m_pFnt->GetActual() );
811 6 : m_pFnt->SetName( numfunc::GetDefBulletFontname(), m_pFnt->GetActual() );
812 6 : m_pFnt->SetStyleName( aEmptyOUStr, m_pFnt->GetActual() );
813 6 : m_pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, m_pFnt->GetActual() );
814 : }
815 :
816 : // Some of the current values are set at the font:
817 24 : if ( ! bRotate )
818 24 : m_pFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
819 : else
820 0 : m_pFnt->SetVertical( pOldFnt->GetOrientation() );
821 :
822 24 : m_pFnt->SetColor(rCol);
823 :
824 24 : Size aFontSize( 0, SPECIAL_FONT_HEIGHT );
825 24 : m_pFnt->SetSize( aFontSize, m_pFnt->GetActual() );
826 :
827 24 : ((SwTxtPaintInfo&)rInf).SetFont( m_pFnt );
828 :
829 : // The maximum width depends on the current orientation
830 24 : const sal_uInt16 nDir = m_pFnt->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
831 : SwTwips nMaxWidth;
832 24 : if (nDir == 900 || nDir == 2700)
833 0 : nMaxWidth = rRect.Height();
834 : else
835 : {
836 : assert(nDir == 0); //Unknown direction set at font
837 24 : nMaxWidth = rRect.Width();
838 : }
839 :
840 : // check if char fits into rectangle
841 24 : const OUString aTmp( cChar );
842 24 : aFontSize = rInf.GetTxtSize( aTmp ).SvLSize();
843 48 : while ( aFontSize.Width() > nMaxWidth )
844 : {
845 0 : SwTwips nFactor = ( 100 * aFontSize.Width() ) / nMaxWidth;
846 0 : const SwTwips nOldWidth = aFontSize.Width();
847 :
848 : // new height for font
849 0 : const sal_uInt8 nAct = m_pFnt->GetActual();
850 0 : aFontSize.Height() = ( 100 * m_pFnt->GetSize( nAct ).Height() ) / nFactor;
851 0 : aFontSize.Width() = ( 100 * m_pFnt->GetSize( nAct).Width() ) / nFactor;
852 :
853 0 : if ( !aFontSize.Width() && !aFontSize.Height() )
854 0 : break;
855 :
856 0 : m_pFnt->SetSize( aFontSize, nAct );
857 :
858 0 : aFontSize = rInf.GetTxtSize( aTmp ).SvLSize();
859 :
860 0 : if ( aFontSize.Width() >= nOldWidth )
861 0 : break;
862 : }
863 :
864 24 : const Point aOldPos( rInf.GetPos() );
865 :
866 : // adjust values so that tab is vertically and horizontally centered
867 24 : SwTwips nX = rRect.Left();
868 24 : SwTwips nY = rRect.Top();
869 24 : switch ( nDir )
870 : {
871 : case 0 :
872 24 : if ( bCenter )
873 0 : nX += ( rRect.Width() - aFontSize.Width() ) / 2;
874 24 : nY += ( rRect.Height() - aFontSize.Height() ) / 2 + rInf.GetAscent();
875 24 : break;
876 : case 900 :
877 0 : if ( bCenter )
878 0 : nX += ( rRect.Width() - aFontSize.Height() ) / 2 + rInf.GetAscent();
879 0 : nY += ( rRect.Height() + aFontSize.Width() ) / 2;
880 0 : break;
881 : case 2700 :
882 0 : if ( bCenter )
883 0 : nX += ( rRect.Width() + aFontSize.Height() ) / 2 - rInf.GetAscent();
884 0 : nY += ( rRect.Height() - aFontSize.Width() ) / 2;
885 0 : break;
886 : }
887 :
888 24 : Point aTmpPos( nX, nY );
889 24 : ((SwTxtPaintInfo&)rInf).SetPos( aTmpPos );
890 24 : sal_uInt16 nOldWidth = rPor.Width();
891 24 : ((SwLinePortion&)rPor).Width( (sal_uInt16)aFontSize.Width() );
892 24 : rInf.DrawText( aTmp, rPor );
893 24 : ((SwLinePortion&)rPor).Width( nOldWidth );
894 24 : ((SwTxtPaintInfo&)rInf).SetFont( (SwFont*)pOldFnt );
895 24 : ((SwTxtPaintInfo&)rInf).SetPos( aOldPos );
896 24 : }
897 :
898 3340 : void SwTxtPaintInfo::DrawRect( const SwRect &rRect, bool bNoGraphic,
899 : bool bRetouche ) const
900 : {
901 3340 : if ( OnWin() || !bRetouche )
902 : {
903 3340 : if( aTxtFly.IsOn() )
904 90 : ((SwTxtPaintInfo*)this)->GetTxtFly().
905 180 : DrawFlyRect( m_pOut, rRect, *this, bNoGraphic );
906 3250 : else if ( bNoGraphic )
907 3250 : m_pOut->DrawRect( rRect.SVRect() );
908 : else
909 : {
910 0 : if(pBrushItem != ((SvxBrushItem*)-1))
911 : {
912 0 : ::DrawGraphic( pBrushItem, m_pOut, aItemRect, rRect );
913 : }
914 : else
915 : {
916 : OSL_ENSURE(false, "DrawRect: Uninitialized BrushItem!" );
917 : }
918 : }
919 : }
920 3340 : }
921 :
922 0 : void SwTxtPaintInfo::DrawTab( const SwLinePortion &rPor ) const
923 : {
924 0 : if( OnWin() )
925 : {
926 0 : SwRect aRect;
927 0 : CalcRect( rPor, &aRect );
928 :
929 0 : if ( ! aRect.HasArea() )
930 0 : return;
931 :
932 0 : const sal_Unicode cChar = GetTxtFrm()->IsRightToLeft() ? CHAR_TAB_RTL : CHAR_TAB;
933 0 : const sal_uInt8 nOptions = DRAW_SPECIAL_OPTIONS_CENTER | DRAW_SPECIAL_OPTIONS_ROTATE;
934 :
935 0 : lcl_DrawSpecial( *this, rPor, aRect, Color(NON_PRINTING_CHARACTER_COLOR), cChar, nOptions );
936 : }
937 : }
938 :
939 0 : void SwTxtPaintInfo::DrawLineBreak( const SwLinePortion &rPor ) const
940 : {
941 0 : if( OnWin() )
942 : {
943 0 : sal_uInt16 nOldWidth = rPor.Width();
944 0 : ((SwLinePortion&)rPor).Width( LINE_BREAK_WIDTH );
945 :
946 0 : SwRect aRect;
947 0 : CalcRect( rPor, &aRect );
948 :
949 0 : if( aRect.HasArea() )
950 : {
951 0 : const sal_Unicode cChar = GetTxtFrm()->IsRightToLeft() ?
952 0 : CHAR_LINEBREAK_RTL : CHAR_LINEBREAK;
953 0 : const sal_uInt8 nOptions = 0;
954 :
955 0 : lcl_DrawSpecial( *this, rPor, aRect, Color(NON_PRINTING_CHARACTER_COLOR), cChar, nOptions );
956 : }
957 :
958 0 : ((SwLinePortion&)rPor).Width( nOldWidth );
959 : }
960 0 : }
961 :
962 24 : void SwTxtPaintInfo::DrawRedArrow( const SwLinePortion &rPor ) const
963 : {
964 24 : Size aSize( SPECIAL_FONT_HEIGHT, SPECIAL_FONT_HEIGHT );
965 24 : SwRect aRect( ((SwArrowPortion&)rPor).GetPos(), aSize );
966 : sal_Unicode cChar;
967 24 : if( ((SwArrowPortion&)rPor).IsLeft() )
968 : {
969 0 : aRect.Pos().Y() += 20 - GetAscent();
970 0 : aRect.Pos().X() += 20;
971 0 : if( aSize.Height() > rPor.Height() )
972 0 : aRect.Height( rPor.Height() );
973 0 : cChar = CHAR_LEFT_ARROW;
974 : }
975 : else
976 : {
977 24 : if( aSize.Height() > rPor.Height() )
978 4 : aRect.Height( rPor.Height() );
979 24 : aRect.Pos().Y() -= aRect.Height() + 20;
980 24 : aRect.Pos().X() -= aRect.Width() + 20;
981 24 : cChar = CHAR_RIGHT_ARROW;
982 : }
983 :
984 24 : if ( GetTxtFrm()->IsVertical() )
985 0 : GetTxtFrm()->SwitchHorizontalToVertical( aRect );
986 :
987 24 : Color aCol( COL_LIGHTRED );
988 :
989 24 : if( aRect.HasArea() )
990 : {
991 24 : const sal_uInt8 nOptions = 0;
992 24 : lcl_DrawSpecial( *this, rPor, aRect, aCol, cChar, nOptions );
993 : }
994 24 : }
995 :
996 32 : void SwTxtPaintInfo::DrawPostIts( const SwLinePortion&, bool bScript ) const
997 : {
998 32 : if( OnWin() && m_pOpt->IsPostIts() )
999 : {
1000 32 : Size aSize;
1001 32 : Point aTmp;
1002 :
1003 32 : const sal_uInt16 nPostItsWidth = m_pOpt->GetPostItsWidth( GetOut() );
1004 32 : const sal_uInt16 nFontHeight = m_pFnt->GetHeight( m_pVsh, *GetOut() );
1005 32 : const sal_uInt16 nFontAscent = m_pFnt->GetAscent( m_pVsh, *GetOut() );
1006 :
1007 32 : switch ( m_pFnt->GetOrientation( GetTxtFrm()->IsVertical() ) )
1008 : {
1009 : case 0 :
1010 32 : aSize.Width() = nPostItsWidth;
1011 32 : aSize.Height() = nFontHeight;
1012 32 : aTmp.X() = aPos.X();
1013 32 : aTmp.Y() = aPos.Y() - nFontAscent;
1014 32 : break;
1015 : case 900 :
1016 0 : aSize.Height() = nPostItsWidth;
1017 0 : aSize.Width() = nFontHeight;
1018 0 : aTmp.X() = aPos.X() - nFontAscent;
1019 0 : aTmp.Y() = aPos.Y();
1020 0 : break;
1021 : case 2700 :
1022 0 : aSize.Height() = nPostItsWidth;
1023 0 : aSize.Width() = nFontHeight;
1024 0 : aTmp.X() = aPos.X() - nFontHeight +
1025 0 : nFontAscent;
1026 0 : aTmp.Y() = aPos.Y();
1027 0 : break;
1028 : }
1029 :
1030 32 : SwRect aTmpRect( aTmp, aSize );
1031 :
1032 32 : if ( GetTxtFrm()->IsRightToLeft() )
1033 0 : GetTxtFrm()->SwitchLTRtoRTL( aTmpRect );
1034 :
1035 32 : if ( GetTxtFrm()->IsVertical() )
1036 0 : GetTxtFrm()->SwitchHorizontalToVertical( aTmpRect );
1037 :
1038 32 : const Rectangle aRect( aTmpRect.SVRect() );
1039 32 : m_pOpt->PaintPostIts( (OutputDevice*)GetOut(), aRect, bScript );
1040 : }
1041 32 : }
1042 :
1043 4 : void SwTxtPaintInfo::DrawCheckBox(const SwFieldFormCheckboxPortion &rPor, bool bChecked) const
1044 : {
1045 4 : SwRect aIntersect;
1046 4 : CalcRect( rPor, &aIntersect, 0 );
1047 4 : if ( aIntersect.HasArea() )
1048 : {
1049 8 : if (OnWin() && SwViewOption::IsFieldShadings() &&
1050 4 : !GetOpt().IsPagePreview())
1051 : {
1052 4 : OutputDevice* pOut = (OutputDevice*)GetOut();
1053 4 : pOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
1054 4 : pOut->SetFillColor( SwViewOption::GetFieldShadingsColor() );
1055 4 : pOut->SetLineColor();
1056 4 : pOut->DrawRect( aIntersect.SVRect() );
1057 4 : pOut->Pop();
1058 : }
1059 4 : const int delta=10;
1060 4 : Rectangle r(aIntersect.Left()+delta, aIntersect.Top()+delta, aIntersect.Right()-delta, aIntersect.Bottom()-delta);
1061 4 : m_pOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
1062 4 : m_pOut->SetLineColor( Color(0, 0, 0));
1063 4 : m_pOut->SetFillColor();
1064 4 : m_pOut->DrawRect( r );
1065 4 : if (bChecked)
1066 : {
1067 2 : m_pOut->DrawLine(r.TopLeft(), r.BottomRight());
1068 2 : m_pOut->DrawLine(r.TopRight(), r.BottomLeft());
1069 : }
1070 4 : m_pOut->Pop();
1071 : }
1072 4 : }
1073 :
1074 3148 : void SwTxtPaintInfo::DrawBackground( const SwLinePortion &rPor ) const
1075 : {
1076 : OSL_ENSURE( OnWin(), "SwTxtPaintInfo::DrawBackground: printer pollution ?" );
1077 :
1078 3148 : SwRect aIntersect;
1079 3148 : CalcRect( rPor, 0, &aIntersect, true );
1080 :
1081 3148 : if ( aIntersect.HasArea() )
1082 : {
1083 3114 : OutputDevice* pOut = (OutputDevice*)GetOut();
1084 3114 : pOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
1085 :
1086 : // For dark background we do not want to have a filled rectangle
1087 3114 : if ( GetVsh() && GetVsh()->GetWin() && lcl_IsDarkBackground( *this ) )
1088 : {
1089 0 : pOut->SetLineColor( SwViewOption::GetFontColor().GetColor() );
1090 : }
1091 : else
1092 : {
1093 3114 : pOut->SetFillColor( SwViewOption::GetFieldShadingsColor() );
1094 3114 : pOut->SetLineColor();
1095 : }
1096 :
1097 3114 : DrawRect( aIntersect, true );
1098 3114 : pOut->Pop();
1099 : }
1100 3148 : }
1101 :
1102 44631 : void SwTxtPaintInfo::DrawBackBrush( const SwLinePortion &rPor ) const
1103 : {
1104 : {
1105 44631 : SwRect aIntersect;
1106 44631 : CalcRect( rPor, &aIntersect, 0, true );
1107 44631 : if(aIntersect.HasArea())
1108 : {
1109 44631 : SwTxtNode *pNd = m_pFrm->GetTxtNode();
1110 44631 : const ::sw::mark::IMark* pFieldmark = NULL;
1111 44631 : if(pNd)
1112 : {
1113 44631 : const SwDoc *doc=pNd->GetDoc();
1114 44631 : if(doc)
1115 : {
1116 44631 : SwIndex aIndex(pNd, GetIdx());
1117 89262 : SwPosition aPosition(*pNd, aIndex);
1118 89262 : pFieldmark=doc->getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
1119 : }
1120 : }
1121 44631 : bool bIsStartMark=(1==GetLen() && CH_TXT_ATR_FIELDSTART==GetTxt()[GetIdx()]);
1122 : if(pFieldmark) {
1123 : OSL_TRACE("Found Fieldmark");
1124 : #if OSL_DEBUG_LEVEL > 1
1125 : OUString str = pFieldmark->ToString( );
1126 : fprintf( stderr, "%s\n", OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr( ) );
1127 : #endif
1128 : }
1129 : if(bIsStartMark) OSL_TRACE("Found StartMark");
1130 133431 : if (OnWin() && (pFieldmark!=NULL || bIsStartMark) &&
1131 44643 : SwViewOption::IsFieldShadings() &&
1132 6 : !GetOpt().IsPagePreview())
1133 : {
1134 6 : OutputDevice* pOutDev = (OutputDevice*)GetOut();
1135 6 : pOutDev->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
1136 6 : pOutDev->SetFillColor( SwViewOption::GetFieldShadingsColor() );
1137 6 : pOutDev->SetLineColor( );
1138 6 : pOutDev->DrawRect( aIntersect.SVRect() );
1139 6 : pOutDev->Pop();
1140 : }
1141 : }
1142 : }
1143 :
1144 44631 : SwRect aIntersect;
1145 44631 : CalcRect( rPor, 0, &aIntersect, true );
1146 :
1147 44631 : if ( aIntersect.HasArea() )
1148 : {
1149 42434 : OutputDevice* pTmpOut = (OutputDevice*)GetOut();
1150 :
1151 : // #i16816# tagged pdf support
1152 42434 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pTmpOut );
1153 :
1154 42434 : Color aFillColor;
1155 :
1156 42434 : if( m_pFnt->GetHighlightColor() != COL_TRANSPARENT )
1157 : {
1158 0 : aFillColor = m_pFnt->GetHighlightColor();
1159 : }
1160 : else
1161 : {
1162 42434 : if( !m_pFnt->GetBackColor() )
1163 86839 : return;
1164 226 : aFillColor = *m_pFnt->GetBackColor();
1165 : }
1166 :
1167 226 : pTmpOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
1168 :
1169 226 : pTmpOut->SetFillColor(aFillColor);
1170 226 : pTmpOut->SetLineColor();
1171 :
1172 226 : DrawRect( aIntersect, true, false );
1173 :
1174 226 : pTmpOut->Pop();
1175 : }
1176 : }
1177 :
1178 44479 : void SwTxtPaintInfo::DrawBorder( const SwLinePortion &rPor ) const
1179 : {
1180 44479 : SwRect aDrawArea;
1181 44479 : CalcRect( rPor, &aDrawArea );
1182 44479 : if ( aDrawArea.HasArea() )
1183 : {
1184 : PaintCharacterBorder(
1185 44479 : *m_pFnt, aDrawArea, GetTxtFrm()->IsVertical(),
1186 88958 : rPor.GetJoinBorderWithPrev(), rPor.GetJoinBorderWithNext());
1187 : }
1188 44479 : }
1189 :
1190 3906 : void SwTxtPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
1191 : const sal_uInt16 nWhich ) const
1192 : {
1193 3906 : if( OnWin() && !IsMulti() )
1194 : {
1195 3802 : bool bDraw = false;
1196 3802 : switch( nWhich )
1197 : {
1198 : case POR_FTN:
1199 : case POR_QUOVADIS:
1200 : case POR_NUMBER:
1201 : case POR_FLD:
1202 : case POR_URL:
1203 : case POR_HIDDEN:
1204 : case POR_TOX:
1205 : case POR_REF:
1206 : case POR_META:
1207 : case POR_CONTROLCHAR:
1208 7476 : if ( !GetOpt().IsPagePreview()
1209 3738 : && !GetOpt().IsReadonly()
1210 3738 : && SwViewOption::IsFieldShadings()
1211 10560 : && ( POR_NUMBER != nWhich
1212 654 : || m_pFrm->GetTxtNode()->HasMarkedLabel())) // #i27615#
1213 : {
1214 3084 : bDraw = true;
1215 : }
1216 3738 : break;
1217 : case POR_INPUTFLD:
1218 : // input field shading also in read-only mode
1219 32 : if ( !GetOpt().IsPagePreview()
1220 16 : && SwViewOption::IsFieldShadings() )
1221 : {
1222 16 : bDraw = true;
1223 : }
1224 16 : break;
1225 0 : case POR_TAB: if ( GetOpt().IsTab() ) bDraw = true; break;
1226 0 : case POR_SOFTHYPH: if ( GetOpt().IsSoftHyph() )bDraw = true; break;
1227 48 : case POR_BLANK: if ( GetOpt().IsHardBlank())bDraw = true; break;
1228 : default:
1229 : {
1230 : OSL_ENSURE( false, "SwTxtPaintInfo::DrawViewOpt: don't know how to draw this" );
1231 0 : break;
1232 : }
1233 : }
1234 3802 : if ( bDraw )
1235 3148 : DrawBackground( rPor );
1236 : }
1237 3906 : }
1238 :
1239 0 : void SwTxtPaintInfo::_NotifyURL( const SwLinePortion &rPor ) const
1240 : {
1241 : OSL_ENSURE( pNoteURL, "NotifyURL: pNoteURL gone with the wind!" );
1242 :
1243 0 : SwRect aIntersect;
1244 0 : CalcRect( rPor, 0, &aIntersect );
1245 :
1246 0 : if( aIntersect.HasArea() )
1247 : {
1248 0 : SwTxtNode *pNd = (SwTxtNode*)GetTxtFrm()->GetTxtNode();
1249 : SwTxtAttr *const pAttr =
1250 0 : pNd->GetTxtAttrAt(GetIdx(), RES_TXTATR_INETFMT);
1251 0 : if( pAttr )
1252 : {
1253 0 : const SwFmtINetFmt& rFmt = pAttr->GetINetFmt();
1254 0 : pNoteURL->InsertURLNote( rFmt.GetValue(), rFmt.GetTargetFrame(),
1255 0 : aIntersect );
1256 : }
1257 : }
1258 0 : }
1259 :
1260 18 : static void lcl_InitHyphValues( PropertyValues &rVals,
1261 : sal_Int16 nMinLeading, sal_Int16 nMinTrailing )
1262 : {
1263 18 : sal_Int32 nLen = rVals.getLength();
1264 :
1265 18 : if (0 == nLen) // yet to be initialized?
1266 : {
1267 18 : rVals.realloc( 2 );
1268 18 : PropertyValue *pVal = rVals.getArray();
1269 :
1270 18 : pVal[0].Name = UPN_HYPH_MIN_LEADING;
1271 18 : pVal[0].Handle = UPH_HYPH_MIN_LEADING;
1272 18 : pVal[0].Value <<= nMinLeading;
1273 :
1274 18 : pVal[1].Name = UPN_HYPH_MIN_TRAILING;
1275 18 : pVal[1].Handle = UPH_HYPH_MIN_TRAILING;
1276 18 : pVal[1].Value <<= nMinTrailing;
1277 : }
1278 0 : else if (2 == nLen) // already initialized once?
1279 : {
1280 0 : PropertyValue *pVal = rVals.getArray();
1281 0 : pVal[0].Value <<= nMinLeading;
1282 0 : pVal[1].Value <<= nMinTrailing;
1283 : }
1284 : else {
1285 : OSL_FAIL( "unexpected size of sequence" );
1286 : }
1287 18 : }
1288 :
1289 0 : const PropertyValues & SwTxtFormatInfo::GetHyphValues() const
1290 : {
1291 : OSL_ENSURE( 2 == aHyphVals.getLength(),
1292 : "hyphenation values not yet initialized" );
1293 0 : return aHyphVals;
1294 : }
1295 :
1296 97770 : bool SwTxtFormatInfo::InitHyph( const bool bAutoHyphen )
1297 : {
1298 97770 : const SwAttrSet& rAttrSet = GetTxtFrm()->GetTxtNode()->GetSwAttrSet();
1299 97770 : SetHanging( rAttrSet.GetHangingPunctuation().GetValue() );
1300 97770 : SetScriptSpace( rAttrSet.GetScriptSpace().GetValue() );
1301 97770 : SetForbiddenChars( rAttrSet.GetForbiddenRule().GetValue() );
1302 97770 : const SvxHyphenZoneItem &rAttr = rAttrSet.GetHyphenZone();
1303 97770 : MaxHyph() = rAttr.GetMaxHyphens();
1304 97770 : const bool bAuto = bAutoHyphen || rAttr.IsHyphen();
1305 97770 : if( bAuto || bInterHyph )
1306 : {
1307 18 : const sal_Int16 nMinimalLeading = std::max(rAttr.GetMinLead(), sal_uInt8(2));
1308 18 : const sal_Int16 nMinimalTrailing = rAttr.GetMinTrail();
1309 18 : lcl_InitHyphValues( aHyphVals, nMinimalLeading, nMinimalTrailing);
1310 : }
1311 97770 : return bAuto;
1312 : }
1313 :
1314 97770 : void SwTxtFormatInfo::CtorInitTxtFormatInfo( SwTxtFrm *pNewFrm, const bool bNewInterHyph,
1315 : const bool bNewQuick, const bool bTst )
1316 : {
1317 97770 : CtorInitTxtPaintInfo( pNewFrm, SwRect() );
1318 :
1319 97770 : bQuick = bNewQuick;
1320 97770 : bInterHyph = bNewInterHyph;
1321 :
1322 : //! needs to be done in this order
1323 97770 : nMinLeading = 2;
1324 97770 : nMinTrailing = 2;
1325 97770 : nMinWordLength = 0;
1326 97770 : bAutoHyph = InitHyph();
1327 :
1328 97770 : bIgnoreFly = false;
1329 97770 : bFakeLineStart = false;
1330 97770 : bShift = false;
1331 97770 : bDropInit = false;
1332 97770 : bTestFormat = bTst;
1333 97770 : nLeft = 0;
1334 97770 : nRight = 0;
1335 97770 : nFirst = 0;
1336 97770 : nRealWidth = 0;
1337 97770 : nForcedLeftMargin = 0;
1338 97770 : pRest = 0;
1339 97770 : nLineHeight = 0;
1340 97770 : nLineNetHeight = 0;
1341 97770 : SetLineStart(0);
1342 97770 : Init();
1343 97770 : }
1344 :
1345 : /**
1346 : * If the Hyphenator returns ERROR or the language is set to NOLANGUAGE
1347 : * we do not hyphenate.
1348 : * Else, we always hyphenate if we do interactive hyphenation.
1349 : * If we do not do interactive hyphenation, we only hyphenate if ParaFmt is
1350 : * set to automatic hyphenation.
1351 : */
1352 66609 : bool SwTxtFormatInfo::IsHyphenate() const
1353 : {
1354 66609 : if( !bInterHyph && !bAutoHyph )
1355 66609 : return false;
1356 :
1357 0 : LanguageType eTmp = GetFont()->GetLanguage();
1358 0 : if( LANGUAGE_DONTKNOW == eTmp || LANGUAGE_NONE == eTmp )
1359 0 : return false;
1360 :
1361 0 : uno::Reference< XHyphenator > xHyph = ::GetHyphenator();
1362 0 : if (!xHyph.is())
1363 0 : return false;
1364 :
1365 0 : if (bInterHyph)
1366 0 : SvxSpellWrapper::CheckHyphLang( xHyph, eTmp );
1367 :
1368 0 : return xHyph->hasLocale( g_pBreakIt->GetLocale(eTmp) );
1369 : }
1370 :
1371 97770 : const SwFmtDrop *SwTxtFormatInfo::GetDropFmt() const
1372 : {
1373 97770 : const SwFmtDrop *pDrop = &GetTxtFrm()->GetTxtNode()->GetSwAttrSet().GetDrop();
1374 195540 : if( 1 >= pDrop->GetLines() ||
1375 12 : ( !pDrop->GetChars() && !pDrop->GetWholeWord() ) )
1376 97758 : pDrop = 0;
1377 97770 : return pDrop;
1378 : }
1379 :
1380 240874 : void SwTxtFormatInfo::Init()
1381 : {
1382 : // Not initialized: pRest, nLeft, nRight, nFirst, nRealWidth
1383 240874 : X(0);
1384 : bArrowDone = bFull = bFtnDone = bErgoDone = bNumDone = bNoEndHyph =
1385 240874 : bNoMidHyph = bStop = bNewLine = bUnderflow = bTabOverflow = false;
1386 :
1387 : // generally we do not allow number portions in follows, except...
1388 240874 : if ( GetTxtFrm()->IsFollow() )
1389 : {
1390 23938 : const SwTxtFrm* pMaster = GetTxtFrm()->FindMaster();
1391 : OSL_ENSURE(pMaster, "pTxtFrm without Master");
1392 23938 : const SwLinePortion* pTmpPara = pMaster ? pMaster->GetPara() : NULL;
1393 :
1394 : // there is a master for this follow and the master does not have
1395 : // any contents (especially it does not have a number portion)
1396 47842 : bNumDone = ! pTmpPara ||
1397 47842 : ! ((SwParaPortion*)pTmpPara)->GetFirstPortion()->IsFlyPortion();
1398 : }
1399 :
1400 240874 : pRoot = 0;
1401 240874 : pLast = 0;
1402 240874 : pFly = 0;
1403 240874 : pLastFld = 0;
1404 240874 : pLastTab = 0;
1405 240874 : pUnderflow = 0;
1406 240874 : cTabDecimal = 0;
1407 240874 : nWidth = nRealWidth;
1408 240874 : nForcedLeftMargin = 0;
1409 240874 : nSoftHyphPos = 0;
1410 240874 : nUnderScorePos = COMPLETE_STRING;
1411 240874 : cHookChar = 0;
1412 240874 : SetIdx(0);
1413 240874 : SetLen( GetTxt().getLength() );
1414 240874 : SetPaintOfst(0);
1415 240874 : }
1416 :
1417 : /**
1418 : * There are a few differences between a copy constructor
1419 : * and the following constructor for multi-line formatting.
1420 : * The root is the first line inside the multi-portion,
1421 : * the line start is the actual position in the text,
1422 : * the line width is the rest width from the surrounding line
1423 : * and the bMulti and bFirstMulti-flag has to be set correctly.
1424 : */
1425 916 : SwTxtFormatInfo::SwTxtFormatInfo( const SwTxtFormatInfo& rInf,
1426 : SwLineLayout& rLay, SwTwips nActWidth ) : SwTxtPaintInfo( rInf ),
1427 916 : bTabOverflow( false )
1428 : {
1429 916 : pRoot = &rLay;
1430 916 : pLast = &rLay;
1431 916 : pFly = NULL;
1432 916 : pLastFld = NULL;
1433 916 : pUnderflow = NULL;
1434 916 : pRest = NULL;
1435 916 : pLastTab = NULL;
1436 :
1437 916 : nSoftHyphPos = 0;
1438 916 : nUnderScorePos = COMPLETE_STRING;
1439 916 : nLineStart = rInf.GetIdx();
1440 916 : nLeft = rInf.nLeft;
1441 916 : nRight = rInf.nRight;
1442 916 : nFirst = rInf.nLeft;
1443 916 : nRealWidth = sal_uInt16(nActWidth);
1444 916 : nWidth = nRealWidth;
1445 916 : nLineHeight = 0;
1446 916 : nLineNetHeight = 0;
1447 916 : nForcedLeftMargin = 0;
1448 :
1449 916 : nMinLeading = 0;
1450 916 : nMinTrailing = 0;
1451 916 : nMinWordLength = 0;
1452 916 : bFull = false;
1453 916 : bFtnDone = true;
1454 916 : bErgoDone = true;
1455 916 : bNumDone = true;
1456 916 : bArrowDone = true;
1457 916 : bStop = false;
1458 916 : bNewLine = true;
1459 916 : bShift = false;
1460 916 : bUnderflow = false;
1461 916 : bInterHyph = false;
1462 916 : bAutoHyph = false;
1463 916 : bDropInit = false;
1464 916 : bQuick = rInf.bQuick;
1465 916 : bNoEndHyph = false;
1466 916 : bNoMidHyph = false;
1467 916 : bIgnoreFly = false;
1468 916 : bFakeLineStart = false;
1469 :
1470 916 : cTabDecimal = 0;
1471 916 : cHookChar = 0;
1472 916 : nMaxHyph = 0;
1473 916 : bTestFormat = rInf.bTestFormat;
1474 916 : SetMulti( true );
1475 916 : SetFirstMulti( rInf.IsFirstMulti() );
1476 916 : }
1477 :
1478 210 : bool SwTxtFormatInfo::_CheckFtnPortion( SwLineLayout* pCurr )
1479 : {
1480 210 : const sal_uInt16 nHeight = pCurr->GetRealHeight();
1481 748 : for( SwLinePortion *pPor = pCurr->GetPortion(); pPor; pPor = pPor->GetPortion() )
1482 : {
1483 556 : if( pPor->IsFtnPortion() && nHeight > ((SwFtnPortion*)pPor)->Orig() )
1484 : {
1485 18 : SetLineHeight( nHeight );
1486 18 : SetLineNetHeight( pCurr->Height() );
1487 18 : return true;
1488 : }
1489 : }
1490 192 : return false;
1491 : }
1492 :
1493 145467 : sal_Int32 SwTxtFormatInfo::ScanPortionEnd( const sal_Int32 nStart,
1494 : const sal_Int32 nEnd )
1495 : {
1496 145467 : cHookChar = 0;
1497 145467 : sal_Int32 i = nStart;
1498 :
1499 : // Used for decimal tab handling:
1500 145467 : const sal_Unicode cTabDec = GetLastTab() ? (sal_Unicode)GetTabDecimal() : 0;
1501 145467 : const sal_Unicode cThousandSep = ',' == cTabDec ? '.' : ',';
1502 :
1503 : // #i45951# German (Switzerland) uses ' as thousand separator
1504 145467 : const sal_Unicode cThousandSep2 = ',' == cTabDec ? '.' : '\'';
1505 :
1506 145467 : bool bNumFound = false;
1507 145467 : const bool bTabCompat = GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
1508 :
1509 6200609 : for( ; i < nEnd; ++i )
1510 : {
1511 6072994 : const sal_Unicode cPos = GetChar( i );
1512 6072994 : switch( cPos )
1513 : {
1514 : case CH_TXTATR_BREAKWORD:
1515 : case CH_TXTATR_INWORD:
1516 0 : if( !HasHint( i ))
1517 0 : break;
1518 : // no break;
1519 :
1520 : case CHAR_SOFTHYPHEN:
1521 : case CHAR_HARDHYPHEN:
1522 : case CHAR_HARDBLANK:
1523 : case CH_TAB:
1524 : case CH_BREAK:
1525 : case CHAR_ZWSP :
1526 : case CHAR_ZWNBSP :
1527 17846 : cHookChar = cPos;
1528 17846 : return i;
1529 :
1530 : case CHAR_UNDERSCORE:
1531 9706 : if ( COMPLETE_STRING == nUnderScorePos )
1532 270 : nUnderScorePos = i;
1533 9706 : break;
1534 :
1535 : default:
1536 6045442 : if ( cTabDec )
1537 : {
1538 74 : if( cTabDec == cPos )
1539 : {
1540 : OSL_ENSURE( cPos, "Unexpected end of string" );
1541 4 : if( cPos ) // robust
1542 : {
1543 4 : cHookChar = cPos;
1544 4 : return i;
1545 : }
1546 : }
1547 :
1548 : // Compatibility: First non-digit character behind a
1549 : // a digit character becomes the hook character
1550 70 : if ( bTabCompat )
1551 : {
1552 70 : if ( ( 0x2F < cPos && cPos < 0x3A ) ||
1553 2 : ( bNumFound && ( cPos == cThousandSep || cPos == cThousandSep2 ) ) )
1554 : {
1555 6 : bNumFound = true;
1556 : }
1557 : else
1558 : {
1559 64 : if ( bNumFound )
1560 : {
1561 2 : cHookChar = cPos;
1562 2 : SetTabDecimal( cPos );
1563 2 : return i;
1564 : }
1565 : }
1566 : }
1567 : }
1568 : }
1569 : }
1570 :
1571 : // Check if character *behind* the portion has
1572 : // to become the hook:
1573 127615 : if ( i == nEnd && i < GetTxt().getLength() && bNumFound )
1574 : {
1575 2 : const sal_Unicode cPos = GetChar( i );
1576 2 : if ( cPos != cTabDec && cPos != cThousandSep && cPos !=cThousandSep2 && ( 0x2F >= cPos || cPos >= 0x3A ) )
1577 : {
1578 2 : cHookChar = GetChar( i );
1579 2 : SetTabDecimal( cHookChar );
1580 : }
1581 : }
1582 :
1583 127615 : return i;
1584 : }
1585 :
1586 139672 : bool SwTxtFormatInfo::LastKernPortion()
1587 : {
1588 139672 : if( GetLast() )
1589 : {
1590 139672 : if( GetLast()->IsKernPortion() )
1591 554 : return true;
1592 147259 : if( GetLast()->Width() || ( GetLast()->GetLen() &&
1593 8141 : !GetLast()->IsHolePortion() ) )
1594 104808 : return false;
1595 : }
1596 34310 : SwLinePortion* pPor = GetRoot();
1597 34310 : SwLinePortion *pKern = NULL;
1598 139074 : while( pPor )
1599 : {
1600 70454 : if( pPor->IsKernPortion() )
1601 30 : pKern = pPor;
1602 70424 : else if( pPor->Width() || ( pPor->GetLen() && !pPor->IsHolePortion() ) )
1603 30288 : pKern = NULL;
1604 70454 : pPor = pPor->GetPortion();
1605 : }
1606 34310 : if( pKern )
1607 : {
1608 12 : SetLast( pKern );
1609 12 : return true;
1610 : }
1611 34298 : return false;
1612 : }
1613 :
1614 4268 : SwTxtSlot::SwTxtSlot(
1615 : const SwTxtSizeInfo *pNew,
1616 : const SwLinePortion *pPor,
1617 : bool bTxtLen,
1618 : bool bExgLists,
1619 : OUString const & rCh )
1620 : : pOldTxt(0)
1621 : , pOldSmartTagList(0)
1622 : , pOldGrammarCheckList(0)
1623 : , pTempList(0)
1624 : , nIdx(0)
1625 : , nLen(0)
1626 4268 : , pInf(NULL)
1627 : {
1628 4268 : if( rCh.isEmpty() )
1629 : {
1630 4264 : bOn = pPor->GetExpTxt( *pNew, aTxt );
1631 : }
1632 : else
1633 : {
1634 4 : aTxt = rCh;
1635 4 : bOn = true;
1636 : }
1637 :
1638 : // The text is replaced ...
1639 4268 : if( bOn )
1640 : {
1641 4264 : pInf = (SwTxtSizeInfo*)pNew;
1642 4264 : nIdx = pInf->GetIdx();
1643 4264 : nLen = pInf->GetLen();
1644 4264 : pOldTxt = &(pInf->GetTxt());
1645 4264 : pInf->SetTxt( aTxt );
1646 4264 : pInf->SetIdx( 0 );
1647 4264 : pInf->SetLen( bTxtLen ? pInf->GetTxt().getLength() : pPor->GetLen() );
1648 :
1649 : // ST2
1650 4264 : if ( bExgLists )
1651 : {
1652 2894 : pOldSmartTagList = static_cast<SwTxtPaintInfo*>(pInf)->GetSmartTags();
1653 2894 : if ( pOldSmartTagList )
1654 : {
1655 0 : const sal_uInt16 nPos = pOldSmartTagList->GetWrongPos(nIdx);
1656 0 : const sal_Int32 nListPos = pOldSmartTagList->Pos(nPos);
1657 0 : if( nListPos == nIdx )
1658 0 : ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList->SubList( nPos ) );
1659 0 : else if( !pTempList && nPos < pOldSmartTagList->Count() && nListPos < nIdx && !aTxt.isEmpty() )
1660 : {
1661 0 : pTempList = new SwWrongList( WRONGLIST_SMARTTAG );
1662 0 : pTempList->Insert( OUString(), 0, 0, aTxt.getLength(), 0 );
1663 0 : ((SwTxtPaintInfo*)pInf)->SetSmartTags( pTempList );
1664 : }
1665 : else
1666 0 : ((SwTxtPaintInfo*)pInf)->SetSmartTags( 0);
1667 : }
1668 2894 : pOldGrammarCheckList = static_cast<SwTxtPaintInfo*>(pInf)->GetGrammarCheckList();
1669 2894 : if ( pOldGrammarCheckList )
1670 : {
1671 0 : const sal_uInt16 nPos = pOldGrammarCheckList->GetWrongPos(nIdx);
1672 0 : const sal_Int32 nListPos = pOldGrammarCheckList->Pos(nPos);
1673 0 : if( nListPos == nIdx )
1674 0 : ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList->SubList( nPos ) );
1675 0 : else if( !pTempList && nPos < pOldGrammarCheckList->Count() && nListPos < nIdx && !aTxt.isEmpty() )
1676 : {
1677 0 : pTempList = new SwWrongList( WRONGLIST_GRAMMAR );
1678 0 : pTempList->Insert( OUString(), 0, 0, aTxt.getLength(), 0 );
1679 0 : ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pTempList );
1680 : }
1681 : else
1682 0 : ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( 0);
1683 : }
1684 : }
1685 : }
1686 4268 : }
1687 :
1688 8536 : SwTxtSlot::~SwTxtSlot()
1689 : {
1690 4268 : if( bOn )
1691 : {
1692 4264 : pInf->SetTxt( *pOldTxt );
1693 4264 : pInf->SetIdx( nIdx );
1694 4264 : pInf->SetLen( nLen );
1695 :
1696 : // ST2
1697 : // Restore old smart tag list
1698 4264 : if ( pOldSmartTagList )
1699 0 : ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList );
1700 4264 : if ( pOldGrammarCheckList )
1701 0 : ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList );
1702 4264 : delete pTempList;
1703 : }
1704 4268 : }
1705 :
1706 43492 : SwFontSave::SwFontSave(const SwTxtSizeInfo &rInf, SwFont *pNew,
1707 : SwAttrIter* pItr)
1708 : : pInf(NULL)
1709 : , pFnt(pNew ? ((SwTxtSizeInfo&)rInf).GetFont() : NULL)
1710 43492 : , pIter(NULL)
1711 : {
1712 43492 : if( pFnt )
1713 : {
1714 35344 : pInf = &((SwTxtSizeInfo&)rInf);
1715 : // In these cases we temporarily switch to the new font:
1716 : // 1. the fonts have a different magic number
1717 : // 2. they have different script types
1718 : // 3. their background colors differ (this is not covered by 1.)
1719 76000 : if( pFnt->DifferentMagic( pNew, pFnt->GetActual() ) ||
1720 10600 : pNew->GetActual() != pFnt->GetActual() ||
1721 15772 : ( ! pNew->GetBackColor() && pFnt->GetBackColor() ) ||
1722 75940 : ( pNew->GetBackColor() && ! pFnt->GetBackColor() ) ||
1723 5280 : ( pNew->GetBackColor() && pFnt->GetBackColor() &&
1724 28 : ( *pNew->GetBackColor() != *pFnt->GetBackColor() ) ) )
1725 : {
1726 30120 : pNew->SetTransparent( true );
1727 30120 : pNew->SetAlign( ALIGN_BASELINE );
1728 30120 : pInf->SetFont( pNew );
1729 : }
1730 : else
1731 5224 : pFnt = 0;
1732 35344 : pNew->Invalidate();
1733 35344 : pNew->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
1734 35344 : if( pItr && pItr->GetFnt() == pFnt )
1735 : {
1736 40 : pIter = pItr;
1737 40 : pIter->SetFnt( pNew );
1738 : }
1739 : }
1740 43492 : }
1741 :
1742 43492 : SwFontSave::~SwFontSave()
1743 : {
1744 43492 : if( pFnt )
1745 : {
1746 : // Reset SwFont
1747 30120 : pFnt->Invalidate();
1748 30120 : pInf->SetFont( pFnt );
1749 30120 : if( pIter )
1750 : {
1751 40 : pIter->SetFnt( pFnt );
1752 40 : pIter->nPos = COMPLETE_STRING;
1753 : }
1754 : }
1755 43492 : }
1756 :
1757 0 : bool SwTxtFormatInfo::ChgHyph( const bool bNew )
1758 : {
1759 0 : const bool bOld = bAutoHyph;
1760 0 : if( bAutoHyph != bNew )
1761 : {
1762 0 : bAutoHyph = bNew;
1763 0 : InitHyph( bNew );
1764 : // Set language in the Hyphenator
1765 0 : if( m_pFnt )
1766 0 : m_pFnt->ChgPhysFnt( m_pVsh, *m_pOut );
1767 : }
1768 0 : return bOld;
1769 270 : }
1770 :
1771 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|