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