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