1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 #include <switerator.hxx>
28 #include <calbck.hxx>
29 #include <node.hxx>
30 #include <ndindex.hxx>
31 #include <swtable.hxx>
32 #include <ftnfrm.hxx>
33 #include <sectfrm.hxx>
34 #include "frmfmt.hxx"
35 #include "cntfrm.hxx"
36 #include "tabfrm.hxx"
37 #include "frmtool.hxx"
38 #include "section.hxx"
39 #include "node2lay.hxx"
40
41 /* -----------------25.02.99 10:31-------------------
42 * Die SwNode2LayImpl-Klasse erledigt die eigentliche Arbeit,
43 * die SwNode2Layout-Klasse ist nur die der Oefffentlichkeit bekannte Schnittstelle
44 * --------------------------------------------------*/
45 class SwNode2LayImpl
46 {
47 SwIterator<SwFrm,SwModify>* pIter;
48 SwModify* pMod;
49 SvPtrarr *pUpperFrms;// Zum Einsammeln der Upper
50 sal_uLong nIndex; // Der Index des einzufuegenden Nodes
51 sal_Bool bMaster : 1; // sal_True => nur Master , sal_False => nur Frames ohne Follow
52 sal_Bool bInit : 1; // Ist am SwClient bereits ein First()-Aufruf erfolgt?
53 public:
54 SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, sal_Bool bSearch );
~SwNode2LayImpl()55 ~SwNode2LayImpl() { delete pIter; delete pUpperFrms; }
56 SwFrm* NextFrm(); // liefert den naechsten "sinnvollen" Frame
57 SwLayoutFrm* UpperFrm( SwFrm* &rpFrm, const SwNode &rNode );
58 void SaveUpperFrms(); // Speichert (und lockt ggf.) die pUpper
59 // Fuegt unter jeden pUpper des Arrays einen Frame ein.
60 void RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd );
61
62 SwFrm* GetFrm( const Point* pDocPos = 0,
63 const SwPosition *pPos = 0,
64 const sal_Bool bCalcFrm = sal_True ) const;
65 };
66
67 /* -----------------25.02.99 10:38-------------------
68 * Hauptaufgabe des Ctor: Das richtige SwModify zu ermitteln,
69 * ueber das iteriert wird.
70 * Uebergibt man bSearch == sal_True, so wird der naechste Cntnt- oder TableNode
71 * gesucht, der Frames besitzt ( zum Einsammeln der pUpper ), ansonsten wird
72 * erwartet, das rNode bereits auf einem solchen Cntnt- oder TableNode sitzt,
73 * vor oder hinter den eingefuegt werden soll.
74 * --------------------------------------------------*/
75
GoNextWithFrm(const SwNodes & rNodes,SwNodeIndex * pIdx)76 SwNode* GoNextWithFrm(const SwNodes& rNodes, SwNodeIndex *pIdx)
77 {
78 if( pIdx->GetIndex() >= rNodes.Count() - 1 )
79 return 0;
80
81 SwNodeIndex aTmp(*pIdx, +1);
82 SwNode* pNd = 0;
83 while( aTmp < rNodes.Count()-1 )
84 {
85 pNd = &aTmp.GetNode();
86 bool bFound = false;
87 if ( pNd->IsCntntNode() )
88 bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0);
89 else if ( pNd->IsTableNode() )
90 bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 );
91 else if( pNd->IsEndNode() && !pNd->StartOfSectionNode()->IsSectionNode() )
92 {
93 pNd = 0;
94 break;
95 }
96 if ( bFound )
97 break;
98 aTmp++;
99 }
100
101 if( aTmp == rNodes.Count()-1 )
102 pNd = 0;
103 else if( pNd )
104 (*pIdx) = aTmp;
105 return pNd;
106 }
107
GoPreviousWithFrm(SwNodeIndex * pIdx)108 SwNode* GoPreviousWithFrm(SwNodeIndex *pIdx)
109 {
110 if( !pIdx->GetIndex() )
111 return 0;
112
113 SwNodeIndex aTmp( *pIdx, -1 );
114 SwNode* pNd(0);
115 while( aTmp.GetIndex() )
116 {
117 pNd = &aTmp.GetNode();
118 bool bFound = false;
119 if ( pNd->IsCntntNode() )
120 bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0);
121 else if ( pNd->IsTableNode() )
122 bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 );
123 else if( pNd->IsStartNode() && !pNd->IsSectionNode() )
124 {
125 pNd = 0;
126 break;
127 }
128 if ( bFound )
129 break;
130 aTmp--;
131 }
132
133 if( !aTmp.GetIndex() )
134 pNd = 0;
135 else if( pNd )
136 (*pIdx) = aTmp;
137 return pNd;
138 }
139
140
SwNode2LayImpl(const SwNode & rNode,sal_uLong nIdx,sal_Bool bSearch)141 SwNode2LayImpl::SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, sal_Bool bSearch )
142 : pUpperFrms( NULL ), nIndex( nIdx ), bInit( sal_False )
143 {
144 const SwNode* pNd;
145 if( bSearch || rNode.IsSectionNode() )
146 {
147 // Suche den naechsten Cntnt/TblNode, der einen Frame besitzt,
148 // damit wir uns vor/hinter ihn haengen koennen
149 if( !bSearch && rNode.GetIndex() < nIndex )
150 {
151 SwNodeIndex aTmp( *rNode.EndOfSectionNode(), +1 );
152 pNd = GoPreviousWithFrm( &aTmp );
153 if( !bSearch && pNd && rNode.GetIndex() > pNd->GetIndex() )
154 pNd = NULL; // Nicht ueber den Bereich hinausschiessen
155 bMaster = sal_False;
156 }
157 else
158 {
159 SwNodeIndex aTmp( rNode, -1 );
160 pNd = GoNextWithFrm( rNode.GetNodes(), &aTmp );
161 bMaster = sal_True;
162 if( !bSearch && pNd && rNode.EndOfSectionIndex() < pNd->GetIndex() )
163 pNd = NULL; // Nicht ueber den Bereich hinausschiessen
164 }
165 }
166 else
167 {
168 pNd = &rNode;
169 bMaster = nIndex < rNode.GetIndex();
170 }
171 if( pNd )
172 {
173 if( pNd->IsCntntNode() )
174 pMod = (SwModify*)pNd->GetCntntNode();
175 else
176 {
177 ASSERT( pNd->IsTableNode(), "For Tablenodes only" );
178 pMod = pNd->GetTableNode()->GetTable().GetFrmFmt();
179 }
180 pIter = new SwIterator<SwFrm,SwModify>( *pMod );
181 }
182 else
183 {
184 pIter = NULL;
185 pMod = 0;
186 }
187 }
188
189 /* -----------------25.02.99 10:41-------------------
190 * SwNode2LayImpl::NextFrm() liefert den naechsten "sinnvollen" Frame,
191 * beim ersten Aufruf wird am eigentlichen Iterator ein First gerufen,
192 * danach die Next-Methode. Das Ergebnis wird auf Brauchbarkeit untersucht,
193 * so werden keine Follows akzeptiert, ein Master wird beim Einsammeln der
194 * pUpper und beim Einfuegen vor ihm akzeptiert. Beim Einfuegen dahinter
195 * wird vom Master ausgehend der letzte Follow gesucht und zurueckgegeben.
196 * Wenn der Frame innerhalb eines SectionFrms liegt, wird noch festgestellt,
197 * ob statt des Frames der SectionFrm der geeignete Rueckgabewert ist, dies
198 * ist der Fall, wenn der neu einzufuegende Node ausserhalb des Bereichs liegt.
199 * --------------------------------------------------*/
NextFrm()200 SwFrm* SwNode2LayImpl::NextFrm()
201 {
202 SwFrm* pRet;
203 if( !pIter )
204 return NULL;
205 if( !bInit )
206 {
207 pRet = pIter->First();
208 bInit = sal_True;
209 }
210 else
211 pRet = pIter->Next();
212 while( pRet )
213 {
214 SwFlowFrm* pFlow = SwFlowFrm::CastFlowFrm( pRet );
215 ASSERT( pFlow, "Cntnt or Table expected?!" );
216 // Follows sind fluechtige Gestalten, deshalb werden sie ignoriert.
217 // Auch wenn wir hinter dem Frame eingefuegt werden sollen, nehmen wir
218 // zunaechst den Master, hangeln uns dann aber zum letzten Follow durch.
219 if( !pFlow->IsFollow() )
220 {
221 if( !bMaster )
222 {
223 while( pFlow->HasFollow() )
224 pFlow = pFlow->GetFollow();
225 pRet = pFlow->GetFrm();
226 }
227 if( pRet->IsInSct() )
228 {
229 SwSectionFrm* pSct = pRet->FindSctFrm();
230 // Vorsicht: Wenn wir in einer Fussnote sind, so kann diese
231 // Layoutmaessig in einem spaltigen Bereich liegen, obwohl
232 // sie nodemaessig ausserhalb liegt. Deshalb muss bei Fussnoten
233 // ueberprueft werden, ob auch der SectionFrm in der Fussnote
234 // und nicht ausserhalb liegt.
235 if( !pRet->IsInFtn() || pSct->IsInFtn() )
236 {
237 ASSERT( pSct && pSct->GetSection(), "Where's my section?" );
238 SwSectionNode* pNd = pSct->GetSection()->GetFmt()->GetSectionNode();
239 ASSERT( pNd, "Lost SectionNode" );
240 // Wenn der erhaltene Frame in einem Bereichsframe steht,
241 // dessen Bereich den Ausgangsnode nicht umfasst, so kehren
242 // wir mit dem SectionFrm zurueck, sonst mit dem Cntnt/TabFrm
243 if( bMaster )
244 {
245 if( pNd->GetIndex() >= nIndex )
246 pRet = pSct;
247 }
248 else if( pNd->EndOfSectionIndex() < nIndex )
249 pRet = pSct;
250 }
251 }
252 return pRet;
253 }
254 pRet = pIter->Next();
255 }
256 return NULL;
257 }
258
SaveUpperFrms()259 void SwNode2LayImpl::SaveUpperFrms()
260 {
261 pUpperFrms = new SvPtrarr( 0, 20 );
262 SwFrm* pFrm;
263 while( 0 != (pFrm = NextFrm()) )
264 {
265 SwFrm* pPrv = pFrm->GetPrev();
266 pFrm = pFrm->GetUpper();
267 if( pFrm )
268 {
269 if( pFrm->IsFtnFrm() )
270 ((SwFtnFrm*)pFrm)->ColLock();
271 else if( pFrm->IsInSct() )
272 pFrm->FindSctFrm()->ColLock();
273 if( pPrv && pPrv->IsSctFrm() )
274 ((SwSectionFrm*)pPrv)->LockJoin();
275 pUpperFrms->Insert( (void*)pPrv, pUpperFrms->Count() );
276 pUpperFrms->Insert( (void*)pFrm, pUpperFrms->Count() );
277 }
278 }
279 delete pIter;
280 pIter = NULL;
281 pMod = 0;
282 }
283
UpperFrm(SwFrm * & rpFrm,const SwNode & rNode)284 SwLayoutFrm* SwNode2LayImpl::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode )
285 {
286 rpFrm = NextFrm();
287 if( !rpFrm )
288 return NULL;
289 SwLayoutFrm* pUpper = rpFrm->GetUpper();
290 if( rpFrm->IsSctFrm() )
291 {
292 const SwNode* pNode = rNode.StartOfSectionNode();
293 if( pNode->IsSectionNode() )
294 {
295 SwFrm* pFrm = bMaster ? rpFrm->FindPrev() : rpFrm->FindNext();
296 if( pFrm && pFrm->IsSctFrm() )
297 {
298 // #137684#: pFrm could be a "dummy"-section
299 if( ((SwSectionFrm*)pFrm)->GetSection() &&
300 (&((SwSectionNode*)pNode)->GetSection() ==
301 ((SwSectionFrm*)pFrm)->GetSection()) )
302 {
303 // OD 2004-06-02 #i22922# - consider columned sections
304 // 'Go down' the section frame as long as the layout frame
305 // is found, which would contain content.
306 while ( pFrm->IsLayoutFrm() &&
307 static_cast<SwLayoutFrm*>(pFrm)->Lower() &&
308 !static_cast<SwLayoutFrm*>(pFrm)->Lower()->IsFlowFrm() &&
309 static_cast<SwLayoutFrm*>(pFrm)->Lower()->IsLayoutFrm() )
310 {
311 pFrm = static_cast<SwLayoutFrm*>(pFrm)->Lower();
312 }
313 ASSERT( pFrm->IsLayoutFrm(),
314 "<SwNode2LayImpl::UpperFrm(..)> - expected upper frame isn't a layout frame." );
315 rpFrm = bMaster ? NULL
316 : static_cast<SwLayoutFrm*>(pFrm)->Lower();
317 ASSERT( !rpFrm || rpFrm->IsFlowFrm(),
318 "<SwNode2LayImpl::UpperFrm(..)> - expected sibling isn't a flow frame." );
319 return static_cast<SwLayoutFrm*>(pFrm);
320 }
321
322 pUpper = new SwSectionFrm(((SwSectionNode*)pNode)->GetSection(), rpFrm);
323 pUpper->Paste( rpFrm->GetUpper(),
324 bMaster ? rpFrm : rpFrm->GetNext() );
325 static_cast<SwSectionFrm*>(pUpper)->Init();
326 rpFrm = NULL;
327 // 'Go down' the section frame as long as the layout frame
328 // is found, which would contain content.
329 while ( pUpper->Lower() &&
330 !pUpper->Lower()->IsFlowFrm() &&
331 pUpper->Lower()->IsLayoutFrm() )
332 {
333 pUpper = static_cast<SwLayoutFrm*>(pUpper->Lower());
334 }
335 return pUpper;
336 }
337 }
338 };
339 if( !bMaster )
340 rpFrm = rpFrm->GetNext();
341 return pUpper;
342 }
343
RestoreUpperFrms(SwNodes & rNds,sal_uLong nStt,sal_uLong nEnd)344 void SwNode2LayImpl::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd )
345 {
346 ASSERT( pUpperFrms, "RestoreUpper without SaveUpper?" )
347 SwNode* pNd;
348 SwDoc *pDoc = rNds.GetDoc();
349 sal_Bool bFirst = sal_True;
350 for( ; nStt < nEnd; ++nStt )
351 {
352 SwFrm* pNew = 0;
353 SwFrm* pNxt;
354 SwLayoutFrm* pUp;
355 if( (pNd = rNds[nStt])->IsCntntNode() )
356 for( sal_uInt16 n = 0; n < pUpperFrms->Count(); )
357 {
358 pNxt = (SwFrm*)(*pUpperFrms)[n++];
359 if( bFirst && pNxt && pNxt->IsSctFrm() )
360 ((SwSectionFrm*)pNxt)->UnlockJoin();
361 pUp = (SwLayoutFrm*)(*pUpperFrms)[n++];
362 if( pNxt )
363 pNxt = pNxt->GetNext();
364 else
365 pNxt = pUp->Lower();
366 pNew = ((SwCntntNode*)pNd)->MakeFrm( pUp );
367 pNew->Paste( pUp, pNxt );
368 (*pUpperFrms)[n-2] = pNew;
369 }
370 else if( pNd->IsTableNode() )
371 for( sal_uInt16 x = 0; x < pUpperFrms->Count(); )
372 {
373 pNxt = (SwFrm*)(*pUpperFrms)[x++];
374 if( bFirst && pNxt && pNxt->IsSctFrm() )
375 ((SwSectionFrm*)pNxt)->UnlockJoin();
376 pUp = (SwLayoutFrm*)(*pUpperFrms)[x++];
377 if( pNxt )
378 pNxt = pNxt->GetNext();
379 else
380 pNxt = pUp->Lower();
381 pNew = ((SwTableNode*)pNd)->MakeFrm( pUp );
382 ASSERT( pNew->IsTabFrm(), "Table exspected" );
383 pNew->Paste( pUp, pNxt );
384 ((SwTabFrm*)pNew)->RegistFlys();
385 (*pUpperFrms)[x-2] = pNew;
386 }
387 else if( pNd->IsSectionNode() )
388 {
389 nStt = pNd->EndOfSectionIndex();
390 for( sal_uInt16 x = 0; x < pUpperFrms->Count(); )
391 {
392 pNxt = (SwFrm*)(*pUpperFrms)[x++];
393 if( bFirst && pNxt && pNxt->IsSctFrm() )
394 ((SwSectionFrm*)pNxt)->UnlockJoin();
395 pUp = (SwLayoutFrm*)(*pUpperFrms)[x++];
396 ASSERT( pUp->GetUpper() || pUp->IsFlyFrm(), "Lost Upper" );
397 ::_InsertCnt( pUp, pDoc, pNd->GetIndex(), sal_False, nStt+1, pNxt );
398 pNxt = pUp->GetLastLower();
399 (*pUpperFrms)[x-2] = pNxt;
400 }
401 }
402 bFirst = sal_False;
403 }
404 for( sal_uInt16 x = 0; x < pUpperFrms->Count(); ++x )
405 {
406 SwFrm* pTmp = (SwFrm*)(*pUpperFrms)[++x];
407 if( pTmp->IsFtnFrm() )
408 ((SwFtnFrm*)pTmp)->ColUnlock();
409 else if ( pTmp->IsInSct() )
410 {
411 SwSectionFrm* pSctFrm = pTmp->FindSctFrm();
412 pSctFrm->ColUnlock();
413 // OD 26.08.2003 #i18103# - invalidate size of section in order to
414 // assure, that the section is formatted, unless it was 'Collocked'
415 // from its 'collection' until its 'restoration'.
416 pSctFrm->_InvalidateSize();
417 }
418 }
419 }
420
GetFrm(const Point * pDocPos,const SwPosition * pPos,const sal_Bool bCalcFrm) const421 SwFrm* SwNode2LayImpl::GetFrm( const Point* pDocPos,
422 const SwPosition *pPos,
423 const sal_Bool bCalcFrm ) const
424 {
425 // mba: test if change of member pIter -> pMod broke anything
426 return pMod ? ::GetFrmOfModify( 0, *pMod, USHRT_MAX, pDocPos, pPos, bCalcFrm ) : 0;
427 }
428
SwNode2Layout(const SwNode & rNd,sal_uLong nIdx)429 SwNode2Layout::SwNode2Layout( const SwNode& rNd, sal_uLong nIdx )
430 {
431 pImpl = new SwNode2LayImpl( rNd, nIdx, sal_False );
432 }
433
SwNode2Layout(const SwNode & rNd)434 SwNode2Layout::SwNode2Layout( const SwNode& rNd )
435 {
436 pImpl = new SwNode2LayImpl( rNd, rNd.GetIndex(), sal_True );
437 pImpl->SaveUpperFrms();
438 }
439
RestoreUpperFrms(SwNodes & rNds,sal_uLong nStt,sal_uLong nEnd)440 void SwNode2Layout::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd )
441 {
442 ASSERT( pImpl, "RestoreUpperFrms without SaveUpperFrms" );
443 pImpl->RestoreUpperFrms( rNds, nStt, nEnd );
444 }
445
NextFrm()446 SwFrm* SwNode2Layout::NextFrm()
447 {
448 return pImpl->NextFrm();
449 }
450
UpperFrm(SwFrm * & rpFrm,const SwNode & rNode)451 SwLayoutFrm* SwNode2Layout::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode )
452 {
453 return pImpl->UpperFrm( rpFrm, rNode );
454 }
455
~SwNode2Layout()456 SwNode2Layout::~SwNode2Layout()
457 {
458 delete pImpl;
459 }
460
GetFrm(const Point * pDocPos,const SwPosition * pPos,const sal_Bool bCalcFrm) const461 SwFrm* SwNode2Layout::GetFrm( const Point* pDocPos,
462 const SwPosition *pPos,
463 const sal_Bool bCalcFrm ) const
464 {
465 return pImpl->GetFrm( pDocPos, pPos, bCalcFrm );
466 }
467
468
469