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