Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <hintids.hxx>
30 : :
31 : : #include <com/sun/star/i18n/ScriptType.hpp>
32 : : #include <vcl/graph.hxx>
33 : : #include <editeng/brshitem.hxx>
34 : : #include <vcl/metric.hxx>
35 : : #include <vcl/outdev.hxx>
36 : : #include <viewopt.hxx> // SwViewOptions
37 : : #include <SwPortionHandler.hxx>
38 : : #include <porlay.hxx>
39 : : #include <porfld.hxx>
40 : : #include <inftxt.hxx>
41 : : #include <blink.hxx> // pBlink
42 : : #include <frmtool.hxx> // DrawGraphic
43 : : #include <viewsh.hxx>
44 : : #include <docsh.hxx>
45 : : #include <doc.hxx>
46 : : #include "rootfrm.hxx"
47 : : #include <breakit.hxx>
48 : : #include <porrst.hxx>
49 : : #include <porftn.hxx> // SwFtnPortion
50 : : #include <accessibilityoptions.hxx>
51 : : #include <editeng/lrspitem.hxx>
52 : :
53 : : #include <unicode/ubidi.h>
54 : :
55 : : using namespace ::com::sun::star;
56 : :
57 : : /*************************************************************************
58 : : * class SwFldPortion
59 : : *************************************************************************/
60 : :
61 : 2033 : SwLinePortion *SwFldPortion::Compress()
62 [ + + ][ + + ]: 2033 : { return (GetLen() || aExpand.Len() || SwLinePortion::Compress()) ? this : 0; }
[ - + ]
63 : :
64 : 336 : SwFldPortion *SwFldPortion::Clone( const XubString &rExpand ) const
65 : : {
66 : : SwFont *pNewFnt;
67 [ + - ]: 336 : if( 0 != ( pNewFnt = pFnt ) )
68 : : {
69 [ + - ]: 336 : pNewFnt = new SwFont( *pFnt );
70 : : }
71 : : // #i107143#
72 : : // pass placeholder property to created <SwFldPortion> instance.
73 [ + - ]: 336 : SwFldPortion* pClone = new SwFldPortion( rExpand, pNewFnt, bPlaceHolder );
74 : 336 : pClone->SetNextOffset( nNextOffset );
75 : 336 : pClone->m_bNoLength = this->m_bNoLength;
76 : 336 : return pClone;
77 : : }
78 : :
79 : 0 : void SwFldPortion::TakeNextOffset( const SwFldPortion* pFld )
80 : : {
81 : : OSL_ENSURE( pFld, "TakeNextOffset: Missing Source" );
82 : 0 : nNextOffset = pFld->GetNextOffset();
83 : 0 : aExpand.Erase( 0, nNextOffset );
84 : 0 : bFollow = sal_True;
85 : 0 : }
86 : :
87 : 2089 : SwFldPortion::SwFldPortion( const XubString &rExpand, SwFont *pFont, sal_Bool bPlaceHold )
88 : : : aExpand(rExpand), pFnt(pFont), nNextOffset(0), nNextScriptChg(STRING_LEN), nViewWidth(0),
89 : : bFollow( sal_False ), bHasFollow( sal_False ), bPlaceHolder( bPlaceHold )
90 [ + - ]: 2089 : , m_bNoLength( sal_False )
91 : : {
92 : 2089 : SetWhichPor( POR_FLD );
93 : 2089 : }
94 : :
95 : 0 : SwFldPortion::SwFldPortion( const SwFldPortion& rFld )
96 : : : SwExpandPortion( rFld ),
97 : 0 : aExpand( rFld.GetExp() ),
98 : 0 : nNextOffset( rFld.GetNextOffset() ),
99 : 0 : nNextScriptChg( rFld.GetNextScriptChg() ),
100 : 0 : bFollow( rFld.IsFollow() ),
101 : 0 : bLeft( rFld.IsLeft() ),
102 : 0 : bHide( rFld.IsHide() ),
103 : 0 : bCenter( rFld.IsCenter() ),
104 : 0 : bHasFollow( rFld.HasFollow() ),
105 : : bPlaceHolder( rFld.bPlaceHolder )
106 [ # # ]: 0 : , m_bNoLength( rFld.m_bNoLength )
107 : : {
108 [ # # ]: 0 : if ( rFld.HasFont() )
109 [ # # ][ # # ]: 0 : pFnt = new SwFont( *rFld.GetFont() );
110 : : else
111 : 0 : pFnt = 0;
112 : :
113 : 0 : SetWhichPor( POR_FLD );
114 : 0 : }
115 : :
116 [ + - ]: 2089 : SwFldPortion::~SwFldPortion()
117 : : {
118 [ + + ][ + - ]: 2089 : delete pFnt;
119 [ + + ]: 2089 : if( pBlink )
120 [ + - ]: 136 : pBlink->Delete( this );
121 [ - + ]: 3500 : }
122 : :
123 : : /*************************************************************************
124 : : * virtual SwFldPortion::GetViewWidth()
125 : : *************************************************************************/
126 : :
127 : 984 : KSHORT SwFldPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
128 : : {
129 : : // Wir stehen zwar im const, aber nViewWidth sollte erst im letzten
130 : : // Moment errechnet werden:
131 : 984 : SwFldPortion* pThis = (SwFldPortion*)this;
132 [ + - ][ + - ]: 2952 : if( !Width() && rInf.OnWin() && !rInf.GetOpt().IsPagePreview() &&
[ + - + -
+ - ][ + - ]
133 : 1968 : !rInf.GetOpt().IsReadonly() && SwViewOption::IsFieldShadings() )
134 : : {
135 [ + + ]: 984 : if( !nViewWidth )
136 [ + - ][ + - ]: 477 : pThis->nViewWidth = rInf.GetTxtSize(rtl::OUString(' ')).Width();
[ + - ]
137 : : }
138 : : else
139 : 0 : pThis->nViewWidth = 0;
140 : 984 : return nViewWidth;
141 : : }
142 : :
143 : : /*************************************************************************
144 : : * virtual SwFldPortion::Format()
145 : : *************************************************************************/
146 : :
147 : : // 8653: in keinem Fall nur SetLen(0);
148 : :
149 : : /*************************************************************************
150 : : * Hilfsklasse SwFldSlot
151 : : **************************************************************************/
152 : :
153 : : class SwFldSlot
154 : : {
155 : : const XubString *pOldTxt;
156 : : XubString aTxt;
157 : : xub_StrLen nIdx;
158 : : xub_StrLen nLen;
159 : : sal_Bool bOn;
160 : : SwTxtFormatInfo *pInf;
161 : : public:
162 : : SwFldSlot( const SwTxtFormatInfo* pNew, const SwFldPortion *pPor );
163 : : ~SwFldSlot();
164 : : };
165 : :
166 : 1753 : SwFldSlot::SwFldSlot( const SwTxtFormatInfo* pNew, const SwFldPortion *pPor )
167 : : {
168 [ + - ]: 1753 : bOn = pPor->GetExpTxt( *pNew, aTxt );
169 : :
170 : : // Der Text wird ausgetauscht...
171 [ + - ]: 1753 : if( bOn )
172 : : {
173 : 1753 : pInf = (SwTxtFormatInfo*)pNew;
174 : 1753 : nIdx = pInf->GetIdx();
175 : 1753 : nLen = pInf->GetLen();
176 : 1753 : pOldTxt = &(pInf->GetTxt());
177 : 1753 : pInf->SetLen( aTxt.Len() );
178 [ + + ]: 1753 : if( pPor->IsFollow() )
179 : : {
180 : 510 : pInf->SetFakeLineStart( nIdx > pInf->GetLineStart() );
181 : 510 : pInf->SetIdx( 0 );
182 : : }
183 : : else
184 : : {
185 [ + - ]: 1243 : XubString aTmp( aTxt );
186 [ + - ]: 1243 : aTxt = *pOldTxt;
187 [ + - ]: 1243 : aTxt.Erase( nIdx, 1 );
188 [ + - ][ + - ]: 1243 : aTxt.Insert( aTmp, nIdx );
189 : : }
190 : 1753 : pInf->SetTxt( aTxt );
191 : : }
192 : 1753 : }
193 : :
194 : 1753 : SwFldSlot::~SwFldSlot()
195 : : {
196 [ + - ]: 1753 : if( bOn )
197 : : {
198 : 1753 : pInf->SetTxt( *pOldTxt );
199 : 1753 : pInf->SetIdx( nIdx );
200 : 1753 : pInf->SetLen( nLen );
201 : 1753 : pInf->SetFakeLineStart( sal_False );
202 : : }
203 : 1753 : }
204 : :
205 : 1753 : void SwFldPortion::CheckScript( const SwTxtSizeInfo &rInf )
206 : : {
207 [ + - ]: 1753 : String aTxt;
208 [ + - ][ + - ]: 1753 : if( GetExpTxt( rInf, aTxt ) && aTxt.Len() && pBreakIt->GetBreakIter().is() )
[ + + ][ + - ]
[ + - ][ + + ]
[ + + # # ]
209 : : {
210 [ + + ]: 1031 : sal_uInt8 nActual = pFnt ? pFnt->GetActual() : rInf.GetFont()->GetActual();
211 : : sal_uInt16 nScript;
212 : : {
213 [ + - ][ + - ]: 1031 : nScript = pBreakIt->GetBreakIter()->getScriptType( aTxt, 0 );
[ + - ][ + - ]
214 : 1031 : xub_StrLen nChg = 0;
215 [ + + ]: 1031 : if( i18n::ScriptType::WEAK == nScript )
216 : : {
217 [ + - ][ + - ]: 26 : nChg =(xub_StrLen)pBreakIt->GetBreakIter()->endOfScript(aTxt,0,nScript);
[ + - ][ + - ]
218 [ + + ]: 26 : if( nChg < aTxt.Len() )
219 [ + - ][ + - ]: 14 : nScript = pBreakIt->GetBreakIter()->getScriptType( aTxt, nChg );
[ + - ][ + - ]
220 : : }
221 : :
222 : : //
223 : : // nNextScriptChg will be evaluated during SwFldPortion::Format()
224 : : //
225 [ + + ]: 1031 : if ( nChg < aTxt.Len() )
226 [ + - ][ + - ]: 1019 : nNextScriptChg = (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( aTxt, nChg, nScript );
[ + - ][ + - ]
227 : : else
228 : 12 : nNextScriptChg = aTxt.Len();
229 : :
230 : : }
231 : : sal_uInt8 nTmp;
232 [ + - - + ]: 1031 : switch ( nScript ) {
233 : 1019 : case i18n::ScriptType::LATIN : nTmp = SW_LATIN; break;
234 : 0 : case i18n::ScriptType::ASIAN : nTmp = SW_CJK; break;
235 : 0 : case i18n::ScriptType::COMPLEX : nTmp = SW_CTL; break;
236 : 12 : default: nTmp = nActual;
237 : : }
238 : :
239 : : // #i16354# Change script type for RTL text to CTL.
240 : 1031 : const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
241 : : // #i98418#
242 : 1864 : const sal_uInt8 nFldDir = ( IsNumberPortion() || IsFtnNumPortion() ) ?
243 : : rSI.GetDefaultDir() :
244 [ + + ][ + - ]: 1864 : rSI.DirType( IsFollow() ? rInf.GetIdx() - 1 : rInf.GetIdx() );
[ + + + + ]
245 [ - + ]: 1031 : if ( UBIDI_RTL == nFldDir )
246 : : {
247 : 0 : UErrorCode nError = U_ZERO_ERROR;
248 [ # # ]: 0 : UBiDi* pBidi = ubidi_openSized( aTxt.Len(), 0, &nError );
249 [ # # ]: 0 : ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(aTxt.GetBuffer()), aTxt.Len(), nFldDir, NULL, &nError );
250 : : int32_t nEnd;
251 : : UBiDiLevel nCurrDir;
252 [ # # ]: 0 : ubidi_getLogicalRun( pBidi, 0, &nEnd, &nCurrDir );
253 [ # # ]: 0 : ubidi_close( pBidi );
254 : 0 : const xub_StrLen nNextDirChg = (xub_StrLen)nEnd;
255 : 0 : nNextScriptChg = Min( nNextScriptChg, nNextDirChg );
256 : :
257 : : // #i89825# change the script type also to CTL
258 : : // if there is no strong LTR char in the LTR run (numbers)
259 [ # # ]: 0 : if ( nCurrDir != UBIDI_RTL )
260 : : {
261 : 0 : nCurrDir = UBIDI_RTL;
262 [ # # ]: 0 : for ( xub_StrLen nCharIdx = 0; nCharIdx < nEnd; ++nCharIdx )
263 : : {
264 [ # # ]: 0 : UCharDirection nCharDir = u_charDirection ( aTxt.GetChar ( nCharIdx ));
265 [ # # ][ # # ]: 0 : if ( nCharDir == U_LEFT_TO_RIGHT ||
[ # # ]
266 : : nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
267 : : nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
268 : : {
269 : 0 : nCurrDir = UBIDI_LTR;
270 : 0 : break;
271 : : }
272 : : }
273 : : }
274 : :
275 [ # # ]: 0 : if ( nCurrDir == UBIDI_RTL )
276 : 0 : nTmp = SW_CTL;
277 : : }
278 : :
279 : : // #i98418#
280 : : // keep determined script type for footnote portions as preferred script type.
281 : : // For footnote portions a font can not be created directly - see footnote
282 : : // portion format method.
283 [ + + ]: 1031 : if ( IsFtnPortion() )
284 : : {
285 [ - + ][ + - ]: 142 : dynamic_cast<SwFtnPortion*>(this)->SetPreferredScriptType( nTmp );
286 : : }
287 [ - + ]: 889 : else if ( nTmp != nActual )
288 : : {
289 [ # # ]: 0 : if( !pFnt )
290 [ # # ][ # # ]: 0 : pFnt = new SwFont( *rInf.GetFont() );
291 : 0 : pFnt->SetActual( nTmp );
292 : : }
293 [ + - ]: 1753 : }
294 : 1753 : }
295 : :
296 : 1753 : sal_Bool SwFldPortion::Format( SwTxtFormatInfo &rInf )
297 : : {
298 : : // Scope wegen aDiffTxt::DTOR!
299 : : xub_StrLen nRest;
300 : : sal_Bool bFull;
301 : 1753 : sal_Bool bEOL = sal_False;
302 : 1753 : long nTxtRest = rInf.GetTxt().Len() - rInf.GetIdx();
303 : : {
304 [ + - ]: 1753 : SwFldSlot aDiffTxt( &rInf, this );
305 [ + - ]: 1753 : SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
306 [ + - ]: 1753 : aLayoutModeModifier.SetAuto();
307 : :
308 : : // Field portion has to be split in several parts if
309 : : // 1. There are script/direction changes inside the field
310 : : // 2. There are portion breaks (tab, break) inside the field:
311 : 1753 : const xub_StrLen nOldFullLen = rInf.GetLen();
312 [ + - ]: 1753 : xub_StrLen nFullLen = rInf.ScanPortionEnd( rInf.GetIdx(), rInf.GetIdx() + nOldFullLen ) - rInf.GetIdx();
313 [ - + ]: 1753 : if ( nNextScriptChg < nFullLen )
314 : : {
315 : 0 : nFullLen = nNextScriptChg;
316 : 0 : rInf.SetHookChar( 0 );
317 : : }
318 : 1753 : rInf.SetLen( nFullLen );
319 : :
320 [ - + ]: 1753 : if ( STRING_LEN != rInf.GetUnderScorePos() &&
[ - + # # ]
321 : 0 : rInf.GetUnderScorePos() > rInf.GetIdx() )
322 : 0 : rInf.SetUnderScorePos( rInf.GetIdx() );
323 : :
324 [ + + ]: 1753 : if( pFnt )
325 [ + - ]: 879 : pFnt->GoMagic( rInf.GetVsh(), pFnt->GetActual() );
326 : :
327 [ + - ]: 1753 : SwFontSave aSave( rInf, pFnt );
328 : :
329 : : // 8674: Laenge muss 0 sein, bei bFull nach Format ist die Laenge
330 : : // gesetzt und wird in nRest uebertragen. Ansonsten bleibt die
331 : : // Laenge erhalten und wuerde auch in nRest einfliessen!
332 : 1753 : SetLen(0);
333 : 1753 : const MSHORT nFollow = IsFollow() ? 0 : 1;
334 : :
335 : : // So komisch es aussieht, die Abfrage auf GetLen() muss wegen der
336 : : // ExpandPortions _hinter_ aDiffTxt (vgl. SoftHyphs)
337 : : // sal_False returnen wegen SetFull ...
338 [ + + ]: 1753 : if( !nFullLen )
339 : : {
340 : : // nicht Init(), weil wir Hoehe und Ascent brauchen
341 : 722 : Width(0);
342 : 722 : bFull = rInf.Width() <= rInf.GetPos().X();
343 : : }
344 : : else
345 : : {
346 : 1031 : xub_StrLen nOldLineStart = rInf.GetLineStart();
347 [ + + ]: 1031 : if( IsFollow() )
348 : 336 : rInf.SetLineStart( 0 );
349 [ + + ][ + + ]: 1031 : rInf.SetNotEOL( nFullLen == nOldFullLen && nTxtRest > nFollow );
350 : :
351 : : // the height depending on the fields font is set,
352 : : // this is required for SwTxtGuess::Guess
353 [ + - ]: 1031 : Height( rInf.GetTxtHeight() );
354 : : // If a kerning portion is inserted after our field portion,
355 : : // the ascent and height must be known
356 [ + - ]: 1031 : SetAscent( rInf.GetAscent() );
357 [ + - ]: 1031 : bFull = SwTxtPortion::Format( rInf );
358 : 1031 : rInf.SetNotEOL( sal_False );
359 : 1031 : rInf.SetLineStart( nOldLineStart );
360 : : }
361 : 1753 : xub_StrLen nTmpLen = GetLen();
362 [ + + ][ - + ]: 1753 : bEOL = !nTmpLen && nFollow && bFull;
[ + + ]
363 : 1753 : nRest = nOldFullLen - nTmpLen;
364 : :
365 : : // Das Zeichen wird in der ersten Portion gehalten.
366 : : // Unbedingt nach Format!
367 [ + + ]: 1753 : SetLen( (m_bNoLength) ? 0 : nFollow );
368 : :
369 [ + + ]: 1753 : if( nRest )
370 : : {
371 : : // aExpand ist noch nicht gekuerzt worden, der neue Ofst
372 : : // ergibt sich durch nRest.
373 : 174 : xub_StrLen nNextOfst = aExpand.Len() - nRest;
374 : :
375 [ - + ]: 174 : if ( IsQuoVadisPortion() )
376 : 0 : nNextOfst = nNextOfst + ((SwQuoVadisPortion*)this)->GetContTxt().Len();
377 : :
378 [ + - ]: 174 : XubString aNew( aExpand, nNextOfst, STRING_LEN );
379 [ + - ]: 174 : aExpand.Erase( nNextOfst, STRING_LEN );
380 : :
381 : : // These characters should not be contained in the follow
382 : : // field portion. They are handled via the HookChar mechanism.
383 [ - + - ]: 174 : switch( aNew.GetChar( 0 ))
384 : : {
385 : 0 : case CH_BREAK : bFull = sal_True;
386 : : // kein break;
387 : : case ' ' :
388 : : case CH_TAB :
389 : : case CHAR_HARDHYPHEN: // non-breaking hyphen
390 : : case CHAR_SOFTHYPHEN:
391 : : case CHAR_HARDBLANK:
392 : : // #i59759# Erase additional control
393 : : // characters from field string, otherwise we get stuck in
394 : : // a loop.
395 : : case CHAR_ZWSP :
396 : : case CHAR_ZWNBSP :
397 : : // #i111750#
398 : : // - Erasing further control characters from field string in
399 : : // to avoid loop.
400 : : case CH_TXTATR_BREAKWORD:
401 : : case CH_TXTATR_INWORD:
402 : : {
403 [ + - ]: 174 : aNew.Erase( 0, 1 );
404 : 174 : ++nNextOfst;
405 : 174 : break;
406 : : }
407 : : default: ;
408 : : }
409 : :
410 : : // Even if there is no more text left for a follow field,
411 : : // we have to build a follow field portion (without font),
412 : : // otherwise the HookChar mechanism would not work.
413 [ + - ]: 174 : SwFldPortion *pFld = Clone( aNew );
414 [ - + ][ # # ]: 174 : if( aNew.Len() && !pFld->GetFont() )
[ - + ]
415 : : {
416 [ # # ][ # # ]: 0 : SwFont *pNewFnt = new SwFont( *rInf.GetFont() );
417 : 0 : pFld->SetFont( pNewFnt );
418 : : }
419 : 174 : pFld->SetFollow( sal_True );
420 : 174 : SetHasFollow( sal_True );
421 : : // In nNextOffset steht bei einem neuangelegten Feld zunaechst
422 : : // der Offset, an dem es selbst im Originalstring beginnt.
423 : : // Wenn beim Formatieren ein FollowFeld angelegt wird, wird
424 : : // der Offset dieses FollowFelds in nNextOffset festgehalten.
425 : 174 : nNextOffset = nNextOffset + nNextOfst;
426 : 174 : pFld->SetNextOffset( nNextOffset );
427 [ + - ]: 174 : rInf.SetRest( pFld );
428 [ + - ][ + - ]: 1753 : }
[ + - ]
429 : : }
430 : :
431 [ - + ][ # # ]: 1753 : if( bEOL && rInf.GetLast() && !rInf.GetUnderFlow() )
[ # # ][ - + ]
432 : 0 : rInf.GetLast()->FormatEOL( rInf );
433 : 1753 : return bFull;
434 : : }
435 : :
436 : : /*************************************************************************
437 : : * virtual SwFldPortion::Paint()
438 : : *************************************************************************/
439 : :
440 : 2054 : void SwFldPortion::Paint( const SwTxtPaintInfo &rInf ) const
441 : : {
442 [ + - ]: 2054 : SwFontSave aSave( rInf, pFnt );
443 : :
444 : : OSL_ENSURE( GetLen() <= 1, "SwFldPortion::Paint: rest-portion polution?" );
445 [ + + ][ - + ]: 2054 : if( Width() && ( !bPlaceHolder || rInf.GetOpt().IsShowPlaceHolderFields() ) )
[ # # ][ + + ]
446 : : {
447 : : // Dies ist eine freizuegige Auslegung der Hintergrundbelegung ...
448 [ + - ]: 1506 : rInf.DrawViewOpt( *this, POR_FLD );
449 [ + - ]: 1506 : SwExpandPortion::Paint( rInf );
450 [ + - ]: 2054 : }
451 : 2054 : }
452 : :
453 : : /*************************************************************************
454 : : * virtual SwFldPortion::GetExpTxt()
455 : : *************************************************************************/
456 : :
457 : 6156 : sal_Bool SwFldPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
458 : : {
459 : 6156 : rTxt = aExpand;
460 [ + + + - : 10092 : if( !rTxt.Len() && rInf.OnWin() &&
+ - + - +
- ][ + + ]
[ + + ]
461 : 1968 : !rInf.GetOpt().IsPagePreview() && !rInf.GetOpt().IsReadonly() &&
462 : 984 : SwViewOption::IsFieldShadings() &&
463 : 984 : !HasFollow() )
464 : 984 : rTxt = ' ';
465 : 6156 : return sal_True;
466 : : }
467 : :
468 : : /*************************************************************************
469 : : * virtual SwFldPortion::HandlePortion()
470 : : *************************************************************************/
471 : :
472 : 23 : void SwFldPortion::HandlePortion( SwPortionHandler& rPH ) const
473 : : {
474 : 23 : sal_Int32 nH = 0;
475 [ + + ]: 23 : if (pFnt)
476 : 5 : nH = pFnt->GetSize(pFnt->GetActual()).Height();
477 : 23 : rPH.Special( GetLen(), aExpand, GetWhichPor(), nH );
478 : 23 : }
479 : :
480 : : /*************************************************************************
481 : : * virtual SwFldPortion::GetTxtSize()
482 : : *************************************************************************/
483 : :
484 : 0 : SwPosSize SwFldPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
485 : : {
486 [ # # ]: 0 : SwFontSave aSave( rInf, pFnt );
487 [ # # ]: 0 : SwPosSize aSize( SwExpandPortion::GetTxtSize( rInf ) );
488 [ # # ]: 0 : return aSize;
489 : : }
490 : :
491 : : /*************************************************************************
492 : : * class SwHiddenPortion
493 : : *************************************************************************/
494 : :
495 : 0 : SwFldPortion *SwHiddenPortion::Clone(const XubString &rExpand ) const
496 : : {
497 : : SwFont *pNewFnt;
498 [ # # ]: 0 : if( 0 != ( pNewFnt = pFnt ) )
499 [ # # ]: 0 : pNewFnt = new SwFont( *pFnt );
500 [ # # ]: 0 : return new SwHiddenPortion( rExpand, pNewFnt );
501 : : }
502 : :
503 : : /*************************************************************************
504 : : * virtual SwHiddenPortion::Paint()
505 : : *************************************************************************/
506 : :
507 : 0 : void SwHiddenPortion::Paint( const SwTxtPaintInfo &rInf ) const
508 : : {
509 [ # # ]: 0 : if( Width() )
510 : : {
511 [ # # ]: 0 : SwFontSave aSave( rInf, pFnt );
512 [ # # ]: 0 : rInf.DrawViewOpt( *this, POR_HIDDEN );
513 [ # # ][ # # ]: 0 : SwExpandPortion::Paint( rInf );
514 : : }
515 : 0 : }
516 : :
517 : : /*************************************************************************
518 : : * virtual SwHiddenPortion::GetExpTxt()
519 : : *************************************************************************/
520 : :
521 : 0 : sal_Bool SwHiddenPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
522 : : {
523 : : // Nicht auf IsHidden() abfragen !
524 : 0 : return SwFldPortion::GetExpTxt( rInf, rTxt );
525 : : }
526 : :
527 : : /*************************************************************************
528 : : * class SwNumberPortion
529 : : *************************************************************************/
530 : :
531 : 536 : SwNumberPortion::SwNumberPortion( const XubString &rExpand,
532 : : SwFont *pFont,
533 : : const sal_Bool bLft,
534 : : const sal_Bool bCntr,
535 : : const KSHORT nMinDst,
536 : : const bool bLabelAlignmentPosAndSpaceModeActive )
537 : : : SwFldPortion( rExpand, pFont ),
538 : : nFixWidth(0),
539 : : nMinDist( nMinDst ),
540 : 536 : mbLabelAlignmentPosAndSpaceModeActive( bLabelAlignmentPosAndSpaceModeActive )
541 : : {
542 : 536 : SetWhichPor( POR_NUMBER );
543 : 536 : SetLeft( bLft );
544 : 536 : SetHide( sal_False );
545 : 536 : SetCenter( bCntr );
546 : 536 : }
547 : :
548 : 0 : xub_StrLen SwNumberPortion::GetCrsrOfst( const MSHORT ) const
549 : : {
550 : 0 : return 0;
551 : : }
552 : :
553 : 174 : SwFldPortion *SwNumberPortion::Clone( const XubString &rExpand ) const
554 : : {
555 : : SwFont *pNewFnt;
556 [ + - ]: 174 : if( 0 != ( pNewFnt = pFnt ) )
557 [ + - ]: 174 : pNewFnt = new SwFont( *pFnt );
558 : :
559 : 174 : return new SwNumberPortion( rExpand, pNewFnt, IsLeft(), IsCenter(),
560 [ + - ]: 174 : nMinDist, mbLabelAlignmentPosAndSpaceModeActive );
561 : : }
562 : :
563 : : /*************************************************************************
564 : : * virtual SwNumberPortion::Format()
565 : : *************************************************************************/
566 : :
567 : : // 5010: Wir sind in der Lage, mehrzeilige NumFelder anzulegen!
568 : : // 3689: Fies ist, wenn man in der Dialogbox soviel Davor-Text
569 : : // eingibt, bis die Zeile ueberlaeuft.
570 : : // Man muss die Fly-Ausweichmanoever beachten!
571 : :
572 : 536 : sal_Bool SwNumberPortion::Format( SwTxtFormatInfo &rInf )
573 : : {
574 : 536 : SetHide( sal_False );
575 : 536 : const sal_Bool bFull = SwFldPortion::Format( rInf );
576 : 536 : SetLen( 0 );
577 : : // a numbering portion can be contained in a rotated portion!!!
578 [ - + ]: 536 : nFixWidth = rInf.IsMulti() ? Height() : Width();
579 : 536 : rInf.SetNumDone( !rInf.GetRest() );
580 [ + + ]: 536 : if( rInf.IsNumDone() )
581 : : {
582 : : // SetAscent( rInf.GetAscent() );
583 : : OSL_ENSURE( Height() && nAscent, "NumberPortions without Height | Ascent" );
584 : :
585 : 362 : long nDiff( 0 );
586 : :
587 [ + + ]: 362 : if ( !mbLabelAlignmentPosAndSpaceModeActive )
588 : : {
589 [ + - + + ]: 376 : if ( !rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) &&
[ + + ]
590 : : // #i32902#
591 : 188 : !IsFtnNumPortion() )
592 : : {
593 : 60 : nDiff = rInf.Left()
594 : 60 : + rInf.GetTxtFrm()->GetTxtNode()->
595 : 60 : GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst()
596 : 60 : - rInf.First()
597 : 60 : + rInf.ForcedLeftMargin();
598 : : }
599 : : else
600 : : {
601 : 128 : nDiff = rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
602 : : }
603 : : }
604 : : // Ein Vorschlag von Juergen und Volkmar:
605 : : // Der Textteil hinter der Numerierung sollte immer
606 : : // mindestens beim linken Rand beginnen.
607 [ + + ]: 362 : if( nDiff < 0 )
608 : 6 : nDiff = 0;
609 [ + + ]: 356 : else if ( nDiff > rInf.X() )
610 : 177 : nDiff -= rInf.X();
611 : : else
612 : 179 : nDiff = 0;
613 : :
614 [ + + ]: 362 : if( nDiff < nFixWidth + nMinDist )
615 : 29 : nDiff = nFixWidth + nMinDist;
616 : : // 2739: Numerierung weicht Fly aus, kein nDiff in der zweiten Runde
617 : : // fieser Sonderfall: FlyFrm liegt in dem Bereich,
618 : : // den wir uns gerade unter den Nagel reissen wollen.
619 : : // Die NumberPortion wird als verborgen markiert.
620 : 362 : const sal_Bool bFly = rInf.GetFly() ||
621 [ + - ][ - + ]: 362 : ( rInf.GetLast() && rInf.GetLast()->IsFlyPortion() );
[ + - ]
622 [ - + ]: 362 : if( nDiff > rInf.Width() )
623 : : {
624 : 0 : nDiff = rInf.Width();
625 [ # # ]: 0 : if ( bFly )
626 : 0 : SetHide( sal_True );
627 : : }
628 : :
629 : : // A numbering portion can be inside a SwRotatedPortion. Then the
630 : : // Height has to be changed
631 [ - + ]: 362 : if ( rInf.IsMulti() )
632 : : {
633 [ # # ]: 0 : if ( Height() < nDiff )
634 : 0 : Height( KSHORT( nDiff ) );
635 : : }
636 [ + + ]: 362 : else if( Width() < nDiff )
637 : 159 : Width( KSHORT(nDiff) );
638 : : }
639 : 536 : return bFull;
640 : : }
641 : :
642 : 0 : void SwNumberPortion::FormatEOL( SwTxtFormatInfo& )
643 : : {
644 : : /* Ein FormatEOL deutet daraufhin, dass der folgende Text
645 : : * nicht mit auf die Zeile passte. Damit die Numerierung mitwandert,
646 : : * wird diese NumberPortion verborgen.
647 : : */
648 : :
649 : : // This caused trouble with flys anchored as characters.
650 : : // If one of these is numbered but does not fit to the line,
651 : : // it calls this function, causing a loop because both the number
652 : : // portion and the fly portion go to the next line
653 : : // SetHide( sal_True );
654 : 0 : }
655 : :
656 : : /*************************************************************************
657 : : * virtual SwNumberPortion::Paint()
658 : : *************************************************************************/
659 : :
660 : 105 : void SwNumberPortion::Paint( const SwTxtPaintInfo &rInf ) const
661 : : {
662 : : /* Eine verborgene NumberPortion wird nicht angezeigt, es sei denn, es gibt
663 : : * Textportions in dieser Zeile oder es gibt ueberhaupt nur eine einzige Zeile.
664 : : */
665 : :
666 [ - + ][ # # ]: 105 : if ( IsHide() && rInf.GetParaPortion() && rInf.GetParaPortion()->GetNext() )
[ # # ][ - + ]
667 : : {
668 : 0 : SwLinePortion *pTmp = GetPortion();
669 [ # # ][ # # ]: 0 : while ( pTmp && !pTmp->InTxtGrp() )
[ # # ]
670 : 0 : pTmp = pTmp->GetPortion();
671 [ # # ]: 0 : if ( !pTmp )
672 : 105 : return;
673 : : }
674 : :
675 : : // calculate the width of the number portion, including follows
676 : 105 : const KSHORT nOldWidth = Width();
677 : 105 : sal_uInt16 nSumWidth = 0;
678 : 105 : sal_uInt16 nOffset = 0;
679 : :
680 : 105 : const SwLinePortion* pTmp = this;
681 [ + - ][ + - ]: 105 : while ( pTmp && pTmp->InNumberGrp() )
[ + - ]
682 : : {
683 : 105 : nSumWidth = nSumWidth + pTmp->Width();
684 [ - + ]: 105 : if ( ((SwNumberPortion*)pTmp)->HasFollow() )
685 : 0 : pTmp = pTmp->GetPortion();
686 : : else
687 : : {
688 : 105 : nOffset = pTmp->Width() - ((SwNumberPortion*)pTmp)->nFixWidth;
689 : 105 : break;
690 : : }
691 : : }
692 : :
693 : : // The master portion takes care for painting the background of the
694 : : // follow field portions
695 [ + - ]: 105 : if ( ! IsFollow() )
696 : : {
697 : 105 : SwLinePortion *pThis = (SwLinePortion*)this;
698 : 105 : pThis->Width( nSumWidth );
699 : 105 : rInf.DrawViewOpt( *this, POR_NUMBER );
700 : 105 : pThis->Width( nOldWidth );
701 : : }
702 : :
703 [ + - ]: 105 : if( aExpand.Len() )
704 : : {
705 : 105 : const SwFont *pTmpFnt = rInf.GetFont();
706 [ + - ]: 105 : sal_Bool bPaintSpace = ( UNDERLINE_NONE != pTmpFnt->GetUnderline() ||
707 [ + - ]: 105 : UNDERLINE_NONE != pTmpFnt->GetOverline() ||
708 [ + - ]: 105 : STRIKEOUT_NONE != pTmpFnt->GetStrikeout() ) &&
709 [ + - ][ + - ]: 315 : !pTmpFnt->IsWordLineMode();
[ - + ][ # # ]
[ # # ]
710 [ - + ][ # # ]: 105 : if( bPaintSpace && pFnt )
711 [ # # ]: 0 : bPaintSpace = ( UNDERLINE_NONE != pFnt->GetUnderline() ||
712 [ # # ]: 0 : UNDERLINE_NONE != pFnt->GetOverline() ||
713 [ # # ]: 0 : STRIKEOUT_NONE != pFnt->GetStrikeout() ) &&
714 [ # # ][ # # ]: 0 : !pFnt->IsWordLineMode();
[ # # ][ # # ]
[ # # ]
715 : :
716 [ + - ]: 105 : SwFontSave aSave( rInf, pFnt );
717 : :
718 [ - + ][ # # ]: 105 : if( nFixWidth == Width() && ! HasFollow() )
[ - + ]
719 [ # # ]: 0 : SwExpandPortion::Paint( rInf );
720 : : else
721 : : {
722 : : // logisches const: Width wird wieder zurueckgesetzt
723 : 105 : SwLinePortion *pThis = (SwLinePortion*)this;
724 [ - + ][ # # ]: 105 : bPaintSpace = bPaintSpace && nFixWidth < nOldWidth;
725 : 105 : KSHORT nSpaceOffs = nFixWidth;
726 : 105 : pThis->Width( nFixWidth );
727 : :
728 [ + - ][ - + : 105 : if( ( IsLeft() && ! rInf.GetTxtFrm()->IsRightToLeft() ) ||
# # # # ]
[ # # ][ + - ]
[ + - ]
729 [ # # ]: 0 : ( ! IsLeft() && ! IsCenter() && rInf.GetTxtFrm()->IsRightToLeft() ) )
730 [ + - ]: 105 : SwExpandPortion::Paint( rInf );
731 : : else
732 : : {
733 [ # # ]: 0 : SwTxtPaintInfo aInf( rInf );
734 [ # # ]: 0 : if( nOffset < nMinDist )
735 : 0 : nOffset = 0;
736 : : else
737 : : {
738 [ # # ]: 0 : if( IsCenter() )
739 : : {
740 : : /* #110778# a / 2 * 2 == a is not a tautology */
741 : 0 : KSHORT nTmpOffset = nOffset;
742 : 0 : nOffset /= 2;
743 [ # # ]: 0 : if( nOffset < nMinDist )
744 : 0 : nOffset = nTmpOffset - nMinDist;
745 : : }
746 : : else
747 : 0 : nOffset = nOffset - nMinDist;
748 : : }
749 : 0 : aInf.X( aInf.X() + nOffset );
750 [ # # ]: 0 : SwExpandPortion::Paint( aInf );
751 [ # # ]: 0 : if( bPaintSpace )
752 [ # # ]: 0 : nSpaceOffs = nSpaceOffs + nOffset;
753 : : }
754 [ - + ][ # # ]: 105 : if( bPaintSpace && nOldWidth > nSpaceOffs )
755 : : {
756 [ # # ]: 0 : SwTxtPaintInfo aInf( rInf );
757 : : static sal_Char const sDoubleSpace[] = " ";
758 : 0 : aInf.X( aInf.X() + nSpaceOffs );
759 : :
760 : : // #i53199# Adjust position of underline:
761 [ # # ]: 0 : if ( rInf.GetUnderFnt() )
762 : : {
763 : 0 : const Point aNewPos( aInf.GetPos().X(), rInf.GetUnderFnt()->GetPos().Y() );
764 : 0 : rInf.GetUnderFnt()->SetPos( aNewPos );
765 : : }
766 : :
767 : 0 : pThis->Width( nOldWidth - nSpaceOffs + 12 );
768 : : {
769 [ # # ]: 0 : SwTxtSlot aDiffTxt( &aInf, this, true, false, sDoubleSpace );
770 [ # # ][ # # ]: 0 : aInf.DrawText( *this, aInf.GetLen(), sal_True );
771 [ # # ]: 0 : }
772 : : }
773 : 105 : pThis->Width( nOldWidth );
774 [ + - ]: 105 : }
775 : : }
776 : : }
777 : :
778 : :
779 : : /*************************************************************************
780 : : * class SwBulletPortion
781 : : *************************************************************************/
782 : :
783 : 36 : SwBulletPortion::SwBulletPortion( const xub_Unicode cBullet,
784 : : const XubString& rBulletFollowedBy,
785 : : SwFont *pFont,
786 : : const sal_Bool bLft,
787 : : const sal_Bool bCntr,
788 : : const KSHORT nMinDst,
789 : : const bool bLabelAlignmentPosAndSpaceModeActive )
790 [ + - ]: 72 : : SwNumberPortion( XubString( rBulletFollowedBy ).Insert( cBullet, 0 ) ,
791 : : pFont, bLft, bCntr, nMinDst,
792 [ + - ]: 36 : bLabelAlignmentPosAndSpaceModeActive )
793 : : {
794 : 36 : SetWhichPor( POR_BULLET );
795 : 36 : }
796 : :
797 : : /*************************************************************************
798 : : * class SwGrfNumPortion
799 : : *************************************************************************/
800 : :
801 : : #define GRFNUM_SECURE 10
802 : :
803 : 0 : SwGrfNumPortion::SwGrfNumPortion(
804 : : SwFrm*,
805 : : const XubString& rGraphicFollowedBy,
806 : : const SvxBrushItem* pGrfBrush,
807 : : const SwFmtVertOrient* pGrfOrient, const Size& rGrfSize,
808 : : const sal_Bool bLft, const sal_Bool bCntr, const KSHORT nMinDst,
809 : : const bool bLabelAlignmentPosAndSpaceModeActive ) :
810 : : SwNumberPortion( rGraphicFollowedBy, NULL, bLft, bCntr, nMinDst,
811 : : bLabelAlignmentPosAndSpaceModeActive ),
812 [ # # ][ # # ]: 0 : pBrush( new SvxBrushItem(RES_BACKGROUND) ), nId( 0 )
813 : : {
814 : 0 : SetWhichPor( POR_GRFNUM );
815 : 0 : SetAnimated( sal_False );
816 : 0 : bReplace = sal_False;
817 [ # # ]: 0 : if( pGrfBrush )
818 : : {
819 [ # # ]: 0 : *pBrush = *pGrfBrush;
820 [ # # ]: 0 : const Graphic* pGraph = pGrfBrush->GetGraphic();
821 [ # # ]: 0 : if( pGraph )
822 [ # # ]: 0 : SetAnimated( pGraph->IsAnimated() );
823 : : else
824 : 0 : bReplace = sal_True;
825 : : }
826 [ # # ]: 0 : if( pGrfOrient )
827 : : {
828 : 0 : nYPos = pGrfOrient->GetPos();
829 : 0 : eOrient = pGrfOrient->GetVertOrient();
830 : : }
831 : : else
832 : : {
833 : 0 : nYPos = 0;
834 : 0 : eOrient = text::VertOrientation::TOP;
835 : : }
836 : 0 : Width( static_cast<sal_uInt16>(rGrfSize.Width() + 2 * GRFNUM_SECURE) );
837 : 0 : nFixWidth = Width();
838 : 0 : nGrfHeight = rGrfSize.Height() + 2 * GRFNUM_SECURE;
839 : 0 : Height( KSHORT(nGrfHeight) );
840 : 0 : bNoPaint = sal_False;
841 : 0 : }
842 : :
843 : 0 : SwGrfNumPortion::~SwGrfNumPortion()
844 : : {
845 [ # # ]: 0 : if ( IsAnimated() )
846 [ # # ][ # # ]: 0 : ( (Graphic*) pBrush->GetGraphic() )->StopAnimation( 0, nId );
847 [ # # ][ # # ]: 0 : delete pBrush;
848 [ # # ]: 0 : }
849 : :
850 : 0 : void SwGrfNumPortion::StopAnimation( OutputDevice* pOut )
851 : : {
852 [ # # ]: 0 : if ( IsAnimated() )
853 : 0 : ( (Graphic*) pBrush->GetGraphic() )->StopAnimation( pOut, nId );
854 : 0 : }
855 : :
856 : 0 : sal_Bool SwGrfNumPortion::Format( SwTxtFormatInfo &rInf )
857 : : {
858 : 0 : SetHide( sal_False );
859 : : // Width( nFixWidth );
860 : 0 : KSHORT nFollowedByWidth( 0 );
861 [ # # ]: 0 : if ( mbLabelAlignmentPosAndSpaceModeActive )
862 : : {
863 : 0 : SwFldPortion::Format( rInf );
864 : 0 : nFollowedByWidth = Width();
865 : 0 : SetLen( 0 );
866 : : }
867 : 0 : Width( nFixWidth + nFollowedByWidth );
868 : 0 : const sal_Bool bFull = rInf.Width() < rInf.X() + Width();
869 : 0 : const sal_Bool bFly = rInf.GetFly() ||
870 [ # # ][ # # ]: 0 : ( rInf.GetLast() && rInf.GetLast()->IsFlyPortion() );
[ # # ]
871 [ # # ]: 0 : SetAscent( static_cast<sal_uInt16>(GetRelPos() > 0 ? GetRelPos() : 0) );
872 [ # # ]: 0 : if( GetAscent() > Height() )
873 : 0 : Height( GetAscent() );
874 : :
875 [ # # ]: 0 : if( bFull )
876 : : {
877 : 0 : Width( rInf.Width() - (KSHORT)rInf.X() );
878 [ # # ]: 0 : if( bFly )
879 : : {
880 : 0 : SetLen( 0 );
881 : 0 : SetNoPaint( sal_True );
882 : 0 : rInf.SetNumDone( sal_False );
883 : 0 : return sal_True;
884 : : }
885 : : }
886 : 0 : rInf.SetNumDone( sal_True );
887 : : // long nDiff = rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
888 : : long nDiff = mbLabelAlignmentPosAndSpaceModeActive
889 : : ? 0
890 [ # # ]: 0 : : rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
891 : : // Ein Vorschlag von Juergen und Volkmar:
892 : : // Der Textteil hinter der Numerierung sollte immer
893 : : // mindestens beim linken Rand beginnen.
894 [ # # ]: 0 : if( nDiff < 0 )
895 : 0 : nDiff = 0;
896 [ # # ]: 0 : else if ( nDiff > rInf.X() )
897 : 0 : nDiff -= rInf.X();
898 [ # # ]: 0 : if( nDiff < nFixWidth + nMinDist )
899 : 0 : nDiff = nFixWidth + nMinDist;
900 : : // 2739: Numerierung weicht Fly aus, kein nDiff in der zweiten Runde
901 : : // fieser Sonderfall: FlyFrm liegt in dem Bereich,
902 : : // den wir uns gerade unter den Nagel reissen wollen.
903 : : // Die NumberPortion wird als verborgen markiert.
904 [ # # ]: 0 : if( nDiff > rInf.Width() )
905 : : {
906 : 0 : nDiff = rInf.Width();
907 [ # # ]: 0 : if( bFly )
908 : 0 : SetHide( sal_True );
909 : : }
910 : :
911 [ # # ]: 0 : if( Width() < nDiff )
912 : 0 : Width( KSHORT(nDiff) );
913 : 0 : return bFull;
914 : : }
915 : :
916 : 0 : void SwGrfNumPortion::Paint( const SwTxtPaintInfo &rInf ) const
917 : : {
918 [ # # ]: 0 : if( DontPaint() )
919 : : return;
920 : : /* Eine verborgene NumberPortion wird nicht angezeigt, es sei denn, es gibt
921 : : * Textportions in dieser Zeile oder es gibt ueberhaupt nur eine einzige Zeile.
922 : : */
923 [ # # ][ # # ]: 0 : if ( IsHide() && rInf.GetParaPortion() && rInf.GetParaPortion()->GetNext() )
[ # # ][ # # ]
924 : : {
925 : 0 : SwLinePortion *pTmp = GetPortion();
926 [ # # ][ # # ]: 0 : while ( pTmp && !pTmp->InTxtGrp() )
[ # # ]
927 : 0 : pTmp = pTmp->GetPortion();
928 [ # # ]: 0 : if ( !pTmp )
929 : : return;
930 : : }
931 : 0 : Point aPos( rInf.X() + GRFNUM_SECURE, rInf.Y() - GetRelPos() + GRFNUM_SECURE );
932 : 0 : long nTmpWidth = Max( (long)0, (long)(nFixWidth - 2 * GRFNUM_SECURE) );
933 : 0 : Size aSize( nTmpWidth, GetGrfHeight() - 2 * GRFNUM_SECURE );
934 : :
935 : : const sal_Bool bTmpLeft = mbLabelAlignmentPosAndSpaceModeActive ||
936 [ # # ]: 0 : ( IsLeft() && ! rInf.GetTxtFrm()->IsRightToLeft() ) ||
937 [ # # ][ # # ]: 0 : ( ! IsLeft() && ! IsCenter() && rInf.GetTxtFrm()->IsRightToLeft() );
[ # # ][ # # ]
[ # # ]
[ # # # # ]
938 : :
939 [ # # ][ # # ]: 0 : if( nFixWidth < Width() && !bTmpLeft )
[ # # ]
940 : : {
941 : 0 : KSHORT nOffset = Width() - nFixWidth;
942 [ # # ]: 0 : if( nOffset < nMinDist )
943 : 0 : nOffset = 0;
944 : : else
945 : : {
946 [ # # ]: 0 : if( IsCenter() )
947 : : {
948 : 0 : nOffset /= 2;
949 [ # # ]: 0 : if( nOffset < nMinDist )
950 : 0 : nOffset = Width() - nFixWidth - nMinDist;
951 : : }
952 : : else
953 : 0 : nOffset = nOffset - nMinDist;
954 : : }
955 : 0 : aPos.X() += nOffset;
956 : : }
957 : :
958 [ # # ]: 0 : if( bReplace )
959 : : {
960 [ # # ]: 0 : KSHORT nTmpH = GetPortion() ? GetPortion()->GetAscent() : 120;
961 : 0 : aSize = Size( nTmpH, nTmpH );
962 : 0 : aPos.Y() = rInf.Y() - nTmpH;
963 : : }
964 : 0 : SwRect aTmp( aPos, aSize );
965 : :
966 : 0 : sal_Bool bDraw = sal_True;
967 : :
968 [ # # ]: 0 : if ( IsAnimated() )
969 : : {
970 : 0 : bDraw = !rInf.GetOpt().IsGraphic();
971 [ # # ]: 0 : if( !nId )
972 : : {
973 : 0 : SetId( long( rInf.GetTxtFrm() ) );
974 : 0 : rInf.GetTxtFrm()->SetAnimation();
975 : : }
976 [ # # ][ # # ]: 0 : if( aTmp.IsOver( rInf.GetPaintRect() ) && !bDraw )
[ # # ][ # # ]
977 : : {
978 [ # # ]: 0 : rInf.NoteAnimation();
979 : 0 : const ViewShell* pViewShell = rInf.GetVsh();
980 : :
981 : : // virtual device, not pdf export
982 [ # # # # ]: 0 : if( OUTDEV_VIRDEV == rInf.GetOut()->GetOutDevType() &&
[ # # ][ # # ]
983 : 0 : pViewShell && pViewShell->GetWin() )
984 : : {
985 [ # # ][ # # ]: 0 : ( (Graphic*) pBrush->GetGraphic() )->StopAnimation(0,nId);
986 [ # # ]: 0 : rInf.GetTxtFrm()->getRootFrm()->GetCurrShell()->InvalidateWindows( aTmp );
987 : : }
988 : :
989 : :
990 [ # # # # : 0 : else if ( pViewShell &&
# # # # ]
[ # # ]
991 : 0 : !pViewShell->GetAccessibilityOptions()->IsStopAnimatedGraphics() &&
992 : 0 : !pViewShell->IsPreView() &&
993 : : // #i9684# Stop animation during printing/pdf export.
994 : 0 : pViewShell->GetWin() )
995 : : {
996 [ # # ]: 0 : ( (Graphic*) pBrush->GetGraphic() )->StartAnimation(
997 [ # # ]: 0 : (OutputDevice*)rInf.GetOut(), aPos, aSize, nId );
998 : : }
999 : :
1000 : : // pdf export, printing, preview, stop animations...
1001 : : else
1002 : 0 : bDraw = sal_True;
1003 : : }
1004 [ # # ]: 0 : if( bDraw )
1005 [ # # ][ # # ]: 0 : ( (Graphic*) pBrush->GetGraphic() )->StopAnimation( 0, nId );
1006 : : }
1007 : :
1008 : 0 : SwRect aRepaint( rInf.GetPaintRect() );
1009 : 0 : const SwTxtFrm& rFrm = *rInf.GetTxtFrm();
1010 [ # # ][ # # ]: 0 : if( rFrm.IsVertical() )
1011 : : {
1012 [ # # ]: 0 : rFrm.SwitchHorizontalToVertical( aTmp );
1013 [ # # ]: 0 : rFrm.SwitchHorizontalToVertical( aRepaint );
1014 : : }
1015 : :
1016 [ # # ][ # # ]: 0 : if( rFrm.IsRightToLeft() )
1017 : : {
1018 [ # # ]: 0 : rFrm.SwitchLTRtoRTL( aTmp );
1019 [ # # ]: 0 : rFrm.SwitchLTRtoRTL( aRepaint );
1020 : : }
1021 : :
1022 [ # # ][ # # ]: 0 : if( bDraw && aTmp.HasArea() )
[ # # ][ # # ]
1023 : 0 : DrawGraphic( pBrush, (OutputDevice*)rInf.GetOut(),
1024 [ # # ][ # # ]: 0 : aTmp, aRepaint, bReplace ? GRFNUM_REPLACE : GRFNUM_YES );
1025 : : }
1026 : :
1027 : 0 : void SwGrfNumPortion::SetBase( long nLnAscent, long nLnDescent,
1028 : : long nFlyAsc, long nFlyDesc )
1029 : : {
1030 [ # # ]: 0 : if ( GetOrient() != text::VertOrientation::NONE )
1031 : : {
1032 : 0 : SetRelPos( 0 );
1033 [ # # ]: 0 : if ( GetOrient() == text::VertOrientation::CENTER )
1034 : 0 : SetRelPos( GetGrfHeight() / 2 );
1035 [ # # ]: 0 : else if ( GetOrient() == text::VertOrientation::TOP )
1036 : 0 : SetRelPos( GetGrfHeight() - GRFNUM_SECURE );
1037 [ # # ]: 0 : else if ( GetOrient() == text::VertOrientation::BOTTOM )
1038 : : ;
1039 [ # # ]: 0 : else if ( GetOrient() == text::VertOrientation::CHAR_CENTER )
1040 : 0 : SetRelPos( ( GetGrfHeight() + nLnAscent - nLnDescent ) / 2 );
1041 [ # # ]: 0 : else if ( GetOrient() == text::VertOrientation::CHAR_TOP )
1042 : 0 : SetRelPos( nLnAscent );
1043 [ # # ]: 0 : else if ( GetOrient() == text::VertOrientation::CHAR_BOTTOM )
1044 : 0 : SetRelPos( GetGrfHeight() - nLnDescent );
1045 : : else
1046 : : {
1047 [ # # ]: 0 : if( GetGrfHeight() >= nFlyAsc + nFlyDesc )
1048 : : {
1049 : : // wenn ich genauso gross bin wie die Zeile, brauche ich mich
1050 : : // nicht an der Zeile nicht weiter ausrichten, ich lasse
1051 : : // dann auch den max. Ascent der Zeile unveraendert
1052 : :
1053 : 0 : SetRelPos( nFlyAsc );
1054 : : }
1055 [ # # ]: 0 : else if ( GetOrient() == text::VertOrientation::LINE_CENTER )
1056 : 0 : SetRelPos( ( GetGrfHeight() + nFlyAsc - nFlyDesc ) / 2 );
1057 [ # # ]: 0 : else if ( GetOrient() == text::VertOrientation::LINE_TOP )
1058 : 0 : SetRelPos( nFlyAsc );
1059 [ # # ]: 0 : else if ( GetOrient() == text::VertOrientation::LINE_BOTTOM )
1060 : 0 : SetRelPos( GetGrfHeight() - nFlyDesc );
1061 : : }
1062 : : }
1063 : 0 : }
1064 : :
1065 : 0 : void SwTxtFrm::StopAnimation( OutputDevice* pOut )
1066 : : {
1067 : : OSL_ENSURE( HasAnimation(), "SwTxtFrm::StopAnimation: Which Animation?" );
1068 [ # # ]: 0 : if( HasPara() )
1069 : : {
1070 : 0 : SwLineLayout *pLine = GetPara();
1071 [ # # ]: 0 : while( pLine )
1072 : : {
1073 : 0 : SwLinePortion *pPor = pLine->GetPortion();
1074 [ # # ]: 0 : while( pPor )
1075 : : {
1076 [ # # ]: 0 : if( pPor->IsGrfNumPortion() )
1077 : 0 : ((SwGrfNumPortion*)pPor)->StopAnimation( pOut );
1078 : : // Die Numerierungsportion sitzt immer vor dem ersten Zeichen,
1079 : : // deshalb koennen wir abbrechen, sobald wir eine Portion mit
1080 : : // einer Laenge > 0 erreicht haben.
1081 [ # # ]: 0 : pPor = pPor->GetLen() ? 0 : pPor->GetPortion();
1082 : : }
1083 [ # # ]: 0 : pLine = pLine->GetLen() ? 0 : pLine->GetNext();
1084 : : }
1085 : : }
1086 : 0 : }
1087 : :
1088 : : /*************************************************************************
1089 : : * SwCombinedPortion::SwCombinedPortion(..)
1090 : : * initializes the script array and clears the width array
1091 : : *************************************************************************/
1092 : :
1093 : 0 : SwCombinedPortion::SwCombinedPortion( const XubString &rTxt )
1094 : 0 : : SwFldPortion( rTxt )
1095 : : {
1096 : 0 : SetLen(1);
1097 : 0 : SetWhichPor( POR_COMBINED );
1098 [ # # ]: 0 : if( aExpand.Len() > 6 )
1099 [ # # ]: 0 : aExpand.Erase( 6 );
1100 : : // Initialization of the scripttype array,
1101 : : // the arrays of width and position are filled by the format function
1102 [ # # ][ # # ]: 0 : if( pBreakIt->GetBreakIter().is() )
1103 : : {
1104 : 0 : sal_uInt8 nScr = SW_SCRIPTS;
1105 [ # # ]: 0 : for( sal_uInt16 i = 0; i < rTxt.Len(); ++i )
1106 : : {
1107 [ # # ][ # # ]: 0 : sal_uInt16 nScript = pBreakIt->GetBreakIter()->getScriptType( rTxt, i );
[ # # ][ # # ]
1108 [ # # # # ]: 0 : switch ( nScript ) {
1109 : 0 : case i18n::ScriptType::LATIN : nScr = SW_LATIN; break;
1110 : 0 : case i18n::ScriptType::ASIAN : nScr = SW_CJK; break;
1111 : 0 : case i18n::ScriptType::COMPLEX : nScr = SW_CTL; break;
1112 : : }
1113 : 0 : aScrType[i] = nScr;
1114 : : }
1115 : : }
1116 : : else
1117 : : {
1118 [ # # ]: 0 : for( sal_uInt16 i = 0; i < 6; aScrType[i++] = 0 )
1119 : : ; // nothing
1120 : : }
1121 : 0 : memset( &aWidth, 0, sizeof(aWidth) );
1122 : 0 : }
1123 : :
1124 : : /*************************************************************************
1125 : : * SwCombinedPortion::Paint(..)
1126 : : *************************************************************************/
1127 : :
1128 : 0 : void SwCombinedPortion::Paint( const SwTxtPaintInfo &rInf ) const
1129 : : {
1130 : : OSL_ENSURE( GetLen() <= 1, "SwFldPortion::Paint: rest-portion polution?" );
1131 [ # # ]: 0 : if( Width() )
1132 : : {
1133 [ # # ]: 0 : rInf.DrawBackBrush( *this );
1134 [ # # ]: 0 : rInf.DrawViewOpt( *this, POR_FLD );
1135 : :
1136 : : // do we have to repaint a post it portion?
1137 [ # # ][ # # ]: 0 : if( rInf.OnWin() && pPortion && !pPortion->Width() )
[ # # ][ # # ]
1138 [ # # ]: 0 : pPortion->PrePaint( rInf, this );
1139 : :
1140 : 0 : sal_uInt16 nCount = aExpand.Len();
1141 [ # # ]: 0 : if( !nCount )
1142 : 0 : return;
1143 : : OSL_ENSURE( nCount < 7, "Too much combined characters" );
1144 : :
1145 : : // the first character of the second row
1146 : 0 : sal_uInt16 nTop = ( nCount + 1 ) / 2;
1147 : :
1148 [ # # ]: 0 : SwFont aTmpFont( *rInf.GetFont() );
1149 [ # # ]: 0 : aTmpFont.SetProportion( nProportion ); // a smaller font
1150 [ # # ]: 0 : SwFontSave aFontSave( rInf, &aTmpFont );
1151 : :
1152 : 0 : sal_uInt16 i = 0;
1153 : 0 : Point aOldPos = rInf.GetPos();
1154 : 0 : Point aOutPos( aOldPos.X(), aOldPos.Y() - nUpPos );// Y of the first row
1155 [ # # ]: 0 : while( i < nCount )
1156 : : {
1157 [ # # ]: 0 : if( i == nTop ) // change the row
1158 : 0 : aOutPos.Y() = aOldPos.Y() + nLowPos; // Y of the second row
1159 : 0 : aOutPos.X() = aOldPos.X() + aPos[i]; // X position
1160 : 0 : const sal_uInt8 nAct = aScrType[i]; // script type
1161 : 0 : aTmpFont.SetActual( nAct );
1162 : : // if there're more than 4 characters to display, we choose fonts
1163 : : // with 2/3 of the original font width.
1164 [ # # ]: 0 : if( aWidth[ nAct ] )
1165 : : {
1166 : 0 : Size aTmpSz = aTmpFont.GetSize( nAct );
1167 [ # # ]: 0 : if( aTmpSz.Width() != aWidth[ nAct ] )
1168 : : {
1169 : 0 : aTmpSz.Width() = aWidth[ nAct ];
1170 [ # # ]: 0 : aTmpFont.SetSize( aTmpSz, nAct );
1171 : : }
1172 : : }
1173 : 0 : ((SwTxtPaintInfo&)rInf).SetPos( aOutPos );
1174 [ # # ]: 0 : rInf.DrawText( aExpand, *this, i, 1 );
1175 : 0 : ++i;
1176 : : }
1177 : : // rInf is const, so we have to take back our manipulations
1178 [ # # ][ # # ]: 0 : ((SwTxtPaintInfo&)rInf).SetPos( aOldPos );
1179 : : }
1180 : : }
1181 : :
1182 : : /*************************************************************************
1183 : : * SwCombinedPortion::Format(..)
1184 : : *************************************************************************/
1185 : :
1186 : 0 : sal_Bool SwCombinedPortion::Format( SwTxtFormatInfo &rInf )
1187 : : {
1188 : 0 : sal_uInt16 nCount = aExpand.Len();
1189 [ # # ]: 0 : if( !nCount )
1190 : : {
1191 : 0 : Width( 0 );
1192 : 0 : return sal_False;
1193 : : }
1194 : :
1195 : : OSL_ENSURE( nCount < 7, "Too much combined characters" );
1196 : : // If there are leading "weak"-scripttyped characters in this portion,
1197 : : // they get the actual scripttype.
1198 : 0 : sal_uInt16 i = 0;
1199 [ # # ][ # # ]: 0 : while( i < nCount && SW_SCRIPTS == aScrType[i] )
[ # # ]
1200 : 0 : aScrType[i++] = rInf.GetFont()->GetActual();
1201 [ # # ]: 0 : if( nCount > 4 )
1202 : : {
1203 : : // more than four? Ok, then we need the 2/3 font width
1204 : 0 : i = 0;
1205 [ # # ]: 0 : while( i < aExpand.Len() )
1206 : : {
1207 : : OSL_ENSURE( aScrType[i] < SW_SCRIPTS, "Combined: Script fault" );
1208 [ # # ]: 0 : if( !aWidth[ aScrType[i] ] )
1209 : : {
1210 [ # # ]: 0 : rInf.GetOut()->SetFont( rInf.GetFont()->GetFnt( aScrType[i] ) );
1211 : 0 : aWidth[ aScrType[i] ] =
1212 [ # # ][ # # ]: 0 : static_cast<sal_uInt16>(2 * rInf.GetOut()->GetFontMetric().GetSize().Width() / 3);
[ # # ]
1213 : : }
1214 : 0 : ++i;
1215 : : }
1216 : : }
1217 : :
1218 : 0 : sal_uInt16 nTop = ( nCount + 1 ) / 2; // the first character of the second line
1219 : 0 : ViewShell *pSh = rInf.GetTxtFrm()->getRootFrm()->GetCurrShell();
1220 [ # # ]: 0 : SwFont aTmpFont( *rInf.GetFont() );
1221 [ # # ]: 0 : SwFontSave aFontSave( rInf, &aTmpFont );
1222 : 0 : nProportion = 55;
1223 : : // In nMainAscent/Descent we store the ascent and descent
1224 : : // of the original surrounding font
1225 : : sal_uInt16 nMaxDescent, nMaxAscent, nMaxWidth;
1226 [ # # ]: 0 : sal_uInt16 nMainDescent = rInf.GetFont()->GetHeight( pSh, *rInf.GetOut() );
1227 [ # # ]: 0 : const sal_uInt16 nMainAscent = rInf.GetFont()->GetAscent( pSh, *rInf.GetOut() );
1228 : 0 : nMainDescent = nMainDescent - nMainAscent;
1229 : : // we start with a 50% font, but if we notice that the combined portion
1230 : : // becomes bigger than the surrounding font, we check 45% and maybe 40%.
1231 [ # # ][ # # : 0 : do
# # # # ]
1232 : : {
1233 : 0 : nProportion -= 5;
1234 [ # # ]: 0 : aTmpFont.SetProportion( nProportion );
1235 : 0 : i = 0;
1236 : 0 : memset( &aPos, 0, sizeof(aPos) );
1237 : 0 : nMaxDescent = 0;
1238 : 0 : nMaxAscent = 0;
1239 : 0 : nMaxWidth = 0;
1240 : 0 : nUpPos = nLowPos = 0;
1241 : :
1242 : : // Now we get the width of all characters.
1243 : : // The ascent and the width of the first line are stored in the
1244 : : // ascent member of the portion, the descent in nLowPos.
1245 : : // The ascent, descent and width of the second line are stored in the
1246 : : // local nMaxAscent, nMaxDescent and nMaxWidth variables.
1247 [ # # ]: 0 : while( i < nCount )
1248 : : {
1249 : 0 : sal_uInt8 nScrp = aScrType[i];
1250 : 0 : aTmpFont.SetActual( nScrp );
1251 [ # # ]: 0 : if( aWidth[ nScrp ] )
1252 : : {
1253 : 0 : Size aFontSize( aTmpFont.GetSize( nScrp ) );
1254 : 0 : aFontSize.Width() = aWidth[ nScrp ];
1255 [ # # ]: 0 : aTmpFont.SetSize( aFontSize, nScrp );
1256 : : }
1257 : :
1258 : 0 : SwDrawTextInfo aDrawInf( pSh, *rInf.GetOut(), 0, aExpand, i, 1 );
1259 [ # # ]: 0 : Size aSize = aTmpFont._GetTxtSize( aDrawInf );
1260 [ # # ]: 0 : sal_uInt16 nAsc = aTmpFont.GetAscent( pSh, *rInf.GetOut() );
1261 : 0 : aPos[ i ] = (sal_uInt16)aSize.Width();
1262 [ # # ]: 0 : if( i == nTop ) // enter the second line
1263 : : {
1264 : 0 : nLowPos = nMaxDescent;
1265 : 0 : Height( nMaxDescent + nMaxAscent );
1266 : 0 : Width( nMaxWidth );
1267 : 0 : SetAscent( nMaxAscent );
1268 : 0 : nMaxAscent = 0;
1269 : 0 : nMaxDescent = 0;
1270 : 0 : nMaxWidth = 0;
1271 : : }
1272 : 0 : nMaxWidth = nMaxWidth + aPos[ i++ ];
1273 [ # # ]: 0 : if( nAsc > nMaxAscent )
1274 : 0 : nMaxAscent = nAsc;
1275 [ # # ]: 0 : if( aSize.Height() - nAsc > nMaxDescent )
1276 : 0 : nMaxDescent = static_cast<sal_uInt16>(aSize.Height() - nAsc);
1277 : : }
1278 : : // for one or two characters we double the width of the portion
1279 [ # # ]: 0 : if( nCount < 3 )
1280 : : {
1281 : 0 : nMaxWidth *= 2;
1282 : 0 : Width( 2*Width() );
1283 [ # # ]: 0 : if( nCount < 2 )
1284 : : {
1285 : 0 : Height( nMaxAscent + nMaxDescent );
1286 : 0 : nLowPos = nMaxDescent;
1287 : : }
1288 : : }
1289 : 0 : Height( Height() + nMaxDescent + nMaxAscent );
1290 : 0 : nUpPos = nMaxAscent;
1291 : 0 : SetAscent( Height() - nMaxDescent - nLowPos );
1292 : 0 : } while( nProportion > 40 && ( GetAscent() > nMainAscent ||
1293 : 0 : Height() - GetAscent() > nMainDescent ) );
1294 : : // if the combined portion is smaller than the surrounding text,
1295 : : // the portion grows. This looks better, if there's a character background.
1296 [ # # ]: 0 : if( GetAscent() < nMainAscent )
1297 : : {
1298 : 0 : Height( Height() + nMainAscent - GetAscent() );
1299 : 0 : SetAscent( nMainAscent );
1300 : : }
1301 [ # # ]: 0 : if( Height() < nMainAscent + nMainDescent )
1302 : 0 : Height( nMainAscent + nMainDescent );
1303 : :
1304 : : // We calculate the x positions of the characters in both lines..
1305 : 0 : sal_uInt16 nTopDiff = 0;
1306 : 0 : sal_uInt16 nBotDiff = 0;
1307 [ # # ]: 0 : if( nMaxWidth > Width() )
1308 : : {
1309 : 0 : nTopDiff = ( nMaxWidth - Width() ) / 2;
1310 : 0 : Width( nMaxWidth );
1311 : : }
1312 : : else
1313 : 0 : nBotDiff = ( Width() - nMaxWidth ) / 2;
1314 [ # # # ]: 0 : switch( nTop)
1315 : : {
1316 : 0 : case 3: aPos[1] = aPos[0] + nTopDiff; // no break
1317 : 0 : case 2: aPos[nTop-1] = Width() - aPos[nTop-1];
1318 : : }
1319 : 0 : aPos[0] = 0;
1320 [ # # # # : 0 : switch( nCount )
# # ]
1321 : : {
1322 : 0 : case 5: aPos[4] = aPos[3] + nBotDiff; // no break
1323 : 0 : case 3: aPos[nTop] = nBotDiff; break;
1324 : 0 : case 6: aPos[4] = aPos[3] + nBotDiff; // no break
1325 : 0 : case 4: aPos[nTop] = 0; // no break
1326 : 0 : case 2: aPos[nCount-1] = Width() - aPos[nCount-1];
1327 : : }
1328 : :
1329 : : // Does the combined portion fit the line?
1330 : 0 : const sal_Bool bFull = rInf.Width() < rInf.X() + Width();
1331 [ # # ]: 0 : if( bFull )
1332 : : {
1333 [ # # ]: 0 : if( rInf.GetLineStart() == rInf.GetIdx() && (!rInf.GetLast()->InFldGrp()
[ # # # # ]
[ # # ]
1334 : 0 : || !((SwFldPortion*)rInf.GetLast())->IsFollow() ) )
1335 : 0 : Width( (sal_uInt16)( rInf.Width() - rInf.X() ) );
1336 : : else
1337 : : {
1338 [ # # ]: 0 : Truncate();
1339 : 0 : Width( 0 );
1340 : 0 : SetLen( 0 );
1341 [ # # ]: 0 : if( rInf.GetLast() )
1342 [ # # ]: 0 : rInf.GetLast()->FormatEOL( rInf );
1343 : : }
1344 : : }
1345 [ # # ][ # # ]: 0 : return bFull;
1346 : : }
1347 : :
1348 : : /*************************************************************************
1349 : : * SwCombinedPortion::GetViewWidth(..)
1350 : : *************************************************************************/
1351 : :
1352 : 0 : KSHORT SwCombinedPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
1353 : : {
1354 [ # # ]: 0 : if( !GetLen() ) // for the dummy part at the end of the line, where
1355 : 0 : return 0; // the combined portion doesn't fit.
1356 : 0 : return SwFldPortion::GetViewWidth( rInf );
1357 : : }
1358 : :
1359 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|