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