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