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 <hintids.hxx>
21 : #include <hints.hxx>
22 : #include <svl/ctloptions.hxx>
23 : #include <sfx2/printer.hxx>
24 : #include <sfx2/sfxuno.hxx>
25 : #include <editeng/langitem.hxx>
26 : #include <editeng/lspcitem.hxx>
27 : #include <editeng/lrspitem.hxx>
28 : #include <editeng/ulspitem.hxx>
29 : #include <editeng/brushitem.hxx>
30 : #include <editeng/pgrditem.hxx>
31 : #include <swmodule.hxx>
32 : #include <SwSmartTagMgr.hxx>
33 : #include <doc.hxx>
34 : #include <IDocumentSettingAccess.hxx>
35 : #include <IDocumentDeviceAccess.hxx>
36 : #include <IDocumentFieldsAccess.hxx>
37 : #include "rootfrm.hxx"
38 : #include <pagefrm.hxx>
39 : #include <viewsh.hxx>
40 : #include <pam.hxx>
41 : #include <ndtxt.hxx>
42 : #include <txtatr.hxx>
43 : #include <paratr.hxx>
44 : #include <viewopt.hxx>
45 : #include <dflyobj.hxx>
46 : #include <flyfrm.hxx>
47 : #include <tabfrm.hxx>
48 : #include <frmtool.hxx>
49 : #include <pagedesc.hxx>
50 : #include <tgrditem.hxx>
51 : #include <dbg_lay.hxx>
52 : #include <fmtfld.hxx>
53 : #include <fmtftn.hxx>
54 : #include <txtfld.hxx>
55 : #include <txtftn.hxx>
56 : #include <charatr.hxx>
57 : #include <ftninfo.hxx>
58 : #include <fmtline.hxx>
59 : #include <txtfrm.hxx>
60 : #include <sectfrm.hxx>
61 : #include <itrform2.hxx>
62 : #include <widorp.hxx>
63 : #include <txtcache.hxx>
64 : #include <fntcache.hxx>
65 : #include <SwGrammarMarkUp.hxx>
66 : #include <lineinfo.hxx>
67 : #include <SwPortionHandler.hxx>
68 : #include <dcontact.hxx>
69 : #include <sortedobjs.hxx>
70 : #include <txtflcnt.hxx>
71 : #include <fmtflcnt.hxx>
72 : #include <fmtcntnt.hxx>
73 : #include <numrule.hxx>
74 : #include <swtable.hxx>
75 : #include <fldupde.hxx>
76 : #include <IGrammarContact.hxx>
77 : #include <switerator.hxx>
78 : #include <ftnidx.hxx>
79 :
80 7688683 : TYPEINIT1( SwTxtFrm, SwCntntFrm );
81 :
82 : // Switches width and height of the text frame
83 88 : void SwTxtFrm::SwapWidthAndHeight()
84 : {
85 88 : if ( ! bIsSwapped )
86 : {
87 44 : const long nPrtOfstX = Prt().Pos().X();
88 44 : Prt().Pos().X() = Prt().Pos().Y();
89 44 : if( IsVertLR() )
90 0 : Prt().Pos().Y() = nPrtOfstX;
91 : else
92 44 : Prt().Pos().Y() = Frm().Width() - ( nPrtOfstX + Prt().Width() );
93 :
94 : }
95 : else
96 : {
97 44 : const long nPrtOfstY = Prt().Pos().Y();
98 44 : Prt().Pos().Y() = Prt().Pos().X();
99 44 : if( IsVertLR() )
100 0 : Prt().Pos().X() = nPrtOfstY;
101 : else
102 44 : Prt().Pos().X() = Frm().Height() - ( nPrtOfstY + Prt().Height() );
103 : }
104 :
105 88 : const long nFrmWidth = Frm().Width();
106 88 : Frm().Width( Frm().Height() );
107 88 : Frm().Height( nFrmWidth );
108 88 : const long nPrtWidth = Prt().Width();
109 88 : Prt().Width( Prt().Height() );
110 88 : Prt().Height( nPrtWidth );
111 :
112 88 : bIsSwapped = ! bIsSwapped;
113 88 : }
114 :
115 : // Calculates the coordinates of a rectangle when switching from
116 : // horizontal to vertical layout.
117 0 : void SwTxtFrm::SwitchHorizontalToVertical( SwRect& rRect ) const
118 : {
119 : // calc offset inside frame
120 : long nOfstX, nOfstY;
121 0 : if ( IsVertLR() )
122 : {
123 0 : nOfstX = rRect.Left() - Frm().Left();
124 0 : nOfstY = rRect.Top() - Frm().Top();
125 : }
126 : else
127 : {
128 0 : nOfstX = rRect.Left() - Frm().Left();
129 0 : nOfstY = rRect.Top() + rRect.Height() - Frm().Top();
130 : }
131 :
132 0 : const long nWidth = rRect.Width();
133 0 : const long nHeight = rRect.Height();
134 :
135 0 : if ( IsVertLR() )
136 0 : rRect.Left(Frm().Left() + nOfstY);
137 : else
138 : {
139 0 : if ( bIsSwapped )
140 0 : rRect.Left( Frm().Left() + Frm().Height() - nOfstY );
141 : else
142 : // frame is rotated
143 0 : rRect.Left( Frm().Left() + Frm().Width() - nOfstY );
144 : }
145 :
146 0 : rRect.Top( Frm().Top() + nOfstX );
147 0 : rRect.Width( nHeight );
148 0 : rRect.Height( nWidth );
149 0 : }
150 :
151 : // Calculates the coordinates of a point when switching from
152 : // horizontal to vertical layout.
153 48 : void SwTxtFrm::SwitchHorizontalToVertical( Point& rPoint ) const
154 : {
155 : // calc offset inside frame
156 48 : const long nOfstX = rPoint.X() - Frm().Left();
157 48 : const long nOfstY = rPoint.Y() - Frm().Top();
158 48 : if ( IsVertLR() )
159 0 : rPoint.X() = Frm().Left() + nOfstY;
160 : else
161 : {
162 48 : if ( bIsSwapped )
163 48 : rPoint.X() = Frm().Left() + Frm().Height() - nOfstY;
164 : else
165 : // calc rotated coords
166 0 : rPoint.X() = Frm().Left() + Frm().Width() - nOfstY;
167 : }
168 :
169 48 : rPoint.Y() = Frm().Top() + nOfstX;
170 48 : }
171 :
172 : // Calculates the a limit value when switching from
173 : // horizontal to vertical layout.
174 0 : long SwTxtFrm::SwitchHorizontalToVertical( long nLimit ) const
175 : {
176 0 : Point aTmp( 0, nLimit );
177 0 : SwitchHorizontalToVertical( aTmp );
178 0 : return aTmp.X();
179 : }
180 :
181 : // Calculates the coordinates of a rectangle when switching from
182 : // vertical to horizontal layout.
183 0 : void SwTxtFrm::SwitchVerticalToHorizontal( SwRect& rRect ) const
184 : {
185 : long nOfstX;
186 :
187 : // calc offset inside frame
188 :
189 0 : if ( IsVertLR() )
190 0 : nOfstX = rRect.Left() - Frm().Left();
191 : else
192 : {
193 0 : if ( bIsSwapped )
194 0 : nOfstX = Frm().Left() + Frm().Height() - ( rRect.Left() + rRect.Width() );
195 : else
196 0 : nOfstX = Frm().Left() + Frm().Width() - ( rRect.Left() + rRect.Width() );
197 : }
198 :
199 0 : const long nOfstY = rRect.Top() - Frm().Top();
200 0 : const long nWidth = rRect.Height();
201 0 : const long nHeight = rRect.Width();
202 :
203 : // calc rotated coords
204 0 : rRect.Left( Frm().Left() + nOfstY );
205 0 : rRect.Top( Frm().Top() + nOfstX );
206 0 : rRect.Width( nWidth );
207 0 : rRect.Height( nHeight );
208 0 : }
209 :
210 : // Calculates the coordinates of a point when switching from
211 : // vertical to horizontal layout.
212 0 : void SwTxtFrm::SwitchVerticalToHorizontal( Point& rPoint ) const
213 : {
214 : long nOfstX;
215 :
216 : // calc offset inside frame
217 :
218 0 : if ( IsVertLR() )
219 0 : nOfstX = rPoint.X() - Frm().Left();
220 : else
221 : {
222 0 : if ( bIsSwapped )
223 0 : nOfstX = Frm().Left() + Frm().Height() - rPoint.X();
224 : else
225 0 : nOfstX = Frm().Left() + Frm().Width() - rPoint.X();
226 : }
227 :
228 0 : const long nOfstY = rPoint.Y() - Frm().Top();
229 :
230 : // calc rotated coords
231 0 : rPoint.X() = Frm().Left() + nOfstY;
232 0 : rPoint.Y() = Frm().Top() + nOfstX;
233 0 : }
234 :
235 : // Calculates the a limit value when switching from
236 : // vertical to horizontal layout.
237 0 : long SwTxtFrm::SwitchVerticalToHorizontal( long nLimit ) const
238 : {
239 0 : Point aTmp( nLimit, 0 );
240 0 : SwitchVerticalToHorizontal( aTmp );
241 0 : return aTmp.Y();
242 : }
243 :
244 1493596 : SwFrmSwapper::SwFrmSwapper( const SwTxtFrm* pTxtFrm, bool bSwapIfNotSwapped )
245 1493596 : : pFrm( pTxtFrm ), bUndo( false )
246 : {
247 1493604 : if ( pFrm->IsVertical() &&
248 26 : ( ( bSwapIfNotSwapped && ! pFrm->IsSwapped() ) ||
249 36 : ( ! bSwapIfNotSwapped && pFrm->IsSwapped() ) ) )
250 : {
251 8 : bUndo = true;
252 8 : ((SwTxtFrm*)pFrm)->SwapWidthAndHeight();
253 : }
254 1493596 : }
255 :
256 1493596 : SwFrmSwapper::~SwFrmSwapper()
257 : {
258 1493596 : if ( bUndo )
259 8 : ((SwTxtFrm*)pFrm)->SwapWidthAndHeight();
260 1493596 : }
261 :
262 550 : void SwTxtFrm::SwitchLTRtoRTL( SwRect& rRect ) const
263 : {
264 550 : SWAP_IF_NOT_SWAPPED( this )
265 :
266 550 : long nWidth = rRect.Width();
267 1100 : rRect.Left( 2 * ( Frm().Left() + Prt().Left() ) +
268 1100 : Prt().Width() - rRect.Right() - 1 );
269 :
270 550 : rRect.Width( nWidth );
271 :
272 550 : UNDO_SWAP( this )
273 550 : }
274 :
275 92 : void SwTxtFrm::SwitchLTRtoRTL( Point& rPoint ) const
276 : {
277 92 : SWAP_IF_NOT_SWAPPED( this )
278 :
279 92 : rPoint.X() = 2 * ( Frm().Left() + Prt().Left() ) + Prt().Width() - rPoint.X() - 1;
280 :
281 92 : UNDO_SWAP( this )
282 92 : }
283 :
284 29546 : SwLayoutModeModifier::SwLayoutModeModifier( const OutputDevice& rOutp ) :
285 29546 : rOut( rOutp ), nOldLayoutMode( rOutp.GetLayoutMode() )
286 : {
287 29546 : }
288 :
289 29546 : SwLayoutModeModifier::~SwLayoutModeModifier()
290 : {
291 29546 : ((OutputDevice&)rOut).SetLayoutMode( nOldLayoutMode );
292 29546 : }
293 :
294 4204 : void SwLayoutModeModifier::Modify( bool bChgToRTL )
295 : {
296 : ((OutputDevice&)rOut).SetLayoutMode( bChgToRTL ?
297 : TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL :
298 4204 : TEXT_LAYOUT_BIDI_STRONG );
299 4204 : }
300 :
301 25810 : void SwLayoutModeModifier::SetAuto()
302 : {
303 25810 : const ComplexTextLayoutMode nNewLayoutMode = nOldLayoutMode & ~TEXT_LAYOUT_BIDI_STRONG;
304 25810 : ((OutputDevice&)rOut).SetLayoutMode( nNewLayoutMode );
305 25810 : }
306 :
307 207875 : SwDigitModeModifier::SwDigitModeModifier( const OutputDevice& rOutp, LanguageType eCurLang ) :
308 207875 : rOut( rOutp ), nOldLanguageType( rOutp.GetDigitLanguage() )
309 : {
310 207875 : LanguageType eLang = eCurLang;
311 207875 : const SvtCTLOptions::TextNumerals nTextNumerals = SW_MOD()->GetCTLOptions().GetCTLTextNumerals();
312 :
313 207875 : if ( SvtCTLOptions::NUMERALS_HINDI == nTextNumerals )
314 0 : eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
315 207875 : else if ( SvtCTLOptions::NUMERALS_ARABIC == nTextNumerals )
316 207875 : eLang = LANGUAGE_ENGLISH;
317 0 : else if ( SvtCTLOptions::NUMERALS_SYSTEM == nTextNumerals )
318 0 : eLang = ::GetAppLanguage();
319 :
320 207875 : ((OutputDevice&)rOut).SetDigitLanguage( eLang );
321 207875 : }
322 :
323 207875 : SwDigitModeModifier::~SwDigitModeModifier()
324 : {
325 207875 : ((OutputDevice&)rOut).SetDigitLanguage( nOldLanguageType );
326 207875 : }
327 :
328 31840 : void SwTxtFrm::Init()
329 : {
330 : OSL_ENSURE( !IsLocked(), "+SwTxtFrm::Init: this is locked." );
331 31840 : if( !IsLocked() )
332 : {
333 31840 : ClearPara();
334 31840 : ResetBlinkPor();
335 : // set flags directly to save a ResetPreps call,
336 : // and thereby an unnecessary GetPara call
337 : // don't set bOrphan, bLocked or bWait to false!
338 : // bOrphan = bFlag7 = bFlag8 = false;
339 : }
340 31840 : }
341 :
342 63976 : SwTxtFrm::SwTxtFrm(SwTxtNode * const pNode, SwFrm* pSib )
343 : : SwCntntFrm( pNode, pSib )
344 : , nAllLines( 0 )
345 : , nThisLines( 0 )
346 : , mnFlyAnchorOfst( 0 )
347 : , mnFlyAnchorOfstNoWrap( 0 )
348 : , mnFtnLine( 0 )
349 : , mnHeightOfLastLine( 0 ) // OD 2004-03-17 #i11860#
350 : , mnAdditionalFirstLineOffset( 0 )
351 : , nOfst( 0 )
352 : , nCacheIdx( USHRT_MAX )
353 : , bLocked( false )
354 : , bWidow( false )
355 : , bJustWidow( false )
356 : , bEmpty( false )
357 : , bInFtnConnect( false )
358 : , bFtn( false )
359 : , bRepaint( false )
360 : , bBlinkPor( false )
361 : , bFieldFollow( false )
362 : , bHasAnimation( false )
363 : , bIsSwapped( false )
364 63976 : , mbFollowFormatAllowed( true ) // OD 14.03.2003 #i11760#
365 : {
366 63976 : mnType = FRMC_TXT;
367 63976 : }
368 :
369 191700 : SwTxtFrm::~SwTxtFrm()
370 : {
371 : // Remove associated SwParaPortion from pTxtCache
372 63900 : ClearPara();
373 :
374 : const SwCntntNode* pCNd;
375 255600 : if( 0 != ( pCNd = PTR_CAST( SwCntntNode, GetRegisteredIn() )) &&
376 255600 : !pCNd->GetDoc()->IsInDtor() && HasFtn() )
377 : {
378 132 : SwTxtNode *pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
379 132 : const SwFtnIdxs &rFtnIdxs = pCNd->GetDoc()->GetFtnIdxs();
380 132 : size_t nPos = 0;
381 132 : sal_uLong nIndex = pCNd->GetIndex();
382 132 : rFtnIdxs.SeekEntry( *pTxtNd, &nPos );
383 : SwTxtFtn* pTxtFtn;
384 132 : if( nPos < rFtnIdxs.size() )
385 : {
386 292 : while( nPos && pTxtNd == &(rFtnIdxs[ nPos ]->GetTxtNode()) )
387 28 : --nPos;
388 132 : if( nPos || pTxtNd != &(rFtnIdxs[ nPos ]->GetTxtNode()) )
389 26 : ++nPos;
390 : }
391 410 : while( nPos < rFtnIdxs.size() )
392 : {
393 172 : pTxtFtn = rFtnIdxs[ nPos ];
394 172 : if( pTxtFtn->GetTxtNode().GetIndex() > nIndex )
395 26 : break;
396 146 : pTxtFtn->DelFrms( this );
397 146 : ++nPos;
398 : }
399 : }
400 127800 : }
401 :
402 356747 : const OUString& SwTxtFrm::GetTxt() const
403 : {
404 356747 : return GetTxtNode()->GetTxt();
405 : }
406 :
407 29440 : void SwTxtFrm::ResetPreps()
408 : {
409 29440 : if ( GetCacheIdx() != USHRT_MAX )
410 : {
411 : SwParaPortion *pPara;
412 29440 : if( 0 != (pPara = GetPara()) )
413 29436 : pPara->ResetPreps();
414 : }
415 29440 : }
416 :
417 1006839 : bool SwTxtFrm::IsHiddenNow() const
418 : {
419 1006839 : SwFrmSwapper aSwapper( this, true );
420 :
421 1006839 : if( !Frm().Width() && IsValid() && GetUpper()->IsValid() )
422 : // invalid when stack overflows (StackHack)!
423 : {
424 : // OSL_FAIL( "SwTxtFrm::IsHiddenNow: thin frame" );
425 0 : return true;
426 : }
427 :
428 1006839 : const bool bHiddenCharsHidePara = GetTxtNode()->HasHiddenCharAttribute( true );
429 1006839 : const bool bHiddenParaField = GetTxtNode()->HasHiddenParaField();
430 1006839 : const SwViewShell* pVsh = getRootFrm()->GetCurrShell();
431 :
432 1006839 : if ( pVsh && ( bHiddenCharsHidePara || bHiddenParaField ) )
433 : {
434 2132 : if (
435 0 : ( bHiddenParaField &&
436 0 : ( !pVsh->GetViewOptions()->IsShowHiddenPara() &&
437 6396 : !pVsh->GetViewOptions()->IsFldName() ) ) ||
438 2132 : ( bHiddenCharsHidePara &&
439 2132 : !pVsh->GetViewOptions()->IsShowHiddenChar() ) )
440 : {
441 2132 : return true;
442 : }
443 : }
444 :
445 1004707 : return false;
446 : }
447 :
448 : // removes Textfrm's attachments, when it's hidden
449 46 : void SwTxtFrm::HideHidden()
450 : {
451 : OSL_ENSURE( !GetFollow() && IsHiddenNow(),
452 : "HideHidden on visible frame of hidden frame has follow" );
453 :
454 46 : const sal_Int32 nEnd = COMPLETE_STRING;
455 46 : HideFootnotes( GetOfst(), nEnd );
456 : // OD 2004-01-15 #110582#
457 46 : HideAndShowObjects();
458 :
459 : // format information is obsolete
460 46 : ClearPara();
461 46 : }
462 :
463 54 : void SwTxtFrm::HideFootnotes( sal_Int32 nStart, sal_Int32 nEnd )
464 : {
465 54 : const SwpHints *pHints = GetTxtNode()->GetpSwpHints();
466 54 : if( pHints )
467 : {
468 54 : const size_t nSize = pHints->Count();
469 54 : SwPageFrm *pPage = 0;
470 160 : for ( size_t i = 0; i < nSize; ++i )
471 : {
472 106 : const SwTxtAttr *pHt = (*pHints)[i];
473 106 : if ( pHt->Which() == RES_TXTATR_FTN )
474 : {
475 0 : const sal_Int32 nIdx = pHt->GetStart();
476 0 : if ( nEnd < nIdx )
477 0 : break;
478 0 : if( nStart <= nIdx )
479 : {
480 0 : if( !pPage )
481 0 : pPage = FindPageFrm();
482 0 : pPage->RemoveFtn( this, (SwTxtFtn*)pHt );
483 : }
484 : }
485 : }
486 : }
487 54 : }
488 :
489 : // #120729# - hotfix
490 : // as-character anchored graphics, which are used for a graphic bullet list.
491 : // As long as these graphic bullet list aren't imported, do not hide a
492 : // at-character anchored object, if
493 : // (a) the document is an imported WW8 document -
494 : // checked by checking certain compatibility options -,
495 : // (b) the paragraph is the last content in the document and
496 : // (c) the anchor character is an as-character anchored graphic.
497 0 : bool sw_HideObj( const SwTxtFrm& _rFrm,
498 : const RndStdIds _eAnchorType,
499 : const sal_Int32 _nObjAnchorPos,
500 : SwAnchoredObject* _pAnchoredObj )
501 : {
502 0 : bool bRet( true );
503 :
504 0 : if (_eAnchorType == FLY_AT_CHAR)
505 : {
506 0 : const IDocumentSettingAccess* pIDSA = _rFrm.GetTxtNode()->getIDocumentSettingAccess();
507 0 : if ( !pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) &&
508 0 : !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) &&
509 0 : !pIDSA->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) &&
510 0 : pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
511 0 : _rFrm.IsInDocBody() && !_rFrm.FindNextCnt() )
512 : {
513 : const sal_Unicode cAnchorChar =
514 0 : _rFrm.GetTxtNode()->GetTxt()[_nObjAnchorPos];
515 0 : if ( cAnchorChar == CH_TXTATR_BREAKWORD )
516 : {
517 : const SwTxtAttr* const pHint(
518 : _rFrm.GetTxtNode()->GetTxtAttrForCharAt(_nObjAnchorPos,
519 0 : RES_TXTATR_FLYCNT) );
520 0 : if ( pHint )
521 : {
522 : const SwFrmFmt* pFrmFmt =
523 0 : static_cast<const SwTxtFlyCnt*>(pHint)->GetFlyCnt().GetFrmFmt();
524 0 : if ( pFrmFmt->Which() == RES_FLYFRMFMT )
525 : {
526 0 : SwNodeIndex nCntntIndex = *(pFrmFmt->GetCntnt().GetCntntIdx());
527 0 : ++nCntntIndex;
528 0 : if ( nCntntIndex.GetNode().IsNoTxtNode() )
529 : {
530 0 : bRet = false;
531 : // set needed data structure values for object positioning
532 0 : SWRECTFN( (&_rFrm) );
533 0 : SwRect aLastCharRect( _rFrm.Frm() );
534 0 : (aLastCharRect.*fnRect->fnSetWidth)( 1 );
535 0 : _pAnchoredObj->maLastCharRect = aLastCharRect;
536 0 : _pAnchoredObj->mnLastTopOfLine = (aLastCharRect.*fnRect->fnGetTop)();
537 0 : }
538 : }
539 : }
540 : }
541 : }
542 : }
543 :
544 0 : return bRet;
545 : }
546 :
547 : /** method to hide/show objects
548 :
549 : OD 2004-01-15 #110582#
550 : method hides respectively shows objects, which are anchored at paragraph,
551 : at/as a character of the paragraph, corresponding to the paragraph and
552 : paragraph portion visibility.
553 :
554 : - is called from HideHidden() - should hide objects in hidden paragraphs and
555 : - from _Format() - should hide/show objects in partly visible paragraphs
556 : */
557 121467 : void SwTxtFrm::HideAndShowObjects()
558 : {
559 121467 : if ( GetDrawObjs() )
560 : {
561 12312 : if ( IsHiddenNow() )
562 : {
563 : // complete paragraph is hidden. Thus, hide all objects
564 0 : for ( size_t i = 0; i < GetDrawObjs()->size(); ++i )
565 : {
566 0 : SdrObject* pObj = (*GetDrawObjs())[i]->DrawObj();
567 0 : SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
568 : // #120729# - hotfix
569 : // under certain conditions
570 0 : const RndStdIds eAnchorType( pContact->GetAnchorId() );
571 0 : const sal_Int32 nObjAnchorPos = pContact->GetCntntAnchorIndex().GetIndex();
572 0 : if ((eAnchorType != FLY_AT_CHAR) ||
573 : sw_HideObj( *this, eAnchorType, nObjAnchorPos,
574 0 : (*GetDrawObjs())[i] ))
575 : {
576 0 : pContact->MoveObjToInvisibleLayer( pObj );
577 : }
578 : }
579 : }
580 : else
581 : {
582 : // paragraph is visible, but can contain hidden text portion.
583 : // first we check if objects are allowed to be hidden:
584 12312 : const SwTxtNode& rNode = *GetTxtNode();
585 12312 : const SwViewShell* pVsh = getRootFrm()->GetCurrShell();
586 24624 : const bool bShouldBeHidden = !pVsh || !pVsh->GetWin() ||
587 24624 : !pVsh->GetViewOptions()->IsShowHiddenChar();
588 :
589 : // Thus, show all objects, which are anchored at paragraph and
590 : // hide/show objects, which are anchored at/as character, according
591 : // to the visibility of the anchor character.
592 127676 : for ( size_t i = 0; i < GetDrawObjs()->size(); ++i )
593 : {
594 115364 : SdrObject* pObj = (*GetDrawObjs())[i]->DrawObj();
595 115364 : SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
596 : // #120729# - determine anchor type only once
597 115364 : const RndStdIds eAnchorType( pContact->GetAnchorId() );
598 :
599 115364 : if (eAnchorType == FLY_AT_PARA)
600 : {
601 109380 : pContact->MoveObjToVisibleLayer( pObj );
602 : }
603 5984 : else if ((eAnchorType == FLY_AT_CHAR) ||
604 : (eAnchorType == FLY_AS_CHAR))
605 : {
606 : sal_Int32 nHiddenStart;
607 : sal_Int32 nHiddenEnd;
608 5984 : const sal_Int32 nObjAnchorPos = pContact->GetCntntAnchorIndex().GetIndex();
609 5984 : SwScriptInfo::GetBoundsOfHiddenRange( rNode, nObjAnchorPos, nHiddenStart, nHiddenEnd, 0 );
610 : // #120729# - hotfix
611 : // under certain conditions
612 5984 : if ( nHiddenStart != COMPLETE_STRING && bShouldBeHidden &&
613 0 : sw_HideObj( *this, eAnchorType, nObjAnchorPos, (*GetDrawObjs())[i] ) )
614 0 : pContact->MoveObjToInvisibleLayer( pObj );
615 : else
616 5984 : pContact->MoveObjToVisibleLayer( pObj );
617 : }
618 : else
619 : {
620 : OSL_FAIL( "<SwTxtFrm::HideAndShowObjects()> - object not anchored at/inside paragraph!?" );
621 : }
622 : }
623 : }
624 : }
625 :
626 121467 : if (IsFollow())
627 : {
628 7352 : SwTxtFrm *pMaster = FindMaster();
629 : OSL_ENSURE(pMaster, "SwTxtFrm without master");
630 7352 : if (pMaster)
631 7352 : pMaster->HideAndShowObjects();
632 : }
633 121467 : }
634 :
635 : // Returns the first possible break point in the current line.
636 : // This method is used in SwTxtFrm::Format() to decide whether the previous
637 : // line has to be formatted as well.
638 : // nFound is <= nEndLine.
639 2891 : sal_Int32 SwTxtFrm::FindBrk( const OUString &rTxt,
640 : const sal_Int32 nStart,
641 : const sal_Int32 nEnd ) const
642 : {
643 2891 : sal_Int32 nFound = nStart;
644 2891 : const sal_Int32 nEndLine = std::min( nEnd, rTxt.getLength() - 1 );
645 :
646 : // skip all leading blanks (see bug #2235).
647 5788 : while( nFound <= nEndLine && ' ' == rTxt[nFound] )
648 : {
649 6 : nFound++;
650 : }
651 :
652 : // A tricky situation with the TxtAttr-Dummy-character (in this case "$"):
653 : // "Dr.$Meyer" at the beginning of the second line. Typing a blank after that
654 : // doesn't result in the word moving into first line, even though that would work.
655 : // For this reason we don't skip the dummy char.
656 69753 : while( nFound <= nEndLine && ' ' != rTxt[nFound] )
657 : {
658 63971 : nFound++;
659 : }
660 :
661 2891 : return nFound;
662 : }
663 :
664 40813 : bool SwTxtFrm::IsIdxInside( const sal_Int32 nPos, const sal_Int32 nLen ) const
665 : {
666 40813 : if( nLen != COMPLETE_STRING && GetOfst() > nPos + nLen ) // the range preceded us
667 380 : return false;
668 :
669 40433 : if( !GetFollow() ) // the range doesn't precede us,
670 38517 : return true; // nobody follows us.
671 :
672 1916 : const sal_Int32 nMax = GetFollow()->GetOfst();
673 :
674 : // either the range overlap or our text has been deleted
675 1916 : if( nMax > nPos || nMax > GetTxt().getLength() )
676 508 : return true;
677 :
678 : // changes made in the first line of a follow can modify the master
679 1408 : const SwParaPortion* pPara = GetFollow()->GetPara();
680 1408 : return pPara && ( nPos <= nMax + pPara->GetLen() );
681 : }
682 :
683 12839 : inline void SwTxtFrm::InvalidateRange(const SwCharRange &aRange, const long nD)
684 : {
685 12839 : if ( IsIdxInside( aRange.Start(), aRange.Len() ) )
686 12793 : _InvalidateRange( aRange, nD );
687 12839 : }
688 :
689 37661 : void SwTxtFrm::_InvalidateRange( const SwCharRange &aRange, const long nD)
690 : {
691 37661 : if ( !HasPara() )
692 17472 : { InvalidateSize();
693 55133 : return;
694 : }
695 :
696 20189 : SetWidow( false );
697 20189 : SwParaPortion *pPara = GetPara();
698 :
699 20189 : bool bInv = false;
700 20189 : if( 0 != nD )
701 : {
702 : // In nDelta the differences betwen old and new
703 : // linelengths are being added, that's why it's negative
704 : // if chars have been added and positive, if chars have
705 : // deleted
706 12476 : pPara->GetDelta() += nD;
707 12476 : bInv = true;
708 : }
709 20189 : SwCharRange &rReformat = pPara->GetReformat();
710 20189 : if(aRange != rReformat) {
711 16137 : if( COMPLETE_STRING == rReformat.Len() )
712 0 : rReformat = aRange;
713 : else
714 16137 : rReformat += aRange;
715 16137 : bInv = true;
716 : }
717 20189 : if(bInv)
718 : {
719 16507 : InvalidateSize();
720 : }
721 : }
722 :
723 134 : void SwTxtFrm::CalcLineSpace()
724 : {
725 : OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
726 : "SwTxtFrm::CalcLineSpace with swapped frame!" );
727 :
728 134 : if( IsLocked() || !HasPara() )
729 264 : return;
730 :
731 : SwParaPortion *pPara;
732 6 : if( GetDrawObjs() ||
733 6 : GetTxtNode()->GetSwAttrSet().GetLRSpace().IsAutoFirst() ||
734 2 : ( pPara = GetPara() )->IsFixLineHeight() )
735 : {
736 0 : Init();
737 0 : return;
738 : }
739 :
740 2 : Size aNewSize( Prt().SSize() );
741 :
742 2 : SwTxtFormatInfo aInf( this );
743 4 : SwTxtFormatter aLine( this, &aInf );
744 2 : if( aLine.GetDropLines() )
745 : {
746 0 : Init();
747 0 : return;
748 : }
749 :
750 2 : aLine.Top();
751 2 : aLine.RecalcRealHeight();
752 :
753 2 : aNewSize.Height() = (aLine.Y() - Frm().Top()) + aLine.GetLineHeight();
754 :
755 2 : SwTwips nDelta = aNewSize.Height() - Prt().Height();
756 : // 4291: underflow with free-flying frames
757 2 : if( aInf.GetTxtFly().IsOn() )
758 : {
759 0 : SwRect aTmpFrm( Frm() );
760 0 : if( nDelta < 0 )
761 0 : aTmpFrm.Height( Prt().Height() );
762 : else
763 0 : aTmpFrm.Height( aNewSize.Height() );
764 0 : if( aInf.GetTxtFly().Relax( aTmpFrm ) )
765 : {
766 0 : Init();
767 0 : return;
768 : }
769 : }
770 :
771 2 : if( nDelta )
772 : {
773 0 : SwTxtFrmBreak aBreak( this );
774 0 : if( GetFollow() || aBreak.IsBreakNow( aLine ) )
775 : {
776 : // if there is a Follow() or if we need to break here, reformat
777 0 : Init();
778 : }
779 : else
780 : {
781 : // everything is business as usual...
782 0 : pPara->SetPrepAdjust();
783 0 : pPara->SetPrep();
784 : }
785 2 : }
786 : }
787 :
788 26420 : static void lcl_SetWrong( SwTxtFrm& rFrm, sal_Int32 nPos, sal_Int32 nCnt, bool bMove )
789 : {
790 26420 : if ( !rFrm.IsFollow() )
791 : {
792 24652 : SwTxtNode* pTxtNode = rFrm.GetTxtNode();
793 24652 : IGrammarContact* pGrammarContact = getGrammarContact( *pTxtNode );
794 : SwGrammarMarkUp* pWrongGrammar = pGrammarContact ?
795 24652 : pGrammarContact->getGrammarCheck( *pTxtNode, false ) :
796 49304 : pTxtNode->GetGrammarCheck();
797 24652 : bool bGrammarProxy = pWrongGrammar != pTxtNode->GetGrammarCheck();
798 24652 : if( bMove )
799 : {
800 19384 : if( pTxtNode->GetWrong() )
801 1440 : pTxtNode->GetWrong()->Move( nPos, nCnt );
802 19384 : if( pWrongGrammar )
803 0 : pWrongGrammar->MoveGrammar( nPos, nCnt );
804 19384 : if( bGrammarProxy && pTxtNode->GetGrammarCheck() )
805 0 : pTxtNode->GetGrammarCheck()->MoveGrammar( nPos, nCnt );
806 19384 : if( pTxtNode->GetSmartTags() )
807 0 : pTxtNode->GetSmartTags()->Move( nPos, nCnt );
808 : }
809 : else
810 : {
811 5268 : if( pTxtNode->GetWrong() )
812 6 : pTxtNode->GetWrong()->Invalidate( nPos, nCnt );
813 5268 : if( pWrongGrammar )
814 0 : pWrongGrammar->Invalidate( nPos, nCnt );
815 5268 : if( pTxtNode->GetSmartTags() )
816 0 : pTxtNode->GetSmartTags()->Invalidate( nPos, nCnt );
817 : }
818 24652 : const sal_Int32 nEnd = nPos + (nCnt > 0 ? nCnt : 1 );
819 24652 : if ( !pTxtNode->GetWrong() && !pTxtNode->IsWrongDirty() )
820 : {
821 35 : pTxtNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) );
822 35 : pTxtNode->GetWrong()->SetInvalid( nPos, nEnd );
823 : }
824 24652 : if ( !pTxtNode->GetSmartTags() && !pTxtNode->IsSmartTagDirty() )
825 : {
826 0 : pTxtNode->SetSmartTags( new SwWrongList( WRONGLIST_SMARTTAG ) );
827 0 : pTxtNode->GetSmartTags()->SetInvalid( nPos, nEnd );
828 : }
829 24652 : pTxtNode->SetWrongDirty( true );
830 24652 : pTxtNode->SetGrammarCheckDirty( true );
831 24652 : pTxtNode->SetWordCountDirty( true );
832 24652 : pTxtNode->SetAutoCompleteWordDirty( true );
833 24652 : pTxtNode->SetSmartTagDirty( true );
834 : }
835 :
836 26420 : SwRootFrm *pRootFrm = rFrm.getRootFrm();
837 26420 : if (pRootFrm)
838 : {
839 26420 : pRootFrm->SetNeedGrammarCheck( true );
840 : }
841 :
842 26420 : SwPageFrm *pPage = rFrm.FindPageFrm();
843 26420 : if( pPage )
844 : {
845 26420 : pPage->InvalidateSpelling();
846 26420 : pPage->InvalidateAutoCompleteWords();
847 26420 : pPage->InvalidateWordCount();
848 26420 : pPage->InvalidateSmartTags();
849 : }
850 26420 : }
851 :
852 28732 : static void lcl_SetScriptInval( SwTxtFrm& rFrm, sal_Int32 nPos )
853 : {
854 28732 : if( rFrm.GetPara() )
855 9724 : rFrm.GetPara()->GetScriptInfo().SetInvalidityA( nPos );
856 28732 : }
857 :
858 1768 : static void lcl_ModifyOfst( SwTxtFrm* pFrm, sal_Int32 nPos, sal_Int32 nLen )
859 : {
860 6922 : while( pFrm && pFrm->GetOfst() <= nPos )
861 3386 : pFrm = pFrm->GetFollow();
862 4428 : while( pFrm )
863 : {
864 892 : if (nLen == COMPLETE_STRING)
865 40 : pFrm->ManipOfst( pFrm->GetTxtNode()->GetTxt().getLength() );
866 : else
867 852 : pFrm->ManipOfst( pFrm->GetOfst() + nLen );
868 892 : pFrm = pFrm->GetFollow();
869 : }
870 1768 : }
871 :
872 : // Related: fdo#56031 filter out attribute changes that don't matter for
873 : // humans/a11y to stop flooding the destination mortal with useless noise
874 14166 : static bool isA11yRelevantAttribute(sal_uInt16 nWhich)
875 : {
876 14166 : return nWhich != RES_CHRATR_RSID;
877 : }
878 :
879 5782 : static bool hasA11yRelevantAttribute( const std::vector<sal_uInt16>& nWhich )
880 : {
881 17346 : for( std::vector<sal_uInt16>::const_iterator nItr = nWhich.begin();
882 11564 : nItr < nWhich.end(); ++nItr )
883 0 : if ( isA11yRelevantAttribute( *nItr ) )
884 0 : return true;
885 :
886 5782 : return false;
887 : }
888 :
889 39362 : void SwTxtFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
890 : {
891 39362 : const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
892 :
893 : // modifications concerning frame attributes are processed by the base class
894 39362 : if( IsInRange( aFrmFmtSetRange, nWhich ) || RES_FMT_CHG == nWhich )
895 : {
896 1302 : SwCntntFrm::Modify( pOld, pNew );
897 1302 : if( nWhich == RES_FMT_CHG && getRootFrm()->GetCurrShell() )
898 : {
899 : // collection has changed
900 550 : Prepare( PREP_CLEAR );
901 550 : _InvalidatePrt();
902 550 : lcl_SetWrong( *this, 0, COMPLETE_STRING, false );
903 550 : SetDerivedR2L( false );
904 550 : CheckDirChange();
905 : // OD 09.12.2002 #105576# - Force complete paint due to existing
906 : // indents.
907 550 : SetCompletePaint();
908 550 : InvalidateLineNum();
909 : }
910 1302 : return;
911 : }
912 :
913 : // while locked ignore all modifications
914 38060 : if( IsLocked() )
915 0 : return;
916 :
917 : // save stack
918 : // warning: one has to ensure that all variables are set
919 : sal_Int32 nPos;
920 : sal_Int32 nLen;
921 38060 : bool bSetFldsDirty = false;
922 38060 : bool bRecalcFtnFlag = false;
923 :
924 38060 : switch( nWhich )
925 : {
926 : case RES_LINENUMBER:
927 : {
928 0 : InvalidateLineNum();
929 : }
930 0 : break;
931 : case RES_INS_TXT:
932 : {
933 18724 : nPos = ((SwInsTxt*)pNew)->nPos;
934 18724 : nLen = ((SwInsTxt*)pNew)->nLen;
935 18724 : if( IsIdxInside( nPos, nLen ) )
936 : {
937 17756 : if( !nLen )
938 : {
939 : // 6969: refresh NumPortions even when line is empty!
940 0 : if( nPos )
941 0 : InvalidateSize();
942 : else
943 0 : Prepare( PREP_CLEAR );
944 : }
945 : else
946 17756 : _InvalidateRange( SwCharRange( nPos, nLen ), nLen );
947 : }
948 18724 : lcl_SetWrong( *this, nPos, nLen, true );
949 18724 : lcl_SetScriptInval( *this, nPos );
950 18724 : bSetFldsDirty = true;
951 18724 : if( HasFollow() )
952 994 : lcl_ModifyOfst( this, nPos, nLen );
953 : }
954 18724 : break;
955 : case RES_DEL_CHR:
956 : {
957 386 : nPos = ((SwDelChr*)pNew)->nPos;
958 386 : InvalidateRange( SwCharRange( nPos, 1 ), -1 );
959 386 : lcl_SetWrong( *this, nPos, -1, true );
960 386 : lcl_SetScriptInval( *this, nPos );
961 386 : bSetFldsDirty = bRecalcFtnFlag = true;
962 386 : if( HasFollow() )
963 44 : lcl_ModifyOfst( this, nPos, COMPLETE_STRING );
964 : }
965 386 : break;
966 : case RES_DEL_TXT:
967 : {
968 2042 : nPos = ((SwDelTxt*)pNew)->nStart;
969 2042 : nLen = ((SwDelTxt*)pNew)->nLen;
970 2042 : const sal_Int32 m = -nLen;
971 2042 : if( IsIdxInside( nPos, nLen ) )
972 : {
973 1322 : if( !nLen )
974 48 : InvalidateSize();
975 : else
976 1274 : InvalidateRange( SwCharRange( nPos, 1 ), m );
977 : }
978 2042 : lcl_SetWrong( *this, nPos, m, true );
979 2042 : lcl_SetScriptInval( *this, nPos );
980 2042 : bSetFldsDirty = bRecalcFtnFlag = true;
981 2042 : if( HasFollow() )
982 730 : lcl_ModifyOfst( this, nPos, nLen );
983 : }
984 2042 : break;
985 : case RES_UPDATE_ATTR:
986 : {
987 5782 : nPos = ((SwUpdateAttr*)pNew)->getStart();
988 5782 : nLen = ((SwUpdateAttr*)pNew)->getEnd() - nPos;
989 5782 : if( IsIdxInside( nPos, nLen ) )
990 : {
991 : // Es muss in jedem Fall neu formatiert werden,
992 : // auch wenn der invalidierte Bereich null ist.
993 : // Beispiel: leere Zeile, 14Pt einstellen !
994 : // if( !nLen ) nLen = 1;
995 :
996 : // 6680: FtnNummern muessen formatiert werden.
997 5782 : if( !nLen )
998 1366 : nLen = 1;
999 :
1000 5782 : _InvalidateRange( SwCharRange( nPos, nLen) );
1001 5782 : const sal_uInt16 nTmp = ((SwUpdateAttr*)pNew)->getWhichAttr();
1002 :
1003 5782 : if( ! nTmp || RES_TXTATR_CHARFMT == nTmp || RES_TXTATR_AUTOFMT == nTmp ||
1004 1666 : RES_FMT_CHG == nTmp || RES_ATTRSET_CHG == nTmp )
1005 : {
1006 4382 : lcl_SetWrong( *this, nPos, nPos + nLen, false );
1007 4382 : lcl_SetScriptInval( *this, nPos );
1008 : }
1009 : }
1010 :
1011 11564 : if( isA11yRelevantAttribute( ((SwUpdateAttr*)pNew)->getWhichAttr() ) &&
1012 5782 : hasA11yRelevantAttribute( ((SwUpdateAttr*)pNew)->getFmtAttr() ) )
1013 : {
1014 : // #i104008#
1015 0 : SwViewShell* pViewSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
1016 0 : if ( pViewSh )
1017 : {
1018 0 : pViewSh->InvalidateAccessibleParaAttrs( *this );
1019 : }
1020 : }
1021 : }
1022 5782 : break;
1023 : case RES_OBJECTDYING:
1024 0 : break;
1025 :
1026 : case RES_PARATR_LINESPACING:
1027 : {
1028 0 : CalcLineSpace();
1029 0 : InvalidateSize();
1030 0 : _InvalidatePrt();
1031 0 : if( IsInSct() && !GetPrev() )
1032 : {
1033 0 : SwSectionFrm *pSect = FindSctFrm();
1034 0 : if( pSect->ContainsAny() == this )
1035 0 : pSect->InvalidatePrt();
1036 : }
1037 :
1038 : // OD 09.01.2004 #i11859# - correction:
1039 : // (1) Also invalidate next frame on next page/column.
1040 : // (2) Skip empty sections and hidden paragraphs
1041 : // Thus, use method <InvalidateNextPrtArea()>
1042 0 : InvalidateNextPrtArea();
1043 :
1044 0 : SetCompletePaint();
1045 : }
1046 0 : break;
1047 :
1048 : case RES_TXTATR_FIELD:
1049 : case RES_TXTATR_ANNOTATION:
1050 : {
1051 1312 : nPos = ((SwFmtFld*)pNew)->GetTxtFld()->GetStart();
1052 1312 : if( IsIdxInside( nPos, 1 ) )
1053 : {
1054 1312 : if( pNew == pOld )
1055 : {
1056 : // only repaint
1057 : // opt: invalidate window?
1058 0 : InvalidatePage();
1059 0 : SetCompletePaint();
1060 : }
1061 : else
1062 1312 : _InvalidateRange( SwCharRange( nPos, 1 ) );
1063 : }
1064 1312 : bSetFldsDirty = true;
1065 : // ST2
1066 1312 : if ( SwSmartTagMgr::Get().IsSmartTagsEnabled() )
1067 0 : lcl_SetWrong( *this, nPos, nPos + 1, false );
1068 : }
1069 1312 : break;
1070 :
1071 : case RES_TXTATR_FTN :
1072 : {
1073 166 : nPos = ((SwFmtFtn*)pNew)->GetTxtFtn()->GetStart();
1074 166 : if( IsInFtn() || IsIdxInside( nPos, 1 ) )
1075 166 : Prepare( PREP_FTN, ((SwFmtFtn*)pNew)->GetTxtFtn() );
1076 166 : break;
1077 : }
1078 :
1079 : case RES_ATTRSET_CHG:
1080 : {
1081 8384 : InvalidateLineNum();
1082 :
1083 8384 : SwAttrSet& rNewSet = *((SwAttrSetChg*)pNew)->GetChgSet();
1084 8384 : const SfxPoolItem* pItem = 0;
1085 8384 : int nClear = 0;
1086 8384 : sal_uInt16 nCount = rNewSet.Count();
1087 :
1088 8384 : if( SfxItemState::SET == rNewSet.GetItemState( RES_TXTATR_FTN, false, &pItem ))
1089 : {
1090 0 : nPos = ((SwFmtFtn*)pItem)->GetTxtFtn()->GetStart();
1091 0 : if( IsIdxInside( nPos, 1 ) )
1092 0 : Prepare( PREP_FTN, pNew );
1093 0 : nClear = 0x01;
1094 0 : --nCount;
1095 : }
1096 :
1097 8384 : if( SfxItemState::SET == rNewSet.GetItemState( RES_TXTATR_FIELD, false, &pItem ))
1098 : {
1099 0 : nPos = ((SwFmtFld*)pItem)->GetTxtFld()->GetStart();
1100 0 : if( IsIdxInside( nPos, 1 ) )
1101 : {
1102 : const SfxPoolItem& rOldItem =
1103 0 : ((SwAttrSetChg*)pOld)->GetChgSet()->Get( RES_TXTATR_FIELD );
1104 0 : if( pItem == &rOldItem )
1105 : {
1106 0 : InvalidatePage();
1107 0 : SetCompletePaint();
1108 : }
1109 : else
1110 0 : _InvalidateRange( SwCharRange( nPos, 1 ) );
1111 : }
1112 0 : nClear |= 0x02;
1113 0 : --nCount;
1114 : }
1115 : bool bLineSpace = SfxItemState::SET == rNewSet.GetItemState(
1116 8384 : RES_PARATR_LINESPACING, false ),
1117 : bRegister = SfxItemState::SET == rNewSet.GetItemState(
1118 8384 : RES_PARATR_REGISTER, false );
1119 8384 : if ( bLineSpace || bRegister )
1120 : {
1121 134 : Prepare( bRegister ? PREP_REGISTER : PREP_ADJUST_FRM );
1122 134 : CalcLineSpace();
1123 134 : InvalidateSize();
1124 134 : _InvalidatePrt();
1125 :
1126 : // OD 09.01.2004 #i11859# - correction:
1127 : // (1) Also invalidate next frame on next page/column.
1128 : // (2) Skip empty sections and hidden paragraphs
1129 : // Thus, use method <InvalidateNextPrtArea()>
1130 134 : InvalidateNextPrtArea();
1131 :
1132 134 : SetCompletePaint();
1133 134 : nClear |= 0x04;
1134 134 : if ( bLineSpace )
1135 : {
1136 134 : --nCount;
1137 134 : if( IsInSct() && !GetPrev() )
1138 : {
1139 0 : SwSectionFrm *pSect = FindSctFrm();
1140 0 : if( pSect->ContainsAny() == this )
1141 0 : pSect->InvalidatePrt();
1142 : }
1143 : }
1144 134 : if ( bRegister )
1145 0 : --nCount;
1146 : }
1147 8384 : if ( SfxItemState::SET == rNewSet.GetItemState( RES_PARATR_SPLIT,
1148 8384 : false ))
1149 : {
1150 0 : if ( GetPrev() )
1151 0 : CheckKeep();
1152 0 : Prepare( PREP_CLEAR );
1153 0 : InvalidateSize();
1154 0 : nClear |= 0x08;
1155 0 : --nCount;
1156 : }
1157 :
1158 16768 : if( SfxItemState::SET == rNewSet.GetItemState( RES_BACKGROUND, false)
1159 8384 : && !IsFollow() && GetDrawObjs() )
1160 : {
1161 0 : SwSortedObjs *pObjs = GetDrawObjs();
1162 0 : for ( size_t i = 0; GetDrawObjs() && i < pObjs->size(); ++i )
1163 : {
1164 0 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1165 0 : if ( pAnchoredObj->ISA(SwFlyFrm) )
1166 : {
1167 0 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
1168 0 : if( !pFly->IsFlyInCntFrm() )
1169 : {
1170 : const SvxBrushItem &rBack =
1171 0 : pFly->GetAttrSet()->GetBackground();
1172 : // OD 20.08.2002 #99657# #GetTransChg#
1173 : // following condition determines, if the fly frame
1174 : // "inherites" the background color of text frame.
1175 : // This is the case, if fly frame background
1176 : // color is "no fill"/"auto fill" and if the fly frame
1177 : // has no background graphic.
1178 : // Thus, check complete fly frame background
1179 : // color and *not* only its transparency value
1180 0 : if ( (rBack.GetColor() == COL_TRANSPARENT) &&
1181 0 : rBack.GetGraphicPos() == GPOS_NONE )
1182 : {
1183 0 : pFly->SetCompletePaint();
1184 0 : pFly->InvalidatePage();
1185 : }
1186 : }
1187 : }
1188 : }
1189 : }
1190 :
1191 8384 : if ( SfxItemState::SET ==
1192 8384 : rNewSet.GetItemState( RES_TXTATR_CHARFMT, false ) )
1193 : {
1194 0 : lcl_SetWrong( *this, 0, COMPLETE_STRING, false );
1195 0 : lcl_SetScriptInval( *this, 0 );
1196 : }
1197 8384 : else if ( SfxItemState::SET ==
1198 16538 : rNewSet.GetItemState( RES_CHRATR_LANGUAGE, false ) ||
1199 : SfxItemState::SET ==
1200 16478 : rNewSet.GetItemState( RES_CHRATR_CJK_LANGUAGE, false ) ||
1201 : SfxItemState::SET ==
1202 8094 : rNewSet.GetItemState( RES_CHRATR_CTL_LANGUAGE, false ) )
1203 336 : lcl_SetWrong( *this, 0, COMPLETE_STRING, false );
1204 8048 : else if ( SfxItemState::SET ==
1205 13358 : rNewSet.GetItemState( RES_CHRATR_FONT, false ) ||
1206 : SfxItemState::SET ==
1207 13128 : rNewSet.GetItemState( RES_CHRATR_CJK_FONT, false ) ||
1208 : SfxItemState::SET ==
1209 5080 : rNewSet.GetItemState( RES_CHRATR_CTL_FONT, false ) )
1210 3198 : lcl_SetScriptInval( *this, 0 );
1211 4850 : else if ( SfxItemState::SET ==
1212 4850 : rNewSet.GetItemState( RES_FRAMEDIR, false ) )
1213 : {
1214 356 : SetDerivedR2L( false );
1215 356 : CheckDirChange();
1216 : // OD 09.12.2002 #105576# - Force complete paint due to existing
1217 : // indents.
1218 356 : SetCompletePaint();
1219 : }
1220 :
1221 8384 : if( nCount )
1222 : {
1223 8384 : if( getRootFrm()->GetCurrShell() )
1224 : {
1225 8384 : Prepare( PREP_CLEAR );
1226 8384 : _InvalidatePrt();
1227 : }
1228 :
1229 8384 : if( nClear )
1230 : {
1231 134 : SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
1232 268 : SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
1233 :
1234 134 : if( 0x01 & nClear )
1235 : {
1236 0 : aOldSet.ClearItem( RES_TXTATR_FTN );
1237 0 : aNewSet.ClearItem( RES_TXTATR_FTN );
1238 : }
1239 134 : if( 0x02 & nClear )
1240 : {
1241 0 : aOldSet.ClearItem( RES_TXTATR_FIELD );
1242 0 : aNewSet.ClearItem( RES_TXTATR_FIELD );
1243 : }
1244 134 : if ( 0x04 & nClear )
1245 : {
1246 134 : if ( bLineSpace )
1247 : {
1248 134 : aOldSet.ClearItem( RES_PARATR_LINESPACING );
1249 134 : aNewSet.ClearItem( RES_PARATR_LINESPACING );
1250 : }
1251 134 : if ( bRegister )
1252 : {
1253 0 : aOldSet.ClearItem( RES_PARATR_REGISTER );
1254 0 : aNewSet.ClearItem( RES_PARATR_REGISTER );
1255 : }
1256 : }
1257 134 : if ( 0x08 & nClear )
1258 : {
1259 0 : aOldSet.ClearItem( RES_PARATR_SPLIT );
1260 0 : aNewSet.ClearItem( RES_PARATR_SPLIT );
1261 : }
1262 268 : SwCntntFrm::Modify( &aOldSet, &aNewSet );
1263 : }
1264 : else
1265 8250 : SwCntntFrm::Modify( pOld, pNew );
1266 : }
1267 :
1268 8384 : if (isA11yRelevantAttribute(nWhich))
1269 : {
1270 : // #i88069#
1271 8384 : SwViewShell* pViewSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
1272 8384 : if ( pViewSh )
1273 : {
1274 8384 : pViewSh->InvalidateAccessibleParaAttrs( *this );
1275 : }
1276 : }
1277 : }
1278 8384 : break;
1279 :
1280 : // 6870: process SwDocPosUpdate
1281 : case RES_DOCPOS_UPDATE:
1282 : {
1283 1238 : if( pOld && pNew )
1284 : {
1285 1238 : const SwDocPosUpdate *pDocPos = (const SwDocPosUpdate*)pOld;
1286 1238 : if( pDocPos->nDocPos <= maFrm.Top() )
1287 : {
1288 1162 : const SwFmtFld *pFld = (const SwFmtFld *)pNew;
1289 : InvalidateRange(
1290 1162 : SwCharRange( pFld->GetTxtFld()->GetStart(), 1 ) );
1291 : }
1292 : }
1293 1238 : break;
1294 : }
1295 : case RES_PARATR_SPLIT:
1296 0 : if ( GetPrev() )
1297 0 : CheckKeep();
1298 0 : Prepare( PREP_CLEAR );
1299 0 : bSetFldsDirty = true;
1300 0 : break;
1301 : case RES_FRAMEDIR :
1302 0 : SetDerivedR2L( false );
1303 0 : CheckDirChange();
1304 0 : break;
1305 : default:
1306 : {
1307 26 : Prepare( PREP_CLEAR );
1308 26 : _InvalidatePrt();
1309 26 : if ( !nWhich )
1310 : {
1311 : // is called by e. g. HiddenPara with 0
1312 : SwFrm *pNxt;
1313 0 : if ( 0 != (pNxt = FindNext()) )
1314 0 : pNxt->InvalidatePrt();
1315 : }
1316 : }
1317 : } // switch
1318 :
1319 38060 : if( bSetFldsDirty )
1320 22464 : GetNode()->getIDocumentFieldsAccess()->SetFieldsDirty( true, GetNode(), 1 );
1321 :
1322 38060 : if ( bRecalcFtnFlag )
1323 2428 : CalcFtnFlag();
1324 : }
1325 :
1326 430 : bool SwTxtFrm::GetInfo( SfxPoolItem &rHnt ) const
1327 : {
1328 430 : if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && ! IsFollow() )
1329 : {
1330 430 : SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt;
1331 430 : const SwPageFrm *pPage = FindPageFrm();
1332 430 : if ( pPage )
1333 : {
1334 430 : if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
1335 : {
1336 : // this should be the one
1337 : // (could only differ temporarily; is that disturbing?)
1338 166 : rInfo.SetInfo( pPage, this );
1339 166 : return false;
1340 : }
1341 576 : if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
1342 156 : (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
1343 : {
1344 : // this could be the one
1345 156 : rInfo.SetInfo( pPage, this );
1346 : }
1347 : }
1348 : }
1349 264 : return true;
1350 : }
1351 :
1352 338 : void SwTxtFrm::PrepWidows( const sal_uInt16 nNeed, bool bNotify )
1353 : {
1354 : OSL_ENSURE(GetFollow() && nNeed, "+SwTxtFrm::Prepare: lost all friends");
1355 :
1356 338 : SwParaPortion *pPara = GetPara();
1357 338 : if ( !pPara )
1358 338 : return;
1359 338 : pPara->SetPrepWidows();
1360 :
1361 338 : sal_uInt16 nHave = nNeed;
1362 :
1363 : // Wir geben ein paar Zeilen ab und schrumpfen im CalcPreps()
1364 338 : SWAP_IF_NOT_SWAPPED( this )
1365 :
1366 338 : SwTxtSizeInfo aInf( this );
1367 676 : SwTxtMargin aLine( this, &aInf );
1368 338 : aLine.Bottom();
1369 338 : sal_Int32 nTmpLen = aLine.GetCurr()->GetLen();
1370 962 : while( nHave && aLine.PrevLine() )
1371 : {
1372 286 : if( nTmpLen )
1373 286 : --nHave;
1374 286 : nTmpLen = aLine.GetCurr()->GetLen();
1375 : }
1376 : // In dieser Ecke tummelten sich einige Bugs: 7513, 7606.
1377 : // Wenn feststeht, dass Zeilen abgegeben werden koennen,
1378 : // muss der Master darueber hinaus die Widow-Regel ueberpruefen.
1379 338 : if( !nHave )
1380 : {
1381 286 : bool bSplit = true;
1382 286 : if( !IsFollow() ) // only a master decides about orphans
1383 : {
1384 274 : const WidowsAndOrphans aWidOrp( this );
1385 314 : bSplit = ( aLine.GetLineNr() >= aWidOrp.GetOrphansLines() &&
1386 314 : aLine.GetLineNr() >= aLine.GetDropLines() );
1387 : }
1388 :
1389 286 : if( bSplit )
1390 : {
1391 52 : GetFollow()->SetOfst( aLine.GetEnd() );
1392 52 : aLine.TruncLines( true );
1393 52 : if( pPara->IsFollowField() )
1394 0 : GetFollow()->SetFieldFollow( true );
1395 : }
1396 : }
1397 338 : if ( bNotify )
1398 : {
1399 338 : _InvalidateSize();
1400 338 : InvalidatePage();
1401 : }
1402 :
1403 676 : UNDO_SWAP( this )
1404 : }
1405 :
1406 14 : static bool lcl_ErgoVadis( SwTxtFrm* pFrm, sal_Int32 &rPos, const PrepareHint ePrep )
1407 : {
1408 14 : const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo();
1409 14 : if( ePrep == PREP_ERGOSUM )
1410 : {
1411 2 : if( rFtnInfo.aErgoSum.isEmpty() )
1412 2 : return false;
1413 0 : rPos = pFrm->GetOfst();
1414 : }
1415 : else
1416 : {
1417 12 : if( rFtnInfo.aQuoVadis.isEmpty() )
1418 12 : return false;
1419 0 : if( pFrm->HasFollow() )
1420 0 : rPos = pFrm->GetFollow()->GetOfst();
1421 : else
1422 0 : rPos = pFrm->GetTxt().getLength();
1423 0 : if( rPos )
1424 0 : --rPos; // our last character
1425 : }
1426 0 : return true;
1427 : }
1428 :
1429 352401 : void SwTxtFrm::Prepare( const PrepareHint ePrep, const void* pVoid,
1430 : bool bNotify )
1431 : {
1432 352401 : SwFrmSwapper aSwapper( this, false );
1433 :
1434 : #if OSL_DEBUG_LEVEL > 1
1435 : const SwTwips nDbgY = Frm().Top();
1436 : (void)nDbgY;
1437 : #endif
1438 :
1439 352401 : if ( IsEmpty() )
1440 : {
1441 29188 : switch ( ePrep )
1442 : {
1443 : case PREP_BOSS_CHGD:
1444 3894 : SetInvalidVert( true ); // Test
1445 : case PREP_WIDOWS_ORPHANS:
1446 : case PREP_WIDOWS:
1447 4082 : case PREP_FTN_GONE : return;
1448 :
1449 : case PREP_POS_CHGD :
1450 : {
1451 : // Auch in (spaltigen) Bereichen ist ein InvalidateSize notwendig,
1452 : // damit formatiert wird und ggf. das bUndersized gesetzt wird.
1453 8000 : if( IsInFly() || IsInSct() )
1454 : {
1455 584 : SwTwips nTmpBottom = GetUpper()->Frm().Top() +
1456 584 : GetUpper()->Prt().Bottom();
1457 584 : if( nTmpBottom < Frm().Bottom() )
1458 748 : break;
1459 : }
1460 : // are there any free-flying frames on this page?
1461 7782 : SwTxtFly aTxtFly( this );
1462 7782 : if( aTxtFly.IsOn() )
1463 : {
1464 : // does any free-flying frame overlap?
1465 740 : if ( aTxtFly.Relax() || IsUndersized() )
1466 304 : break;
1467 : }
1468 7478 : if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue())
1469 0 : break;
1470 :
1471 7478 : SwTextGridItem const*const pGrid(GetGridItem(FindPageFrm()));
1472 7478 : if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
1473 0 : break;
1474 :
1475 : // #i28701# - consider anchored objects
1476 7478 : if ( GetDrawObjs() )
1477 8 : break;
1478 :
1479 7470 : return;
1480 : }
1481 : default:
1482 17106 : break;
1483 : }
1484 : }
1485 :
1486 340849 : if( !HasPara() && PREP_MUST_FIT != ePrep )
1487 : {
1488 256457 : SetInvalidVert( true ); // Test
1489 : OSL_ENSURE( !IsLocked(), "SwTxtFrm::Prepare: three of a perfect pair" );
1490 256457 : if ( bNotify )
1491 187586 : InvalidateSize();
1492 : else
1493 68871 : _InvalidateSize();
1494 256457 : return;
1495 : }
1496 :
1497 : // get object from cache while locking
1498 84392 : SwTxtLineAccess aAccess( this );
1499 84392 : SwParaPortion *pPara = aAccess.GetPara();
1500 :
1501 84392 : switch( ePrep )
1502 : {
1503 0 : case PREP_MOVEFTN : Frm().Height(0);
1504 0 : Prt().Height(0);
1505 0 : _InvalidatePrt();
1506 0 : _InvalidateSize();
1507 : /* no break here */
1508 17958 : case PREP_ADJUST_FRM : pPara->SetPrepAdjust();
1509 35912 : if( IsFtnNumFrm() != pPara->IsFtnNum() ||
1510 17954 : IsUndersized() )
1511 : {
1512 4322 : InvalidateRange( SwCharRange( 0, 1 ), 1);
1513 4322 : if( GetOfst() && !IsFollow() )
1514 0 : _SetOfst( 0 );
1515 : }
1516 17958 : break;
1517 524 : case PREP_MUST_FIT : pPara->SetPrepMustFit();
1518 : /* no break here */
1519 2411 : case PREP_WIDOWS_ORPHANS : pPara->SetPrepAdjust();
1520 2411 : break;
1521 :
1522 : case PREP_WIDOWS :
1523 : // MustFit is stronger than anything else
1524 338 : if( pPara->IsPrepMustFit() )
1525 0 : return;
1526 : // see comment in WidowsAndOrphans::FindOrphans and CalcPreps()
1527 338 : PrepWidows( *(const sal_uInt16 *)pVoid, bNotify );
1528 338 : break;
1529 :
1530 : case PREP_FTN :
1531 : {
1532 262 : SwTxtFtn *pFtn = (SwTxtFtn *)pVoid;
1533 262 : if( IsInFtn() )
1534 : {
1535 : // am I the first TxtFrm of a footnote?
1536 56 : if( !GetPrev() )
1537 : // Wir sind also ein TxtFrm der Fussnote, die
1538 : // die Fussnotenzahl zur Anzeige bringen muss.
1539 : // Oder den ErgoSum-Text...
1540 52 : InvalidateRange( SwCharRange( 0, 1 ), 1);
1541 :
1542 56 : if( !GetNext() )
1543 : {
1544 : // Wir sind der letzte Ftn, jetzt muessten die
1545 : // QuoVadis-Texte geupdated werden.
1546 54 : const SwFtnInfo &rFtnInfo = GetNode()->GetDoc()->GetFtnInfo();
1547 54 : if( !pPara->UpdateQuoVadis( rFtnInfo.aQuoVadis ) )
1548 : {
1549 54 : sal_Int32 nPos = pPara->GetParLen();
1550 54 : if( nPos )
1551 12 : --nPos;
1552 54 : InvalidateRange( SwCharRange( nPos, 1 ), 1);
1553 : }
1554 : }
1555 : }
1556 : else
1557 : {
1558 : // we are the TxtFrm _with_ the footnote
1559 206 : const sal_Int32 nPos = pFtn->GetStart();
1560 206 : InvalidateRange( SwCharRange( nPos, 1 ), 1);
1561 : }
1562 262 : break;
1563 : }
1564 : case PREP_BOSS_CHGD :
1565 : {
1566 : // Test
1567 : {
1568 8338 : SetInvalidVert( false );
1569 8338 : bool bOld = IsVertical();
1570 8338 : SetInvalidVert( true );
1571 8338 : if( bOld != IsVertical() )
1572 0 : InvalidateRange( SwCharRange( GetOfst(), COMPLETE_STRING ) );
1573 : }
1574 :
1575 8338 : if( HasFollow() )
1576 : {
1577 46 : sal_Int32 nNxtOfst = GetFollow()->GetOfst();
1578 46 : if( nNxtOfst )
1579 46 : --nNxtOfst;
1580 46 : InvalidateRange( SwCharRange( nNxtOfst, 1 ), 1);
1581 : }
1582 8338 : if( IsInFtn() )
1583 : {
1584 : sal_Int32 nPos;
1585 0 : if( lcl_ErgoVadis( this, nPos, PREP_QUOVADIS ) )
1586 0 : InvalidateRange( SwCharRange( nPos, 1 ), 0 );
1587 0 : if( lcl_ErgoVadis( this, nPos, PREP_ERGOSUM ) )
1588 0 : InvalidateRange( SwCharRange( nPos, 1 ), 0 );
1589 : }
1590 : // 4739: if we have a page number field, we must invalidate those spots
1591 8338 : SwpHints *pHints = GetTxtNode()->GetpSwpHints();
1592 8338 : if( pHints )
1593 : {
1594 6082 : const size_t nSize = pHints->Count();
1595 6082 : const sal_Int32 nEnd = GetFollow() ?
1596 6082 : GetFollow()->GetOfst() : COMPLETE_STRING;
1597 22810 : for ( size_t i = 0; i < nSize; ++i )
1598 : {
1599 16756 : const SwTxtAttr *pHt = (*pHints)[i];
1600 16756 : const sal_Int32 nStart = pHt->GetStart();
1601 16756 : if( nStart >= GetOfst() )
1602 : {
1603 16756 : if( nStart >= nEnd )
1604 28 : break;
1605 :
1606 : // 4029: wenn wir zurueckfliessen und eine Ftn besitzen, so
1607 : // fliesst die Ftn in jedem Fall auch mit. Damit sie nicht im
1608 : // Weg steht, schicken wir uns ein ADJUST_FRM.
1609 : // pVoid != 0 bedeutet MoveBwd()
1610 16728 : const sal_uInt16 nWhich = pHt->Which();
1611 33460 : if( RES_TXTATR_FIELD == nWhich ||
1612 16712 : (HasFtn() && pVoid && RES_TXTATR_FTN == nWhich))
1613 26 : InvalidateRange( SwCharRange( nStart, 1 ), 1 );
1614 : }
1615 : }
1616 : }
1617 : // A new boss, a new chance for growing
1618 8338 : if( IsUndersized() )
1619 : {
1620 348 : _InvalidateSize();
1621 348 : InvalidateRange( SwCharRange( GetOfst(), 1 ), 1);
1622 : }
1623 8338 : break;
1624 : }
1625 :
1626 : case PREP_POS_CHGD :
1627 : {
1628 25552 : if ( GetValidPrtAreaFlag() )
1629 : {
1630 24832 : SwTextGridItem const*const pGrid(GetGridItem(FindPageFrm()));
1631 24832 : if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
1632 12 : InvalidatePrt();
1633 : }
1634 :
1635 : // if we don't overlap with anybody:
1636 : // did any free-flying frame overlapped _before_ the position change?
1637 25552 : bool bFormat = pPara->HasFly();
1638 25552 : if( !bFormat )
1639 : {
1640 25452 : if( IsInFly() )
1641 : {
1642 956 : SwTwips nTmpBottom = GetUpper()->Frm().Top() +
1643 956 : GetUpper()->Prt().Bottom();
1644 956 : if( nTmpBottom < Frm().Bottom() )
1645 0 : bFormat = true;
1646 : }
1647 25452 : if( !bFormat )
1648 : {
1649 25452 : if ( GetDrawObjs() )
1650 : {
1651 438 : const size_t nCnt = GetDrawObjs()->size();
1652 1100 : for ( size_t i = 0; i < nCnt; ++i )
1653 : {
1654 698 : SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
1655 : // #i28701# - consider all
1656 : // to-character anchored objects
1657 698 : if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
1658 : == FLY_AT_CHAR )
1659 : {
1660 36 : bFormat = true;
1661 36 : break;
1662 : }
1663 : }
1664 : }
1665 25452 : if( !bFormat )
1666 : {
1667 : // are there any free-flying frames on this page?
1668 25416 : SwTxtFly aTxtFly( this );
1669 25416 : if( aTxtFly.IsOn() )
1670 : {
1671 : // does any free-flying frame overlap?
1672 6126 : bFormat = aTxtFly.Relax() || IsUndersized();
1673 25416 : }
1674 : }
1675 : }
1676 : }
1677 :
1678 25552 : if( bFormat )
1679 : {
1680 3942 : if( !IsLocked() )
1681 : {
1682 3942 : if( pPara->GetRepaint().HasArea() )
1683 3942 : SetCompletePaint();
1684 3942 : Init();
1685 3942 : pPara = 0;
1686 3942 : _InvalidateSize();
1687 : }
1688 : }
1689 : else
1690 : {
1691 21610 : if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
1692 0 : Prepare( PREP_REGISTER, 0, bNotify );
1693 : // Durch Positionsverschiebungen mit Ftns muessen die
1694 : // Frames neu adjustiert werden.
1695 21610 : else if( HasFtn() )
1696 : {
1697 8 : Prepare( PREP_ADJUST_FRM, 0, bNotify );
1698 8 : _InvalidateSize();
1699 : }
1700 : else
1701 21602 : return; // damit kein SetPrep() erfolgt.
1702 : }
1703 3950 : break;
1704 : }
1705 : case PREP_REGISTER:
1706 0 : if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
1707 : {
1708 0 : pPara->SetPrepAdjust();
1709 0 : CalcLineSpace();
1710 : // possible that pPara was deleted above; retrieve it again
1711 0 : pPara = aAccess.GetPara();
1712 0 : InvalidateSize();
1713 0 : _InvalidatePrt();
1714 : SwFrm* pNxt;
1715 0 : if ( 0 != ( pNxt = GetIndNext() ) )
1716 : {
1717 0 : pNxt->_InvalidatePrt();
1718 0 : if ( pNxt->IsLayoutFrm() )
1719 0 : pNxt->InvalidatePage();
1720 : }
1721 0 : SetCompletePaint();
1722 : }
1723 0 : break;
1724 : case PREP_FTN_GONE :
1725 : {
1726 : // Wenn ein Follow uns ruft, weil eine Fussnote geloescht wird, muss unsere
1727 : // letzte Zeile formatiert werden, damit ggf. die erste Zeile des Follows
1728 : // hochrutschen kann, die extra auf die naechste Seite gerutscht war, um mit
1729 : // der Fussnote zusammen zu sein, insbesondere bei spaltigen Bereichen.
1730 : OSL_ENSURE( GetFollow(), "PREP_FTN_GONE darf nur vom Follow gerufen werden" );
1731 0 : sal_Int32 nPos = GetFollow()->GetOfst();
1732 0 : if( IsFollow() && GetOfst() == nPos ) // falls wir gar keine Textmasse besitzen,
1733 0 : FindMaster()->Prepare( PREP_FTN_GONE ); // rufen wir das Prepare unseres Masters
1734 0 : if( nPos )
1735 0 : --nPos; // das Zeichen vor unserem Follow
1736 0 : InvalidateRange( SwCharRange( nPos, 1 ), 0 );
1737 0 : return;
1738 : }
1739 : case PREP_ERGOSUM:
1740 : case PREP_QUOVADIS:
1741 : {
1742 : sal_Int32 nPos;
1743 14 : if( lcl_ErgoVadis( this, nPos, ePrep ) )
1744 0 : InvalidateRange( SwCharRange( nPos, 1 ), 0 );
1745 : }
1746 14 : break;
1747 : case PREP_FLY_ATTR_CHG:
1748 : {
1749 322 : if( pVoid )
1750 : {
1751 313 : sal_Int32 nWhere = CalcFlyPos( (SwFrmFmt*)pVoid );
1752 : OSL_ENSURE( COMPLETE_STRING != nWhere, "Prepare: Why me?" );
1753 313 : InvalidateRange( SwCharRange( nWhere, 1 ) );
1754 313 : return;
1755 : }
1756 : // else: continue with default case block
1757 : }
1758 : case PREP_CLEAR:
1759 : default:
1760 : {
1761 29206 : if( IsLocked() )
1762 : {
1763 6006 : if( PREP_FLY_ARRIVE == ePrep || PREP_FLY_LEAVE == ePrep )
1764 : {
1765 4668 : sal_Int32 nLen = ( GetFollow() ? GetFollow()->GetOfst() :
1766 4668 : COMPLETE_STRING ) - GetOfst();
1767 4650 : InvalidateRange( SwCharRange( GetOfst(), nLen ), 0 );
1768 : }
1769 : }
1770 : else
1771 : {
1772 23200 : if( pPara->GetRepaint().HasArea() )
1773 21728 : SetCompletePaint();
1774 23200 : Init();
1775 23200 : pPara = 0;
1776 23200 : if( GetOfst() && !IsFollow() )
1777 12 : _SetOfst( 0 );
1778 23200 : if ( bNotify )
1779 23140 : InvalidateSize();
1780 : else
1781 60 : _InvalidateSize();
1782 : }
1783 29206 : return; // no SetPrep() happened
1784 : }
1785 : }
1786 33271 : if( pPara )
1787 29329 : pPara->SetPrep();
1788 : }
1789 :
1790 : // Small Helper class:
1791 : // Prepares a test format.
1792 : // The frame is changed in size and position, its SwParaPortion is moved aside
1793 : // and a new one is created.
1794 : // To achieve this, run formatting with bTestFormat flag set.
1795 : // In the destructor the TxtFrm is reset to its original state.
1796 : class SwTestFormat
1797 : {
1798 : SwTxtFrm *pFrm;
1799 : SwParaPortion *pOldPara;
1800 : SwRect aOldFrm, aOldPrt;
1801 : public:
1802 : SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPrv, SwTwips nMaxHeight );
1803 : ~SwTestFormat();
1804 : };
1805 :
1806 178 : SwTestFormat::SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPre, SwTwips nMaxHeight )
1807 178 : : pFrm( pTxtFrm )
1808 : {
1809 178 : aOldFrm = pFrm->Frm();
1810 178 : aOldPrt = pFrm->Prt();
1811 :
1812 178 : SWRECTFN( pFrm )
1813 178 : SwTwips nLower = (pFrm->*fnRect->fnGetBottomMargin)();
1814 :
1815 178 : pFrm->Frm() = pFrm->GetUpper()->Prt();
1816 178 : pFrm->Frm() += pFrm->GetUpper()->Frm().Pos();
1817 :
1818 178 : (pFrm->Frm().*fnRect->fnSetHeight)( nMaxHeight );
1819 178 : if( pFrm->GetPrev() )
1820 178 : (pFrm->Frm().*fnRect->fnSetPosY)(
1821 178 : (pFrm->GetPrev()->Frm().*fnRect->fnGetBottom)() -
1822 356 : ( bVert ? nMaxHeight + 1 : 0 ) );
1823 :
1824 178 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
1825 178 : const SwBorderAttrs &rAttrs = *aAccess.Get();
1826 178 : (pFrm->Prt().*fnRect->fnSetPosX)( rAttrs.CalcLeft( pFrm ) );
1827 :
1828 178 : if( pPre )
1829 : {
1830 178 : SwTwips nUpper = pFrm->CalcUpperSpace( &rAttrs, pPre );
1831 178 : (pFrm->Prt().*fnRect->fnSetPosY)( nUpper );
1832 : }
1833 178 : (pFrm->Prt().*fnRect->fnSetHeight)(
1834 356 : std::max( 0L , (pFrm->Frm().*fnRect->fnGetHeight)() -
1835 534 : (pFrm->Prt().*fnRect->fnGetTop)() - nLower ) );
1836 178 : (pFrm->Prt().*fnRect->fnSetWidth)(
1837 178 : (pFrm->Frm().*fnRect->fnGetWidth)() -
1838 356 : ( rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm ) ) );
1839 178 : pOldPara = pFrm->HasPara() ? pFrm->GetPara() : NULL;
1840 178 : pFrm->SetPara( new SwParaPortion(), false );
1841 :
1842 : OSL_ENSURE( ! pFrm->IsSwapped(), "A frame is swapped before _Format" );
1843 :
1844 178 : if ( pFrm->IsVertical() )
1845 0 : pFrm->SwapWidthAndHeight();
1846 :
1847 356 : SwTxtFormatInfo aInf( pFrm, false, true, true );
1848 356 : SwTxtFormatter aLine( pFrm, &aInf );
1849 :
1850 178 : pFrm->_Format( aLine, aInf );
1851 :
1852 178 : if ( pFrm->IsVertical() )
1853 0 : pFrm->SwapWidthAndHeight();
1854 :
1855 178 : OSL_ENSURE( ! pFrm->IsSwapped(), "A frame is swapped after _Format" );
1856 178 : }
1857 :
1858 178 : SwTestFormat::~SwTestFormat()
1859 : {
1860 178 : pFrm->Frm() = aOldFrm;
1861 178 : pFrm->Prt() = aOldPrt;
1862 178 : pFrm->SetPara( pOldPara );
1863 178 : }
1864 :
1865 178 : bool SwTxtFrm::TestFormat( const SwFrm* pPrv, SwTwips &rMaxHeight, bool &bSplit )
1866 : {
1867 : PROTOCOL_ENTER( this, PROT_TESTFORMAT, 0, 0 )
1868 :
1869 178 : if( IsLocked() && GetUpper()->Prt().Width() <= 0 )
1870 0 : return false;
1871 :
1872 178 : SwTestFormat aSave( this, pPrv, rMaxHeight );
1873 :
1874 178 : return SwTxtFrm::WouldFit( rMaxHeight, bSplit, true );
1875 : }
1876 :
1877 : /* SwTxtFrm::WouldFit()
1878 : * true: wenn ich aufspalten kann.
1879 : * Es soll und braucht nicht neu formatiert werden.
1880 : * Wir gehen davon aus, dass bereits formatiert wurde und dass
1881 : * die Formatierungsdaten noch aktuell sind.
1882 : * Wir gehen davon aus, dass die Framebreiten des evtl. Masters und
1883 : * Follows gleich sind. Deswegen wird kein FindBreak() mit FindOrphans()
1884 : * gerufen.
1885 : * Die benoetigte Hoehe wird von nMaxHeight abgezogen!
1886 : */
1887 :
1888 5730 : bool SwTxtFrm::WouldFit( SwTwips &rMaxHeight, bool &bSplit, bool bTst )
1889 : {
1890 : OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
1891 : "SwTxtFrm::WouldFit with swapped frame" );
1892 5730 : SWRECTFN( this );
1893 :
1894 5730 : if( IsLocked() )
1895 0 : return false;
1896 :
1897 : // it can happen that the IdleCollector removed the cached information
1898 5730 : if( !IsEmpty() )
1899 2302 : GetFormatted();
1900 :
1901 : // OD 2004-05-24 #i27801# - correction: 'short cut' for empty paragraph
1902 : // can *not* be applied, if test format is in progress. The test format doesn't
1903 : // adjust the frame and the printing area - see method <SwTxtFrm::_Format(..)>,
1904 : // which is called in <SwTxtFrm::TestFormat(..)>
1905 5730 : if ( IsEmpty() && !bTst )
1906 : {
1907 3420 : bSplit = false;
1908 3420 : SwTwips nHeight = bVert ? Prt().SSize().Width() : Prt().SSize().Height();
1909 3420 : if( rMaxHeight < nHeight )
1910 20 : return false;
1911 : else
1912 : {
1913 3400 : rMaxHeight -= nHeight;
1914 3400 : return true;
1915 : }
1916 : }
1917 :
1918 : // In sehr unguenstigen Faellen kann GetPara immer noch 0 sein.
1919 : // Dann returnen wir true, um auf der neuen Seite noch einmal
1920 : // anformatiert zu werden.
1921 : OSL_ENSURE( HasPara() || IsHiddenNow(), "WouldFit: GetFormatted() and then !HasPara()" );
1922 2310 : if( !HasPara() || ( !(Frm().*fnRect->fnGetHeight)() && IsHiddenNow() ) )
1923 0 : return true;
1924 :
1925 : // Da das Orphan-Flag nur sehr fluechtig existiert, wird als zweite
1926 : // Bedingung ueberprueft, ob die Rahmengroesse durch CalcPreps
1927 : // auf riesengross gesetzt wird, um ein MoveFwd zu erzwingen.
1928 4620 : if( IsWidow() || ( bVert ?
1929 0 : ( 0 == Frm().Left() ) :
1930 2310 : ( LONG_MAX - 20000 < Frm().Bottom() ) ) )
1931 : {
1932 6 : SetWidow(false);
1933 6 : if ( GetFollow() )
1934 : {
1935 : // Wenn wir hier durch eine Widow-Anforderung unseres Follows gelandet
1936 : // sind, wird ueberprueft, ob es ueberhaupt einen Follow mit einer
1937 : // echten Hoehe gibt, andernfalls (z.B. in neu angelegten SctFrms)
1938 : // ignorieren wir das IsWidow() und pruefen doch noch, ob wir
1939 : // genung Platz finden.
1940 18 : if( ( ( ! bVert && LONG_MAX - 20000 >= Frm().Bottom() ) ||
1941 6 : ( bVert && 0 < Frm().Left() ) ) &&
1942 0 : ( GetFollow()->IsVertical() ?
1943 0 : !GetFollow()->Frm().Width() :
1944 0 : !GetFollow()->Frm().Height() ) )
1945 : {
1946 0 : SwTxtFrm* pFoll = GetFollow()->GetFollow();
1947 0 : while( pFoll &&
1948 0 : ( pFoll->IsVertical() ?
1949 0 : !pFoll->Frm().Width() :
1950 0 : !pFoll->Frm().Height() ) )
1951 0 : pFoll = pFoll->GetFollow();
1952 0 : if( pFoll )
1953 0 : return false;
1954 : }
1955 : else
1956 6 : return false;
1957 : }
1958 : }
1959 :
1960 2304 : SWAP_IF_NOT_SWAPPED( this );
1961 :
1962 2304 : SwTxtSizeInfo aInf( this );
1963 4608 : SwTxtMargin aLine( this, &aInf );
1964 :
1965 2304 : WidowsAndOrphans aFrmBreak( this, rMaxHeight, bSplit );
1966 :
1967 2304 : bool bRet = true;
1968 :
1969 2304 : aLine.Bottom();
1970 : // is breaking necessary?
1971 2304 : bSplit = !aFrmBreak.IsInside( aLine );
1972 2304 : if ( bSplit )
1973 232 : bRet = !aFrmBreak.IsKeepAlways() && aFrmBreak.WouldFit( aLine, rMaxHeight, bTst );
1974 : else
1975 : {
1976 : // we need the total height including the current line
1977 2072 : aLine.Top();
1978 2450 : do
1979 : {
1980 2450 : rMaxHeight -= aLine.GetLineHeight();
1981 2450 : } while ( aLine.Next() );
1982 : }
1983 :
1984 2304 : UNDO_SWAP( this )
1985 :
1986 4608 : return bRet;
1987 : }
1988 :
1989 6702 : sal_uInt16 SwTxtFrm::GetParHeight() const
1990 : {
1991 : OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
1992 : "SwTxtFrm::GetParHeight with swapped frame" );
1993 :
1994 6702 : if( !HasPara() )
1995 : { // Fuer nichtleere Absaetze ist dies ein Sonderfall, da koennen wir
1996 : // bei UnderSized ruhig nur 1 Twip mehr anfordern.
1997 1886 : sal_uInt16 nRet = (sal_uInt16)Prt().SSize().Height();
1998 1886 : if( IsUndersized() )
1999 : {
2000 1886 : if( IsEmpty() || GetTxt().isEmpty() )
2001 1680 : nRet = (sal_uInt16)EmptyHeight();
2002 : else
2003 206 : ++nRet;
2004 : }
2005 1886 : return nRet;
2006 : }
2007 :
2008 : // FME, OD 08.01.2004 #i11859# - refactoring and improve code
2009 4816 : const SwLineLayout* pLineLayout = GetPara();
2010 4816 : sal_uInt16 nHeight = pLineLayout ? pLineLayout->GetRealHeight() : 0;
2011 4816 : if( GetOfst() && !IsFollow() ) // Ist dieser Absatz gescrollt? Dann ist unsere
2012 0 : nHeight *= 2; // bisherige Hoehe mind. eine Zeilenhoehe zu gering
2013 : // OD 2004-03-04 #115793#
2014 11666 : while ( pLineLayout && pLineLayout->GetNext() )
2015 : {
2016 2034 : pLineLayout = pLineLayout->GetNext();
2017 2034 : nHeight = nHeight + pLineLayout->GetRealHeight();
2018 : }
2019 :
2020 4816 : return nHeight;
2021 : }
2022 :
2023 : // returns this _always_ in the formated state!
2024 157232 : SwTxtFrm* SwTxtFrm::GetFormatted( bool bForceQuickFormat )
2025 : {
2026 157232 : SWAP_IF_SWAPPED( this )
2027 :
2028 : // Kann gut sein, dass mir der IdleCollector mir die gecachten
2029 : // Informationen entzogen hat. Calc() ruft unser Format.
2030 : // Nicht bei leeren Absaetzen!
2031 157232 : if( !HasPara() && !(IsValid() && IsEmpty()) )
2032 : {
2033 : // Calc() must be called, because frame position can be wrong
2034 306 : const bool bFormat = GetValidSizeFlag();
2035 306 : Calc();
2036 : // Es kann durchaus sein, dass Calc() das Format()
2037 : // nicht anstiess (weil wir einst vom Idle-Zerstoerer
2038 : // aufgefordert wurden unsere Formatinformationen wegzuschmeissen).
2039 : // 6995: Optimierung mit FormatQuick()
2040 306 : if( bFormat && !FormatQuick( bForceQuickFormat ) )
2041 0 : Format();
2042 : }
2043 :
2044 157232 : UNDO_SWAP( this )
2045 :
2046 157232 : return this;
2047 : }
2048 :
2049 1084 : SwTwips SwTxtFrm::CalcFitToContent()
2050 : {
2051 : // #i31490#
2052 : // If we are currently locked, we better return with a
2053 : // fairly reasonable value:
2054 1084 : if ( IsLocked() )
2055 0 : return Prt().Width();
2056 :
2057 1084 : SwParaPortion* pOldPara = GetPara();
2058 1084 : SwParaPortion *pDummy = new SwParaPortion();
2059 1084 : SetPara( pDummy, false );
2060 1084 : const SwPageFrm* pPage = FindPageFrm();
2061 :
2062 1084 : const Point aOldFrmPos = Frm().Pos();
2063 1084 : const SwTwips nOldFrmWidth = Frm().Width();
2064 1084 : const SwTwips nOldPrtWidth = Prt().Width();
2065 1084 : const SwTwips nPageWidth = GetUpper()->IsVertical() ?
2066 0 : pPage->Prt().Height() :
2067 1084 : pPage->Prt().Width();
2068 :
2069 1084 : Frm().Width( nPageWidth );
2070 1084 : Prt().Width( nPageWidth );
2071 :
2072 : // #i25422# objects anchored as character in RTL
2073 1084 : if ( IsRightToLeft() )
2074 0 : Frm().Pos().X() += nOldFrmWidth - nPageWidth;
2075 :
2076 : // #i31490#
2077 1084 : SwTxtFrmLocker aLock( this );
2078 :
2079 2168 : SwTxtFormatInfo aInf( this, false, true, true );
2080 1084 : aInf.SetIgnoreFly( true );
2081 2168 : SwTxtFormatter aLine( this, &aInf );
2082 2168 : SwHookOut aHook( aInf );
2083 :
2084 : // #i54031# - assure mininum of MINLAY twips.
2085 : const SwTwips nMax = std::max( (SwTwips)MINLAY,
2086 1084 : aLine._CalcFitToContent() + 1 );
2087 :
2088 1084 : Frm().Width( nOldFrmWidth );
2089 1084 : Prt().Width( nOldPrtWidth );
2090 :
2091 : // #i25422# objects anchored as character in RTL
2092 1084 : if ( IsRightToLeft() )
2093 0 : Frm().Pos() = aOldFrmPos;
2094 :
2095 1084 : SetPara( pOldPara );
2096 :
2097 2168 : return nMax;
2098 : }
2099 :
2100 : /** simulate format for a list item paragraph, whose list level attributes
2101 : are in LABEL_ALIGNMENT mode, in order to determine additional first
2102 : line offset for the real text formatting due to the value of label
2103 : adjustment attribute of the list level.
2104 : */
2105 131507 : void SwTxtFrm::CalcAdditionalFirstLineOffset()
2106 : {
2107 131507 : if ( IsLocked() )
2108 131507 : return;
2109 :
2110 : // reset additional first line offset
2111 131507 : mnAdditionalFirstLineOffset = 0;
2112 :
2113 131507 : const SwTxtNode* pTxtNode( GetTxtNode() );
2114 136263 : if ( pTxtNode && pTxtNode->IsNumbered() && pTxtNode->IsCountedInList() &&
2115 4756 : pTxtNode->GetNumRule() )
2116 : {
2117 4756 : int nListLevel = pTxtNode->GetActualListLevel();
2118 :
2119 4756 : if (nListLevel < 0)
2120 0 : nListLevel = 0;
2121 :
2122 4756 : if (nListLevel >= MAXLEVEL)
2123 0 : nListLevel = MAXLEVEL - 1;
2124 :
2125 : const SwNumFmt& rNumFmt =
2126 4756 : pTxtNode->GetNumRule()->Get( static_cast<sal_uInt16>(nListLevel) );
2127 4756 : if ( rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2128 : {
2129 : // keep current paragraph portion and apply dummy paragraph portion
2130 4296 : SwParaPortion* pOldPara = GetPara();
2131 4296 : SwParaPortion *pDummy = new SwParaPortion();
2132 4296 : SetPara( pDummy, false );
2133 :
2134 : // lock paragraph
2135 4296 : SwTxtFrmLocker aLock( this );
2136 :
2137 : // simulate text formatting
2138 8592 : SwTxtFormatInfo aInf( this, false, true, true );
2139 4296 : aInf.SetIgnoreFly( true );
2140 8592 : SwTxtFormatter aLine( this, &aInf );
2141 8592 : SwHookOut aHook( aInf );
2142 4296 : aLine._CalcFitToContent();
2143 :
2144 : // determine additional first line offset
2145 4296 : const SwLinePortion* pFirstPortion = aLine.GetCurr()->GetFirstPortion();
2146 4296 : if ( pFirstPortion->InNumberGrp() && !pFirstPortion->IsFtnNumPortion() )
2147 : {
2148 4264 : SwTwips nNumberPortionWidth( pFirstPortion->Width() );
2149 :
2150 4264 : const SwLinePortion* pPortion = pFirstPortion->GetPortion();
2151 12828 : while ( pPortion &&
2152 4300 : pPortion->InNumberGrp() && !pPortion->IsFtnNumPortion())
2153 : {
2154 18 : nNumberPortionWidth += pPortion->Width();
2155 18 : pPortion = pPortion->GetPortion();
2156 : }
2157 :
2158 8528 : if ( ( IsRightToLeft() &&
2159 8530 : rNumFmt.GetNumAdjust() == SVX_ADJUST_LEFT ) ||
2160 8528 : ( !IsRightToLeft() &&
2161 4264 : rNumFmt.GetNumAdjust() == SVX_ADJUST_RIGHT ) )
2162 : {
2163 2 : mnAdditionalFirstLineOffset = -nNumberPortionWidth;
2164 : }
2165 4262 : else if ( rNumFmt.GetNumAdjust() == SVX_ADJUST_CENTER )
2166 : {
2167 0 : mnAdditionalFirstLineOffset = -(nNumberPortionWidth/2);
2168 : }
2169 : }
2170 :
2171 : // restore paragraph portion
2172 8592 : SetPara( pOldPara );
2173 : }
2174 : }
2175 : }
2176 :
2177 : /** determine height of last line for the calculation of the proportional line
2178 : spacing
2179 :
2180 : OD 08.01.2004 #i11859#
2181 : OD 2004-03-17 #i11860# - method <GetHeightOfLastLineForPropLineSpacing()>
2182 : replace by method <_CalcHeightOfLastLine()>. Height of last line will be
2183 : stored in new member <mnHeightOfLastLine> and can be accessed via method
2184 : <GetHeightOfLastLine()>
2185 : OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont>
2186 : in order to force the usage of the former algorithm to determine the
2187 : height of the last line, which uses the font.
2188 : */
2189 134807 : void SwTxtFrm::_CalcHeightOfLastLine( const bool _bUseFont )
2190 : {
2191 : // #i71281#
2192 : // invalidate printing area, if height of last line changes
2193 134807 : const SwTwips mnOldHeightOfLastLine( mnHeightOfLastLine );
2194 : // determine output device
2195 134807 : SwViewShell* pVsh = getRootFrm()->GetCurrShell();
2196 : OSL_ENSURE( pVsh, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no SwViewShell" );
2197 : // #i78921# - make code robust, according to provided patch
2198 : // There could be no <SwViewShell> instance in the case of loading a binary
2199 : // StarOffice file format containing an embedded Writer document.
2200 134807 : if ( !pVsh )
2201 : {
2202 0 : return;
2203 : }
2204 134807 : OutputDevice* pOut = pVsh->GetOut();
2205 134807 : const IDocumentSettingAccess* pIDSA = GetTxtNode()->getIDocumentSettingAccess();
2206 134891 : if ( !pVsh->GetViewOptions()->getBrowseMode() ||
2207 84 : pVsh->GetViewOptions()->IsPrtFormat() )
2208 : {
2209 134723 : pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
2210 : }
2211 : OSL_ENSURE( pOut, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no OutputDevice" );
2212 : // #i78921# - make code robust, according to provided patch
2213 134807 : if ( !pOut )
2214 : {
2215 0 : return;
2216 : }
2217 :
2218 : // determine height of last line
2219 :
2220 134807 : if ( _bUseFont || pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING ) )
2221 : {
2222 : // former determination of last line height for proprotional line
2223 : // spacing - take height of font set at the paragraph
2224 4496 : SwFont aFont( GetAttrSet(), pIDSA );
2225 :
2226 : // we must ensure that the font is restored correctly on the OutputDevice
2227 : // otherwise Last!=Owner could occur
2228 4496 : if ( pLastFont )
2229 : {
2230 4496 : SwFntObj *pOldFont = pLastFont;
2231 4496 : pLastFont = NULL;
2232 4496 : aFont.SetFntChg( true );
2233 4496 : aFont.ChgPhysFnt( pVsh, *pOut );
2234 4496 : mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut );
2235 4496 : pLastFont->Unlock();
2236 4496 : pLastFont = pOldFont;
2237 4496 : pLastFont->SetDevFont( pVsh, *pOut );
2238 : }
2239 : else
2240 : {
2241 0 : vcl::Font aOldFont = pOut->GetFont();
2242 0 : aFont.SetFntChg( true );
2243 0 : aFont.ChgPhysFnt( pVsh, *pOut );
2244 0 : mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut );
2245 0 : pLastFont->Unlock();
2246 0 : pLastFont = NULL;
2247 0 : pOut->SetFont( aOldFont );
2248 4496 : }
2249 : }
2250 : else
2251 : {
2252 : // new determination of last line height - take actually height of last line
2253 : // #i89000#
2254 : // assure same results, if paragraph is undersized
2255 130311 : if ( IsUndersized() )
2256 : {
2257 10072 : mnHeightOfLastLine = 0;
2258 : }
2259 : else
2260 : {
2261 120239 : bool bCalcHeightOfLastLine = true;
2262 120239 : if ( ( !HasPara() && IsEmpty( ) ) || GetTxt().isEmpty() )
2263 : {
2264 49027 : mnHeightOfLastLine = EmptyHeight();
2265 49027 : bCalcHeightOfLastLine = false;
2266 : }
2267 :
2268 120239 : if ( bCalcHeightOfLastLine )
2269 : {
2270 : OSL_ENSURE( HasPara(),
2271 : "<SwTxtFrm::_CalcHeightOfLastLine()> - missing paragraph portions." );
2272 71212 : const SwLineLayout* pLineLayout = GetPara();
2273 246174 : while ( pLineLayout && pLineLayout->GetNext() )
2274 : {
2275 : // iteration to last line
2276 103750 : pLineLayout = pLineLayout->GetNext();
2277 : }
2278 71212 : if ( pLineLayout )
2279 : {
2280 : SwTwips nAscent, nDescent, nDummy1, nDummy2;
2281 : // #i47162# - suppress consideration of
2282 : // fly content portions and the line portion.
2283 : pLineLayout->MaxAscentDescent( nAscent, nDescent,
2284 : nDummy1, nDummy2,
2285 71212 : 0, true );
2286 : // #i71281#
2287 : // Suppress wrong invalidation of printing area, if method is
2288 : // called recursive.
2289 : // Thus, member <mnHeightOfLastLine> is only set directly, if
2290 : // no recursive call is needed.
2291 71212 : const SwTwips nNewHeightOfLastLine = nAscent + nDescent;
2292 : // #i47162# - if last line only contains
2293 : // fly content portions, <mnHeightOfLastLine> is zero.
2294 : // In this case determine height of last line by the font
2295 71212 : if ( nNewHeightOfLastLine == 0 )
2296 : {
2297 4446 : _CalcHeightOfLastLine( true );
2298 : }
2299 : else
2300 : {
2301 66766 : mnHeightOfLastLine = nNewHeightOfLastLine;
2302 : }
2303 : }
2304 : }
2305 : }
2306 : }
2307 : // #i71281#
2308 : // invalidate printing area, if height of last line changes
2309 134807 : if ( mnHeightOfLastLine != mnOldHeightOfLastLine )
2310 : {
2311 60837 : InvalidatePrt();
2312 : }
2313 : }
2314 :
2315 : // OD 07.01.2004 #i11859# - change return data type
2316 : // add default parameter <_bNoPropLineSpacing> to control, if the
2317 : // value of a proportional line spacing is returned or not
2318 : // OD 07.01.2004 - trying to describe purpose of method:
2319 : // Method returns the value of the inter line spacing for a text frame.
2320 : // Such a value exists for proportional line spacings ("1,5 Lines",
2321 : // "Double", "Proportional" and for leading line spacing ("Leading").
2322 : // By parameter <_bNoPropLineSpace> (default value false) it can be
2323 : // controlled, if the value of a proportional line spacing is returned.
2324 166938 : long SwTxtFrm::GetLineSpace( const bool _bNoPropLineSpace ) const
2325 : {
2326 166938 : long nRet = 0;
2327 :
2328 166938 : const SwAttrSet* pSet = GetAttrSet();
2329 166938 : const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
2330 :
2331 166938 : switch( rSpace.GetInterLineSpaceRule() )
2332 : {
2333 : case SVX_INTER_LINE_SPACE_PROP:
2334 : {
2335 : // OD 07.01.2004 #i11859#
2336 54230 : if ( _bNoPropLineSpace )
2337 : {
2338 33738 : break;
2339 : }
2340 :
2341 : // OD 2004-03-17 #i11860# - use method <GetHeightOfLastLine()>
2342 20492 : nRet = GetHeightOfLastLine();
2343 :
2344 20492 : long nTmp = nRet;
2345 20492 : nTmp *= rSpace.GetPropLineSpace();
2346 20492 : nTmp /= 100;
2347 20492 : nTmp -= nRet;
2348 20492 : if ( nTmp > 0 )
2349 19816 : nRet = nTmp;
2350 : else
2351 676 : nRet = 0;
2352 : }
2353 20492 : break;
2354 : case SVX_INTER_LINE_SPACE_FIX:
2355 : {
2356 0 : if ( rSpace.GetInterLineSpace() > 0 )
2357 0 : nRet = rSpace.GetInterLineSpace();
2358 : }
2359 0 : break;
2360 : default:
2361 112708 : break;
2362 : }
2363 166938 : return nRet;
2364 : }
2365 :
2366 2720 : sal_uInt16 SwTxtFrm::FirstLineHeight() const
2367 : {
2368 2720 : if ( !HasPara() )
2369 : {
2370 274 : if( IsEmpty() && IsValid() )
2371 272 : return IsVertical() ? (sal_uInt16)Prt().Width() : (sal_uInt16)Prt().Height();
2372 2 : return USHRT_MAX;
2373 : }
2374 2446 : const SwParaPortion *pPara = GetPara();
2375 2446 : if ( !pPara )
2376 0 : return USHRT_MAX;
2377 :
2378 2446 : return pPara->Height();
2379 : }
2380 :
2381 38 : sal_uInt16 SwTxtFrm::GetLineCount( sal_Int32 nPos )
2382 : {
2383 38 : sal_uInt16 nRet = 0;
2384 38 : SwTxtFrm *pFrm = this;
2385 38 : do
2386 : {
2387 38 : pFrm->GetFormatted();
2388 38 : if( !pFrm->HasPara() )
2389 0 : break;
2390 38 : SwTxtSizeInfo aInf( pFrm );
2391 76 : SwTxtMargin aLine( pFrm, &aInf );
2392 38 : if( COMPLETE_STRING == nPos )
2393 38 : aLine.Bottom();
2394 : else
2395 0 : aLine.CharToLine( nPos );
2396 38 : nRet = nRet + aLine.GetLineNr();
2397 76 : pFrm = pFrm->GetFollow();
2398 38 : } while ( pFrm && pFrm->GetOfst() <= nPos );
2399 38 : return nRet;
2400 : }
2401 :
2402 131155 : void SwTxtFrm::ChgThisLines()
2403 : {
2404 : // not necessary to format here (GerFormatted etc.), because we have to come from there!
2405 131155 : sal_uLong nNew = 0;
2406 131155 : const SwLineNumberInfo &rInf = GetNode()->GetDoc()->GetLineNumberInfo();
2407 131155 : if ( !GetTxt().isEmpty() && HasPara() )
2408 : {
2409 75652 : SwTxtSizeInfo aInf( this );
2410 151304 : SwTxtMargin aLine( this, &aInf );
2411 75652 : if ( rInf.IsCountBlankLines() )
2412 : {
2413 75652 : aLine.Bottom();
2414 75652 : nNew = (sal_uLong)aLine.GetLineNr();
2415 : }
2416 : else
2417 : {
2418 0 : do
2419 : {
2420 0 : if( aLine.GetCurr()->HasCntnt() )
2421 0 : ++nNew;
2422 0 : } while ( aLine.NextLine() );
2423 75652 : }
2424 : }
2425 55503 : else if ( rInf.IsCountBlankLines() )
2426 55503 : nNew = 1;
2427 :
2428 131155 : if ( nNew != nThisLines )
2429 : {
2430 60419 : if ( !IsInTab() && GetAttrSet()->GetLineNumber().IsCount() )
2431 : {
2432 43061 : nAllLines -= nThisLines;
2433 43061 : nThisLines = nNew;
2434 43061 : nAllLines += nThisLines;
2435 43061 : SwFrm *pNxt = GetNextCntntFrm();
2436 86616 : while( pNxt && pNxt->IsInTab() )
2437 : {
2438 494 : if( 0 != (pNxt = pNxt->FindTabFrm()) )
2439 494 : pNxt = pNxt->FindNextCnt();
2440 : }
2441 43061 : if( pNxt )
2442 33564 : pNxt->InvalidateLineNum();
2443 :
2444 : // Extend repaint to the bottom.
2445 43061 : if ( HasPara() )
2446 : {
2447 31163 : SwRepaint& rRepaint = GetPara()->GetRepaint();
2448 31163 : rRepaint.Bottom( std::max( rRepaint.Bottom(),
2449 62326 : Frm().Top()+Prt().Bottom()));
2450 : }
2451 : }
2452 : else // Paragraphs which are not counted should not manipulate the AllLines.
2453 17358 : nThisLines = nNew;
2454 : }
2455 131155 : }
2456 :
2457 62548 : void SwTxtFrm::RecalcAllLines()
2458 : {
2459 62548 : ValidateLineNum();
2460 :
2461 62548 : const SwAttrSet *pAttrSet = GetAttrSet();
2462 :
2463 62548 : if ( !IsInTab() )
2464 : {
2465 43802 : const sal_uLong nOld = GetAllLines();
2466 43802 : const SwFmtLineNumber &rLineNum = pAttrSet->GetLineNumber();
2467 : sal_uLong nNewNum;
2468 43802 : const bool bRestart = GetTxtNode()->GetDoc()->GetLineNumberInfo().IsRestartEachPage();
2469 :
2470 43802 : if ( !IsFollow() && rLineNum.GetStartValue() && rLineNum.IsCount() )
2471 6 : nNewNum = rLineNum.GetStartValue() - 1;
2472 : // If it is a follow or not has not be considered if it is a restart at each page; the
2473 : // restart should also take affekt at follows.
2474 43796 : else if ( bRestart && FindPageFrm()->FindFirstBodyCntnt() == this )
2475 : {
2476 0 : nNewNum = 0;
2477 : }
2478 : else
2479 : {
2480 43796 : SwCntntFrm *pPrv = GetPrevCntntFrm();
2481 223450 : while ( pPrv &&
2482 116980 : (pPrv->IsInTab() || pPrv->IsInDocBody() != IsInDocBody()) )
2483 33590 : pPrv = pPrv->GetPrevCntntFrm();
2484 :
2485 : // #i78254# Restart line numbering at page change
2486 : // First body content may be in table!
2487 43796 : if ( bRestart && pPrv && pPrv->FindPageFrm() != FindPageFrm() )
2488 0 : pPrv = 0;
2489 :
2490 43796 : nNewNum = pPrv ? ((SwTxtFrm*)pPrv)->GetAllLines() : 0;
2491 : }
2492 43802 : if ( rLineNum.IsCount() )
2493 43454 : nNewNum += GetThisLines();
2494 :
2495 43802 : if ( nOld != nNewNum )
2496 : {
2497 34540 : nAllLines = nNewNum;
2498 34540 : SwCntntFrm *pNxt = GetNextCntntFrm();
2499 575006 : while ( pNxt &&
2500 371334 : (pNxt->IsInTab() || pNxt->IsInDocBody() != IsInDocBody()) )
2501 158272 : pNxt = pNxt->GetNextCntntFrm();
2502 34540 : if ( pNxt )
2503 : {
2504 31110 : if ( pNxt->GetUpper() != GetUpper() )
2505 13849 : pNxt->InvalidateLineNum();
2506 : else
2507 17261 : pNxt->_InvalidateLineNum();
2508 : }
2509 : }
2510 : }
2511 62548 : }
2512 :
2513 1800 : void SwTxtFrm::VisitPortions( SwPortionHandler& rPH ) const
2514 : {
2515 1800 : const SwParaPortion* pPara = IsValid() ? GetPara() : NULL;
2516 :
2517 1800 : if (pPara)
2518 : {
2519 1006 : if ( IsFollow() )
2520 0 : rPH.Skip( GetOfst() );
2521 :
2522 1006 : const SwLineLayout* pLine = pPara;
2523 3070 : while ( pLine )
2524 : {
2525 1058 : const SwLinePortion* pPor = pLine->GetFirstPortion();
2526 3550 : while ( pPor )
2527 : {
2528 1434 : pPor->HandlePortion( rPH );
2529 1434 : pPor = pPor->GetPortion();
2530 : }
2531 :
2532 1058 : rPH.LineBreak(pLine->Width());
2533 1058 : pLine = pLine->GetNext();
2534 : }
2535 : }
2536 :
2537 1800 : rPH.Finish();
2538 1800 : }
2539 :
2540 159299 : const SwScriptInfo* SwTxtFrm::GetScriptInfo() const
2541 : {
2542 159299 : const SwParaPortion* pPara = GetPara();
2543 159299 : return pPara ? &pPara->GetScriptInfo() : 0;
2544 : }
2545 :
2546 : // Helper function for SwTxtFrm::CalcBasePosForFly()
2547 206368 : static SwTwips lcl_CalcFlyBasePos( const SwTxtFrm& rFrm, SwRect aFlyRect,
2548 : SwTxtFly& rTxtFly )
2549 : {
2550 206368 : SWRECTFN( (&rFrm) )
2551 206368 : SwTwips nRet = rFrm.IsRightToLeft() ?
2552 276 : (rFrm.Frm().*fnRect->fnGetRight)() :
2553 206644 : (rFrm.Frm().*fnRect->fnGetLeft)();
2554 :
2555 218 : do
2556 : {
2557 206544 : SwRect aRect = rTxtFly.GetFrm( aFlyRect );
2558 206544 : if ( 0 != (aRect.*fnRect->fnGetWidth)() )
2559 : {
2560 704 : if ( rFrm.IsRightToLeft() )
2561 : {
2562 0 : if ( (aRect.*fnRect->fnGetRight)() -
2563 0 : (aFlyRect.*fnRect->fnGetRight)() >= 0 )
2564 : {
2565 : (aFlyRect.*fnRect->fnSetRight)(
2566 0 : (aRect.*fnRect->fnGetLeft)() );
2567 0 : nRet = (aRect.*fnRect->fnGetLeft)();
2568 : }
2569 : else
2570 206326 : break;
2571 : }
2572 : else
2573 : {
2574 1408 : if ( (aFlyRect.*fnRect->fnGetLeft)() -
2575 704 : (aRect.*fnRect->fnGetLeft)() >= 0 )
2576 : {
2577 : (aFlyRect.*fnRect->fnSetLeft)(
2578 218 : (aRect.*fnRect->fnGetRight)() + 1 );
2579 218 : nRet = (aRect.*fnRect->fnGetRight)();
2580 : }
2581 : else
2582 486 : break;
2583 : }
2584 : }
2585 : else
2586 205840 : break;
2587 : }
2588 218 : while ( (aFlyRect.*fnRect->fnGetWidth)() > 0 );
2589 :
2590 206368 : return nRet;
2591 : }
2592 :
2593 130361 : void SwTxtFrm::CalcBaseOfstForFly()
2594 : {
2595 : OSL_ENSURE( !IsVertical() || !IsSwapped(),
2596 : "SwTxtFrm::CalcBasePosForFly with swapped frame!" );
2597 :
2598 130361 : const SwNode* pNode = GetTxtNode();
2599 130361 : if ( !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_FLY_OFFSETS) )
2600 157538 : return;
2601 :
2602 103184 : SWRECTFN( this )
2603 :
2604 103184 : SwRect aFlyRect( Frm().Pos() + Prt().Pos(), Prt().SSize() );
2605 :
2606 : // Get first 'real' line and adjust position and height of line rectangle
2607 : // OD 08.09.2003 #110978#, #108749#, #110354# - correct behaviour,
2608 : // if no 'real' line exists (empty paragraph with and without a dummy portion)
2609 : {
2610 103184 : SwTwips nTop = (aFlyRect.*fnRect->fnGetTop)();
2611 103184 : const SwLineLayout* pLay = GetPara();
2612 103184 : SwTwips nLineHeight = 200;
2613 206484 : while( pLay && pLay->IsDummy() && pLay->GetNext() )
2614 : {
2615 116 : nTop += pLay->Height();
2616 116 : pLay = pLay->GetNext();
2617 : }
2618 103184 : if ( pLay )
2619 : {
2620 79496 : nLineHeight = pLay->Height();
2621 : }
2622 103184 : (aFlyRect.*fnRect->fnSetTopAndHeight)( nTop, nLineHeight );
2623 : }
2624 :
2625 103184 : SwTxtFly aTxtFly( this );
2626 103184 : aTxtFly.SetIgnoreCurrentFrame( true );
2627 103184 : aTxtFly.SetIgnoreContour( true );
2628 : // #118809# - ignore objects in page header|footer for
2629 : // text frames not in page header|footer
2630 103184 : aTxtFly.SetIgnoreObjsInHeaderFooter( true );
2631 103184 : SwTwips nRet1 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly );
2632 103184 : aTxtFly.SetIgnoreCurrentFrame( false );
2633 103184 : SwTwips nRet2 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly );
2634 :
2635 : // make values relative to frame start position
2636 103184 : SwTwips nLeft = IsRightToLeft() ?
2637 138 : (Frm().*fnRect->fnGetRight)() :
2638 103322 : (Frm().*fnRect->fnGetLeft)();
2639 :
2640 103184 : mnFlyAnchorOfst = nRet1 - nLeft;
2641 103184 : mnFlyAnchorOfstNoWrap = nRet2 - nLeft;
2642 : }
2643 :
2644 : /* repaint all text frames of the given text node */
2645 0 : void SwTxtFrm::repaintTextFrames( const SwTxtNode& rNode )
2646 : {
2647 0 : SwIterator<SwTxtFrm,SwTxtNode> aIter( rNode );
2648 0 : for( const SwTxtFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
2649 : {
2650 0 : SwRect aRec( pFrm->PaintArea() );
2651 0 : const SwRootFrm *pRootFrm = pFrm->getRootFrm();
2652 0 : SwViewShell *pCurShell = pRootFrm ? pRootFrm->GetCurrShell() : NULL;
2653 0 : if( pCurShell )
2654 0 : pCurShell->InvalidateWindows( aRec );
2655 0 : }
2656 270 : }
2657 :
2658 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|