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 "viewsh.hxx"
21 : #include "doc.hxx"
22 : #include "pagefrm.hxx"
23 : #include "rootfrm.hxx"
24 : #include "ndtxt.hxx"
25 : #include "txtatr.hxx"
26 : #include <SwPortionHandler.hxx>
27 : #include <txtftn.hxx>
28 : #include <flyfrm.hxx>
29 : #include <fmtftn.hxx>
30 : #include <ftninfo.hxx>
31 : #include <charfmt.hxx>
32 : #include <dflyobj.hxx>
33 : #include <rowfrm.hxx>
34 : #include <editeng/brushitem.hxx>
35 : #include <editeng/charrotateitem.hxx>
36 : #include <breakit.hxx>
37 : #include <com/sun/star/i18n/ScriptType.hpp>
38 : #include <tabfrm.hxx>
39 : // #i28701#
40 : #include <sortedobjs.hxx>
41 :
42 : #include "swfont.hxx" // new SwFont
43 : #include "porftn.hxx"
44 : #include "porfly.hxx"
45 : #include "porlay.hxx"
46 : #include "txtfrm.hxx"
47 : #include "itrform2.hxx"
48 : #include "ftnfrm.hxx" // FindQuoVadisFrm(),
49 : #include "pagedesc.hxx"
50 : #include "redlnitr.hxx" // SwRedlnItr
51 : #include "sectfrm.hxx" // SwSectionFrm
52 : #include "layouter.hxx" // Endnote-Collection
53 : #include "frmtool.hxx"
54 : #include "ndindex.hxx"
55 :
56 : using namespace ::com::sun::star;
57 :
58 : /*************************************************************************
59 : * _IsFtnNumFrm()
60 : *************************************************************************/
61 :
62 125 : sal_Bool SwTxtFrm::_IsFtnNumFrm() const
63 : {
64 125 : const SwFtnFrm* pFtn = FindFtnFrm()->GetMaster();
65 250 : while( pFtn && !pFtn->ContainsCntnt() )
66 0 : pFtn = pFtn->GetMaster();
67 125 : return !pFtn;
68 : }
69 :
70 : /*************************************************************************
71 : * FindFtn()
72 : *************************************************************************/
73 :
74 : // Sucht innerhalb einer Master-Follow-Kette den richtigen TxtFrm zum SwTxtFtn
75 :
76 154 : SwTxtFrm *SwTxtFrm::FindFtnRef( const SwTxtFtn *pFtn )
77 : {
78 154 : SwTxtFrm *pFrm = this;
79 154 : const bool bFwd = *pFtn->GetStart() >= GetOfst();
80 345 : while( pFrm )
81 : {
82 154 : if( SwFtnBossFrm::FindFtn( pFrm, pFtn ) )
83 117 : return pFrm;
84 : pFrm = bFwd ? pFrm->GetFollow() :
85 37 : pFrm->IsFollow() ? pFrm->FindMaster() : 0;
86 : }
87 37 : return pFrm;
88 : }
89 :
90 : /*************************************************************************
91 : * CalcFtnFlag()
92 : *************************************************************************/
93 :
94 : #ifdef DBG_UTIL
95 : void SwTxtFrm::CalcFtnFlag( xub_StrLen nStop )//For testing the SplitFrm
96 : #else
97 3090 : void SwTxtFrm::CalcFtnFlag()
98 : #endif
99 : {
100 3090 : bFtn = sal_False;
101 :
102 3090 : const SwpHints *pHints = GetTxtNode()->GetpSwpHints();
103 3090 : if( !pHints )
104 4377 : return;
105 :
106 1803 : const sal_uInt16 nSize = pHints->Count();
107 :
108 : #ifdef DBG_UTIL
109 : const xub_StrLen nEnd = nStop != STRING_LEN ? nStop
110 : : GetFollow() ? GetFollow()->GetOfst() : STRING_LEN;
111 : #else
112 1803 : const xub_StrLen nEnd = GetFollow() ? GetFollow()->GetOfst() : STRING_LEN;
113 : #endif
114 :
115 4721 : for ( sal_uInt16 i = 0; i < nSize; ++i )
116 : {
117 3004 : const SwTxtAttr *pHt = (*pHints)[i];
118 3004 : if ( pHt->Which() == RES_TXTATR_FTN )
119 : {
120 86 : const xub_StrLen nIdx = *pHt->GetStart();
121 86 : if ( nEnd < nIdx )
122 0 : break;
123 86 : if( GetOfst() <= nIdx )
124 : {
125 86 : bFtn = sal_True;
126 86 : break;
127 : }
128 : }
129 : }
130 : }
131 :
132 : /*************************************************************************
133 : * CalcPrepFtnAdjust()
134 : *************************************************************************/
135 :
136 11 : sal_Bool SwTxtFrm::CalcPrepFtnAdjust()
137 : {
138 : OSL_ENSURE( HasFtn(), "Wer ruft mich da?" );
139 11 : SwFtnBossFrm *pBoss = FindFtnBossFrm( sal_True );
140 11 : const SwFtnFrm *pFtn = pBoss->FindFirstFtn( this );
141 33 : if( pFtn && FTNPOS_CHAPTER != GetNode()->GetDoc()->GetFtnInfo().ePos &&
142 11 : ( !pBoss->GetUpper()->IsSctFrm() ||
143 0 : !((SwSectionFrm*)pBoss->GetUpper())->IsFtnAtEnd() ) )
144 : {
145 11 : const SwFtnContFrm *pCont = pBoss->FindFtnCont();
146 11 : bool bReArrange = true;
147 :
148 11 : SWRECTFN( this )
149 44 : if ( pCont && (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(),
150 33 : (Frm().*fnRect->fnGetBottom)() ) > 0 )
151 : {
152 22 : pBoss->RearrangeFtns( (Frm().*fnRect->fnGetBottom)(), sal_False,
153 33 : pFtn->GetAttr() );
154 11 : ValidateBodyFrm();
155 11 : ValidateFrm();
156 11 : pFtn = pBoss->FindFirstFtn( this );
157 : }
158 : else
159 0 : bReArrange = false;
160 11 : if( !pCont || !pFtn || bReArrange != (pFtn->FindFtnBossFrm() == pBoss) )
161 : {
162 0 : SwTxtFormatInfo aInf( this );
163 0 : SwTxtFormatter aLine( this, &aInf );
164 0 : aLine.TruncLines();
165 0 : SetPara( 0 ); //Wird ggf. geloescht!
166 0 : ResetPreps();
167 0 : return sal_False;
168 : }
169 : }
170 11 : return sal_True;
171 : }
172 :
173 :
174 : /*************************************************************************
175 : * lcl_GetFtnLower()
176 : *
177 : * Local helper function. Checks if nLower should be taken as the boundary
178 : * for the footnote.
179 : *************************************************************************/
180 :
181 176 : static SwTwips lcl_GetFtnLower( const SwTxtFrm* pFrm, SwTwips nLower )
182 : {
183 : // nLower is an absolute value. It denotes the bottom of the line
184 : // containing the footnote.
185 176 : SWRECTFN( pFrm )
186 :
187 : OSL_ENSURE( !pFrm->IsVertical() || !pFrm->IsSwapped(),
188 : "lcl_GetFtnLower with swapped frame" );
189 :
190 : SwTwips nAdd;
191 176 : SwTwips nRet = nLower;
192 :
193 : //
194 : // Check if text is inside a table.
195 : //
196 176 : if ( pFrm->IsInTab() )
197 : {
198 : //
199 : // If pFrm is inside a table, we have to check if
200 : // a) The table is not allowed to split or
201 : // b) The table row is not allowed to split
202 : //
203 : // Inside a table, there are no footnotes,
204 : // see SwFrm::FindFtnBossFrm. So we don't have to check
205 : // the case that pFrm is inside a (footnote collecting) section
206 : // within the table.
207 : //
208 0 : const SwFrm* pRow = pFrm;
209 0 : while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
210 0 : pRow = pRow->GetUpper();
211 0 : const SwTabFrm* pTabFrm = (SwTabFrm*)pRow->GetUpper();
212 :
213 : OSL_ENSURE( pTabFrm && pRow &&
214 : pRow->GetUpper()->IsTabFrm(), "Upper of row should be tab" );
215 :
216 0 : const bool bDontSplit = !pTabFrm->IsFollow() &&
217 0 : !pTabFrm->IsLayoutSplitAllowed();
218 :
219 0 : SwTwips nMin = 0;
220 0 : if ( bDontSplit )
221 0 : nMin = (pTabFrm->Frm().*fnRect->fnGetBottom)();
222 0 : else if ( !((SwRowFrm*)pRow)->IsRowSplitAllowed() )
223 0 : nMin = (pRow->Frm().*fnRect->fnGetBottom)();
224 :
225 0 : if ( nMin && (*fnRect->fnYDiff)( nMin, nLower ) > 0 )
226 0 : nRet = nMin;
227 :
228 0 : nAdd = (pRow->GetUpper()->*fnRect->fnGetBottomMargin)();
229 : }
230 : else
231 176 : nAdd = (pFrm->*fnRect->fnGetBottomMargin)();
232 :
233 176 : if( nAdd > 0 )
234 : {
235 0 : if ( bVert )
236 0 : nRet -= nAdd;
237 : else
238 0 : nRet += nAdd;
239 : }
240 :
241 : // #i10770#: If there are fly frames anchored at previous paragraphs,
242 : // the deadline should consider their lower borders.
243 176 : const SwFrm* pStartFrm = pFrm->GetUpper()->GetLower();
244 : OSL_ENSURE( pStartFrm, "Upper has no lower" );
245 176 : SwTwips nFlyLower = bVert ? LONG_MAX : 0;
246 430 : while ( pStartFrm != pFrm )
247 : {
248 : OSL_ENSURE( pStartFrm, "Frame chain is broken" );
249 78 : if ( pStartFrm->GetDrawObjs() )
250 : {
251 0 : const SwSortedObjs &rObjs = *pStartFrm->GetDrawObjs();
252 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
253 : {
254 0 : SwAnchoredObject* pAnchoredObj = rObjs[i];
255 0 : SwRect aRect( pAnchoredObj->GetObjRect() );
256 :
257 0 : if ( !pAnchoredObj->ISA(SwFlyFrm) ||
258 0 : static_cast<SwFlyFrm*>(pAnchoredObj)->IsValid() )
259 : {
260 0 : const SwTwips nBottom = (aRect.*fnRect->fnGetBottom)();
261 0 : if ( (*fnRect->fnYDiff)( nBottom, nFlyLower ) > 0 )
262 0 : nFlyLower = nBottom;
263 : }
264 : }
265 : }
266 :
267 78 : pStartFrm = pStartFrm->GetNext();
268 : }
269 :
270 176 : if ( bVert )
271 0 : nRet = std::min( nRet, nFlyLower );
272 : else
273 176 : nRet = std::max( nRet, nFlyLower );
274 :
275 176 : return nRet;
276 : }
277 :
278 :
279 : /*************************************************************************
280 : * SwTxtFrm::GetFtnLine()
281 : *************************************************************************/
282 :
283 99 : SwTwips SwTxtFrm::GetFtnLine( const SwTxtFtn *pFtn ) const
284 : {
285 : OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
286 : "SwTxtFrm::GetFtnLine with swapped frame" );
287 :
288 99 : SwTxtFrm *pThis = (SwTxtFrm*)this;
289 :
290 99 : if( !HasPara() )
291 : {
292 : // #109071# GetFormatted() does not work here, bacause most probably
293 : // the frame is currently locked. We return the previous value.
294 0 : return pThis->mnFtnLine > 0 ?
295 : pThis->mnFtnLine :
296 0 : IsVertical() ? Frm().Left() : Frm().Bottom();
297 : }
298 :
299 99 : SWAP_IF_NOT_SWAPPED( this )
300 :
301 99 : SwTxtInfo aInf( pThis );
302 99 : SwTxtIter aLine( pThis, &aInf );
303 99 : const xub_StrLen nPos = *pFtn->GetStart();
304 99 : aLine.CharToLine( nPos );
305 :
306 99 : SwTwips nRet = aLine.Y() + SwTwips(aLine.GetLineHeight());
307 99 : if( IsVertical() )
308 0 : nRet = SwitchHorizontalToVertical( nRet );
309 :
310 99 : UNDO_SWAP( this )
311 :
312 99 : nRet = lcl_GetFtnLower( pThis, nRet );
313 :
314 99 : pThis->mnFtnLine = nRet;
315 99 : return nRet;
316 : }
317 :
318 : /*************************************************************************
319 : * SwTxtFrm::GetFtnRstHeight()
320 : *************************************************************************/
321 :
322 : // Ermittelt die max. erreichbare Hoehe des TxtFrm im Ftn-Bereich.
323 : // Sie wird eingeschraenkt durch den unteren Rand der Zeile mit
324 : // der Ftn-Referenz.
325 :
326 134 : SwTwips SwTxtFrm::_GetFtnFrmHeight() const
327 : {
328 : OSL_ENSURE( !IsFollow() && IsInFtn(), "SwTxtFrm::SetFtnLine: moon walk" );
329 :
330 134 : const SwFtnFrm *pFtnFrm = FindFtnFrm();
331 134 : const SwTxtFrm *pRef = (const SwTxtFrm *)pFtnFrm->GetRef();
332 134 : const SwFtnBossFrm *pBoss = FindFtnBossFrm();
333 268 : if( pBoss != pRef->FindFtnBossFrm( !pFtnFrm->GetAttr()->
334 134 : GetFtn().IsEndNote() ) )
335 9 : return 0;
336 :
337 125 : SWAP_IF_SWAPPED( this )
338 :
339 125 : SwTwips nHeight = pRef->IsInFtnConnect() ?
340 125 : 1 : pRef->GetFtnLine( pFtnFrm->GetAttr() );
341 125 : if( nHeight )
342 : {
343 : // So komisch es aussehen mag: Die erste Ftn auf der Seite darf sich
344 : // nicht mit der Ftn-Referenz beruehren, wenn wir im Ftn-Bereich Text
345 : // eingeben.
346 125 : const SwFrm *pCont = pFtnFrm->GetUpper();
347 : //Hoehe innerhalb des Cont, die ich mir 'eh noch genehmigen darf.
348 125 : SWRECTFN( pCont )
349 250 : SwTwips nTmp = (*fnRect->fnYDiff)( (pCont->*fnRect->fnGetPrtBottom)(),
350 375 : (Frm().*fnRect->fnGetTop)() );
351 :
352 : #if OSL_DEBUG_LEVEL > 0
353 : if( nTmp < 0 )
354 : {
355 : bool bInvalidPos = false;
356 : const SwLayoutFrm* pTmp = GetUpper();
357 : while( !bInvalidPos && pTmp )
358 : {
359 : bInvalidPos = !pTmp->GetValidPosFlag() ||
360 : !pTmp->Lower()->GetValidPosFlag();
361 : if( pTmp == pCont )
362 : break;
363 : pTmp = pTmp->GetUpper();
364 : }
365 : OSL_ENSURE( bInvalidPos, "Hanging below FtnCont" );
366 : }
367 : #endif
368 :
369 125 : if ( (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(), nHeight) > 0 )
370 : {
371 : //Wachstumspotential den Containers.
372 125 : if ( !pRef->IsInFtnConnect() )
373 : {
374 51 : SwSaveFtnHeight aSave( (SwFtnBossFrm*)pBoss, nHeight );
375 51 : nHeight = ((SwFtnContFrm*)pCont)->Grow( LONG_MAX, sal_True );
376 : }
377 : else
378 74 : nHeight = ((SwFtnContFrm*)pCont)->Grow( LONG_MAX, sal_True );
379 :
380 125 : nHeight += nTmp;
381 125 : if( nHeight < 0 )
382 0 : nHeight = 0;
383 : }
384 : else
385 : { // The container has to shrink
386 0 : nTmp += (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(), nHeight);
387 0 : if( nTmp > 0 )
388 0 : nHeight = nTmp;
389 : else
390 0 : nHeight = 0;
391 : }
392 : }
393 :
394 125 : UNDO_SWAP( this )
395 :
396 125 : return nHeight;
397 : }
398 :
399 : /*************************************************************************
400 : * SwTxtFrm::FindQuoVadisFrm()
401 : *************************************************************************/
402 :
403 64 : SwTxtFrm *SwTxtFrm::FindQuoVadisFrm()
404 : {
405 : // Erstmal feststellen, ob wir in einem FtnFrm stehen:
406 64 : if( GetIndPrev() || !IsInFtn() )
407 0 : return 0;
408 :
409 : // Zum Vorgaenger-FtnFrm
410 64 : SwFtnFrm *pFtnFrm = FindFtnFrm()->GetMaster();
411 64 : if( !pFtnFrm )
412 64 : return 0;
413 :
414 : // Nun den letzten Cntnt:
415 0 : const SwCntntFrm *pCnt = pFtnFrm->ContainsCntnt();
416 0 : if( !pCnt )
417 0 : return NULL;
418 : const SwCntntFrm *pLast;
419 0 : do
420 0 : { pLast = pCnt;
421 0 : pCnt = pCnt->GetNextCntntFrm();
422 0 : } while( pCnt && pFtnFrm->IsAnLower( pCnt ) );
423 0 : return (SwTxtFrm*)pLast;
424 : }
425 :
426 : /*************************************************************************
427 : * SwTxtFrm::RemoveFtn()
428 : *************************************************************************/
429 :
430 1889 : void SwTxtFrm::RemoveFtn( const xub_StrLen nStart, const xub_StrLen nLen )
431 : {
432 1889 : if ( !IsFtnAllowed() )
433 146 : return;
434 :
435 1743 : SwpHints *pHints = GetTxtNode()->GetpSwpHints();
436 1743 : if( !pHints )
437 0 : return;
438 :
439 1743 : bool bRollBack = nLen != STRING_LEN;
440 1743 : sal_uInt16 nSize = pHints->Count();
441 : xub_StrLen nEnd;
442 : SwTxtFrm* pSource;
443 1743 : if( bRollBack )
444 : {
445 0 : nEnd = nStart + nLen;
446 0 : pSource = GetFollow();
447 0 : if( !pSource )
448 0 : return;
449 : }
450 : else
451 : {
452 1743 : nEnd = STRING_LEN;
453 1743 : pSource = this;
454 : }
455 :
456 1743 : if( nSize )
457 : {
458 1743 : SwPageFrm* pUpdate = NULL;
459 1743 : bool bRemove = false;
460 1743 : SwFtnBossFrm *pFtnBoss = 0;
461 1743 : SwFtnBossFrm *pEndBoss = 0;
462 : bool bFtnEndDoc
463 1743 : = FTNPOS_CHAPTER == GetNode()->GetDoc()->GetFtnInfo().ePos;
464 6317 : for ( sal_uInt16 i = nSize; i; )
465 : {
466 2908 : SwTxtAttr *pHt = pHints->GetTextHint(--i);
467 2908 : if ( RES_TXTATR_FTN != pHt->Which() )
468 2831 : continue;
469 :
470 77 : const xub_StrLen nIdx = *pHt->GetStart();
471 77 : if( nStart > nIdx )
472 77 : break;
473 :
474 0 : if( nEnd >= nIdx )
475 : {
476 0 : SwTxtFtn *pFtn = (SwTxtFtn*)pHt;
477 0 : sal_Bool bEndn = pFtn->GetFtn().IsEndNote();
478 :
479 0 : if( bEndn )
480 : {
481 0 : if( !pEndBoss )
482 0 : pEndBoss = pSource->FindFtnBossFrm();
483 : }
484 : else
485 : {
486 0 : if( !pFtnBoss )
487 : {
488 0 : pFtnBoss = pSource->FindFtnBossFrm( sal_True );
489 0 : if( pFtnBoss->GetUpper()->IsSctFrm() )
490 : {
491 : SwSectionFrm* pSect = (SwSectionFrm*)
492 0 : pFtnBoss->GetUpper();
493 0 : if( pSect->IsFtnAtEnd() )
494 0 : bFtnEndDoc = false;
495 : }
496 : }
497 : }
498 :
499 : // Wir loeschen nicht, sondern wollen die Ftn verschieben.
500 : // Drei Faelle koennen auftreten:
501 : // 1) Es gibt weder Follow noch PrevFollow
502 : // -> RemoveFtn() (vielleicht sogar ein OSL_ENSURE(wert)
503 : // 2) nStart > GetOfst, ich habe einen Follow
504 : // -> Ftn wandert in den Follow
505 : // 3) nStart < GetOfst, ich bin ein Follow
506 : // -> Ftn wandert in den PrevFollow
507 : // beide muessen auf einer Seite/in einer Spalte stehen.
508 :
509 : SwFtnFrm *pFtnFrm = bEndn ? pEndBoss->FindFtn( pSource, pFtn ) :
510 0 : pFtnBoss->FindFtn( pSource, pFtn );
511 :
512 0 : if( pFtnFrm )
513 : {
514 0 : const bool bEndDoc = bEndn ? true : bFtnEndDoc;
515 0 : if( bRollBack )
516 : {
517 0 : while ( pFtnFrm )
518 : {
519 0 : pFtnFrm->SetRef( this );
520 0 : pFtnFrm = pFtnFrm->GetFollow();
521 0 : SetFtn( sal_True );
522 : }
523 : }
524 0 : else if( GetFollow() )
525 : {
526 0 : SwCntntFrm *pDest = GetFollow();
527 0 : while( pDest->GetFollow() && ((SwTxtFrm*)pDest->
528 0 : GetFollow())->GetOfst() <= nIdx )
529 0 : pDest = pDest->GetFollow();
530 : OSL_ENSURE( !pDest->FindFtnBossFrm( !bEndn )->FindFtn(
531 : pDest,pFtn),"SwTxtFrm::RemoveFtn: footnote exists");
532 :
533 : //Nicht ummelden sondern immer Moven.
534 : // OD 08.11.2002 #104840# - use <SwlayoutFrm::IsBefore(::)>
535 0 : if ( bEndDoc ||
536 0 : !pFtnFrm->FindFtnBossFrm()->IsBefore( pDest->FindFtnBossFrm( !bEndn ) )
537 : )
538 : {
539 0 : SwPageFrm* pTmp = pFtnFrm->FindPageFrm();
540 0 : if( pUpdate && pUpdate != pTmp )
541 0 : pUpdate->UpdateFtnNum();
542 0 : pUpdate = pTmp;
543 0 : while ( pFtnFrm )
544 : {
545 0 : pFtnFrm->SetRef( pDest );
546 0 : pFtnFrm = pFtnFrm->GetFollow();
547 : }
548 : }
549 : else
550 : {
551 0 : if( bEndn )
552 0 : pEndBoss->MoveFtns( this, pDest, pFtn );
553 : else
554 0 : pFtnBoss->MoveFtns( this, pDest, pFtn );
555 0 : bRemove = true;
556 : }
557 0 : ((SwTxtFrm*)pDest)->SetFtn( sal_True );
558 :
559 : OSL_ENSURE( pDest->FindFtnBossFrm( !bEndn )->FindFtn( pDest,
560 : pFtn),"SwTxtFrm::RemoveFtn: footnote ChgRef failed");
561 : }
562 : else
563 : {
564 0 : if( !bEndDoc || ( bEndn && pEndBoss->IsInSct() &&
565 0 : !SwLayouter::Collecting( GetNode()->GetDoc(),
566 0 : pEndBoss->FindSctFrm(), NULL ) ) )
567 : {
568 0 : if( bEndn )
569 0 : pEndBoss->RemoveFtn( this, pFtn );
570 : else
571 0 : pFtnBoss->RemoveFtn( this, pFtn );
572 0 : bRemove = bRemove || !bEndDoc;
573 : OSL_ENSURE( bEndn ? !pEndBoss->FindFtn( this, pFtn ) :
574 : !pFtnBoss->FindFtn( this, pFtn ),
575 : "SwTxtFrm::RemoveFtn: can't get off that footnote" );
576 : }
577 : }
578 : }
579 : }
580 : }
581 1743 : if( pUpdate )
582 0 : pUpdate->UpdateFtnNum();
583 : // Wir bringen die Oszillation zum stehen:
584 1743 : if( bRemove && !bFtnEndDoc && HasPara() )
585 : {
586 0 : ValidateBodyFrm();
587 0 : ValidateFrm();
588 : }
589 : }
590 : // Folgendes Problem: Aus dem FindBreak heraus wird das RemoveFtn aufgerufen,
591 : // weil die letzte Zeile an den Follow abgegeben werden soll. Der Offset
592 : // des Follows ist aber veraltet, er wird demnaechst gesetzt. CalcFntFlag ist
593 : // auf einen richtigen Follow-Offset angewiesen. Deshalb wird hier kurzfristig
594 : // der Follow-Offset manipuliert.
595 1743 : xub_StrLen nOldOfst = STRING_LEN;
596 1743 : if( HasFollow() && nStart > GetOfst() )
597 : {
598 3 : nOldOfst = GetFollow()->GetOfst();
599 3 : GetFollow()->ManipOfst( nStart + ( bRollBack ? nLen : 0 ) );
600 : }
601 1743 : pSource->CalcFtnFlag();
602 1743 : if( nOldOfst < STRING_LEN )
603 3 : GetFollow()->ManipOfst( nOldOfst );
604 : }
605 :
606 : /*************************************************************************
607 : * SwTxtFormatter::ConnectFtn()
608 : *************************************************************************/
609 : // sal_False, wenn irgendetwas schief gegangen ist.
610 : // Es gibt eigentlich nur zwei Moeglichkeiten:
611 : // a) Die Ftn ist bereits vorhanden
612 : // => dann wird sie gemoved, wenn ein anderer pSrcFrm gefunden wurde
613 : // b) Die Ftn ist nicht vorhanden
614 : // => dann wird sie fuer uns angelegt.
615 : // Ob die Ftn schliesslich auf unserer Spalte/Seite landet oder nicht,
616 : // spielt in diesem Zusammenhang keine Rolle.
617 : // Optimierungen bei Endnoten.
618 : // Noch ein Problem: wenn die Deadline im Ftn-Bereich liegt, muss die
619 : // Ftn verschoben werden.
620 :
621 77 : void SwTxtFrm::ConnectFtn( SwTxtFtn *pFtn, const SwTwips nDeadLine )
622 : {
623 : OSL_ENSURE( !IsVertical() || !IsSwapped(),
624 : "SwTxtFrm::ConnectFtn with swapped frame" );
625 :
626 77 : bFtn = sal_True;
627 77 : bInFtnConnect = sal_True; //Bloss zuruecksetzen!
628 77 : sal_Bool bEnd = pFtn->GetFtn().IsEndNote();
629 :
630 : //
631 : // We want to store this value, because it is needed as a fallback
632 : // in GetFtnLine(), if there is no paragraph information available
633 : //
634 77 : mnFtnLine = nDeadLine;
635 :
636 : // Wir brauchen immer einen Boss (Spalte/Seite)
637 : SwSectionFrm *pSect;
638 77 : SwCntntFrm *pCntnt = this;
639 77 : if( bEnd && IsInSct() )
640 : {
641 0 : pSect = FindSctFrm();
642 0 : if( pSect->IsEndnAtEnd() )
643 0 : pCntnt = pSect->FindLastCntnt( FINDMODE_ENDNOTE );
644 0 : if( !pCntnt )
645 0 : pCntnt = this;
646 : }
647 :
648 77 : SwFtnBossFrm *pBoss = pCntnt->FindFtnBossFrm( !bEnd );
649 :
650 : #if OSL_DEBUG_LEVEL > 1
651 : SwTwips nRstHeight = GetRstHeight();
652 : #endif
653 :
654 77 : pSect = pBoss->FindSctFrm();
655 19 : bool bDocEnd = bEnd ? !( pSect && pSect->IsEndnAtEnd() ) :
656 116 : ( !( pSect && pSect->IsFtnAtEnd() ) &&
657 212 : FTNPOS_CHAPTER == GetNode()->GetDoc()->GetFtnInfo().ePos );
658 : //Ftn kann beim Follow angemeldet sein.
659 77 : SwCntntFrm *pSrcFrm = FindFtnRef( pFtn );
660 :
661 77 : if( bDocEnd )
662 : {
663 20 : if( pSect && pSrcFrm )
664 : {
665 0 : SwFtnFrm *pFtnFrm = pBoss->FindFtn( pSrcFrm, pFtn );
666 0 : if( pFtnFrm && pFtnFrm->IsInSct() )
667 : {
668 0 : pBoss->RemoveFtn( pSrcFrm, pFtn );
669 0 : pSrcFrm = 0;
670 : }
671 : }
672 : }
673 57 : else if( bEnd && pSect )
674 : {
675 0 : SwFtnFrm *pFtnFrm = pSrcFrm ? pBoss->FindFtn( pSrcFrm, pFtn ) : NULL;
676 0 : if( pFtnFrm && !pFtnFrm->GetUpper() )
677 0 : pFtnFrm = NULL;
678 0 : SwDoc *pDoc = GetNode()->GetDoc();
679 0 : if( SwLayouter::Collecting( pDoc, pSect, pFtnFrm ) )
680 : {
681 0 : if( !pSrcFrm )
682 : {
683 0 : SwFtnFrm *pNew = new SwFtnFrm(pDoc->GetDfltFrmFmt(),this,this,pFtn);
684 0 : SwNodeIndex aIdx( *pFtn->GetStartNode(), 1 );
685 0 : ::_InsertCnt( pNew, pDoc, aIdx.GetIndex() );
686 0 : GetNode()->getIDocumentLayoutAccess()->GetLayouter()->CollectEndnote( pNew );
687 : }
688 0 : else if( pSrcFrm != this )
689 0 : pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
690 0 : bInFtnConnect = sal_False;
691 0 : return;
692 : }
693 0 : else if( pSrcFrm )
694 : {
695 0 : SwFtnBossFrm *pFtnBoss = pFtnFrm->FindFtnBossFrm();
696 0 : if( !pFtnBoss->IsInSct() ||
697 0 : pFtnBoss->ImplFindSctFrm()->GetSection()!=pSect->GetSection() )
698 : {
699 0 : pBoss->RemoveFtn( pSrcFrm, pFtn );
700 0 : pSrcFrm = 0;
701 : }
702 : }
703 : }
704 :
705 77 : if( bDocEnd || bEnd )
706 : {
707 20 : if( !pSrcFrm )
708 5 : pBoss->AppendFtn( this, pFtn );
709 15 : else if( pSrcFrm != this )
710 0 : pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
711 20 : bInFtnConnect = sal_False;
712 20 : return;
713 : }
714 :
715 57 : SwSaveFtnHeight aHeight( pBoss, nDeadLine );
716 :
717 57 : if( !pSrcFrm ) // Es wurde ueberhaupt keine Ftn gefunden.
718 32 : pBoss->AppendFtn( this, pFtn );
719 : else
720 : {
721 25 : SwFtnFrm *pFtnFrm = pBoss->FindFtn( pSrcFrm, pFtn );
722 25 : SwFtnBossFrm *pFtnBoss = pFtnFrm->FindFtnBossFrm();
723 :
724 25 : bool bBrutal = false;
725 :
726 25 : if( pFtnBoss == pBoss ) // Ref und Ftn sind auf der selben Seite/Spalte.
727 : {
728 25 : SwFrm *pCont = pFtnFrm->GetUpper();
729 :
730 25 : SWRECTFN ( pCont )
731 50 : long nDiff = (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(),
732 75 : nDeadLine );
733 :
734 25 : if( nDiff >= 0 )
735 : {
736 : //Wenn die Fussnote bei einem Follow angemeldet ist, so ist
737 : //es jetzt an der Zeit sie umzumelden.
738 25 : if ( pSrcFrm != this )
739 0 : pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
740 : //Es steht Platz zur Verfuegung, also kann die Fussnote evtl.
741 : //wachsen.
742 25 : if ( pFtnFrm->GetFollow() && nDiff > 0 )
743 : {
744 0 : SwTwips nHeight = (pCont->Frm().*fnRect->fnGetHeight)();
745 0 : pBoss->RearrangeFtns( nDeadLine, sal_False, pFtn );
746 0 : ValidateBodyFrm();
747 0 : ValidateFrm();
748 0 : ViewShell *pSh = getRootFrm()->GetCurrShell();
749 0 : if ( pSh && nHeight == (pCont->Frm().*fnRect->fnGetHeight)() )
750 : //Damit uns nix durch die Lappen geht.
751 0 : pSh->InvalidateWindows( pCont->Frm() );
752 : }
753 25 : bInFtnConnect = sal_False;
754 25 : return;
755 : }
756 : else
757 0 : bBrutal = true;
758 : }
759 : else
760 : {
761 : // Ref und Ftn sind nicht auf einer Seite, Move-Versuch ist noetig.
762 0 : SwFrm* pTmp = this;
763 0 : while( pTmp->GetNext() && pSrcFrm != pTmp )
764 0 : pTmp = pTmp->GetNext();
765 0 : if( pSrcFrm == pTmp )
766 0 : bBrutal = true;
767 : else
768 : { // Wenn unser Boss in einem spaltigen Bereich sitzt, es aber auf
769 : // der Seite schon einen FtnContainer gibt, hilft nur die brutale
770 : // Methode
771 0 : if( pSect && pSect->FindFtnBossFrm( !bEnd )->FindFtnCont() )
772 0 : bBrutal = true;
773 : // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
774 0 : else if ( !pFtnFrm->GetPrev() ||
775 0 : pFtnBoss->IsBefore( pBoss )
776 : )
777 : {
778 0 : SwFtnBossFrm *pSrcBoss = pSrcFrm->FindFtnBossFrm( !bEnd );
779 0 : pSrcBoss->MoveFtns( pSrcFrm, this, pFtn );
780 : }
781 : else
782 0 : pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
783 : }
784 : }
785 :
786 : // Die brutale Loesung: Fussnote entfernen und appenden.
787 : // Es muss SetFtnDeadLine() gerufen werden, weil nach
788 : // RemoveFtn die nMaxFtnHeight evtl. besser auf unsere Wuensche
789 : // eingestellt werden kann.
790 0 : if( bBrutal )
791 : {
792 0 : pBoss->RemoveFtn( pSrcFrm, pFtn, sal_False );
793 : SwSaveFtnHeight *pHeight = bEnd ? NULL :
794 0 : new SwSaveFtnHeight( pBoss, nDeadLine );
795 0 : pBoss->AppendFtn( this, pFtn );
796 0 : delete pHeight;
797 : }
798 : }
799 :
800 : // In spaltigen Bereichen, die noch nicht bis zum Seitenrand gehen,
801 : // ist kein RearrangeFtns sinnvoll, da der Fussnotencontainer noch
802 : // nicht kalkuliert worden ist.
803 32 : if( !pSect || !pSect->Growable() )
804 : {
805 : // Umgebung validieren, um Oszillationen zu verhindern.
806 32 : SwSaveFtnHeight aNochmal( pBoss, nDeadLine );
807 32 : ValidateBodyFrm();
808 32 : pBoss->RearrangeFtns( nDeadLine, sal_True );
809 32 : ValidateFrm();
810 : }
811 0 : else if( pSect->IsFtnAtEnd() )
812 : {
813 0 : ValidateBodyFrm();
814 0 : ValidateFrm();
815 : }
816 :
817 : #if OSL_DEBUG_LEVEL > 1
818 : // pFtnFrm kann sich durch Calc veraendert haben ...
819 : SwFtnFrm *pFtnFrm = pBoss->FindFtn( this, pFtn );
820 : if( pFtnFrm && pBoss != pFtnFrm->FindFtnBossFrm( !bEnd ) )
821 : {
822 : int bla = 5;
823 : (void)bla;
824 : }
825 : nRstHeight = GetRstHeight();
826 : (void)nRstHeight;
827 : #endif
828 32 : bInFtnConnect = sal_False;
829 32 : return;
830 : }
831 :
832 :
833 :
834 : /*************************************************************************
835 : * SwTxtFormatter::NewFtnPortion()
836 : *************************************************************************/
837 :
838 : // Die Portion fuer die Ftn-Referenz im Text
839 77 : SwFtnPortion *SwTxtFormatter::NewFtnPortion( SwTxtFormatInfo &rInf,
840 : SwTxtAttr *pHint )
841 : {
842 : OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
843 : "NewFtnPortion with unswapped frame" );
844 :
845 77 : if( !pFrm->IsFtnAllowed() )
846 0 : return 0;
847 :
848 77 : SwTxtFtn *pFtn = (SwTxtFtn*)pHint;
849 77 : SwFmtFtn& rFtn = (SwFmtFtn&)pFtn->GetFtn();
850 77 : SwDoc *pDoc = pFrm->GetNode()->GetDoc();
851 :
852 77 : if( rInf.IsTest() )
853 0 : return new SwFtnPortion( rFtn.GetViewNumStr( *pDoc ), pFtn );
854 :
855 77 : SWAP_IF_SWAPPED( pFrm )
856 :
857 : KSHORT nReal;
858 : {
859 77 : KSHORT nOldReal = pCurr->GetRealHeight();
860 77 : KSHORT nOldAscent = pCurr->GetAscent();
861 77 : KSHORT nOldHeight = pCurr->Height();
862 77 : ((SwTxtFormatter*)this)->CalcRealHeight();
863 77 : nReal = pCurr->GetRealHeight();
864 77 : if( nReal < nOldReal )
865 0 : nReal = nOldReal;
866 77 : pCurr->SetRealHeight( nOldReal );
867 77 : pCurr->Height( nOldHeight );
868 77 : pCurr->SetAscent( nOldAscent );
869 : }
870 :
871 77 : SwTwips nLower = Y() + nReal;
872 :
873 77 : const bool bVertical = pFrm->IsVertical();
874 77 : if( bVertical )
875 0 : nLower = pFrm->SwitchHorizontalToVertical( nLower );
876 :
877 77 : nLower = lcl_GetFtnLower( pFrm, nLower );
878 :
879 : //6995: Wir frischen nur auf. Das Connect tut fuer diesen Fall nix
880 : //Brauchbares, sondern wuerde stattdessen fuer diesen Fall meist die
881 : //Ftn wegwerfen und neu erzeugen.
882 :
883 77 : if( !rInf.IsQuick() )
884 77 : pFrm->ConnectFtn( pFtn, nLower );
885 :
886 77 : SwTxtFrm *pScrFrm = pFrm->FindFtnRef( pFtn );
887 77 : SwFtnBossFrm *pBoss = pFrm->FindFtnBossFrm( !rFtn.IsEndNote() );
888 77 : SwFtnFrm *pFtnFrm = NULL;
889 77 : if( pScrFrm )
890 77 : pFtnFrm = pBoss->FindFtn( pScrFrm, pFtn );
891 :
892 : // Wir erkundigen uns, ob durch unser Append irgendeine
893 : // Fussnote noch auf der Seite/Spalte steht. Wenn nicht verschwindet
894 : // auch unsere Zeile. Dies fuehrt zu folgendem erwuenschten
895 : // Verhalten: Ftn1 pass noch auf die Seite/Spalte, Ftn2 nicht mehr.
896 : // Also bleibt die Ftn2-Referenz auf der Seite/Spalte stehen. Die
897 : // Fussnote selbst folgt aber erst auf der naechsten Seite/Spalte.
898 : // Ausnahme: Wenn keine weitere Zeile auf diese Seite/Spalte passt,
899 : // so sollte die Ftn2-Referenz auch auf die naechste wandern.
900 77 : if( !rFtn.IsEndNote() )
901 : {
902 58 : SwSectionFrm *pSct = pBoss->FindSctFrm();
903 58 : bool bAtSctEnd = pSct && pSct->IsFtnAtEnd();
904 58 : if( FTNPOS_CHAPTER != pDoc->GetFtnInfo().ePos || bAtSctEnd )
905 : {
906 57 : SwFrm* pFtnCont = pBoss->FindFtnCont();
907 : // Wenn der Boss in einem Bereich liegt, kann es sich nur um eine
908 : // Spalte dieses Bereichs handeln. Wenn dies nicht die erste Spalte
909 : // ist, duerfen wir ausweichen
910 114 : if( !pFrm->IsInTab() && ( GetLineNr() > 1 || pFrm->GetPrev() ||
911 42 : ( !bAtSctEnd && pFrm->GetIndPrev() ) ||
912 0 : ( pSct && pBoss->GetPrev() ) ) )
913 : {
914 36 : if( !pFtnCont )
915 : {
916 0 : rInf.SetStop( sal_True );
917 0 : UNDO_SWAP( pFrm )
918 0 : return 0;
919 : }
920 : else
921 : {
922 : // Es darf keine Fussnotencontainer in spaltigen Bereichen und
923 : // gleichzeitig auf der Seite/Seitenspalte geben
924 36 : if( pSct && !bAtSctEnd ) // liegt unser Container in einem (spaltigen) Bereich?
925 : {
926 0 : SwFtnBossFrm* pTmp = pBoss->FindSctFrm()->FindFtnBossFrm( sal_True );
927 0 : SwFtnContFrm* pFtnC = pTmp->FindFtnCont();
928 0 : if( pFtnC )
929 : {
930 0 : SwFtnFrm* pTmpFrm = (SwFtnFrm*)pFtnC->Lower();
931 0 : if( pTmpFrm && *pTmpFrm < pFtn )
932 : {
933 0 : rInf.SetStop( sal_True );
934 0 : UNDO_SWAP( pFrm )
935 0 : return 0;
936 : }
937 : }
938 : }
939 : // Ist dies die letzte passende Zeile?
940 36 : SwTwips nTmpBot = Y() + nReal * 2;
941 :
942 36 : if( bVertical )
943 0 : nTmpBot = pFrm->SwitchHorizontalToVertical( nTmpBot );
944 :
945 36 : SWRECTFN( pFtnCont )
946 :
947 : const long nDiff = (*fnRect->fnYDiff)(
948 72 : (pFtnCont->Frm().*fnRect->fnGetTop)(),
949 108 : nTmpBot );
950 :
951 36 : if( pScrFrm && nDiff < 0 )
952 : {
953 0 : if( pFtnFrm )
954 : {
955 0 : SwFtnBossFrm *pFtnBoss = pFtnFrm->FindFtnBossFrm();
956 0 : if( pFtnBoss != pBoss )
957 : {
958 : // Wir sind in der letzte Zeile und die Fussnote
959 : // ist auf eine andere Seite gewandert, dann wollen
960 : // wir mit ...
961 0 : rInf.SetStop( sal_True );
962 0 : UNDO_SWAP( pFrm )
963 0 : return 0;
964 : }
965 : }
966 : }
967 : }
968 : }
969 : }
970 : }
971 : // Endlich: FtnPortion anlegen und raus hier...
972 : SwFtnPortion *pRet = new SwFtnPortion( rFtn.GetViewNumStr( *pDoc ),
973 77 : pFtn, nReal );
974 77 : rInf.SetFtnInside( true );
975 :
976 77 : UNDO_SWAP( pFrm )
977 :
978 77 : return pRet;
979 : }
980 :
981 : /*************************************************************************
982 : * SwTxtFormatter::NewFtnNumPortion()
983 : *************************************************************************/
984 :
985 : // Die Portion fuer die Ftn-Nummerierung im Ftn-Bereich
986 :
987 72 : SwNumberPortion *SwTxtFormatter::NewFtnNumPortion( SwTxtFormatInfo &rInf ) const
988 : {
989 : OSL_ENSURE( pFrm->IsInFtn() && !pFrm->GetIndPrev() && !rInf.IsFtnDone(),
990 : "This is the wrong place for a ftnnumber" );
991 144 : if( rInf.GetTxtStart() != nStart ||
992 72 : rInf.GetTxtStart() != rInf.GetIdx() )
993 0 : return 0;
994 :
995 72 : const SwFtnFrm* pFtnFrm = pFrm->FindFtnFrm();
996 72 : const SwTxtFtn* pFtn = pFtnFrm->GetAttr();
997 :
998 : // Aha, wir sind also im Fussnotenbereich
999 72 : SwFmtFtn& rFtn = (SwFmtFtn&)pFtn->GetFtn();
1000 :
1001 72 : SwDoc *pDoc = pFrm->GetNode()->GetDoc();
1002 72 : XubString aFtnTxt( rFtn.GetViewNumStr( *pDoc, sal_True ));
1003 :
1004 : const SwEndNoteInfo* pInfo;
1005 72 : if( rFtn.IsEndNote() )
1006 8 : pInfo = &pDoc->GetEndNoteInfo();
1007 : else
1008 64 : pInfo = &pDoc->GetFtnInfo();
1009 72 : const SwAttrSet& rSet = pInfo->GetCharFmt(*pDoc)->GetAttrSet();
1010 :
1011 72 : const SwAttrSet* pParSet = &rInf.GetCharAttr();
1012 72 : const IDocumentSettingAccess* pIDSA = pFrm->GetTxtNode()->getIDocumentSettingAccess();
1013 72 : SwFont *pNumFnt = new SwFont( pParSet, pIDSA );
1014 :
1015 : // #i37142#
1016 : // Underline style of paragraph font should not be considered
1017 : // Overline style of paragraph font should not be considered
1018 : // Weight style of paragraph font should not be considered
1019 : // Posture style of paragraph font should not be considered
1020 : // See also #i18463# and SwTxtFormatter::NewNumberPortion()
1021 72 : pNumFnt->SetUnderline( UNDERLINE_NONE );
1022 72 : pNumFnt->SetOverline( UNDERLINE_NONE );
1023 72 : pNumFnt->SetItalic( ITALIC_NONE, SW_LATIN );
1024 72 : pNumFnt->SetItalic( ITALIC_NONE, SW_CJK );
1025 72 : pNumFnt->SetItalic( ITALIC_NONE, SW_CTL );
1026 72 : pNumFnt->SetWeight( WEIGHT_NORMAL, SW_LATIN );
1027 72 : pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CJK );
1028 72 : pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CTL );
1029 :
1030 72 : pNumFnt->SetDiffFnt(&rSet, pIDSA );
1031 72 : pNumFnt->SetVertical( pNumFnt->GetOrientation(), pFrm->IsVertical() );
1032 :
1033 72 : SwFtnNumPortion* pNewPor = new SwFtnNumPortion( aFtnTxt, pNumFnt );
1034 72 : pNewPor->SetLeft( !pFrm->IsRightToLeft() );
1035 72 : return pNewPor;
1036 : }
1037 :
1038 : /*************************************************************************
1039 : * SwTxtFormatter::NewErgoSumPortion()
1040 : *************************************************************************/
1041 :
1042 0 : XubString lcl_GetPageNumber( const SwPageFrm* pPage )
1043 : {
1044 : OSL_ENSURE( pPage, "GetPageNumber: Homeless TxtFrm" );
1045 0 : MSHORT nVirtNum = pPage->GetVirtPageNum();
1046 0 : const SvxNumberType& rNum = pPage->GetPageDesc()->GetNumType();
1047 0 : return rNum.GetNumStr( nVirtNum );
1048 : }
1049 :
1050 72 : SwErgoSumPortion *SwTxtFormatter::NewErgoSumPortion( SwTxtFormatInfo &rInf ) const
1051 : {
1052 : // Wir koennen nicht davon ausgehen, dass wir ein Follow sind
1053 : // 7983: GetIdx() nicht nStart
1054 288 : if( !pFrm->IsInFtn() || pFrm->GetPrev() ||
1055 288 : rInf.IsErgoDone() || rInf.GetIdx() != pFrm->GetOfst() ||
1056 72 : pFrm->ImplFindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
1057 8 : return 0;
1058 :
1059 : // Aha, wir sind also im Fussnotenbereich
1060 64 : const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo();
1061 64 : SwTxtFrm *pQuoFrm = pFrm->FindQuoVadisFrm();
1062 64 : if( !pQuoFrm )
1063 64 : return 0;
1064 0 : const SwPageFrm* pPage = pFrm->FindPageFrm();
1065 0 : const SwPageFrm* pQuoPage = pQuoFrm->FindPageFrm();
1066 0 : if( pPage == pQuoFrm->FindPageFrm() )
1067 0 : return 0; // Wenn der QuoVadis auf der selben (spaltigen) Seite steht
1068 0 : const XubString aPage = lcl_GetPageNumber( pPage );
1069 0 : SwParaPortion *pPara = pQuoFrm->GetPara();
1070 0 : if( pPara )
1071 0 : pPara->SetErgoSumNum( aPage );
1072 0 : if( !rFtnInfo.aErgoSum.Len() )
1073 0 : return 0;
1074 : SwErgoSumPortion *pErgo = new SwErgoSumPortion( rFtnInfo.aErgoSum,
1075 0 : lcl_GetPageNumber( pQuoPage ) );
1076 0 : return pErgo;
1077 : }
1078 :
1079 : /*************************************************************************
1080 : * SwTxtFormatter::FormatQuoVadis()
1081 : *************************************************************************/
1082 :
1083 115 : xub_StrLen SwTxtFormatter::FormatQuoVadis( const xub_StrLen nOffset )
1084 : {
1085 : OSL_ENSURE( ! pFrm->IsVertical() || ! pFrm->IsSwapped(),
1086 : "SwTxtFormatter::FormatQuoVadis with swapped frame" );
1087 :
1088 115 : if( !pFrm->IsInFtn() || pFrm->ImplFindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
1089 8 : return nOffset;
1090 :
1091 107 : const SwFrm* pErgoFrm = pFrm->FindFtnFrm()->GetFollow();
1092 107 : if( !pErgoFrm && pFrm->HasFollow() )
1093 0 : pErgoFrm = pFrm->GetFollow();
1094 107 : if( !pErgoFrm )
1095 107 : return nOffset;
1096 :
1097 0 : if( pErgoFrm == pFrm->GetNext() )
1098 : {
1099 0 : SwFrm *pCol = pFrm->FindColFrm();
1100 0 : while( pCol && !pCol->GetNext() )
1101 0 : pCol = pCol->GetUpper()->FindColFrm();
1102 0 : if( pCol )
1103 0 : return nOffset;
1104 : }
1105 : else
1106 : {
1107 0 : const SwPageFrm* pPage = pFrm->FindPageFrm();
1108 0 : const SwPageFrm* pErgoPage = pErgoFrm->FindPageFrm();
1109 0 : if( pPage == pErgoPage )
1110 0 : return nOffset; // Wenn der ErgoSum auf der selben Seite steht
1111 : }
1112 :
1113 0 : SwTxtFormatInfo &rInf = GetInfo();
1114 0 : const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo();
1115 0 : if( !rFtnInfo.aQuoVadis.Len() )
1116 0 : return nOffset;
1117 :
1118 : // Ein Wort zu QuoVadis/ErgoSum:
1119 : // Fuer diese Texte wird der am Absatz eingestellte Font verwendet.
1120 : // Wir initialisieren uns also:
1121 : // ResetFont();
1122 0 : FeedInf( rInf );
1123 0 : SeekStartAndChg( rInf, sal_True );
1124 0 : if( GetRedln() && pCurr->HasRedline() )
1125 0 : GetRedln()->Seek( *pFnt, nOffset, 0 );
1126 :
1127 : // Ein fieser Sonderfall: Flyfrms reichen in die Zeile und stehen
1128 : // natuerlich da, wo wir unseren Quovadis Text reinsetzen wollen.
1129 : // Erst mal sehen, ob es so schlimm ist:
1130 0 : SwLinePortion *pPor = pCurr->GetFirstPortion();
1131 0 : KSHORT nLastLeft = 0;
1132 0 : while( pPor )
1133 : {
1134 0 : if ( pPor->IsFlyPortion() )
1135 0 : nLastLeft = ( (SwFlyPortion*) pPor)->Fix() +
1136 0 : ( (SwFlyPortion*) pPor)->Width();
1137 0 : pPor = pPor->GetPortion();
1138 : }
1139 : // Das alte Spiel: wir wollen, dass die Zeile an einer bestimmten
1140 : // Stelle umbricht, also beeinflussen wir die Width.
1141 : // nLastLeft ist jetzt quasi der rechte Rand.
1142 0 : const KSHORT nOldRealWidth = rInf.RealWidth();
1143 0 : rInf.RealWidth( nOldRealWidth - nLastLeft );
1144 :
1145 0 : XubString aErgo = lcl_GetPageNumber( pErgoFrm->FindPageFrm() );
1146 0 : SwQuoVadisPortion *pQuo = new SwQuoVadisPortion(rFtnInfo.aQuoVadis, aErgo );
1147 0 : pQuo->SetAscent( rInf.GetAscent() );
1148 0 : pQuo->Height( rInf.GetTxtHeight() );
1149 0 : pQuo->Format( rInf );
1150 0 : sal_uInt16 nQuoWidth = pQuo->Width();
1151 0 : SwLinePortion* pCurrPor = pQuo;
1152 :
1153 0 : while ( rInf.GetRest() )
1154 : {
1155 0 : SwLinePortion* pFollow = rInf.GetRest();
1156 0 : rInf.SetRest( 0 );
1157 0 : pCurrPor->Move( rInf );
1158 :
1159 : OSL_ENSURE( pFollow->IsQuoVadisPortion(),
1160 : "Quo Vadis, rest of QuoVadisPortion" );
1161 :
1162 : // format the rest and append it to the other QuoVadis parts
1163 0 : pFollow->Format( rInf );
1164 0 : nQuoWidth = nQuoWidth + pFollow->Width();
1165 :
1166 0 : pCurrPor->Append( pFollow );
1167 0 : pCurrPor = pFollow;
1168 : }
1169 :
1170 0 : nLastLeft = nOldRealWidth - nQuoWidth;
1171 0 : Right( Right() - nQuoWidth );
1172 :
1173 0 : SWAP_IF_NOT_SWAPPED( pFrm )
1174 :
1175 0 : const xub_StrLen nRet = FormatLine( nStart );
1176 :
1177 0 : UNDO_SWAP( pFrm )
1178 :
1179 0 : Right( rInf.Left() + nOldRealWidth - 1 );
1180 :
1181 0 : nLastLeft = nOldRealWidth - pCurr->Width();
1182 0 : FeedInf( rInf );
1183 :
1184 : // Es kann durchaus sein, dass am Ende eine Marginportion steht,
1185 : // die beim erneuten Aufspannen nur Aerger bereiten wuerde.
1186 0 : pPor = pCurr->FindLastPortion();
1187 0 : SwGluePortion *pGlue = pPor->IsMarginPortion() ?
1188 0 : (SwMarginPortion*) pPor : 0;
1189 0 : if( pGlue )
1190 : {
1191 0 : pGlue->Height( 0 );
1192 0 : pGlue->Width( 0 );
1193 0 : pGlue->SetLen( 0 );
1194 0 : pGlue->SetAscent( 0 );
1195 0 : pGlue->SetPortion( NULL );
1196 0 : pGlue->SetFixWidth(0);
1197 : }
1198 :
1199 : // Luxus: Wir sorgen durch das Aufspannen von Glues dafuer,
1200 : // dass der QuoVadis-Text rechts erscheint:
1201 0 : nLastLeft = nLastLeft - nQuoWidth;
1202 0 : if( nLastLeft )
1203 : {
1204 0 : if( nLastLeft > pQuo->GetAscent() ) // Mindestabstand
1205 : {
1206 0 : switch( GetAdjust() )
1207 : {
1208 : case SVX_ADJUST_BLOCK:
1209 : {
1210 0 : if( !pCurr->GetLen() ||
1211 0 : CH_BREAK != GetInfo().GetChar(nStart+pCurr->GetLen()-1))
1212 0 : nLastLeft = pQuo->GetAscent();
1213 0 : nQuoWidth = nQuoWidth + nLastLeft;
1214 0 : break;
1215 : }
1216 : case SVX_ADJUST_RIGHT:
1217 : {
1218 0 : nLastLeft = pQuo->GetAscent();
1219 0 : nQuoWidth = nQuoWidth + nLastLeft;
1220 0 : break;
1221 : }
1222 : case SVX_ADJUST_CENTER:
1223 : {
1224 0 : nQuoWidth = nQuoWidth + pQuo->GetAscent();
1225 0 : long nDiff = nLastLeft - nQuoWidth;
1226 0 : if( nDiff < 0 )
1227 : {
1228 0 : nLastLeft = pQuo->GetAscent();
1229 0 : nQuoWidth = (sal_uInt16)(-nDiff + nLastLeft);
1230 : }
1231 : else
1232 : {
1233 0 : nQuoWidth = 0;
1234 0 : nLastLeft = sal_uInt16(( pQuo->GetAscent() + nDiff ) / 2);
1235 : }
1236 0 : break;
1237 : }
1238 : default:
1239 0 : nQuoWidth = nQuoWidth + nLastLeft;
1240 : }
1241 : }
1242 : else
1243 0 : nQuoWidth = nQuoWidth + nLastLeft;
1244 0 : if( nLastLeft )
1245 : {
1246 0 : pGlue = new SwGluePortion(0);
1247 0 : pGlue->Width( nLastLeft );
1248 0 : pPor->Append( pGlue );
1249 0 : pPor = pPor->GetPortion();
1250 : }
1251 : }
1252 :
1253 : // Jetzt aber: die QuoVadis-Portion wird angedockt:
1254 0 : pCurrPor = pQuo;
1255 0 : while ( pCurrPor )
1256 : {
1257 : // pPor->Append deletes the pPortoin pointer of pPor. Therefore
1258 : // we have to keep a pointer to the next portion
1259 0 : pQuo = (SwQuoVadisPortion*)pCurrPor->GetPortion();
1260 0 : pPor->Append( pCurrPor );
1261 0 : pPor = pPor->GetPortion();
1262 0 : pCurrPor = pQuo;
1263 : }
1264 :
1265 0 : pCurr->Width( pCurr->Width() + KSHORT( nQuoWidth ) );
1266 :
1267 : // Und noch einmal adjustieren wegen des Adjustment und nicht zu Letzt
1268 : // wegen folgendem Sonderfall: In der Zeile hat der DummUser durchgaengig
1269 : // einen kleineren Font eingestellt als der vom QuoVadis-Text ...
1270 0 : CalcAdjustLine( pCurr );
1271 :
1272 : // Uff...
1273 0 : return nRet;
1274 : }
1275 :
1276 :
1277 : /*************************************************************************
1278 : * SwTxtFormatter::MakeDummyLine()
1279 : *************************************************************************/
1280 :
1281 : // MakeDummyLine() erzeugt eine Line, die bis zum unteren Seitenrand
1282 : // reicht. DummyLines bzw. DummyPortions sorgen dafuer, dass Oszillationen
1283 : // zum stehen kommen, weil Rueckflussmoeglichkeiten genommen werden.
1284 : // Sie werden bei absatzgebundenen Frames in Fussnoten und bei Ftn-
1285 : // Oszillationen verwendet.
1286 :
1287 0 : void SwTxtFormatter::MakeDummyLine()
1288 : {
1289 0 : KSHORT nRstHeight = GetFrmRstHeight();
1290 0 : if( pCurr && nRstHeight > pCurr->Height() )
1291 : {
1292 0 : SwLineLayout *pLay = new SwLineLayout;
1293 0 : nRstHeight = nRstHeight - pCurr->Height();
1294 0 : pLay->Height( nRstHeight );
1295 0 : pLay->SetAscent( nRstHeight );
1296 0 : Insert( pLay );
1297 0 : Next();
1298 : }
1299 0 : }
1300 :
1301 : /*************************************************************************
1302 : * class SwFtnSave
1303 : *************************************************************************/
1304 : class SwFtnSave
1305 : {
1306 : SwTxtSizeInfo *pInf;
1307 : SwFont *pFnt;
1308 : SwFont *pOld;
1309 : public:
1310 : SwFtnSave( const SwTxtSizeInfo &rInf,
1311 : const SwTxtFtn *pTxtFtn,
1312 : const bool bApplyGivenScriptType,
1313 : const sal_uInt8 nGivenScriptType );
1314 : ~SwFtnSave();
1315 : };
1316 :
1317 : /*************************************************************************
1318 : * SwFtnSave::SwFtnSave()
1319 : *************************************************************************/
1320 :
1321 156 : SwFtnSave::SwFtnSave( const SwTxtSizeInfo &rInf,
1322 : const SwTxtFtn* pTxtFtn,
1323 : const bool bApplyGivenScriptType,
1324 : const sal_uInt8 nGivenScriptType )
1325 : : pInf( &((SwTxtSizeInfo&)rInf) )
1326 : , pFnt( 0 )
1327 156 : , pOld( 0 )
1328 : {
1329 156 : if( pTxtFtn && rInf.GetTxtFrm() )
1330 : {
1331 156 : pFnt = ((SwTxtSizeInfo&)rInf).GetFont();
1332 156 : pOld = new SwFont( *pFnt );
1333 156 : pOld->GetTox() = pFnt->GetTox();
1334 156 : pFnt->GetTox() = 0;
1335 156 : SwFmtFtn& rFtn = (SwFmtFtn&)pTxtFtn->GetFtn();
1336 156 : const SwDoc *pDoc = rInf.GetTxtFrm()->GetNode()->GetDoc();
1337 :
1338 : // #i98418#
1339 156 : if ( bApplyGivenScriptType )
1340 : {
1341 156 : pFnt->SetActual( nGivenScriptType );
1342 : }
1343 : else
1344 : {
1345 : // examine text and set script
1346 0 : OUString aTmpStr( rFtn.GetViewNumStr( *pDoc ) );
1347 0 : pFnt->SetActual( SwScriptInfo::WhichFont( 0, &aTmpStr, 0 ) );
1348 : }
1349 :
1350 : const SwEndNoteInfo* pInfo;
1351 156 : if( rFtn.IsEndNote() )
1352 34 : pInfo = &pDoc->GetEndNoteInfo();
1353 : else
1354 122 : pInfo = &pDoc->GetFtnInfo();
1355 156 : const SwAttrSet& rSet = pInfo->GetAnchorCharFmt((SwDoc&)*pDoc)->GetAttrSet();
1356 156 : pFnt->SetDiffFnt( &rSet, rInf.GetTxtFrm()->GetNode()->getIDocumentSettingAccess() );
1357 :
1358 : // we reduce footnote size, if we are inside a double line portion
1359 156 : if ( ! pOld->GetEscapement() && 50 == pOld->GetPropr() )
1360 : {
1361 0 : Size aSize = pFnt->GetSize( pFnt->GetActual() );
1362 0 : pFnt->SetSize( Size( (long)aSize.Width() / 2,
1363 0 : (long)aSize.Height() / 2 ),
1364 0 : pFnt->GetActual() );
1365 : }
1366 :
1367 : // set the correct rotation at the footnote font
1368 : const SfxPoolItem* pItem;
1369 156 : if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_ROTATE,
1370 156 : sal_True, &pItem ))
1371 0 : pFnt->SetVertical( ((SvxCharRotateItem*)pItem)->GetValue(),
1372 0 : rInf.GetTxtFrm()->IsVertical() );
1373 :
1374 156 : pFnt->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
1375 :
1376 156 : if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_BACKGROUND,
1377 156 : sal_True, &pItem ))
1378 0 : pFnt->SetBackColor( new Color( ((SvxBrushItem*)pItem)->GetColor() ) );
1379 : }
1380 : else
1381 0 : pFnt = NULL;
1382 156 : }
1383 :
1384 : /*************************************************************************
1385 : * SwFtnSave::~SwFtnSave()
1386 : *************************************************************************/
1387 :
1388 156 : SwFtnSave::~SwFtnSave()
1389 : {
1390 156 : if( pFnt )
1391 : {
1392 : // SwFont zurueckstellen
1393 156 : *pFnt = *pOld;
1394 156 : pFnt->GetTox() = pOld->GetTox();
1395 156 : pFnt->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
1396 156 : delete pOld;
1397 : }
1398 156 : }
1399 :
1400 : /*************************************************************************
1401 : * SwFtnPortion::SwFtnPortion()
1402 : *************************************************************************/
1403 :
1404 77 : SwFtnPortion::SwFtnPortion( const XubString &rExpand,
1405 : SwTxtFtn *pFootn, KSHORT nReal )
1406 : : SwFldPortion( rExpand, 0 )
1407 : , pFtn(pFootn)
1408 : , nOrigHeight( nReal )
1409 : // #i98418#
1410 : , mbPreferredScriptTypeSet( false )
1411 77 : , mnPreferredScriptType( SW_LATIN )
1412 : {
1413 77 : SetLen(1);
1414 77 : SetWhichPor( POR_FTN );
1415 77 : }
1416 :
1417 : /*************************************************************************
1418 : * SwFtnPortion::GetExpTxt()
1419 : *************************************************************************/
1420 :
1421 323 : sal_Bool SwFtnPortion::GetExpTxt( const SwTxtSizeInfo &, OUString &rTxt ) const
1422 : {
1423 323 : rTxt = aExpand;
1424 323 : return sal_True;
1425 : }
1426 :
1427 : /*************************************************************************
1428 : * virtual SwFtnPortion::Format()
1429 : *************************************************************************/
1430 :
1431 77 : sal_Bool SwFtnPortion::Format( SwTxtFormatInfo &rInf )
1432 : {
1433 : // #i98418#
1434 : // SwFtnSave aFtnSave( rInf, pFtn );
1435 77 : SwFtnSave aFtnSave( rInf, pFtn, mbPreferredScriptTypeSet, mnPreferredScriptType );
1436 : // the idx is manipulated in SwExpandPortion::Format
1437 : // this flag indicates, that a footnote is allowed to trigger
1438 : // an underflow during SwTxtGuess::Guess
1439 77 : rInf.SetFakeLineStart( rInf.GetIdx() > rInf.GetLineStart() );
1440 77 : sal_Bool bFull = SwFldPortion::Format( rInf );
1441 77 : rInf.SetFakeLineStart( sal_False );
1442 77 : SetAscent( rInf.GetAscent() );
1443 77 : Height( rInf.GetTxtHeight() );
1444 77 : rInf.SetFtnDone( !bFull );
1445 77 : if( !bFull )
1446 77 : rInf.SetParaFtn();
1447 77 : return bFull;
1448 : }
1449 :
1450 : /*************************************************************************
1451 : * virtual SwFtnPortion::Paint()
1452 : *************************************************************************/
1453 :
1454 79 : void SwFtnPortion::Paint( const SwTxtPaintInfo &rInf ) const
1455 : {
1456 : // #i98418#
1457 : // SwFtnSave aFtnSave( rInf, pFtn );
1458 79 : SwFtnSave aFtnSave( rInf, pFtn, mbPreferredScriptTypeSet, mnPreferredScriptType );
1459 79 : rInf.DrawViewOpt( *this, POR_FTN );
1460 79 : SwExpandPortion::Paint( rInf );
1461 79 : }
1462 :
1463 : /*************************************************************************
1464 : * virtual SwFtnPortion::GetTxtSize()
1465 : *************************************************************************/
1466 :
1467 0 : SwPosSize SwFtnPortion::GetTxtSize( const SwTxtSizeInfo &rInfo ) const
1468 : {
1469 : // #i98418#
1470 : // SwFtnSave aFtnSave( rInfo, pFtn );
1471 0 : SwFtnSave aFtnSave( rInfo, pFtn, mbPreferredScriptTypeSet, mnPreferredScriptType );
1472 0 : return SwExpandPortion::GetTxtSize( rInfo );
1473 : }
1474 :
1475 : // #i98418#
1476 77 : void SwFtnPortion::SetPreferredScriptType( sal_uInt8 nPreferredScriptType )
1477 : {
1478 77 : mbPreferredScriptTypeSet = true;
1479 77 : mnPreferredScriptType = nPreferredScriptType;
1480 77 : }
1481 :
1482 : /*************************************************************************
1483 : * class SwQuoVadisPortion
1484 : *************************************************************************/
1485 :
1486 0 : SwFldPortion *SwQuoVadisPortion::Clone( const OUString &rExpand ) const
1487 0 : { return new SwQuoVadisPortion( rExpand, aErgo ); }
1488 :
1489 0 : SwQuoVadisPortion::SwQuoVadisPortion( const XubString &rExp, const XubString& rStr )
1490 0 : : SwFldPortion( rExp ), aErgo(rStr)
1491 : {
1492 0 : SetLen(0);
1493 0 : SetWhichPor( POR_QUOVADIS );
1494 0 : }
1495 :
1496 : /*************************************************************************
1497 : * virtual SwQuoVadisPortion::Format()
1498 : *************************************************************************/
1499 :
1500 0 : sal_Bool SwQuoVadisPortion::Format( SwTxtFormatInfo &rInf )
1501 : {
1502 : // erster Versuch, vielleicht passt der Text
1503 0 : CheckScript( rInf );
1504 0 : sal_Bool bFull = SwFldPortion::Format( rInf );
1505 0 : SetLen( 0 );
1506 :
1507 0 : if( bFull )
1508 : {
1509 : // zweiter Versuch, wir kuerzen den String:
1510 0 : aExpand = OUString("...");
1511 0 : bFull = SwFldPortion::Format( rInf );
1512 0 : SetLen( 0 );
1513 0 : if( bFull )
1514 : // dritter Versuch, es langt: jetzt wird gestaucht:
1515 0 : Width( sal_uInt16(rInf.Width() - rInf.X()) );
1516 :
1517 : // 8317: keine mehrzeiligen Felder bei QuoVadis und ErgoSum
1518 0 : if( rInf.GetRest() )
1519 : {
1520 0 : delete rInf.GetRest();
1521 0 : rInf.SetRest( 0 );
1522 : }
1523 : }
1524 0 : return bFull;
1525 : }
1526 :
1527 : /*************************************************************************
1528 : * virtual SwQuoVadisPortion::GetExpTxt()
1529 : *************************************************************************/
1530 :
1531 0 : sal_Bool SwQuoVadisPortion::GetExpTxt( const SwTxtSizeInfo &, OUString &rTxt ) const
1532 : {
1533 0 : rTxt = aExpand;
1534 : // if this QuoVadisPortion has a follow, the follow is responsible for
1535 : // the ergo text.
1536 0 : if ( ! HasFollow() )
1537 0 : rTxt += aErgo;
1538 0 : return sal_True;
1539 : }
1540 :
1541 : /*************************************************************************
1542 : * virtual SwQuoVadisPortion::HandlePortion()
1543 : *************************************************************************/
1544 :
1545 0 : void SwQuoVadisPortion::HandlePortion( SwPortionHandler& rPH ) const
1546 : {
1547 0 : String aString( aExpand );
1548 0 : aString += aErgo;
1549 0 : rPH.Special( GetLen(), aString, GetWhichPor() );
1550 0 : }
1551 :
1552 : /*************************************************************************
1553 : * virtual SwQuoVadisPortion::Paint()
1554 : *************************************************************************/
1555 :
1556 0 : void SwQuoVadisPortion::Paint( const SwTxtPaintInfo &rInf ) const
1557 : {
1558 : // Wir wollen _immer_ per DrawStretchText ausgeben,
1559 : // weil nErgo schnell mal wechseln kann.
1560 0 : if( PrtWidth() )
1561 : {
1562 0 : rInf.DrawViewOpt( *this, POR_QUOVADIS );
1563 0 : SwTxtSlot aDiffTxt( &rInf, this, true, false );
1564 0 : SwFontSave aSave( rInf, pFnt );
1565 0 : rInf.DrawText( *this, rInf.GetLen(), sal_True );
1566 : }
1567 0 : }
1568 :
1569 : /*************************************************************************
1570 : * class SwErgoSumPortion
1571 : *************************************************************************/
1572 :
1573 0 : SwFldPortion *SwErgoSumPortion::Clone( const OUString &rExpand ) const
1574 : {
1575 0 : return new SwErgoSumPortion( rExpand, OUString() );
1576 : }
1577 :
1578 0 : SwErgoSumPortion::SwErgoSumPortion( const XubString &rExp, const XubString& rStr )
1579 0 : : SwFldPortion( rExp )
1580 : {
1581 0 : SetLen(0);
1582 0 : aExpand += rStr;
1583 :
1584 : // 7773: sinnvolle Massnahme: ein Blank Abstand zum Text
1585 0 : aExpand += OUString(' ');
1586 0 : SetWhichPor( POR_ERGOSUM );
1587 0 : }
1588 :
1589 0 : xub_StrLen SwErgoSumPortion::GetCrsrOfst( const KSHORT ) const
1590 : {
1591 0 : return 0;
1592 : }
1593 :
1594 : /*************************************************************************
1595 : * virtual SwErgoSumPortion::Format()
1596 : *************************************************************************/
1597 :
1598 0 : sal_Bool SwErgoSumPortion::Format( SwTxtFormatInfo &rInf )
1599 : {
1600 0 : sal_Bool bFull = SwFldPortion::Format( rInf );
1601 0 : SetLen( 0 );
1602 0 : rInf.SetErgoDone( sal_True );
1603 :
1604 : // 8317: keine mehrzeiligen Felder bei QuoVadis und ErgoSum
1605 0 : if( bFull && rInf.GetRest() )
1606 : {
1607 0 : delete rInf.GetRest();
1608 0 : rInf.SetRest( 0 );
1609 : }
1610 :
1611 : // We return false in order to get some text into the current line,
1612 : // even if it's full (better than looping)
1613 0 : return sal_False;
1614 : }
1615 :
1616 :
1617 : /*************************************************************************
1618 : * SwParaPortion::SetErgoSumNum()
1619 : *************************************************************************/
1620 :
1621 0 : void SwParaPortion::SetErgoSumNum( const XubString& rErgo )
1622 : {
1623 0 : SwLineLayout *pLay = this;
1624 0 : while( pLay->GetNext() )
1625 : {
1626 0 : pLay = pLay->GetNext();
1627 : }
1628 0 : SwLinePortion *pPor = pLay;
1629 0 : SwQuoVadisPortion *pQuo = 0;
1630 0 : while( pPor && !pQuo )
1631 : {
1632 0 : if ( pPor->IsQuoVadisPortion() )
1633 0 : pQuo = (SwQuoVadisPortion*)pPor;
1634 0 : pPor = pPor->GetPortion();
1635 : }
1636 0 : if( pQuo )
1637 0 : pQuo->SetNumber( rErgo );
1638 0 : }
1639 :
1640 : /*************************************************************************
1641 : * SwParaPortion::UpdateQuoVadis()
1642 : *
1643 : * Wird im SwTxtFrm::Prepare() gerufen
1644 : *************************************************************************/
1645 :
1646 27 : sal_Bool SwParaPortion::UpdateQuoVadis( const XubString &rQuo )
1647 : {
1648 27 : SwLineLayout *pLay = this;
1649 54 : while( pLay->GetNext() )
1650 : {
1651 0 : pLay = pLay->GetNext();
1652 : }
1653 27 : SwLinePortion *pPor = pLay;
1654 27 : SwQuoVadisPortion *pQuo = 0;
1655 112 : while( pPor && !pQuo )
1656 : {
1657 58 : if ( pPor->IsQuoVadisPortion() )
1658 0 : pQuo = (SwQuoVadisPortion*)pPor;
1659 58 : pPor = pPor->GetPortion();
1660 : }
1661 :
1662 27 : if( !pQuo )
1663 27 : return sal_False;
1664 :
1665 0 : return pQuo->GetQuoTxt() == rQuo;
1666 99 : }
1667 :
1668 :
1669 :
1670 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|