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 0 : SwLineInfo::SwLineInfo()
98 : : pRuler( 0 ),
99 : pSpace( 0 ),
100 : nVertAlign( 0 ),
101 : nDefTabStop( 0 ),
102 : bListTabStopIncluded( false ),
103 0 : nListTabStopPosition( 0 )
104 : {
105 0 : }
106 :
107 0 : SwLineInfo::~SwLineInfo()
108 : {
109 0 : delete pRuler;
110 0 : }
111 0 : void SwLineInfo::CtorInitLineInfo( const SwAttrSet& rAttrSet,
112 : const SwTxtNode& rTxtNode )
113 : {
114 0 : delete pRuler;
115 0 : pRuler = new SvxTabStopItem( rAttrSet.GetTabStops() );
116 0 : if ( rTxtNode.GetListTabStopPosition( nListTabStopPosition ) )
117 : {
118 0 : bListTabStopIncluded = true;
119 :
120 : // insert the list tab stop into SvxTabItem instance <pRuler>
121 : const SvxTabStop aListTabStop( nListTabStopPosition,
122 0 : SVX_TAB_ADJUST_LEFT );
123 0 : pRuler->Insert( aListTabStop );
124 :
125 : // remove default tab stops, which are before the inserted list tab stop
126 0 : for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
127 : {
128 0 : if ( (*pRuler)[i].GetTabPos() < nListTabStopPosition &&
129 0 : (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
130 : {
131 0 : pRuler->Remove(i);
132 0 : continue;
133 : }
134 : }
135 : }
136 :
137 0 : if ( !rTxtNode.getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
138 : {
139 : // remove default tab stop at position 0
140 0 : for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
141 : {
142 0 : if ( (*pRuler)[i].GetTabPos() == 0 &&
143 0 : (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
144 : {
145 0 : pRuler->Remove(i);
146 0 : break;
147 : }
148 : }
149 : }
150 :
151 0 : pSpace = &rAttrSet.GetLineSpacing();
152 0 : nVertAlign = rAttrSet.GetParaVertAlign().GetValue();
153 0 : nDefTabStop = MSHRT_MAX;
154 0 : }
155 :
156 0 : void SwTxtInfo::CtorInitTxtInfo( SwTxtFrm *pFrm )
157 : {
158 0 : pPara = pFrm->GetPara();
159 0 : nTxtStart = pFrm->GetOfst();
160 0 : if( !pPara )
161 : {
162 : OSL_ENSURE( pPara, "+SwTxtInfo::CTOR: missing paragraph information" );
163 0 : pFrm->Format();
164 0 : pPara = pFrm->GetPara();
165 : }
166 0 : }
167 :
168 0 : SwTxtInfo::SwTxtInfo( const SwTxtInfo &rInf )
169 0 : : pPara( ((SwTxtInfo&)rInf).GetParaPortion() ),
170 0 : nTxtStart( rInf.GetTxtStart() )
171 0 : { }
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 0 : inline sal_Int32 GetMinLen( const SwTxtSizeInfo &rInf )
187 : {
188 0 : const sal_Int32 nTxtLen = rInf.GetTxt().getLength();
189 0 : if (rInf.GetLen() == COMPLETE_STRING)
190 0 : return nTxtLen;
191 0 : const sal_Int32 nInfLen = rInf.GetIdx() + rInf.GetLen();
192 0 : return std::min(nTxtLen, nInfLen);
193 : }
194 :
195 0 : SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew )
196 : : SwTxtInfo( rNew ),
197 0 : m_pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()),
198 0 : m_pVsh(((SwTxtSizeInfo&)rNew).GetVsh()),
199 0 : m_pOut(((SwTxtSizeInfo&)rNew).GetOut()),
200 0 : m_pRef(((SwTxtSizeInfo&)rNew).GetRefDev()),
201 0 : m_pFnt(((SwTxtSizeInfo&)rNew).GetFont()),
202 0 : m_pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()),
203 : m_pFrm(rNew.m_pFrm),
204 0 : m_pOpt(&rNew.GetOpt()),
205 0 : m_pTxt(&rNew.GetTxt()),
206 0 : m_nIdx(rNew.GetIdx()),
207 0 : m_nLen(rNew.GetLen()),
208 0 : m_nKanaIdx( rNew.GetKanaIdx() ),
209 0 : m_bOnWin( rNew.OnWin() ),
210 0 : m_bNotEOL( rNew.NotEOL() ),
211 0 : m_bURLNotify( rNew.URLNotify() ),
212 0 : m_bStopUnderflow( rNew.StopUnderflow() ),
213 0 : m_bFtnInside( rNew.IsFtnInside() ),
214 0 : m_bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ),
215 0 : m_bMulti( rNew.IsMulti() ),
216 0 : m_bFirstMulti( rNew.IsFirstMulti() ),
217 0 : m_bRuby( rNew.IsRuby() ),
218 0 : m_bHanging( rNew.IsHanging() ),
219 0 : m_bScriptSpace( rNew.HasScriptSpace() ),
220 0 : m_bForbiddenChars( rNew.HasForbiddenChars() ),
221 0 : m_bSnapToGrid( rNew.SnapToGrid() ),
222 0 : m_nDirection( rNew.GetDirection() )
223 : {
224 : #if OSL_DEBUG_LEVEL > 0
225 : ChkOutDev( *this );
226 : #endif
227 0 : }
228 :
229 0 : void SwTxtSizeInfo::CtorInitTxtSizeInfo( SwTxtFrm *pFrame, SwFont *pNewFnt,
230 : const sal_Int32 nNewIdx, const sal_Int32 nNewLen )
231 : {
232 0 : m_pKanaComp = NULL;
233 0 : m_nKanaIdx = 0;
234 0 : m_pFrm = pFrame;
235 0 : CtorInitTxtInfo( m_pFrm );
236 0 : const SwTxtNode *pNd = m_pFrm->GetTxtNode();
237 0 : m_pVsh = m_pFrm->getRootFrm()->GetCurrShell();
238 :
239 : // Get the output and reference device
240 0 : if ( m_pVsh )
241 : {
242 0 : m_pOut = m_pVsh->GetOut();
243 0 : m_pRef = &m_pVsh->GetRefDev();
244 0 : 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 0 : if ( m_pFrm->IsRightToLeft() )
266 : {
267 0 : m_pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
268 0 : m_pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
269 0 : m_nDirection = DIR_RIGHT2LEFT;
270 : }
271 : else
272 : {
273 0 : m_pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
274 0 : m_pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
275 0 : m_nDirection = DIR_LEFT2RIGHT;
276 : }
277 :
278 : // The Options
279 :
280 : m_pOpt = m_pVsh ?
281 0 : m_pVsh->GetViewOptions() :
282 0 : 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 0 : m_bURLNotify = pNoteURL && !m_bOnWin;
287 :
288 0 : SetSnapToGrid( pNd->GetSwAttrSet().GetParaGrid().GetValue() &&
289 0 : m_pFrm->IsInDocBody() );
290 :
291 0 : m_pFnt = pNewFnt;
292 0 : m_pUnderFnt = 0;
293 0 : m_pTxt = &pNd->GetTxt();
294 :
295 0 : m_nIdx = nNewIdx;
296 0 : m_nLen = nNewLen;
297 0 : m_bNotEOL = false;
298 0 : m_bStopUnderflow = m_bFtnInside = m_bOtherThanFtnInside = false;
299 : m_bMulti = m_bFirstMulti = m_bRuby = m_bHanging = m_bScriptSpace =
300 0 : m_bForbiddenChars = false;
301 :
302 0 : SetLen( GetMinLen( *this ) );
303 0 : }
304 :
305 0 : SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew, const OUString* pTxt,
306 : const sal_Int32 nIndex, const sal_Int32 nLength )
307 : : SwTxtInfo( rNew ),
308 0 : m_pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()),
309 0 : m_pVsh(((SwTxtSizeInfo&)rNew).GetVsh()),
310 0 : m_pOut(((SwTxtSizeInfo&)rNew).GetOut()),
311 0 : m_pRef(((SwTxtSizeInfo&)rNew).GetRefDev()),
312 0 : m_pFnt(((SwTxtSizeInfo&)rNew).GetFont()),
313 0 : m_pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()),
314 : m_pFrm( rNew.m_pFrm ),
315 0 : m_pOpt(&rNew.GetOpt()),
316 : m_pTxt(pTxt),
317 : m_nIdx(nIndex),
318 : m_nLen(nLength),
319 0 : m_nKanaIdx( rNew.GetKanaIdx() ),
320 0 : m_bOnWin( rNew.OnWin() ),
321 0 : m_bNotEOL( rNew.NotEOL() ),
322 0 : m_bURLNotify( rNew.URLNotify() ),
323 0 : m_bStopUnderflow( rNew.StopUnderflow() ),
324 0 : m_bFtnInside( rNew.IsFtnInside() ),
325 0 : m_bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ),
326 0 : m_bMulti( rNew.IsMulti() ),
327 0 : m_bFirstMulti( rNew.IsFirstMulti() ),
328 0 : m_bRuby( rNew.IsRuby() ),
329 0 : m_bHanging( rNew.IsHanging() ),
330 0 : m_bScriptSpace( rNew.HasScriptSpace() ),
331 0 : m_bForbiddenChars( rNew.HasForbiddenChars() ),
332 0 : m_bSnapToGrid( rNew.SnapToGrid() ),
333 0 : m_nDirection( rNew.GetDirection() )
334 : {
335 : #if OSL_DEBUG_LEVEL > 0
336 : ChkOutDev( *this );
337 : #endif
338 0 : SetLen( GetMinLen( *this ) );
339 0 : }
340 :
341 0 : 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 0 : GetFont()->Invalidate();
347 0 : GetFont()->ChgPhysFnt( m_pVsh, *GetOut() );
348 0 : }
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 0 : 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 0 : SwDrawTextInfo aDrawInf( m_pVsh, *pOutDev, pSI, rTxt, nIndex, nLength );
367 0 : aDrawInf.SetFrm( m_pFrm );
368 0 : aDrawInf.SetFont( m_pFnt );
369 0 : aDrawInf.SetSnapToGrid( SnapToGrid() );
370 0 : aDrawInf.SetKanaComp( nComp );
371 0 : return m_pFnt->_GetTxtSize( aDrawInf );
372 : }
373 :
374 0 : SwPosSize SwTxtSizeInfo::GetTxtSize() const
375 : {
376 : const SwScriptInfo& rSI =
377 0 : ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
378 :
379 : // in some cases, compression is not allowed or suppressed for
380 : // performance reasons
381 0 : sal_uInt16 nComp =( SW_CJK == GetFont()->GetActual() &&
382 0 : rSI.CountCompChg() &&
383 0 : ! IsMulti() ) ?
384 : GetKanaComp() :
385 0 : 0 ;
386 :
387 0 : SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rSI, *m_pTxt, m_nIdx, m_nLen );
388 0 : aDrawInf.SetFrm( m_pFrm );
389 0 : aDrawInf.SetFont( m_pFnt );
390 0 : aDrawInf.SetSnapToGrid( SnapToGrid() );
391 0 : aDrawInf.SetKanaComp( nComp );
392 0 : return m_pFnt->_GetTxtSize( aDrawInf );
393 : }
394 :
395 0 : 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 0 : SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, pSI, *m_pTxt, nIndex, nLength );
400 0 : aDrawInf.SetFrm( m_pFrm );
401 0 : aDrawInf.SetFont( m_pFnt );
402 0 : aDrawInf.SetSnapToGrid( SnapToGrid() );
403 0 : aDrawInf.SetKanaComp( nComp );
404 0 : SwPosSize aSize = m_pFnt->_GetTxtSize( aDrawInf );
405 0 : nMaxSizeDiff = (sal_uInt16)aDrawInf.GetKanaDiff();
406 0 : nMinSize = aSize.Width();
407 0 : }
408 :
409 0 : sal_Int32 SwTxtSizeInfo::GetTxtBreak( const long nLineWidth,
410 : const sal_Int32 nMaxLen,
411 : const sal_uInt16 nComp ) const
412 : {
413 : const SwScriptInfo& rScriptInfo =
414 0 : ( (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 0 : *m_pTxt, GetIdx(), nMaxLen );
419 0 : aDrawInf.SetFrm( m_pFrm );
420 0 : aDrawInf.SetFont( m_pFnt );
421 0 : aDrawInf.SetSnapToGrid( SnapToGrid() );
422 0 : aDrawInf.SetKanaComp( nComp );
423 0 : aDrawInf.SetHyphPos( 0 );
424 :
425 0 : 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 0 : bool SwTxtSizeInfo::_HasHint( const SwTxtNode* pTxtNode, sal_Int32 nPos )
449 : {
450 0 : return pTxtNode->GetTxtAttrForCharAt(nPos);
451 : }
452 :
453 0 : void SwTxtPaintInfo::CtorInitTxtPaintInfo( SwTxtFrm *pFrame, const SwRect &rPaint )
454 : {
455 0 : CtorInitTxtSizeInfo( pFrame );
456 0 : aTxtFly.CtorInitTxtFly( pFrame ),
457 0 : aPaintRect = rPaint;
458 0 : nSpaceIdx = 0;
459 0 : pSpaceAdd = NULL;
460 0 : pWrongList = NULL;
461 0 : pGrammarCheckList = NULL;
462 0 : pSmartTags = NULL;
463 :
464 : #if OSL_DEBUG_LEVEL > 1
465 : pBrushItem = ((SvxBrushItem*)-1);
466 : #else
467 0 : pBrushItem = 0;
468 : #endif
469 0 : }
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 0 : SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf )
485 : : SwTxtSizeInfo( rInf ),
486 0 : pWrongList( rInf.GetpWrongList() ),
487 0 : pGrammarCheckList( rInf.GetGrammarCheckList() ),
488 0 : pSmartTags( rInf.GetSmartTags() ),
489 0 : pSpaceAdd( rInf.GetpSpaceAdd() ),
490 0 : pBrushItem( rInf.GetBrushItem() ),
491 0 : aTxtFly( *rInf.GetTxtFly() ),
492 0 : aPos( rInf.GetPos() ),
493 0 : aPaintRect( rInf.GetPaintRect() ),
494 0 : nSpaceIdx( rInf.GetSpaceIdx() )
495 0 : { }
496 :
497 : extern Color aGlobalRetoucheColor;
498 :
499 : /*************************************************************************
500 : * lcl_IsDarkBackground
501 : *
502 : * Returns if the current background color is dark.
503 : *************************************************************************/
504 :
505 0 : static bool lcl_IsDarkBackground( const SwTxtPaintInfo& rInf )
506 : {
507 0 : const Color* pCol = rInf.GetFont()->GetBackColor();
508 0 : if( ! pCol || COL_TRANSPARENT == pCol->GetColor() )
509 : {
510 : const SvxBrushItem* pItem;
511 0 : SwRect aOrigBackRect;
512 :
513 : //UUUU
514 0 : 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 0 : if( rInf.GetTxtFrm()->GetBackgroundBrush( aFillAttributes, pItem, pCol, aOrigBackRect, false ) )
521 : {
522 0 : if ( !pCol )
523 0 : pCol = &pItem->GetColor();
524 :
525 : // Determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
526 0 : if ( pCol->GetColor() == COL_TRANSPARENT)
527 0 : pCol = NULL;
528 : }
529 : else
530 0 : pCol = NULL;
531 : }
532 :
533 0 : if( !pCol )
534 0 : pCol = &aGlobalRetoucheColor;
535 :
536 0 : return pCol->IsDark();
537 : }
538 :
539 : /*************************************************************************
540 : * SwTxtPaintInfo::_DrawText()
541 : *************************************************************************/
542 :
543 0 : 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 0 : if( !nLength )
550 0 : return;
551 :
552 0 : if( GetFont()->IsBlink() && OnWin() && rPor.Width() )
553 : {
554 : // check if accessibility options allow blinking portions:
555 0 : const SwViewShell* pSh = GetTxtFrm()->getRootFrm()->GetCurrShell();
556 0 : if ( pSh && ! pSh->GetAccessibilityOptions()->IsStopAnimatedText() &&
557 0 : ! pSh->IsPreview() )
558 : {
559 0 : if( !pBlink )
560 0 : pBlink = new SwBlink();
561 :
562 0 : Point aPoint( aPos );
563 :
564 0 : if ( GetTxtFrm()->IsRightToLeft() )
565 0 : GetTxtFrm()->SwitchLTRtoRTL( aPoint );
566 :
567 0 : if ( TEXT_LAYOUT_BIDI_STRONG != GetOut()->GetLayoutMode() )
568 0 : aPoint.X() -= rPor.Width();
569 :
570 0 : if ( GetTxtFrm()->IsVertical() )
571 0 : GetTxtFrm()->SwitchHorizontalToVertical( aPoint );
572 :
573 0 : pBlink->Insert( aPoint, &rPor, GetTxtFrm(), m_pFnt->GetOrientation() );
574 :
575 0 : if( !pBlink->IsVisible() )
576 0 : 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 0 : SwScriptInfo* pSI = 0;
587 0 : if ( ! rPor.InFldGrp() )
588 0 : pSI = &GetParaPortion()->GetScriptInfo();
589 :
590 : // in some cases, kana compression is not allowed or suppressed for
591 : // performance reasons
592 0 : sal_uInt16 nComp = 0;
593 0 : if ( ! IsMulti() )
594 0 : nComp = GetKanaComp();
595 :
596 0 : bool bCfgIsAutoGrammar = false;
597 0 : SvtLinguConfig().GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bCfgIsAutoGrammar;
598 0 : const bool bBullet = OnWin() && GetOpt().IsBlank() && IsNoSymbol();
599 0 : const bool bTmpWrong = bWrong && OnWin() && GetOpt().IsOnlineSpell();
600 0 : const bool bTmpGrammarCheck = bGrammarCheck && OnWin() && bCfgIsAutoGrammar && GetOpt().IsOnlineSpell();
601 0 : 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 0 : rPor.Width(), bBullet );
606 :
607 0 : aDrawInf.SetLeft( GetPaintRect().Left() );
608 0 : aDrawInf.SetRight( GetPaintRect().Right());
609 :
610 0 : aDrawInf.SetUnderFnt( m_pUnderFnt );
611 :
612 0 : const long nSpaceAdd = ( rPor.IsBlankPortion() || rPor.IsDropPortion() ||
613 0 : rPor.InNumberGrp() ) ? 0 : GetSpaceAdd();
614 0 : if ( nSpaceAdd )
615 : {
616 0 : sal_Int32 nCharCnt = 0;
617 : // #i41860# Thai justified alignment needs some
618 : // additional information:
619 0 : aDrawInf.SetNumberOfBlanks( rPor.InTxtGrp() ?
620 0 : static_cast<const SwTxtPortion&>(rPor).GetSpaceCnt( *this, nCharCnt ) :
621 0 : 0 );
622 : }
623 :
624 0 : aDrawInf.SetSpace( nSpaceAdd );
625 0 : aDrawInf.SetKanaComp( nComp );
626 :
627 : // the font is used to identify the current script via nActual
628 0 : aDrawInf.SetFont( m_pFnt );
629 : // the frame is used to identify the orientation
630 0 : aDrawInf.SetFrm( GetTxtFrm() );
631 : // we have to know if the paragraph should snap to grid
632 0 : aDrawInf.SetSnapToGrid( SnapToGrid() );
633 : // for underlining we must know when not to add extra space behind
634 : // a character in justified mode
635 0 : aDrawInf.SetSpaceStop( ! rPor.GetPortion() ||
636 0 : rPor.GetPortion()->InFixMargGrp() ||
637 0 : rPor.GetPortion()->IsHolePortion() );
638 :
639 : // Draw text next to the left border
640 0 : Point aFontPos(aPos);
641 0 : if( m_pFnt->GetLeftBorder() && !static_cast<const SwTxtPortion&>(rPor).GetJoinBorderWithPrev() )
642 : {
643 0 : const sal_uInt16 nLeftBorderSpace = m_pFnt->GetLeftBorderSpace();
644 0 : if ( GetTxtFrm()->IsRightToLeft() )
645 : {
646 0 : aFontPos.X() -= nLeftBorderSpace;
647 : }
648 : else
649 : {
650 0 : switch( m_pFnt->GetOrientation(GetTxtFrm()->IsVertical()) )
651 : {
652 : case 0 :
653 0 : aFontPos.X() += nLeftBorderSpace;
654 0 : 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 0 : if( aFontPos.X() < 0 )
667 0 : aFontPos.X() = 0;
668 0 : if( aFontPos.X() < 0 )
669 0 : aFontPos.X() = 0;
670 : }
671 :
672 0 : if( GetTxtFly()->IsOn() )
673 : {
674 : // aPos needs to be the TopLeft, because we cannot calculate the
675 : // ClipRects otherwise
676 0 : const Point aPoint( aFontPos.X(), aFontPos.Y() - rPor.GetAscent() );
677 0 : const Size aSize( rPor.Width(), rPor.Height() );
678 0 : aDrawInf.SetPos( aPoint );
679 0 : aDrawInf.SetSize( aSize );
680 0 : aDrawInf.SetAscent( rPor.GetAscent() );
681 0 : aDrawInf.SetKern( bKern ? rPor.Width() : 0 );
682 0 : aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
683 0 : aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
684 0 : aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL );
685 0 : GetTxtFly()->DrawTextOpaque( aDrawInf );
686 : }
687 : else
688 : {
689 0 : aDrawInf.SetPos( aFontPos );
690 0 : if( bKern )
691 0 : m_pFnt->_DrawStretchText( aDrawInf );
692 : else
693 : {
694 0 : aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
695 0 : aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
696 0 : aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL );
697 0 : m_pFnt->_DrawText( aDrawInf );
698 : }
699 0 : }
700 : }
701 :
702 0 : void SwTxtPaintInfo::CalcRect( const SwLinePortion& rPor,
703 : SwRect* pRect, SwRect* pIntersect,
704 : const bool bInsideBox ) const
705 : {
706 0 : Size aSize( rPor.Width(), rPor.Height() );
707 0 : if( rPor.IsHangingPortion() )
708 0 : aSize.Width() = ((SwHangingPortion&)rPor).GetInnerWidth();
709 0 : if( rPor.InSpaceGrp() && GetSpaceAdd() )
710 : {
711 0 : SwTwips nAdd = rPor.CalcSpacing( GetSpaceAdd(), *this );
712 0 : if( rPor.InFldGrp() && GetSpaceAdd() < 0 && nAdd )
713 0 : nAdd += GetSpaceAdd() / SPACING_PRECISION_FACTOR;
714 0 : aSize.Width() += nAdd;
715 : }
716 :
717 0 : Point aPoint;
718 :
719 0 : if( IsRotated() )
720 : {
721 0 : long nTmp = aSize.Width();
722 0 : aSize.Width() = aSize.Height();
723 0 : aSize.Height() = nTmp;
724 0 : if ( 1 == GetDirection() )
725 : {
726 0 : aPoint.A() = X() - rPor.GetAscent();
727 0 : 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 0 : aPoint.A() = X();
738 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
739 0 : if ( GetTxtFrm()->IsVertLR() )
740 0 : aPoint.B() = Y() - rPor.Height() + rPor.GetAscent();
741 : else
742 0 : aPoint.B() = Y() - rPor.GetAscent();
743 : }
744 :
745 : // Adjust x coordinate if we are inside a bidi portion
746 0 : const bool bFrmDir = GetTxtFrm()->IsRightToLeft();
747 0 : const bool bCounterDir = ( !bFrmDir && DIR_RIGHT2LEFT == GetDirection() ) ||
748 0 : ( bFrmDir && DIR_LEFT2RIGHT == GetDirection() );
749 :
750 0 : if ( bCounterDir )
751 0 : aPoint.A() -= aSize.Width();
752 :
753 0 : SwRect aRect( aPoint, aSize );
754 :
755 0 : if ( GetTxtFrm()->IsRightToLeft() )
756 0 : GetTxtFrm()->SwitchLTRtoRTL( aRect );
757 :
758 0 : if ( GetTxtFrm()->IsVertical() )
759 0 : GetTxtFrm()->SwitchHorizontalToVertical( aRect );
760 :
761 0 : if( bInsideBox && rPor.InTxtGrp() )
762 : {
763 : const bool bJoinWithPrev =
764 0 : static_cast<const SwTxtPortion&>(rPor).GetJoinBorderWithPrev();
765 : const bool bJoinWithNext =
766 0 : static_cast<const SwTxtPortion&>(rPor).GetJoinBorderWithNext();
767 0 : const bool bIsVert = GetTxtFrm()->IsVertical();
768 0 : aRect.Top(aRect.Top() + GetFont()->CalcShadowSpace(SHADOW_TOP, bIsVert, bJoinWithPrev, bJoinWithNext ));
769 0 : aRect.Bottom(aRect.Bottom() - GetFont()->CalcShadowSpace(SHADOW_BOTTOM, bIsVert, bJoinWithPrev, bJoinWithNext ));
770 0 : aRect.Left(aRect.Left() + GetFont()->CalcShadowSpace(SHADOW_LEFT, bIsVert, bJoinWithPrev, bJoinWithNext ));
771 0 : aRect.Right(aRect.Right() - GetFont()->CalcShadowSpace(SHADOW_RIGHT, bIsVert, bJoinWithPrev, bJoinWithNext ));
772 : }
773 :
774 0 : if ( pRect )
775 0 : *pRect = aRect;
776 :
777 0 : if( aRect.HasArea() && pIntersect )
778 : {
779 0 : ::SwAlignRect( aRect, (SwViewShell*)GetVsh() );
780 :
781 0 : if ( GetOut()->IsClipRegion() )
782 : {
783 0 : SwRect aClip( GetOut()->GetClipRegion().GetBoundRect() );
784 0 : aRect.Intersection( aClip );
785 : }
786 :
787 0 : *pIntersect = aRect;
788 : }
789 0 : }
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 0 : 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 0 : bool bCenter = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_CENTER );
807 0 : bool bRotate = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_ROTATE );
808 :
809 : // rRect is given in absolute coordinates
810 0 : if ( rInf.GetTxtFrm()->IsRightToLeft() )
811 0 : rInf.GetTxtFrm()->SwitchRTLtoLTR( rRect );
812 0 : if ( rInf.GetTxtFrm()->IsVertical() )
813 0 : rInf.GetTxtFrm()->SwitchVerticalToHorizontal( rRect );
814 :
815 0 : const SwFont* pOldFnt = rInf.GetFont();
816 :
817 : // Font is generated only once:
818 : static SwFont* m_pFnt = 0;
819 0 : if ( ! m_pFnt )
820 : {
821 0 : m_pFnt = new SwFont( *pOldFnt );
822 0 : m_pFnt->SetFamily( FAMILY_DONTKNOW, m_pFnt->GetActual() );
823 0 : m_pFnt->SetName( numfunc::GetDefBulletFontname(), m_pFnt->GetActual() );
824 0 : m_pFnt->SetStyleName( aEmptyOUStr, m_pFnt->GetActual() );
825 0 : m_pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, m_pFnt->GetActual() );
826 : }
827 :
828 : // Some of the current values are set at the font:
829 0 : if ( ! bRotate )
830 0 : m_pFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
831 : else
832 0 : m_pFnt->SetVertical( pOldFnt->GetOrientation() );
833 :
834 0 : m_pFnt->SetColor(rCol);
835 :
836 0 : Size aFontSize( 0, SPECIAL_FONT_HEIGHT );
837 0 : m_pFnt->SetSize( aFontSize, m_pFnt->GetActual() );
838 :
839 0 : ((SwTxtPaintInfo&)rInf).SetFont( m_pFnt );
840 :
841 : // The maximum width depends on the current orientation
842 0 : const sal_uInt16 nDir = m_pFnt->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
843 : SwTwips nMaxWidth;
844 0 : if (nDir == 900 || nDir == 2700)
845 0 : nMaxWidth = rRect.Height();
846 : else
847 : {
848 : assert(nDir == 0); //Unknown direction set at font
849 0 : nMaxWidth = rRect.Width();
850 : }
851 :
852 : // check if char fits into rectangle
853 0 : const OUString aTmp( cChar );
854 0 : aFontSize = rInf.GetTxtSize( aTmp ).SvLSize();
855 0 : 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 0 : const Point aOldPos( rInf.GetPos() );
877 :
878 : // adjust values so that tab is vertically and horizontally centered
879 0 : SwTwips nX = rRect.Left();
880 0 : SwTwips nY = rRect.Top();
881 0 : switch ( nDir )
882 : {
883 : case 0 :
884 0 : if ( bCenter )
885 0 : nX += ( rRect.Width() - aFontSize.Width() ) / 2;
886 0 : nY += ( rRect.Height() - aFontSize.Height() ) / 2 + rInf.GetAscent();
887 0 : 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 0 : Point aTmpPos( nX, nY );
901 0 : ((SwTxtPaintInfo&)rInf).SetPos( aTmpPos );
902 0 : sal_uInt16 nOldWidth = rPor.Width();
903 0 : ((SwLinePortion&)rPor).Width( (sal_uInt16)aFontSize.Width() );
904 0 : rInf.DrawText( aTmp, rPor );
905 0 : ((SwLinePortion&)rPor).Width( nOldWidth );
906 0 : ((SwTxtPaintInfo&)rInf).SetFont( (SwFont*)pOldFnt );
907 0 : ((SwTxtPaintInfo&)rInf).SetPos( aOldPos );
908 0 : }
909 :
910 0 : void SwTxtPaintInfo::DrawRect( const SwRect &rRect, bool bNoGraphic,
911 : bool bRetouche ) const
912 : {
913 0 : if ( OnWin() || !bRetouche )
914 : {
915 0 : if( aTxtFly.IsOn() )
916 : ((SwTxtPaintInfo*)this)->GetTxtFly()->
917 0 : DrawFlyRect( m_pOut, rRect, *this, bNoGraphic );
918 0 : else if ( bNoGraphic )
919 0 : 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 0 : }
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 0 : void SwTxtPaintInfo::DrawRedArrow( const SwLinePortion &rPor ) const
998 : {
999 0 : Size aSize( SPECIAL_FONT_HEIGHT, SPECIAL_FONT_HEIGHT );
1000 0 : SwRect aRect( ((SwArrowPortion&)rPor).GetPos(), aSize );
1001 : sal_Unicode cChar;
1002 0 : 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 0 : if( aSize.Height() > rPor.Height() )
1013 0 : aRect.Height( rPor.Height() );
1014 0 : aRect.Pos().Y() -= aRect.Height() + 20;
1015 0 : aRect.Pos().X() -= aRect.Width() + 20;
1016 0 : cChar = CHAR_RIGHT_ARROW;
1017 : }
1018 :
1019 0 : if ( GetTxtFrm()->IsVertical() )
1020 0 : GetTxtFrm()->SwitchHorizontalToVertical( aRect );
1021 :
1022 0 : Color aCol( COL_LIGHTRED );
1023 :
1024 0 : if( aRect.HasArea() )
1025 : {
1026 0 : const sal_uInt8 nOptions = 0;
1027 0 : lcl_DrawSpecial( *this, rPor, aRect, aCol, cChar, nOptions );
1028 : }
1029 0 : }
1030 :
1031 0 : void SwTxtPaintInfo::DrawPostIts( const SwLinePortion&, bool bScript ) const
1032 : {
1033 0 : if( OnWin() && m_pOpt->IsPostIts() )
1034 : {
1035 0 : Size aSize;
1036 0 : Point aTmp;
1037 :
1038 0 : const sal_uInt16 nPostItsWidth = m_pOpt->GetPostItsWidth( GetOut() );
1039 0 : const sal_uInt16 nFontHeight = m_pFnt->GetHeight( m_pVsh, *GetOut() );
1040 0 : const sal_uInt16 nFontAscent = m_pFnt->GetAscent( m_pVsh, *GetOut() );
1041 :
1042 0 : switch ( m_pFnt->GetOrientation( GetTxtFrm()->IsVertical() ) )
1043 : {
1044 : case 0 :
1045 0 : aSize.Width() = nPostItsWidth;
1046 0 : aSize.Height() = nFontHeight;
1047 0 : aTmp.X() = aPos.X();
1048 0 : aTmp.Y() = aPos.Y() - nFontAscent;
1049 0 : 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 0 : SwRect aTmpRect( aTmp, aSize );
1066 :
1067 0 : if ( GetTxtFrm()->IsRightToLeft() )
1068 0 : GetTxtFrm()->SwitchLTRtoRTL( aTmpRect );
1069 :
1070 0 : if ( GetTxtFrm()->IsVertical() )
1071 0 : GetTxtFrm()->SwitchHorizontalToVertical( aTmpRect );
1072 :
1073 0 : const Rectangle aRect( aTmpRect.SVRect() );
1074 0 : m_pOpt->PaintPostIts( (OutputDevice*)GetOut(), aRect, bScript );
1075 : }
1076 0 : }
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 0 : void SwTxtPaintInfo::DrawBackground( const SwLinePortion &rPor ) const
1110 : {
1111 : OSL_ENSURE( OnWin(), "SwTxtPaintInfo::DrawBackground: printer pollution ?" );
1112 :
1113 0 : SwRect aIntersect;
1114 0 : CalcRect( rPor, 0, &aIntersect, true );
1115 :
1116 0 : if ( aIntersect.HasArea() )
1117 : {
1118 0 : OutputDevice* pOut = (OutputDevice*)GetOut();
1119 0 : pOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
1120 :
1121 : // For dark background we do not want to have a filled rectangle
1122 0 : if ( GetVsh() && GetVsh()->GetWin() && lcl_IsDarkBackground( *this ) )
1123 : {
1124 0 : pOut->SetLineColor( SwViewOption::GetFontColor().GetColor() );
1125 : }
1126 : else
1127 : {
1128 0 : pOut->SetFillColor( SwViewOption::GetFieldShadingsColor() );
1129 0 : pOut->SetLineColor();
1130 : }
1131 :
1132 0 : DrawRect( aIntersect, true );
1133 0 : pOut->Pop();
1134 : }
1135 0 : }
1136 :
1137 0 : void SwTxtPaintInfo::DrawBackBrush( const SwLinePortion &rPor ) const
1138 : {
1139 : {
1140 0 : SwRect aIntersect;
1141 0 : CalcRect( rPor, &aIntersect, 0, true );
1142 0 : if(aIntersect.HasArea())
1143 : {
1144 0 : SwTxtNode *pNd = m_pFrm->GetTxtNode();
1145 0 : const ::sw::mark::IMark* pFieldmark = NULL;
1146 0 : if(pNd)
1147 : {
1148 0 : const SwDoc *doc=pNd->GetDoc();
1149 0 : if(doc)
1150 : {
1151 0 : SwIndex aIndex(pNd, GetIdx());
1152 0 : SwPosition aPosition(*pNd, aIndex);
1153 0 : pFieldmark=doc->getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
1154 : }
1155 : }
1156 0 : 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 0 : if (OnWin() && (pFieldmark!=NULL || bIsStartMark) &&
1166 0 : 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 0 : SwRect aIntersect;
1180 0 : CalcRect( rPor, 0, &aIntersect, true );
1181 :
1182 0 : if ( aIntersect.HasArea() )
1183 : {
1184 0 : OutputDevice* pTmpOut = (OutputDevice*)GetOut();
1185 :
1186 : // #i16816# tagged pdf support
1187 0 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pTmpOut );
1188 :
1189 0 : Color aFillColor;
1190 :
1191 0 : if( m_pFnt->GetHighlightColor() != COL_TRANSPARENT )
1192 : {
1193 0 : aFillColor = m_pFnt->GetHighlightColor();
1194 : }
1195 : else
1196 : {
1197 0 : if( !m_pFnt->GetBackColor() )
1198 0 : return;
1199 0 : aFillColor = *m_pFnt->GetBackColor();
1200 : }
1201 :
1202 0 : pTmpOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
1203 :
1204 0 : pTmpOut->SetFillColor(aFillColor);
1205 0 : pTmpOut->SetLineColor();
1206 :
1207 0 : DrawRect( aIntersect, true, false );
1208 :
1209 0 : pTmpOut->Pop();
1210 : }
1211 : }
1212 :
1213 0 : void SwTxtPaintInfo::DrawBorder( const SwLinePortion &rPor ) const
1214 : {
1215 0 : SwRect aDrawArea;
1216 0 : CalcRect( rPor, &aDrawArea );
1217 0 : if ( aDrawArea.HasArea() )
1218 : {
1219 : PaintCharacterBorder(
1220 0 : *m_pFnt, aDrawArea, GetTxtFrm()->IsVertical(),
1221 0 : rPor.GetJoinBorderWithPrev(), rPor.GetJoinBorderWithNext());
1222 : }
1223 0 : }
1224 :
1225 0 : void SwTxtPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
1226 : const MSHORT nWhich ) const
1227 : {
1228 0 : if( OnWin() && !IsMulti() )
1229 : {
1230 0 : bool bDraw = false;
1231 0 : 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 0 : if ( !GetOpt().IsPagePreview()
1244 0 : && !GetOpt().IsReadonly()
1245 0 : && SwViewOption::IsFieldShadings()
1246 0 : && ( POR_NUMBER != nWhich
1247 0 : || m_pFrm->GetTxtNode()->HasMarkedLabel())) // #i27615#
1248 : {
1249 0 : bDraw = true;
1250 : }
1251 0 : break;
1252 : case POR_INPUTFLD:
1253 : // input field shading also in read-only mode
1254 0 : if ( !GetOpt().IsPagePreview()
1255 0 : && SwViewOption::IsFieldShadings() )
1256 : {
1257 0 : bDraw = true;
1258 : }
1259 0 : break;
1260 0 : case POR_TAB: if ( GetOpt().IsTab() ) bDraw = true; break;
1261 0 : case POR_SOFTHYPH: if ( GetOpt().IsSoftHyph() )bDraw = true; break;
1262 0 : 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 0 : if ( bDraw )
1270 0 : DrawBackground( rPor );
1271 : }
1272 0 : }
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 0 : static void lcl_InitHyphValues( PropertyValues &rVals,
1296 : sal_Int16 nMinLeading, sal_Int16 nMinTrailing )
1297 : {
1298 0 : sal_Int32 nLen = rVals.getLength();
1299 :
1300 0 : if (0 == nLen) // yet to be initialized?
1301 : {
1302 0 : rVals.realloc( 2 );
1303 0 : PropertyValue *pVal = rVals.getArray();
1304 :
1305 0 : pVal[0].Name = UPN_HYPH_MIN_LEADING;
1306 0 : pVal[0].Handle = UPH_HYPH_MIN_LEADING;
1307 0 : pVal[0].Value <<= nMinLeading;
1308 :
1309 0 : pVal[1].Name = UPN_HYPH_MIN_TRAILING;
1310 0 : pVal[1].Handle = UPH_HYPH_MIN_TRAILING;
1311 0 : 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 0 : }
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 0 : bool SwTxtFormatInfo::InitHyph( const bool bAutoHyphen )
1332 : {
1333 0 : const SwAttrSet& rAttrSet = GetTxtFrm()->GetTxtNode()->GetSwAttrSet();
1334 0 : SetHanging( rAttrSet.GetHangingPunctuation().GetValue() );
1335 0 : SetScriptSpace( rAttrSet.GetScriptSpace().GetValue() );
1336 0 : SetForbiddenChars( rAttrSet.GetForbiddenRule().GetValue() );
1337 0 : const SvxHyphenZoneItem &rAttr = rAttrSet.GetHyphenZone();
1338 0 : MaxHyph() = rAttr.GetMaxHyphens();
1339 0 : const bool bAuto = bAutoHyphen || rAttr.IsHyphen();
1340 0 : if( bAuto || bInterHyph )
1341 : {
1342 0 : const sal_Int16 nMinimalLeading = std::max(rAttr.GetMinLead(), sal_uInt8(2));
1343 0 : const sal_Int16 nMinimalTrailing = rAttr.GetMinTrail();
1344 0 : lcl_InitHyphValues( aHyphVals, nMinimalLeading, nMinimalTrailing);
1345 : }
1346 0 : return bAuto;
1347 : }
1348 :
1349 0 : void SwTxtFormatInfo::CtorInitTxtFormatInfo( SwTxtFrm *pNewFrm, const bool bNewInterHyph,
1350 : const bool bNewQuick, const bool bTst )
1351 : {
1352 0 : CtorInitTxtPaintInfo( pNewFrm, SwRect() );
1353 :
1354 0 : bQuick = bNewQuick;
1355 0 : bInterHyph = bNewInterHyph;
1356 :
1357 : //! needs to be done in this order
1358 0 : nMinLeading = 2;
1359 0 : nMinTrailing = 2;
1360 0 : nMinWordLength = 0;
1361 0 : bAutoHyph = InitHyph();
1362 :
1363 0 : bIgnoreFly = false;
1364 0 : bFakeLineStart = false;
1365 0 : bShift = false;
1366 0 : bDropInit = false;
1367 0 : bTestFormat = bTst;
1368 0 : nLeft = 0;
1369 0 : nRight = 0;
1370 0 : nFirst = 0;
1371 0 : nRealWidth = 0;
1372 0 : nForcedLeftMargin = 0;
1373 0 : pRest = 0;
1374 0 : nLineHeight = 0;
1375 0 : nLineNettoHeight = 0;
1376 0 : SetLineStart(0);
1377 0 : Init();
1378 0 : }
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 0 : bool SwTxtFormatInfo::IsHyphenate() const
1389 : {
1390 0 : if( !bInterHyph && !bAutoHyph )
1391 0 : 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 0 : const SwFmtDrop *SwTxtFormatInfo::GetDropFmt() const
1413 : {
1414 0 : const SwFmtDrop *pDrop = &GetTxtFrm()->GetTxtNode()->GetSwAttrSet().GetDrop();
1415 0 : if( 1 >= pDrop->GetLines() ||
1416 0 : ( !pDrop->GetChars() && !pDrop->GetWholeWord() ) )
1417 0 : pDrop = 0;
1418 0 : return pDrop;
1419 : }
1420 :
1421 0 : void SwTxtFormatInfo::Init()
1422 : {
1423 : // Not initialized: pRest, nLeft, nRight, nFirst, nRealWidth
1424 0 : X(0);
1425 : bArrowDone = bFull = bFtnDone = bErgoDone = bNumDone = bNoEndHyph =
1426 0 : bNoMidHyph = bStop = bNewLine = bUnderflow = bTabOverflow = false;
1427 :
1428 : // generally we do not allow number portions in follows, except...
1429 0 : if ( GetTxtFrm()->IsFollow() )
1430 : {
1431 0 : const SwTxtFrm* pMaster = GetTxtFrm()->FindMaster();
1432 : OSL_ENSURE(pMaster, "pTxtFrm without Master");
1433 0 : 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 0 : bNumDone = ! pTmpPara ||
1438 0 : ! ((SwParaPortion*)pTmpPara)->GetFirstPortion()->IsFlyPortion();
1439 : }
1440 :
1441 0 : pRoot = 0;
1442 0 : pLast = 0;
1443 0 : pFly = 0;
1444 0 : pLastFld = 0;
1445 0 : pLastTab = 0;
1446 0 : pUnderflow = 0;
1447 0 : cTabDecimal = 0;
1448 0 : nWidth = nRealWidth;
1449 0 : nForcedLeftMargin = 0;
1450 0 : nSoftHyphPos = 0;
1451 0 : nUnderScorePos = COMPLETE_STRING;
1452 0 : cHookChar = 0;
1453 0 : SetIdx(0);
1454 0 : SetLen( GetTxt().getLength() );
1455 0 : SetPaintOfst(0);
1456 0 : }
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 0 : SwTxtFormatInfo::SwTxtFormatInfo( const SwTxtFormatInfo& rInf,
1468 : SwLineLayout& rLay, SwTwips nActWidth ) : SwTxtPaintInfo( rInf ),
1469 0 : bTabOverflow( false )
1470 : {
1471 0 : pRoot = &rLay;
1472 0 : pLast = &rLay;
1473 0 : pFly = NULL;
1474 0 : pLastFld = NULL;
1475 0 : pUnderflow = NULL;
1476 0 : pRest = NULL;
1477 0 : pLastTab = NULL;
1478 :
1479 0 : nSoftHyphPos = 0;
1480 0 : nUnderScorePos = COMPLETE_STRING;
1481 0 : nLineStart = rInf.GetIdx();
1482 0 : nLeft = rInf.nLeft;
1483 0 : nRight = rInf.nRight;
1484 0 : nFirst = rInf.nLeft;
1485 0 : nRealWidth = KSHORT(nActWidth);
1486 0 : nWidth = nRealWidth;
1487 0 : nLineHeight = 0;
1488 0 : nLineNettoHeight = 0;
1489 0 : nForcedLeftMargin = 0;
1490 :
1491 0 : nMinLeading = 0;
1492 0 : nMinTrailing = 0;
1493 0 : nMinWordLength = 0;
1494 0 : bFull = false;
1495 0 : bFtnDone = true;
1496 0 : bErgoDone = true;
1497 0 : bNumDone = true;
1498 0 : bArrowDone = true;
1499 0 : bStop = false;
1500 0 : bNewLine = true;
1501 0 : bShift = false;
1502 0 : bUnderflow = false;
1503 0 : bInterHyph = false;
1504 0 : bAutoHyph = false;
1505 0 : bDropInit = false;
1506 0 : bQuick = rInf.bQuick;
1507 0 : bNoEndHyph = false;
1508 0 : bNoMidHyph = false;
1509 0 : bIgnoreFly = false;
1510 0 : bFakeLineStart = false;
1511 :
1512 0 : cTabDecimal = 0;
1513 0 : cHookChar = 0;
1514 0 : nMaxHyph = 0;
1515 0 : bTestFormat = rInf.bTestFormat;
1516 0 : SetMulti( true );
1517 0 : SetFirstMulti( rInf.IsFirstMulti() );
1518 0 : }
1519 :
1520 0 : bool SwTxtFormatInfo::_CheckFtnPortion( SwLineLayout* pCurr )
1521 : {
1522 0 : const KSHORT nHeight = pCurr->GetRealHeight();
1523 0 : for( SwLinePortion *pPor = pCurr->GetPortion(); pPor; pPor = pPor->GetPortion() )
1524 : {
1525 0 : if( pPor->IsFtnPortion() && nHeight > ((SwFtnPortion*)pPor)->Orig() )
1526 : {
1527 0 : SetLineHeight( nHeight );
1528 0 : SetLineNettoHeight( pCurr->Height() );
1529 0 : return true;
1530 : }
1531 : }
1532 0 : return false;
1533 : }
1534 :
1535 0 : sal_Int32 SwTxtFormatInfo::ScanPortionEnd( const sal_Int32 nStart,
1536 : const sal_Int32 nEnd )
1537 : {
1538 0 : cHookChar = 0;
1539 0 : sal_Int32 i = nStart;
1540 :
1541 : // Used for decimal tab handling:
1542 :
1543 0 : const sal_Unicode cTabDec = GetLastTab() ? (sal_Unicode)GetTabDecimal() : 0;
1544 0 : const sal_Unicode cThousandSep = ',' == cTabDec ? '.' : ',';
1545 : // #i45951# German (Switzerland) uses ' as thousand separator
1546 0 : const sal_Unicode cThousandSep2 = ',' == cTabDec ? '.' : '\'';
1547 :
1548 0 : bool bNumFound = false;
1549 0 : const bool bTabCompat = GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
1550 :
1551 0 : for( ; i < nEnd; ++i )
1552 : {
1553 0 : const sal_Unicode cPos = GetChar( i );
1554 0 : 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 0 : cHookChar = cPos;
1570 0 : return i;
1571 :
1572 : case CHAR_UNDERSCORE:
1573 0 : if ( COMPLETE_STRING == nUnderScorePos )
1574 0 : nUnderScorePos = i;
1575 0 : break;
1576 :
1577 : default:
1578 0 : if ( cTabDec )
1579 : {
1580 0 : if( cTabDec == cPos )
1581 : {
1582 : OSL_ENSURE( cPos, "Unexpected end of string" );
1583 0 : if( cPos ) // robust
1584 : {
1585 0 : cHookChar = cPos;
1586 0 : return i;
1587 : }
1588 : }
1589 :
1590 : // Compatibility: First non-digit character behind a
1591 : // a digit character becomes the hook character
1592 :
1593 0 : if ( bTabCompat )
1594 : {
1595 0 : if ( ( 0x2F < cPos && cPos < 0x3A ) ||
1596 0 : ( bNumFound && ( cPos == cThousandSep || cPos == cThousandSep2 ) ) )
1597 : {
1598 0 : bNumFound = true;
1599 : }
1600 : else
1601 : {
1602 0 : if ( bNumFound )
1603 : {
1604 0 : cHookChar = cPos;
1605 0 : SetTabDecimal( cPos );
1606 0 : return i;
1607 : }
1608 : }
1609 : }
1610 : }
1611 : }
1612 : }
1613 :
1614 : // Check if character *behind* the portion has
1615 : // to become the hook:
1616 0 : if ( i == nEnd && i < GetTxt().getLength() && bNumFound )
1617 : {
1618 0 : const sal_Unicode cPos = GetChar( i );
1619 0 : if ( cPos != cTabDec && cPos != cThousandSep && cPos !=cThousandSep2 && ( 0x2F >= cPos || cPos >= 0x3A ) )
1620 : {
1621 0 : cHookChar = GetChar( i );
1622 0 : SetTabDecimal( cHookChar );
1623 : }
1624 : }
1625 :
1626 0 : return i;
1627 : }
1628 :
1629 0 : bool SwTxtFormatInfo::LastKernPortion()
1630 : {
1631 0 : if( GetLast() )
1632 : {
1633 0 : if( GetLast()->IsKernPortion() )
1634 0 : return true;
1635 0 : if( GetLast()->Width() || ( GetLast()->GetLen() &&
1636 0 : !GetLast()->IsHolePortion() ) )
1637 0 : return false;
1638 : }
1639 0 : SwLinePortion* pPor = GetRoot();
1640 0 : SwLinePortion *pKern = NULL;
1641 0 : while( pPor )
1642 : {
1643 0 : if( pPor->IsKernPortion() )
1644 0 : pKern = pPor;
1645 0 : else if( pPor->Width() || ( pPor->GetLen() && !pPor->IsHolePortion() ) )
1646 0 : pKern = NULL;
1647 0 : pPor = pPor->GetPortion();
1648 : }
1649 0 : if( pKern )
1650 : {
1651 0 : SetLast( pKern );
1652 0 : return true;
1653 : }
1654 0 : return false;
1655 : }
1656 :
1657 0 : 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 0 : , pInf(NULL)
1670 : {
1671 0 : if( pCh )
1672 : {
1673 0 : aTxt = OUString( pCh, strlen(pCh), RTL_TEXTENCODING_MS_1252 );
1674 0 : bOn = true;
1675 : }
1676 : else
1677 0 : bOn = pPor->GetExpTxt( *pNew, aTxt );
1678 :
1679 : // The text is replaced ...
1680 0 : if( bOn )
1681 : {
1682 0 : pInf = (SwTxtSizeInfo*)pNew;
1683 0 : nIdx = pInf->GetIdx();
1684 0 : nLen = pInf->GetLen();
1685 0 : pOldTxt = &(pInf->GetTxt());
1686 0 : pInf->SetTxt( aTxt );
1687 0 : pInf->SetIdx( 0 );
1688 0 : pInf->SetLen( bTxtLen ? pInf->GetTxt().getLength() : pPor->GetLen() );
1689 :
1690 : // ST2
1691 0 : if ( bExgLists )
1692 : {
1693 0 : pOldSmartTagList = static_cast<SwTxtPaintInfo*>(pInf)->GetSmartTags();
1694 0 : 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 0 : pOldGrammarCheckList = static_cast<SwTxtPaintInfo*>(pInf)->GetGrammarCheckList();
1710 0 : 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 0 : }
1728 :
1729 0 : SwTxtSlot::~SwTxtSlot()
1730 : {
1731 0 : if( bOn )
1732 : {
1733 0 : pInf->SetTxt( *pOldTxt );
1734 0 : pInf->SetIdx( nIdx );
1735 0 : pInf->SetLen( nLen );
1736 :
1737 : // ST2
1738 : // Restore old smart tag list
1739 0 : if ( pOldSmartTagList )
1740 0 : ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList );
1741 0 : if ( pOldGrammarCheckList )
1742 0 : ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList );
1743 0 : delete pTempList;
1744 : }
1745 0 : }
1746 :
1747 0 : SwFontSave::SwFontSave(const SwTxtSizeInfo &rInf, SwFont *pNew,
1748 : SwAttrIter* pItr)
1749 : : pInf(NULL)
1750 : , pFnt(pNew ? ((SwTxtSizeInfo&)rInf).GetFont() : NULL)
1751 0 : , pIter(NULL)
1752 : {
1753 0 : if( pFnt )
1754 : {
1755 0 : 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 0 : if( pFnt->DifferentMagic( pNew, pFnt->GetActual() ) ||
1761 0 : pNew->GetActual() != pFnt->GetActual() ||
1762 0 : ( ! pNew->GetBackColor() && pFnt->GetBackColor() ) ||
1763 0 : ( pNew->GetBackColor() && ! pFnt->GetBackColor() ) ||
1764 0 : ( pNew->GetBackColor() && pFnt->GetBackColor() &&
1765 0 : ( *pNew->GetBackColor() != *pFnt->GetBackColor() ) ) )
1766 : {
1767 0 : pNew->SetTransparent( true );
1768 0 : pNew->SetAlign( ALIGN_BASELINE );
1769 0 : pInf->SetFont( pNew );
1770 : }
1771 : else
1772 0 : pFnt = 0;
1773 0 : pNew->Invalidate();
1774 0 : pNew->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
1775 0 : if( pItr && pItr->GetFnt() == pFnt )
1776 : {
1777 0 : pIter = pItr;
1778 0 : pIter->SetFnt( pNew );
1779 : }
1780 : }
1781 0 : }
1782 :
1783 0 : SwFontSave::~SwFontSave()
1784 : {
1785 0 : if( pFnt )
1786 : {
1787 : // Reset SwFont
1788 0 : pFnt->Invalidate();
1789 0 : pInf->SetFont( pFnt );
1790 0 : if( pIter )
1791 : {
1792 0 : pIter->SetFnt( pFnt );
1793 0 : pIter->nPos = COMPLETE_STRING;
1794 : }
1795 : }
1796 0 : }
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: */
|