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