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