xref: /aoo41x/main/sw/source/core/unocore/unoobj2.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <rtl/ustrbuf.hxx>
32 #include <swtypes.hxx>
33 #include <hintids.hxx>
34 #include <cmdid.h>
35 #include <hints.hxx>
36 #include <IMark.hxx>
37 #include <bookmrk.hxx>
38 #include <frmfmt.hxx>
39 #include <doc.hxx>
40 #include <IDocumentUndoRedo.hxx>
41 #include <ndtxt.hxx>
42 #include <ndnotxt.hxx>
43 #include <unocrsr.hxx>
44 #include <swundo.hxx>
45 #include <rootfrm.hxx>
46 #include <flyfrm.hxx>
47 #include <ftnidx.hxx>
48 #include <sfx2/linkmgr.hxx>
49 #include <docary.hxx>
50 #include <paratr.hxx>
51 #include <tools/urlobj.hxx>
52 #include <pam.hxx>
53 #include <tools/cachestr.hxx>
54 #include <shellio.hxx>
55 #include <swerror.h>
56 #include <swtblfmt.hxx>
57 #include <docsh.hxx>
58 #include <docstyle.hxx>
59 #include <charfmt.hxx>
60 #include <txtfld.hxx>
61 #include <fmtfld.hxx>
62 #include <fmtpdsc.hxx>
63 #include <pagedesc.hxx>
64 #include <poolfmt.hrc>
65 #include <poolfmt.hxx>
66 #include <edimp.hxx>
67 #include <fchrfmt.hxx>
68 #include <cntfrm.hxx>
69 #include <pagefrm.hxx>
70 #include <doctxm.hxx>
71 #include <sfx2/docfilt.hxx>
72 #include <sfx2/docfile.hxx>
73 #include <sfx2/fcontnr.hxx>
74 #include <fmtrfmrk.hxx>
75 #include <txtrfmrk.hxx>
76 #include <unoparaframeenum.hxx>
77 #include <unofootnote.hxx>
78 #include <unotextbodyhf.hxx>
79 #include <unotextrange.hxx>
80 #include <unoparagraph.hxx>
81 #include <unomap.hxx>
82 #include <unoport.hxx>
83 #include <unocrsrhelper.hxx>
84 #include <unosett.hxx>
85 #include <unoprnms.hxx>
86 #include <unotbl.hxx>
87 #include <unodraw.hxx>
88 #include <unocoll.hxx>
89 #include <unostyle.hxx>
90 #include <unofield.hxx>
91 #include <fmtanchr.hxx>
92 #include <editeng/flstitem.hxx>
93 #include <editeng/unolingu.hxx>
94 #include <svtools/ctrltool.hxx>
95 #include <flypos.hxx>
96 #include <txtftn.hxx>
97 #include <fmtftn.hxx>
98 #include <fmtcntnt.hxx>
99 #include <com/sun/star/text/WrapTextMode.hpp>
100 #include <com/sun/star/text/TextContentAnchorType.hpp>
101 #include <com/sun/star/style/PageStyleLayout.hpp>
102 #include <com/sun/star/text/XTextDocument.hpp>
103 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
104 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
105 #include <unoidx.hxx>
106 #include <unoframe.hxx>
107 #include <fmthdft.hxx>
108 #include <vos/mutex.hxx>
109 #include <vcl/svapp.hxx>
110 #include <fmtflcnt.hxx>
111 #define _SVSTDARR_USHORTS
112 #define _SVSTDARR_USHORTSSORT
113 #define _SVSTDARR_XUB_STRLEN
114 #include <svl/svstdarr.hxx>
115 #include <editeng/brshitem.hxx>
116 #include <fmtclds.hxx>
117 #include <dcontact.hxx>
118 #include <dflyobj.hxx>
119 #include <crsskip.hxx>
120 #include <vector>
121 #include <sortedobjs.hxx>
122 #include <sortopt.hxx>
123 #include <algorithm>
124 #include <iterator>
125 #include <boost/bind.hpp>
126 #include <switerator.hxx>
127 
128 using namespace ::com::sun::star;
129 using ::rtl::OUString;
130 
131 
132 namespace sw {
133 
134 sal_Bool SupportsServiceImpl(
135         size_t const nServices, char const*const pServices[],
136         ::rtl::OUString const & rServiceName)
137 {
138     for (size_t i = 0; i < nServices; ++i)
139     {
140         if (rServiceName.equalsAscii(pServices[i]))
141         {
142             return sal_True;
143         }
144     }
145     return sal_False;
146 }
147 
148 uno::Sequence< ::rtl::OUString >
149 GetSupportedServiceNamesImpl(
150         size_t const nServices, char const*const pServices[])
151 {
152     uno::Sequence< ::rtl::OUString > ret(nServices);
153     for (size_t i = 0; i < nServices; ++i)
154     {
155         ret[i] = C2U(pServices[i]);
156     }
157     return ret;
158 }
159 
160 } // namespace sw
161 
162 
163 namespace sw {
164 
165 void DeepCopyPaM(SwPaM const & rSource, SwPaM & rTarget)
166 {
167     rTarget = rSource;
168 
169     if (rSource.GetNext() != &rSource)
170     {
171         SwPaM *pPam = static_cast<SwPaM *>(rSource.GetNext());
172         do
173         {
174             // create new PaM
175             SwPaM *const pNew = new SwPaM(*pPam);
176             // insert into ring
177             pNew->MoveTo(&rTarget);
178             pPam = static_cast<SwPaM *>(pPam->GetNext());
179         }
180         while (pPam != &rSource);
181     }
182 }
183 
184 } // namespace sw
185 
186 struct FrameDependSortListLess
187 {
188     bool operator() (FrameDependSortListEntry const& r1,
189                      FrameDependSortListEntry const& r2)
190     {
191         return  (r1.nIndex <  r2.nIndex)
192             || ((r1.nIndex == r2.nIndex) && (r1.nOrder < r2.nOrder));
193     }
194 };
195 
196 // OD 2004-05-07 #i28701# - adjust 4th parameter
197 void CollectFrameAtNode( SwClient& rClnt, const SwNodeIndex& rIdx,
198                          FrameDependSortList_t & rFrames,
199                          const bool _bAtCharAnchoredObjs )
200 {
201     // _bAtCharAnchoredObjs:
202     // <sal_True>: at-character anchored objects are collected
203     // <sal_False>: at-paragraph anchored objects are collected
204 
205 	// alle Rahmen, Grafiken und OLEs suchen, die an diesem Absatz
206 	// gebunden sind
207 	SwDoc* pDoc = rIdx.GetNode().GetDoc();
208 
209     sal_uInt16 nChkType = static_cast< sal_uInt16 >((_bAtCharAnchoredObjs)
210             ? FLY_AT_CHAR : FLY_AT_PARA);
211 	const SwCntntFrm* pCFrm;
212 	const SwCntntNode* pCNd;
213     if( pDoc->GetCurrentViewShell() &&	//swmod 071108//swmod 071225
214         0 != (pCNd = rIdx.GetNode().GetCntntNode()) &&
215 		0 != (pCFrm = pCNd->getLayoutFrm( pDoc->GetCurrentLayout())) )
216 	{
217         const SwSortedObjs *pObjs = pCFrm->GetDrawObjs();
218 		if( pObjs )
219 			for( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
220 			{
221                 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
222                 SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
223                 if ( rFmt.GetAnchor().GetAnchorId() == nChkType )
224                 {
225                     // create SwDepend and insert into array
226                     SwDepend* pNewDepend = new SwDepend( &rClnt, &rFmt );
227                     xub_StrLen idx =
228                         rFmt.GetAnchor().GetCntntAnchor()->nContent.GetIndex();
229                     sal_uInt32 nOrder = rFmt.GetAnchor().GetOrder();
230 
231                     // OD 2004-05-07 #i28701# - sorting no longer needed,
232                     // because list <SwSortedObjs> is already sorted.
233                     FrameDependSortListEntry entry(idx, nOrder, pNewDepend);
234                     rFrames.push_back(entry);
235                 }
236             }
237 	}
238 	else
239 	{
240         const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
241 		sal_uInt16 nSize = rFmts.Count();
242 		for ( sal_uInt16 i = 0; i < nSize; i++)
243 		{
244 			const SwFrmFmt* pFmt = rFmts[ i ];
245 			const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
246 			const SwPosition* pAnchorPos;
247 			if( rAnchor.GetAnchorId() == nChkType &&
248 				0 != (pAnchorPos = rAnchor.GetCntntAnchor()) &&
249 					pAnchorPos->nNode == rIdx )
250 			{
251 				//jetzt einen SwDepend anlegen und in das Array einfuegen
252 				SwDepend* pNewDepend = new SwDepend( &rClnt, (SwFrmFmt*)pFmt);
253 
254                 // OD 2004-05-07 #i28701# - determine insert position for
255                 // sorted <rFrameArr>
256                 xub_StrLen nIndex = pAnchorPos->nContent.GetIndex();
257                 sal_uInt32 nOrder = rAnchor.GetOrder();
258 
259                 FrameDependSortListEntry entry(nIndex, nOrder, pNewDepend);
260                 rFrames.push_back(entry);
261             }
262         }
263         ::std::sort(rFrames.begin(), rFrames.end(), FrameDependSortListLess());
264     }
265 }
266 
267 /****************************************************************************
268 	ActionContext
269 ****************************************************************************/
270 UnoActionContext::UnoActionContext(SwDoc *const pDoc)
271     : m_pDoc(pDoc)
272 {
273     SwRootFrm *const pRootFrm = m_pDoc->GetCurrentLayout();
274     if (pRootFrm)
275     {
276         pRootFrm->StartAllAction();
277     }
278 }
279 
280 UnoActionContext::~UnoActionContext()
281 {
282     // Doc may already have been removed here
283     if (m_pDoc)
284     {
285         SwRootFrm *const pRootFrm = m_pDoc->GetCurrentLayout();
286         if (pRootFrm)
287         {
288             pRootFrm->EndAllAction();
289         }
290     }
291 }
292 
293 /****************************************************************************
294     ActionRemoveContext
295 ****************************************************************************/
296 UnoActionRemoveContext::UnoActionRemoveContext(SwDoc *const pDoc)
297     : m_pDoc(pDoc)
298 {
299     SwRootFrm *const pRootFrm = m_pDoc->GetCurrentLayout();
300     if (pRootFrm)
301     {
302         pRootFrm->UnoRemoveAllActions();
303     }
304 }
305 
306 /* -----------------07.07.98 12:05-------------------
307  *
308  * --------------------------------------------------*/
309 UnoActionRemoveContext::~UnoActionRemoveContext()
310 {
311     SwRootFrm *const pRootFrm = m_pDoc->GetCurrentLayout();
312     if (pRootFrm)
313     {
314         pRootFrm->UnoRestoreAllActions();
315     }
316 }
317 
318 
319 void ClientModify(SwClient* pClient, const SfxPoolItem *pOld, const SfxPoolItem *pNew)
320 {
321 	switch( pOld ? pOld->Which() : 0 )
322 	{
323 	case RES_REMOVE_UNO_OBJECT:
324 	case RES_OBJECTDYING:
325 		if( (void*)pClient->GetRegisteredIn() == ((SwPtrMsgPoolItem *)pOld)->pObject )
326 			((SwModify*)pClient->GetRegisteredIn())->Remove(pClient);
327 		break;
328 
329 	case RES_FMT_CHG:
330 		// wurden wir an das neue umgehaengt und wird das alte geloscht?
331 		if( ((SwFmtChg*)pNew)->pChangedFmt == pClient->GetRegisteredIn() &&
332 			((SwFmtChg*)pOld)->pChangedFmt->IsFmtInDTOR() )
333 			((SwModify*)pClient->GetRegisteredIn())->Remove(pClient);
334 		break;
335 	}
336 }
337 
338 
339 void SwUnoCursorHelper::SetCrsrAttr(SwPaM & rPam,
340         const SfxItemSet& rSet,
341         const SetAttrMode nAttrMode, const bool bTableMode)
342 {
343     const SetAttrMode nFlags = nAttrMode | nsSetAttrMode::SETATTR_APICALL;
344 	SwDoc* pDoc = rPam.GetDoc();
345 	//StartEndAction
346 	UnoActionContext aAction(pDoc);
347     if (rPam.GetNext() != &rPam)    // Ring of Cursors
348     {
349         pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSATTR, NULL);
350 
351         SwPaM *pCurrent = &rPam;
352         do
353         {
354             if (pCurrent->HasMark() &&
355                 ( (bTableMode) ||
356                   (*pCurrent->GetPoint() != *pCurrent->GetMark()) ))
357             {
358                 pDoc->InsertItemSet(*pCurrent, rSet, nFlags);
359             }
360             pCurrent= static_cast<SwPaM *>(pCurrent->GetNext());
361         } while (pCurrent != &rPam);
362 
363         pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSATTR, NULL);
364     }
365     else
366     {
367 //			if( !HasSelection() )
368 //				UpdateAttr();
369         pDoc->InsertItemSet( rPam, rSet, nFlags );
370 	}
371 	//#outline level,add by zhaojianwei
372 	if( rSet.GetItemState( RES_PARATR_OUTLINELEVEL, false ) >= SFX_ITEM_AVAILABLE )
373 	{
374 		SwTxtNode * pTmpNode = rPam.GetNode()->GetTxtNode();
375 		if ( pTmpNode )
376 		{
377 			rPam.GetDoc()->GetNodes().UpdateOutlineNode( *pTmpNode );
378 		}
379 	}
380 	//<-end,zhaojianwei
381 }
382 
383 // --> OD 2006-07-12 #i63870#
384 // split third parameter <bCurrentAttrOnly> into new parameters <bOnlyTxtAttr>
385 // and <bGetFromChrFmt> to get better control about resulting <SfxItemSet>
386 void SwUnoCursorHelper::GetCrsrAttr(SwPaM & rPam,
387         SfxItemSet & rSet, const bool bOnlyTxtAttr, const bool bGetFromChrFmt)
388 {
389 	static const sal_uInt16 nMaxLookup = 1000;
390 	SfxItemSet aSet( *rSet.GetPool(), rSet.GetRanges() );
391 	SfxItemSet *pSet = &rSet;
392     SwPaM *pCurrent = & rPam;
393     do
394     {
395         SwPosition const & rStart( *pCurrent->Start() );
396         SwPosition const & rEnd( *pCurrent->End() );
397         const sal_uLong nSttNd = rStart.nNode.GetIndex();
398         const sal_uLong nEndNd = rEnd  .nNode.GetIndex();
399 
400         if (nEndNd - nSttNd >= nMaxLookup)
401         {
402             rSet.ClearItem();
403             rSet.InvalidateAllItems();
404             return;// uno::Any();
405         }
406 
407         // the first node inserts the values into the get set
408         // all other nodes merge their values into the get set
409         for (sal_uLong n = nSttNd; n <= nEndNd; ++n)
410         {
411             SwNode *const pNd = rPam.GetDoc()->GetNodes()[ n ];
412             switch (pNd->GetNodeType())
413             {
414                 case ND_TEXTNODE:
415                 {
416                     const xub_StrLen nStart = (n == nSttNd)
417                         ? rStart.nContent.GetIndex() : 0;
418                     const xub_StrLen nEnd   = (n == nEndNd)
419                         ? rEnd.nContent.GetIndex()
420                         : static_cast<SwTxtNode*>(pNd)->GetTxt().Len();
421                     static_cast<SwTxtNode*>(pNd)->GetAttr(
422                         *pSet, nStart, nEnd, bOnlyTxtAttr, bGetFromChrFmt);
423                 }
424                 break;
425                 case ND_GRFNODE:
426                 case ND_OLENODE:
427                     static_cast<SwCntntNode*>(pNd)->GetAttr( *pSet );
428                 break;
429 
430                 default:
431                     continue; // skip this node
432             }
433 
434             if (pSet != &rSet)
435             {
436                 rSet.MergeValues( aSet );
437             }
438             else
439             {
440                 pSet = &aSet;
441             }
442 
443             if (aSet.Count())
444             {
445                 aSet.ClearItem();
446             }
447         }
448         pCurrent= static_cast<SwPaM *>(pCurrent->GetNext());
449     } while ( pCurrent != &rPam );
450 }
451 
452 /******************************************************************
453  * SwXParagraphEnumeration
454  ******************************************************************/
455 
456 class SwXParagraphEnumeration::Impl
457     : public SwClient
458 {
459 
460 public:
461 
462     uno::Reference< text::XText > const     m_xParentText;
463     const CursorType        m_eCursorType;
464     /// Start node of the cell _or_ table the enumeration belongs to.
465     /// Used to restrict the movement of the UNO cursor to the cell and its
466     /// embedded tables.
467     SwStartNode const*const m_pOwnStartNode;
468     SwTable const*const     m_pOwnTable;
469     const sal_uLong             m_nEndIndex;
470     sal_Int32               m_nFirstParaStart;
471     sal_Int32               m_nLastParaEnd;
472     bool                    m_bFirstParagraph;
473     uno::Reference< text::XTextContent >    m_xNextPara;
474 
475     Impl(   uno::Reference< text::XText > const& xParent,
476             ::std::auto_ptr<SwUnoCrsr> pCursor,
477             const CursorType eType,
478             SwStartNode const*const pStartNode, SwTable const*const pTable)
479         : SwClient( pCursor.release() )
480         , m_xParentText( xParent )
481         , m_eCursorType( eType )
482         // remember table and start node for later travelling
483         // (used in export of tables in tables)
484         , m_pOwnStartNode( pStartNode )
485         // for import of tables in tables we have to remember the actual
486         // table and start node of the current position in the enumeration.
487         , m_pOwnTable( pTable )
488         , m_nEndIndex( GetCursor()->End()->nNode.GetIndex() )
489         , m_nFirstParaStart( -1 )
490         , m_nLastParaEnd( -1 )
491         , m_bFirstParagraph( true )
492     {
493         OSL_ENSURE(m_xParentText.is(), "SwXParagraphEnumeration: no parent?");
494         OSL_ENSURE(GetRegisteredIn(),  "SwXParagraphEnumeration: no cursor?");
495         OSL_ENSURE(   !((CURSOR_SELECTION_IN_TABLE == eType) ||
496                         (CURSOR_TBLTEXT == eType))
497                    || (m_pOwnTable && m_pOwnStartNode),
498             "SwXParagraphEnumeration: table type but no start node or table?");
499 
500         if ((CURSOR_SELECTION == m_eCursorType) ||
501             (CURSOR_SELECTION_IN_TABLE == m_eCursorType))
502         {
503             SwUnoCrsr & rCursor = *GetCursor();
504             rCursor.Normalize();
505             m_nFirstParaStart = rCursor.GetPoint()->nContent.GetIndex();
506             m_nLastParaEnd = rCursor.GetMark()->nContent.GetIndex();
507             rCursor.DeleteMark();
508         }
509     }
510 
511     ~Impl() {
512         // Impl owns the cursor; delete it here: SolarMutex is locked
513         delete GetRegisteredIn();
514     }
515 
516     SwUnoCrsr * GetCursor() {
517         return static_cast<SwUnoCrsr*>(
518                 const_cast<SwModify*>(GetRegisteredIn()));
519     }
520 
521     uno::Reference< text::XTextContent > NextElement_Impl()
522         throw (container::NoSuchElementException, lang::WrappedTargetException,
523                 uno::RuntimeException);
524 protected:
525     // SwClient
526     virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
527 
528 };
529 
530 void SwXParagraphEnumeration::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
531 {
532     ClientModify(this, pOld, pNew);
533 }
534 
535 SwXParagraphEnumeration::SwXParagraphEnumeration(
536         uno::Reference< text::XText > const& xParent,
537         ::std::auto_ptr<SwUnoCrsr> pCursor,
538         const CursorType eType,
539         SwStartNode const*const pStartNode, SwTable const*const pTable)
540     : m_pImpl( new SwXParagraphEnumeration::Impl(xParent, pCursor, eType,
541                     pStartNode, pTable) )
542 {
543 }
544 
545 SwXParagraphEnumeration::~SwXParagraphEnumeration()
546 {
547 }
548 
549 OUString SAL_CALL
550 SwXParagraphEnumeration::getImplementationName() throw (uno::RuntimeException)
551 {
552 	return C2U("SwXParagraphEnumeration");
553 }
554 
555 static char const*const g_ServicesParagraphEnum[] =
556 {
557     "com.sun.star.text.ParagraphEnumeration",
558 };
559 static const size_t g_nServicesParagraphEnum(
560     sizeof(g_ServicesParagraphEnum)/sizeof(g_ServicesParagraphEnum[0]));
561 
562 sal_Bool SAL_CALL
563 SwXParagraphEnumeration::supportsService(const OUString& rServiceName)
564 throw (uno::RuntimeException)
565 {
566     return ::sw::SupportsServiceImpl(
567             g_nServicesParagraphEnum, g_ServicesParagraphEnum, rServiceName);
568 }
569 
570 uno::Sequence< OUString > SAL_CALL
571 SwXParagraphEnumeration::getSupportedServiceNames()
572 throw (uno::RuntimeException)
573 {
574     return ::sw::GetSupportedServiceNamesImpl(
575             g_nServicesParagraphEnum, g_ServicesParagraphEnum);
576 }
577 
578 sal_Bool SAL_CALL
579 SwXParagraphEnumeration::hasMoreElements() throw (uno::RuntimeException)
580 {
581 	vos::OGuard aGuard(Application::GetSolarMutex());
582 
583     return (m_pImpl->m_bFirstParagraph) ? sal_True : m_pImpl->m_xNextPara.is();
584 }
585 
586 //!! compare to SwShellTableCrsr::FillRects() in viscrs.cxx
587 static SwTableNode *
588 lcl_FindTopLevelTable(
589         SwTableNode *const pTblNode, SwTable const*const pOwnTable)
590 {
591 	// find top-most table in current context (section) level
592 
593 	SwTableNode * pLast = pTblNode;
594 	for (SwTableNode* pTmp = pLast;
595 		 pTmp != NULL  &&  &pTmp->GetTable() != pOwnTable;	/* we must not go up higher than the own table! */
596          pTmp = pTmp->StartOfSectionNode()->FindTableNode() )
597 	{
598 		pLast = pTmp;
599 	}
600 	return pLast;
601 }
602 
603 
604 static bool
605 lcl_CursorIsInSection(
606         SwUnoCrsr const*const pUnoCrsr, SwStartNode const*const pOwnStartNode)
607 {
608 	// returns true if the cursor is in the section (or in a sub section!)
609 	// represented by pOwnStartNode
610 
611     bool bRes = true;
612 	if (pUnoCrsr && pOwnStartNode)
613 	{
614 		const SwEndNode * pOwnEndNode = pOwnStartNode->EndOfSectionNode();
615 		bRes = pOwnStartNode->GetIndex() <= pUnoCrsr->Start()->nNode.GetIndex() &&
616 			   pUnoCrsr->End()->nNode.GetIndex() <= pOwnEndNode->GetIndex();
617 	}
618 	return bRes;
619 }
620 
621 
622 uno::Reference< text::XTextContent >
623 SwXParagraphEnumeration::Impl::NextElement_Impl()
624 throw (container::NoSuchElementException, lang::WrappedTargetException,
625         uno::RuntimeException)
626 {
627     SwUnoCrsr *const pUnoCrsr = GetCursor();
628     if (!pUnoCrsr)
629     {
630         throw uno::RuntimeException();
631     }
632 
633     // check for exceeding selections
634     if (!m_bFirstParagraph &&
635         ((CURSOR_SELECTION == m_eCursorType) ||
636          (CURSOR_SELECTION_IN_TABLE == m_eCursorType)))
637     {
638         SwPosition* pStart = pUnoCrsr->Start();
639         const ::std::auto_ptr<SwUnoCrsr> aNewCrsr(
640             pUnoCrsr->GetDoc()->CreateUnoCrsr(*pStart, sal_False) );
641         // one may also go into tables here
642         if ((CURSOR_TBLTEXT != m_eCursorType) &&
643             (CURSOR_SELECTION_IN_TABLE != m_eCursorType))
644         {
645             aNewCrsr->SetRemainInSection( sal_False );
646         }
647 
648         // os 2005-01-14: This part is only necessary to detect movements out
649         // of a selection; if there is no selection we don't have to care
650         SwTableNode *const pTblNode = aNewCrsr->GetNode()->FindTableNode();
651         if (((CURSOR_TBLTEXT != m_eCursorType) &&
652             (CURSOR_SELECTION_IN_TABLE != m_eCursorType)) && pTblNode)
653         {
654             aNewCrsr->GetPoint()->nNode = pTblNode->EndOfSectionIndex();
655             aNewCrsr->Move(fnMoveForward, fnGoNode);
656         }
657         else
658         {
659             aNewCrsr->MovePara(fnParaNext, fnParaStart);
660         }
661         if (m_nEndIndex < aNewCrsr->Start()->nNode.GetIndex())
662         {
663             return 0;
664         }
665     }
666 
667     sal_Bool bInTable = sal_False;
668     if (!m_bFirstParagraph)
669     {
670         pUnoCrsr->SetRemainInSection( sal_False );
671         // what to do if already in a table?
672         SwTableNode * pTblNode = pUnoCrsr->GetNode()->FindTableNode();
673         pTblNode = lcl_FindTopLevelTable( pTblNode, m_pOwnTable );
674         if (pTblNode && (&pTblNode->GetTable() != m_pOwnTable))
675         {
676             // this is a foreign table: go to end
677             pUnoCrsr->GetPoint()->nNode = pTblNode->EndOfSectionIndex();
678             if (!pUnoCrsr->Move(fnMoveForward, fnGoNode))
679             {
680                 return 0;
681             }
682             bInTable = sal_True;
683         }
684     }
685 
686     uno::Reference< text::XTextContent >  xRef;
687     // the cursor must remain in the current section or a subsection
688     // before AND after the movement...
689     if (lcl_CursorIsInSection( pUnoCrsr, m_pOwnStartNode ) &&
690         (m_bFirstParagraph || bInTable ||
691         (pUnoCrsr->MovePara(fnParaNext, fnParaStart) &&
692             lcl_CursorIsInSection( pUnoCrsr, m_pOwnStartNode ))))
693     {
694         SwPosition* pStart = pUnoCrsr->Start();
695         const sal_Int32 nFirstContent =
696             (m_bFirstParagraph) ? m_nFirstParaStart : -1;
697         const sal_Int32 nLastContent =
698             (m_nEndIndex == pStart->nNode.GetIndex()) ? m_nLastParaEnd : -1;
699 
700         // position in a table, or in a simple paragraph?
701         SwTableNode * pTblNode = pUnoCrsr->GetNode()->FindTableNode();
702         pTblNode = lcl_FindTopLevelTable( pTblNode, m_pOwnTable );
703         if (/*CURSOR_TBLTEXT != eCursorType && CURSOR_SELECTION_IN_TABLE != eCursorType && */
704             pTblNode && (&pTblNode->GetTable() != m_pOwnTable))
705         {
706             // this is a foreign table
707             SwFrmFmt* pTableFmt =
708                 static_cast<SwFrmFmt*>(pTblNode->GetTable().GetFrmFmt());
709             text::XTextTable *const pTable =
710                 SwXTextTables::GetObject( *pTableFmt );
711             xRef = static_cast<text::XTextContent*>(
712                     static_cast<SwXTextTable*>(pTable));
713         }
714         else
715         {
716             text::XText *const pText = m_xParentText.get();
717             xRef = SwXParagraph::CreateXParagraph(*pUnoCrsr->GetDoc(),
718                 *pStart->nNode.GetNode().GetTxtNode(),
719                 static_cast<SwXText*>(pText), nFirstContent, nLastContent);
720         }
721     }
722 
723     return xRef;
724 }
725 
726 uno::Any SAL_CALL SwXParagraphEnumeration::nextElement()
727 throw (container::NoSuchElementException, lang::WrappedTargetException,
728         uno::RuntimeException)
729 {
730 	vos::OGuard aGuard(Application::GetSolarMutex());
731 
732     if (m_pImpl->m_bFirstParagraph)
733     {
734         m_pImpl->m_xNextPara = m_pImpl->NextElement_Impl();
735         m_pImpl->m_bFirstParagraph = false;
736     }
737     const uno::Reference< text::XTextContent > xRef = m_pImpl->m_xNextPara;
738     if (!xRef.is())
739     {
740         throw container::NoSuchElementException();
741     }
742     m_pImpl->m_xNextPara = m_pImpl->NextElement_Impl();
743 
744     uno::Any aRet;
745     aRet <<= xRef;
746 	return aRet;
747 }
748 
749 /******************************************************************
750  * SwXTextRange
751  ******************************************************************/
752 
753 class SwXTextRange::Impl
754     : public SwClient
755 {
756 
757 public:
758 
759     const SfxItemPropertySet &  m_rPropSet;
760     const enum RangePosition    m_eRangePosition;
761     SwDoc &                     m_rDoc;
762     uno::Reference<text::XText> m_xParentText;
763     SwDepend            m_ObjectDepend; // register at format of table or frame
764     ::sw::mark::IMark * m_pMark;
765 
766     Impl(   SwDoc & rDoc, const enum RangePosition eRange,
767             SwFrmFmt *const pTblFmt = 0,
768             const uno::Reference< text::XText > & xParent = 0)
769         : SwClient()
770         , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
771         , m_eRangePosition(eRange)
772         , m_rDoc(rDoc)
773         , m_xParentText(xParent)
774         , m_ObjectDepend(this, pTblFmt)
775         , m_pMark(0)
776     {
777     }
778 
779     ~Impl()
780     {
781         // Impl owns the bookmark; delete it here: SolarMutex is locked
782         Invalidate();
783     }
784 
785     void Invalidate()
786     {
787         if (m_pMark)
788         {
789             m_rDoc.getIDocumentMarkAccess()->deleteMark(m_pMark);
790             m_pMark = 0;
791         }
792     }
793 
794     const ::sw::mark::IMark * GetBookmark() const { return m_pMark; }
795 protected:
796     // SwClient
797     virtual void    Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
798 
799 };
800 
801 void SwXTextRange::Impl::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
802 {
803     const bool bAlreadyRegistered = 0 != GetRegisteredIn();
804     ClientModify(this, pOld, pNew);
805     if (m_ObjectDepend.GetRegisteredIn())
806     {
807         ClientModify(&m_ObjectDepend, pOld, pNew);
808         // if the depend was removed then the range must be removed too
809         if (!m_ObjectDepend.GetRegisteredIn() && GetRegisteredIn())
810         {
811             const_cast<SwModify*>(GetRegisteredIn())->Remove(this);
812         }
813         // or if the range has been removed but the depend ist still
814         // connected then the depend must be removed
815         else if (bAlreadyRegistered && !GetRegisteredIn() &&
816                     m_ObjectDepend.GetRegisteredIn())
817         {
818             const_cast<SwModify*>(m_ObjectDepend.GetRegisteredIn())
819                 ->Remove(& m_ObjectDepend);
820         }
821     }
822     if (!GetRegisteredIn())
823     {
824         m_pMark = 0;
825     }
826 }
827 
828 
829 SwXTextRange::SwXTextRange(SwPaM& rPam,
830         const uno::Reference< text::XText > & xParent,
831         const enum RangePosition eRange)
832     : m_pImpl( new SwXTextRange::Impl(*rPam.GetDoc(), eRange, 0, xParent) )
833 {
834     SetPositions(rPam);
835 }
836 
837 SwXTextRange::SwXTextRange(SwFrmFmt& rTblFmt)
838     : m_pImpl(
839         new SwXTextRange::Impl(*rTblFmt.GetDoc(), RANGE_IS_TABLE, &rTblFmt) )
840 {
841     SwTable *const pTable = SwTable::FindTable( &rTblFmt );
842     SwTableNode *const pTblNode = pTable->GetTableNode();
843     SwPosition aPosition( *pTblNode );
844     SwPaM aPam( aPosition );
845 
846     SetPositions( aPam );
847 }
848 
849 SwXTextRange::~SwXTextRange()
850 {
851 }
852 
853 const SwDoc * SwXTextRange::GetDoc() const
854 {
855     return & m_pImpl->m_rDoc;
856 }
857 
858 SwDoc * SwXTextRange::GetDoc()
859 {
860     return & m_pImpl->m_rDoc;
861 }
862 
863 
864 void SwXTextRange::Invalidate()
865 {
866     m_pImpl->Invalidate();
867 }
868 
869 void SwXTextRange::SetPositions(const SwPaM& rPam)
870 {
871     m_pImpl->Invalidate();
872     IDocumentMarkAccess* const pMA = m_pImpl->m_rDoc.getIDocumentMarkAccess();
873     m_pImpl->m_pMark = pMA->makeMark(rPam, ::rtl::OUString(),
874                 IDocumentMarkAccess::UNO_BOOKMARK);
875     m_pImpl->m_pMark->Add(m_pImpl.get());
876 }
877 
878 void SwXTextRange::DeleteAndInsert(
879         const ::rtl::OUString& rText, const bool bForceExpandHints)
880 throw (uno::RuntimeException)
881 {
882     if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
883     {
884         // setString on table not allowed
885         throw uno::RuntimeException();
886     }
887 
888     const SwPosition aPos(GetDoc()->GetNodes().GetEndOfContent());
889     SwCursor aCursor(aPos, 0, false);
890     if (GetPositions(aCursor))
891     {
892         UnoActionContext aAction(& m_pImpl->m_rDoc);
893         m_pImpl->m_rDoc.GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
894         if (aCursor.HasMark())
895         {
896             m_pImpl->m_rDoc.DeleteAndJoin(aCursor);
897         }
898 
899         if (rText.getLength())
900         {
901             SwUnoCursorHelper::DocInsertStringSplitCR(
902                     m_pImpl->m_rDoc, aCursor, rText, bForceExpandHints);
903 
904             SwUnoCursorHelper::SelectPam(aCursor, true);
905             aCursor.Left(rText.getLength(), CRSR_SKIP_CHARS, sal_False, sal_False);
906         }
907         SetPositions(aCursor);
908         m_pImpl->m_rDoc.GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
909     }
910 }
911 
912 const uno::Sequence< sal_Int8 > & SwXTextRange::getUnoTunnelId()
913 {
914     static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
915     return aSeq;
916 }
917 
918 // XUnoTunnel
919 sal_Int64 SAL_CALL
920 SwXTextRange::getSomething(const uno::Sequence< sal_Int8 >& rId)
921 throw (uno::RuntimeException)
922 {
923     return ::sw::UnoTunnelImpl<SwXTextRange>(rId, this);
924 }
925 
926 OUString SAL_CALL
927 SwXTextRange::getImplementationName() throw (uno::RuntimeException)
928 {
929     return OUString::createFromAscii("SwXTextRange");
930 }
931 
932 static char const*const g_ServicesTextRange[] =
933 {
934     "com.sun.star.text.TextRange",
935     "com.sun.star.style.CharacterProperties",
936     "com.sun.star.style.CharacterPropertiesAsian",
937     "com.sun.star.style.CharacterPropertiesComplex",
938     "com.sun.star.style.ParagraphProperties",
939     "com.sun.star.style.ParagraphPropertiesAsian",
940     "com.sun.star.style.ParagraphPropertiesComplex",
941 };
942 static const size_t g_nServicesTextRange(
943     sizeof(g_ServicesTextRange)/sizeof(g_ServicesTextRange[0]));
944 
945 sal_Bool SAL_CALL SwXTextRange::supportsService(const OUString& rServiceName)
946 throw (uno::RuntimeException)
947 {
948     return ::sw::SupportsServiceImpl(
949             g_nServicesTextRange, g_ServicesTextRange, rServiceName);
950 }
951 
952 uno::Sequence< OUString > SAL_CALL
953 SwXTextRange::getSupportedServiceNames() throw (uno::RuntimeException)
954 {
955     return ::sw::GetSupportedServiceNamesImpl(
956             g_nServicesTextRange, g_ServicesTextRange);
957 }
958 
959 uno::Reference< text::XText > SAL_CALL
960 SwXTextRange::getText() throw (uno::RuntimeException)
961 {
962     vos::OGuard aGuard(Application::GetSolarMutex());
963 
964     if (!m_pImpl->m_xParentText.is())
965     {
966         if (m_pImpl->m_eRangePosition == RANGE_IS_TABLE &&
967             m_pImpl->m_ObjectDepend.GetRegisteredIn())
968         {
969             SwFrmFmt const*const pTblFmt = static_cast<SwFrmFmt const*>(
970                     m_pImpl->m_ObjectDepend.GetRegisteredIn());
971             SwTable const*const pTable = SwTable::FindTable( pTblFmt );
972             SwTableNode const*const pTblNode = pTable->GetTableNode();
973             const SwPosition aPosition( *pTblNode );
974             m_pImpl->m_xParentText =
975                 ::sw::CreateParentXText(m_pImpl->m_rDoc, aPosition);
976         }
977     }
978     OSL_ENSURE(m_pImpl->m_xParentText.is(), "SwXTextRange::getText: no text");
979     return m_pImpl->m_xParentText;
980 }
981 
982 uno::Reference< text::XTextRange > SAL_CALL
983 SwXTextRange::getStart() throw (uno::RuntimeException)
984 {
985     vos::OGuard aGuard(Application::GetSolarMutex());
986 
987     uno::Reference< text::XTextRange >  xRet;
988     ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
989     if (!m_pImpl->m_xParentText.is())
990     {
991         getText();
992     }
993     if(pBkmk)
994     {
995         SwPaM aPam(pBkmk->GetMarkStart());
996         xRet = new SwXTextRange(aPam, m_pImpl->m_xParentText);
997     }
998     else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
999     {
1000         // start and end are this, if its a table
1001         xRet = this;
1002     }
1003     else
1004     {
1005         throw uno::RuntimeException();
1006     }
1007     return xRet;
1008 }
1009 
1010 uno::Reference< text::XTextRange > SAL_CALL
1011 SwXTextRange::getEnd() throw (uno::RuntimeException)
1012 {
1013     vos::OGuard aGuard(Application::GetSolarMutex());
1014 
1015     uno::Reference< text::XTextRange >  xRet;
1016     ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
1017     if (!m_pImpl->m_xParentText.is())
1018     {
1019         getText();
1020     }
1021     if(pBkmk)
1022     {
1023         SwPaM aPam(pBkmk->GetMarkEnd());
1024         xRet = new SwXTextRange(aPam, m_pImpl->m_xParentText);
1025     }
1026     else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
1027     {
1028         // start and end are this, if its a table
1029         xRet = this;
1030     }
1031     else
1032     {
1033         throw uno::RuntimeException();
1034     }
1035     return xRet;
1036 }
1037 
1038 OUString SAL_CALL SwXTextRange::getString() throw (uno::RuntimeException)
1039 {
1040     vos::OGuard aGuard(Application::GetSolarMutex());
1041 
1042     OUString sRet;
1043     // for tables there is no bookmark, thus also no text
1044     // one could export the table as ASCII here maybe?
1045     SwPaM aPaM(GetDoc()->GetNodes());
1046     if (GetPositions(aPaM) && aPaM.HasMark())
1047     {
1048         SwUnoCursorHelper::GetTextFromPam(aPaM, sRet);
1049     }
1050     return sRet;
1051 }
1052 
1053 void SAL_CALL SwXTextRange::setString(const OUString& rString)
1054 throw (uno::RuntimeException)
1055 {
1056     vos::OGuard aGuard(Application::GetSolarMutex());
1057 
1058     DeleteAndInsert(rString, false);
1059 }
1060 
1061 bool SwXTextRange::GetPositions(SwPaM& rToFill) const
1062 {
1063     ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
1064     if(pBkmk)
1065     {
1066         *rToFill.GetPoint() = pBkmk->GetMarkPos();
1067         if(pBkmk->IsExpanded())
1068         {
1069             rToFill.SetMark();
1070             *rToFill.GetMark() = pBkmk->GetOtherMarkPos();
1071         }
1072         else
1073         {
1074             rToFill.DeleteMark();
1075         }
1076         return true;
1077     }
1078     return false;
1079 }
1080 
1081 namespace sw {
1082 
1083 bool XTextRangeToSwPaM( SwUnoInternalPaM & rToFill,
1084         const uno::Reference< text::XTextRange > & xTextRange)
1085 {
1086     bool bRet = false;
1087 
1088     uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
1089     SwXTextRange* pRange = 0;
1090     OTextCursorHelper* pCursor = 0;
1091     SwXTextPortion* pPortion = 0;
1092     SwXText* pText = 0;
1093     SwXParagraph* pPara = 0;
1094     if(xRangeTunnel.is())
1095     {
1096         pRange  = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
1097         pCursor =
1098             ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
1099         pPortion=
1100             ::sw::UnoTunnelGetImplementation<SwXTextPortion>(xRangeTunnel);
1101         pText   = ::sw::UnoTunnelGetImplementation<SwXText>(xRangeTunnel);
1102         pPara   = ::sw::UnoTunnelGetImplementation<SwXParagraph>(xRangeTunnel);
1103     }
1104 
1105     // if it's a text then create a temporary cursor there and re-use
1106     // the pCursor variable
1107     // #i108489#: Reference in outside scope to keep cursor alive
1108     uno::Reference< text::XTextCursor > xTextCursor;
1109     if (pText)
1110     {
1111         xTextCursor.set( pText->CreateCursor() );
1112         xTextCursor->gotoEnd(sal_True);
1113         const uno::Reference<lang::XUnoTunnel> xCrsrTunnel(
1114                 xTextCursor, uno::UNO_QUERY);
1115         pCursor =
1116             ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xCrsrTunnel);
1117     }
1118     if(pRange && pRange->GetDoc() == rToFill.GetDoc())
1119     {
1120         bRet = pRange->GetPositions(rToFill);
1121     }
1122     else
1123     {
1124         if (pPara)
1125         {
1126             bRet = pPara->SelectPaM(rToFill);
1127         }
1128         else
1129         {
1130             SwDoc* const pDoc = (pCursor) ? pCursor->GetDoc()
1131                 : ((pPortion) ? pPortion->GetCursor()->GetDoc() : 0);
1132             const SwPaM* const pUnoCrsr = (pCursor) ? pCursor->GetPaM()
1133                 : ((pPortion) ? pPortion->GetCursor() : 0);
1134             if (pUnoCrsr && pDoc == rToFill.GetDoc())
1135             {
1136                 DBG_ASSERT((SwPaM*)pUnoCrsr->GetNext() == pUnoCrsr,
1137                         "what to do about rings?");
1138                 bRet = true;
1139                 *rToFill.GetPoint() = *pUnoCrsr->GetPoint();
1140                 if (pUnoCrsr->HasMark())
1141                 {
1142                     rToFill.SetMark();
1143                     *rToFill.GetMark() = *pUnoCrsr->GetMark();
1144                 }
1145                 else
1146                     rToFill.DeleteMark();
1147             }
1148         }
1149     }
1150     return bRet;
1151 }
1152 
1153 static bool
1154 lcl_IsStartNodeInFormat(const bool bHeader, SwStartNode *const pSttNode,
1155     SwFrmFmt const*const pFrmFmt, SwFrmFmt*& rpFormat)
1156 {
1157     bool bRet = false;
1158     const SfxItemSet& rSet = pFrmFmt->GetAttrSet();
1159     const SfxPoolItem* pItem;
1160     if (SFX_ITEM_SET == rSet.GetItemState(
1161             static_cast<sal_uInt16>(bHeader ? RES_HEADER : RES_FOOTER),
1162             sal_True, &pItem))
1163     {
1164         SfxPoolItem *const pItemNonConst(const_cast<SfxPoolItem *>(pItem));
1165         SwFrmFmt *const pHeadFootFmt = (bHeader) ?
1166             static_cast<SwFmtHeader*>(pItemNonConst)->GetHeaderFmt() :
1167             static_cast<SwFmtFooter*>(pItemNonConst)->GetFooterFmt();
1168         if (pHeadFootFmt)
1169         {
1170             const SwFmtCntnt& rFlyCntnt = pHeadFootFmt->GetCntnt();
1171             const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
1172             SwStartNode const*const pCurSttNode = rNode.FindSttNodeByType(
1173                 (bHeader) ? SwHeaderStartNode : SwFooterStartNode);
1174             if (pCurSttNode && (pCurSttNode == pSttNode))
1175             {
1176                 rpFormat = pHeadFootFmt;
1177                 bRet = true;
1178             }
1179         }
1180     }
1181     return bRet;
1182 }
1183 
1184 } // namespace sw
1185 
1186 uno::Reference< text::XTextRange >
1187 SwXTextRange::CreateXTextRange(
1188     SwDoc & rDoc, const SwPosition& rPos, const SwPosition *const pMark)
1189 {
1190     const uno::Reference<text::XText> xParentText(
1191             ::sw::CreateParentXText(rDoc, rPos));
1192     const ::std::auto_ptr<SwUnoCrsr> pNewCrsr(
1193             rDoc.CreateUnoCrsr(rPos, sal_False));
1194     if(pMark)
1195     {
1196         pNewCrsr->SetMark();
1197         *pNewCrsr->GetMark() = *pMark;
1198     }
1199     const bool isCell( dynamic_cast<SwXCell*>(xParentText.get()) );
1200     const uno::Reference< text::XTextRange > xRet(
1201         new SwXTextRange(*pNewCrsr, xParentText,
1202             isCell ? RANGE_IN_CELL : RANGE_IN_TEXT) );
1203     return xRet;
1204 }
1205 
1206 namespace sw {
1207 
1208 uno::Reference< text::XText >
1209 CreateParentXText(SwDoc & rDoc, const SwPosition& rPos)
1210 {
1211     uno::Reference< text::XText > xParentText;
1212     SwStartNode* pSttNode = rPos.nNode.GetNode().StartOfSectionNode();
1213     while(pSttNode && pSttNode->IsSectionNode())
1214     {
1215         pSttNode = pSttNode->StartOfSectionNode();
1216     }
1217     SwStartNodeType eType = pSttNode->GetStartNodeType();
1218     switch(eType)
1219     {
1220         case SwTableBoxStartNode:
1221         {
1222             SwTableNode const*const pTblNode = pSttNode->FindTableNode();
1223             SwFrmFmt *const pTableFmt =
1224                 static_cast<SwFrmFmt*>(pTblNode->GetTable().GetFrmFmt());
1225             SwTableBox *const  pBox = pSttNode->GetTblBox();
1226 
1227             xParentText = (pBox)
1228                 ? SwXCell::CreateXCell( pTableFmt, pBox )
1229                 : new SwXCell( pTableFmt, *pSttNode );
1230         }
1231         break;
1232         case SwFlyStartNode:
1233         {
1234             SwFrmFmt *const pFmt = pSttNode->GetFlyFmt();
1235             if (0 != pFmt)
1236             {
1237                 SwXTextFrame* pFrame = SwIterator<SwXTextFrame,SwFmt>::FirstElement( *pFmt );
1238                 xParentText = pFrame ? pFrame : new SwXTextFrame( *pFmt );
1239             }
1240         }
1241         break;
1242         case SwHeaderStartNode:
1243         case SwFooterStartNode:
1244         {
1245             const bool bHeader = (SwHeaderStartNode == eType);
1246             const sal_uInt16 nPDescCount = rDoc.GetPageDescCnt();
1247             for(sal_uInt16 i = 0; i < nPDescCount; i++)
1248             {
1249                 const SwPageDesc& rDesc =
1250                     // C++ is retarded
1251                     const_cast<SwDoc const&>(rDoc).GetPageDesc( i );
1252                 const SwFrmFmt* pFrmFmtMaster = &rDesc.GetMaster();
1253                 const SwFrmFmt* pFrmFmtLeft = &rDesc.GetLeft();
1254 
1255                 SwFrmFmt* pHeadFootFmt = 0;
1256                 if (!lcl_IsStartNodeInFormat(bHeader, pSttNode, pFrmFmtMaster,
1257                             pHeadFootFmt))
1258                 {
1259                     lcl_IsStartNodeInFormat(bHeader, pSttNode, pFrmFmtLeft,
1260                             pHeadFootFmt);
1261                 }
1262 
1263                 if (pHeadFootFmt)
1264                 {
1265                     xParentText = SwXHeadFootText::CreateXHeadFootText(
1266                             *pHeadFootFmt, bHeader);
1267                 }
1268             }
1269         }
1270         break;
1271         case SwFootnoteStartNode:
1272         {
1273             const sal_uInt16 nFtnCnt = rDoc.GetFtnIdxs().Count();
1274             uno::Reference< text::XFootnote >  xRef;
1275             for (sal_uInt16 n = 0; n < nFtnCnt; ++n )
1276             {
1277                 const SwTxtFtn* pTxtFtn = rDoc.GetFtnIdxs()[ n ];
1278                 const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
1279                 pTxtFtn = rFtn.GetTxtFtn();
1280 #if OSL_DEBUG_LEVEL > 1
1281                 const SwStartNode* pTmpSttNode =
1282                         pTxtFtn->GetStartNode()->GetNode().
1283                                 FindSttNodeByType(SwFootnoteStartNode);
1284                 (void)pTmpSttNode;
1285 #endif
1286 
1287                 if (pSttNode == pTxtFtn->GetStartNode()->GetNode().
1288                                     FindSttNodeByType(SwFootnoteStartNode))
1289                 {
1290                     xParentText = SwXFootnote::CreateXFootnote(rDoc, rFtn);
1291                     break;
1292                 }
1293             }
1294         }
1295         break;
1296         default:
1297         {
1298             // then it is the body text
1299             const uno::Reference<frame::XModel> xModel =
1300                 rDoc.GetDocShell()->GetBaseModel();
1301             const uno::Reference< text::XTextDocument > xDoc(
1302                 xModel, uno::UNO_QUERY);
1303             xParentText = xDoc->getText();
1304         }
1305     }
1306     OSL_ENSURE(xParentText.is(), "no parent text?");
1307     return xParentText;
1308 }
1309 
1310 } // namespace sw
1311 
1312 uno::Reference< container::XEnumeration > SAL_CALL
1313 SwXTextRange::createContentEnumeration(const OUString& rServiceName)
1314 throw (uno::RuntimeException)
1315 {
1316     vos::OGuard g(Application::GetSolarMutex());
1317 
1318     if (!rServiceName.equalsAscii("com.sun.star.text.TextContent"))
1319     {
1320         throw uno::RuntimeException();
1321     }
1322 
1323     if (!GetDoc() || !m_pImpl->GetBookmark())
1324     {
1325         throw uno::RuntimeException();
1326     }
1327     const SwPosition aPos(GetDoc()->GetNodes().GetEndOfContent());
1328     const ::std::auto_ptr<SwUnoCrsr> pNewCrsr(
1329             m_pImpl->m_rDoc.CreateUnoCrsr(aPos, sal_False));
1330     if (!GetPositions(*pNewCrsr))
1331     {
1332         throw uno::RuntimeException();
1333     }
1334 
1335     const uno::Reference< container::XEnumeration > xRet =
1336         new SwXParaFrameEnumeration(*pNewCrsr, PARAFRAME_PORTION_TEXTRANGE);
1337     return xRet;
1338 }
1339 
1340 uno::Reference< container::XEnumeration > SAL_CALL
1341 SwXTextRange::createEnumeration() throw (uno::RuntimeException)
1342 {
1343     vos::OGuard g(Application::GetSolarMutex());
1344 
1345     if (!GetDoc() || !m_pImpl->GetBookmark())
1346     {
1347         throw uno::RuntimeException();
1348     }
1349     const SwPosition aPos(GetDoc()->GetNodes().GetEndOfContent());
1350     ::std::auto_ptr<SwUnoCrsr> pNewCrsr(
1351             m_pImpl->m_rDoc.CreateUnoCrsr(aPos, sal_False));
1352     if (!GetPositions(*pNewCrsr))
1353     {
1354         throw uno::RuntimeException();
1355     }
1356     if (!m_pImpl->m_xParentText.is())
1357     {
1358         getText();
1359     }
1360 
1361     const CursorType eSetType = (RANGE_IN_CELL == m_pImpl->m_eRangePosition)
1362             ? CURSOR_SELECTION_IN_TABLE : CURSOR_SELECTION;
1363     const uno::Reference< container::XEnumeration > xRet =
1364         new SwXParagraphEnumeration(m_pImpl->m_xParentText, pNewCrsr, eSetType);
1365     return xRet;
1366 }
1367 
1368 uno::Type SAL_CALL SwXTextRange::getElementType() throw (uno::RuntimeException)
1369 {
1370     return text::XTextRange::static_type();
1371 }
1372 
1373 sal_Bool SAL_CALL SwXTextRange::hasElements() throw (uno::RuntimeException)
1374 {
1375     return sal_True;
1376 }
1377 
1378 uno::Sequence< OUString > SAL_CALL
1379 SwXTextRange::getAvailableServiceNames() throw (uno::RuntimeException)
1380 {
1381     uno::Sequence< OUString > aRet(1);
1382     OUString* pArray = aRet.getArray();
1383     pArray[0] = OUString::createFromAscii("com.sun.star.text.TextContent");
1384     return aRet;
1385 }
1386 
1387 uno::Reference< beans::XPropertySetInfo > SAL_CALL
1388 SwXTextRange::getPropertySetInfo() throw (uno::RuntimeException)
1389 {
1390 	vos::OGuard aGuard(Application::GetSolarMutex());
1391 
1392     static uno::Reference< beans::XPropertySetInfo > xRef =
1393         m_pImpl->m_rPropSet.getPropertySetInfo();
1394 	return xRef;
1395 }
1396 
1397 void SAL_CALL
1398 SwXTextRange::setPropertyValue(
1399         const OUString& rPropertyName, const uno::Any& rValue)
1400 throw (beans::UnknownPropertyException, beans::PropertyVetoException,
1401         lang::IllegalArgumentException, lang::WrappedTargetException,
1402         uno::RuntimeException)
1403 {
1404 	vos::OGuard aGuard(Application::GetSolarMutex());
1405 
1406     if (!GetDoc() || !m_pImpl->GetBookmark())
1407     {
1408         throw uno::RuntimeException();
1409     }
1410 	SwPaM aPaM(GetDoc()->GetNodes());
1411     GetPositions(aPaM);
1412     SwUnoCursorHelper::SetPropertyValue(aPaM, m_pImpl->m_rPropSet,
1413             rPropertyName, rValue);
1414 }
1415 
1416 uno::Any SAL_CALL
1417 SwXTextRange::getPropertyValue(const OUString& rPropertyName)
1418 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1419         uno::RuntimeException)
1420 {
1421 	vos::OGuard aGuard(Application::GetSolarMutex());
1422 
1423     if (!GetDoc() || !m_pImpl->GetBookmark())
1424     {
1425         throw uno::RuntimeException();
1426     }
1427     SwPaM aPaM(GetDoc()->GetNodes());
1428     GetPositions(aPaM);
1429     return SwUnoCursorHelper::GetPropertyValue(aPaM, m_pImpl->m_rPropSet,
1430             rPropertyName);
1431 }
1432 
1433 void SAL_CALL
1434 SwXTextRange::addPropertyChangeListener(
1435         const ::rtl::OUString& /*rPropertyName*/,
1436         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1437 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1438     uno::RuntimeException)
1439 {
1440     OSL_ENSURE(false,
1441         "SwXTextRange::addPropertyChangeListener(): not implemented");
1442 }
1443 
1444 void SAL_CALL
1445 SwXTextRange::removePropertyChangeListener(
1446         const ::rtl::OUString& /*rPropertyName*/,
1447         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1448 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1449     uno::RuntimeException)
1450 {
1451     OSL_ENSURE(false,
1452         "SwXTextRange::removePropertyChangeListener(): not implemented");
1453 }
1454 
1455 void SAL_CALL
1456 SwXTextRange::addVetoableChangeListener(
1457         const ::rtl::OUString& /*rPropertyName*/,
1458         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1459 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1460     uno::RuntimeException)
1461 {
1462     OSL_ENSURE(false,
1463         "SwXTextRange::addVetoableChangeListener(): not implemented");
1464 }
1465 
1466 void SAL_CALL
1467 SwXTextRange::removeVetoableChangeListener(
1468         const ::rtl::OUString& /*rPropertyName*/,
1469         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1470 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1471         uno::RuntimeException)
1472 {
1473     OSL_ENSURE(false,
1474         "SwXTextRange::removeVetoableChangeListener(): not implemented");
1475 }
1476 
1477 beans::PropertyState SAL_CALL
1478 SwXTextRange::getPropertyState(const OUString& rPropertyName)
1479 throw (beans::UnknownPropertyException, uno::RuntimeException)
1480 {
1481 	vos::OGuard aGuard(Application::GetSolarMutex());
1482 
1483     if (!GetDoc() || !m_pImpl->GetBookmark())
1484     {
1485         throw uno::RuntimeException();
1486     }
1487     SwPaM aPaM(GetDoc()->GetNodes());
1488     GetPositions(aPaM);
1489     return SwUnoCursorHelper::GetPropertyState(aPaM, m_pImpl->m_rPropSet,
1490             rPropertyName);
1491 }
1492 
1493 uno::Sequence< beans::PropertyState > SAL_CALL
1494 SwXTextRange::getPropertyStates(const uno::Sequence< OUString >& rPropertyName)
1495 throw (beans::UnknownPropertyException, uno::RuntimeException)
1496 {
1497     vos::OGuard g(Application::GetSolarMutex());
1498 
1499     if (!GetDoc() || !m_pImpl->GetBookmark())
1500     {
1501         throw uno::RuntimeException();
1502     }
1503     SwPaM aPaM(GetDoc()->GetNodes());
1504     GetPositions(aPaM);
1505     return SwUnoCursorHelper::GetPropertyStates(aPaM, m_pImpl->m_rPropSet,
1506             rPropertyName);
1507 }
1508 
1509 void SAL_CALL SwXTextRange::setPropertyToDefault(const OUString& rPropertyName)
1510 throw (beans::UnknownPropertyException, uno::RuntimeException)
1511 {
1512 	vos::OGuard aGuard(Application::GetSolarMutex());
1513 
1514     if (!GetDoc() || !m_pImpl->GetBookmark())
1515     {
1516         throw uno::RuntimeException();
1517     }
1518     SwPaM aPaM(GetDoc()->GetNodes());
1519     GetPositions(aPaM);
1520     SwUnoCursorHelper::SetPropertyToDefault(aPaM, m_pImpl->m_rPropSet,
1521             rPropertyName);
1522 }
1523 
1524 uno::Any SAL_CALL
1525 SwXTextRange::getPropertyDefault(const OUString& rPropertyName)
1526 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1527         uno::RuntimeException)
1528 {
1529 	vos::OGuard aGuard(Application::GetSolarMutex());
1530 
1531     if (!GetDoc() || !m_pImpl->GetBookmark())
1532     {
1533         throw uno::RuntimeException();
1534     }
1535     SwPaM aPaM(GetDoc()->GetNodes());
1536     GetPositions(aPaM);
1537     return SwUnoCursorHelper::GetPropertyDefault(aPaM, m_pImpl->m_rPropSet,
1538             rPropertyName);
1539 }
1540 
1541 void SAL_CALL
1542 SwXTextRange::makeRedline(
1543     const ::rtl::OUString& rRedlineType,
1544     const uno::Sequence< beans::PropertyValue >& rRedlineProperties )
1545 throw (lang::IllegalArgumentException, uno::RuntimeException)
1546 {
1547     vos::OGuard aGuard(Application::GetSolarMutex());
1548 
1549     if (!GetDoc() || !m_pImpl->GetBookmark())
1550     {
1551         throw uno::RuntimeException();
1552     }
1553     SwPaM aPaM(GetDoc()->GetNodes());
1554     SwXTextRange::GetPositions(aPaM);
1555     SwUnoCursorHelper::makeRedline( aPaM, rRedlineType, rRedlineProperties );
1556 }
1557 
1558 /******************************************************************
1559  * SwXTextRanges
1560  ******************************************************************/
1561 
1562 class SwXTextRanges::Impl
1563     : public SwClient
1564 {
1565 
1566 public:
1567 
1568     ::std::vector< uno::Reference< text::XTextRange > > m_Ranges;
1569 
1570     Impl(SwPaM *const pPaM)
1571         : SwClient( (pPaM)
1572             ? pPaM->GetDoc()->CreateUnoCrsr(*pPaM->GetPoint())
1573             : 0 )
1574     {
1575         if (pPaM)
1576         {
1577             ::sw::DeepCopyPaM(*pPaM, *GetCursor());
1578         }
1579         MakeRanges();
1580     }
1581 
1582     ~Impl() {
1583         // Impl owns the cursor; delete it here: SolarMutex is locked
1584         delete GetRegisteredIn();
1585     }
1586 
1587     SwUnoCrsr * GetCursor() {
1588         return static_cast<SwUnoCrsr*>(
1589                 const_cast<SwModify*>(GetRegisteredIn()));
1590     }
1591 
1592     void MakeRanges();
1593 protected:
1594     // SwClient
1595     virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
1596 
1597 };
1598 
1599 void SwXTextRanges::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
1600 {
1601     ClientModify(this, pOld, pNew);
1602 }
1603 
1604 void SwXTextRanges::Impl::MakeRanges()
1605 {
1606     SwUnoCrsr *const pCursor = GetCursor();
1607     if (pCursor)
1608     {
1609         SwPaM *pTmpCursor = pCursor;
1610         do {
1611             const uno::Reference< text::XTextRange > xRange(
1612                     SwXTextRange::CreateXTextRange(
1613                         *pTmpCursor->GetDoc(),
1614                         *pTmpCursor->GetPoint(), pTmpCursor->GetMark()));
1615             if (xRange.is())
1616             {
1617                 m_Ranges.push_back(xRange);
1618             }
1619             pTmpCursor = static_cast<SwPaM*>(pTmpCursor->GetNext());
1620         }
1621         while (pTmpCursor != pCursor);
1622     }
1623 }
1624 
1625 const SwUnoCrsr* SwXTextRanges::GetCursor() const
1626 {
1627     return m_pImpl->GetCursor();
1628 }
1629 
1630 SwXTextRanges::SwXTextRanges(SwPaM *const pPaM)
1631     : m_pImpl( new SwXTextRanges::Impl(pPaM) )
1632 {
1633 }
1634 
1635 SwXTextRanges::~SwXTextRanges()
1636 {
1637 }
1638 
1639 const uno::Sequence< sal_Int8 > & SwXTextRanges::getUnoTunnelId()
1640 {
1641     static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
1642 	return aSeq;
1643 }
1644 
1645 sal_Int64 SAL_CALL
1646 SwXTextRanges::getSomething(const uno::Sequence< sal_Int8 >& rId)
1647 throw (uno::RuntimeException)
1648 {
1649     return ::sw::UnoTunnelImpl<SwXTextRanges>(rId, this);
1650 }
1651 
1652 /****************************************************************************
1653  *	Text positions
1654  * 	Bis zum ersten Zugriff auf eine TextPosition wird ein SwCursor gehalten,
1655  * danach wird ein Array mit uno::Reference< XTextPosition >  angelegt
1656  *
1657 ****************************************************************************/
1658 OUString SAL_CALL
1659 SwXTextRanges::getImplementationName() throw (uno::RuntimeException)
1660 {
1661 	return C2U("SwXTextRanges");
1662 }
1663 
1664 static char const*const g_ServicesTextRanges[] =
1665 {
1666     "com.sun.star.text.TextRanges",
1667 };
1668 static const size_t g_nServicesTextRanges(
1669     sizeof(g_ServicesTextRanges)/sizeof(g_ServicesTextRanges[0]));
1670 
1671 sal_Bool SAL_CALL SwXTextRanges::supportsService(const OUString& rServiceName)
1672 throw (uno::RuntimeException)
1673 {
1674     return ::sw::SupportsServiceImpl(
1675             g_nServicesTextRanges, g_ServicesTextRanges, rServiceName);
1676 }
1677 
1678 uno::Sequence< OUString > SAL_CALL
1679 SwXTextRanges::getSupportedServiceNames() throw (uno::RuntimeException)
1680 {
1681     return ::sw::GetSupportedServiceNamesImpl(
1682             g_nServicesTextRanges, g_ServicesTextRanges);
1683 }
1684 
1685 sal_Int32 SAL_CALL SwXTextRanges::getCount() throw (uno::RuntimeException)
1686 {
1687 	vos::OGuard aGuard(Application::GetSolarMutex());
1688 
1689     return static_cast<sal_Int32>(m_pImpl->m_Ranges.size());
1690 }
1691 
1692 uno::Any SAL_CALL SwXTextRanges::getByIndex(sal_Int32 nIndex)
1693 throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException,
1694         uno::RuntimeException)
1695 {
1696 	vos::OGuard aGuard(Application::GetSolarMutex());
1697 
1698     if ((nIndex < 0) ||
1699         (static_cast<size_t>(nIndex) >= m_pImpl->m_Ranges.size()))
1700     {
1701         throw lang::IndexOutOfBoundsException();
1702     }
1703     uno::Any ret;
1704     ret <<= (m_pImpl->m_Ranges.at(nIndex));
1705     return ret;
1706 }
1707 
1708 uno::Type SAL_CALL
1709 SwXTextRanges::getElementType() throw (uno::RuntimeException)
1710 {
1711     return text::XTextRange::static_type();
1712 }
1713 
1714 sal_Bool SAL_CALL SwXTextRanges::hasElements() throw (uno::RuntimeException)
1715 {
1716     // no mutex necessary: getCount() does locking
1717 	return getCount() > 0;
1718 }
1719 
1720 void SwUnoCursorHelper::SetString(SwCursor & rCursor, const OUString& rString)
1721 {
1722 	// Start/EndAction
1723     SwDoc *const pDoc = rCursor.GetDoc();
1724 	UnoActionContext aAction(pDoc);
1725     pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
1726     if (rCursor.HasMark())
1727     {
1728         pDoc->DeleteAndJoin(rCursor);
1729     }
1730     if (rString.getLength())
1731     {
1732         String aText(rString);
1733         const bool bSuccess( SwUnoCursorHelper::DocInsertStringSplitCR(
1734                     *pDoc, rCursor, aText, false ) );
1735         DBG_ASSERT( bSuccess, "DocInsertStringSplitCR" );
1736         (void) bSuccess;
1737         SwUnoCursorHelper::SelectPam(rCursor, true);
1738         rCursor.Left(rString.getLength(), CRSR_SKIP_CHARS, sal_False, sal_False);
1739     }
1740     pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
1741 }
1742 
1743 /******************************************************************
1744  * SwXParaFrameEnumeration
1745  ******************************************************************/
1746 
1747 class SwXParaFrameEnumeration::Impl
1748     : public SwClient
1749 {
1750 
1751 public:
1752 
1753     // created by hasMoreElements
1754     uno::Reference< text::XTextContent > m_xNextObject;
1755     FrameDependList_t m_Frames;
1756 
1757     Impl(SwPaM const & rPaM)
1758         : SwClient(rPaM.GetDoc()->CreateUnoCrsr(*rPaM.GetPoint(), sal_False))
1759     {
1760         if (rPaM.HasMark())
1761         {
1762             GetCursor()->SetMark();
1763             *GetCursor()->GetMark() = *rPaM.GetMark();
1764         }
1765     }
1766 
1767     ~Impl() {
1768         // Impl owns the cursor; delete it here: SolarMutex is locked
1769         delete GetRegisteredIn();
1770     }
1771 
1772     SwUnoCrsr * GetCursor() {
1773         return static_cast<SwUnoCrsr*>(
1774                 const_cast<SwModify*>(GetRegisteredIn()));
1775     }
1776 protected:
1777     // SwClient
1778     virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
1779 
1780 };
1781 
1782 struct InvalidFrameDepend {
1783     bool operator() (::boost::shared_ptr<SwDepend> const & rEntry)
1784     { return !rEntry->GetRegisteredIn(); }
1785 };
1786 
1787 void SwXParaFrameEnumeration::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
1788 {
1789     ClientModify(this, pOld, pNew);
1790     if(!GetRegisteredIn())
1791     {
1792         m_Frames.clear();
1793         m_xNextObject = 0;
1794     }
1795     else
1796     {
1797         // check if any frame went away...
1798         FrameDependList_t::iterator const iter =
1799             ::std::remove_if(m_Frames.begin(), m_Frames.end(),
1800                     InvalidFrameDepend());
1801         m_Frames.erase(iter, m_Frames.end());
1802     }
1803 }
1804 
1805 static sal_Bool
1806 lcl_CreateNextObject(SwUnoCrsr& i_rUnoCrsr,
1807         uno::Reference<text::XTextContent> & o_rNextObject,
1808         FrameDependList_t & i_rFrames)
1809 {
1810     if (!i_rFrames.size())
1811         return sal_False;
1812 
1813     SwFrmFmt *const pFormat = static_cast<SwFrmFmt*>(const_cast<SwModify*>(
1814                 i_rFrames.front()->GetRegisteredIn()));
1815     i_rFrames.pop_front();
1816     // the format should be valid here, otherwise the client
1817     // would have been removed in ::Modify
1818     // check for a shape first
1819     SwDrawContact* const pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement( *pFormat );
1820     if (pContact)
1821     {
1822         SdrObject * const pSdr = pContact->GetMaster();
1823         if (pSdr)
1824         {
1825             o_rNextObject.set(pSdr->getUnoShape(), uno::UNO_QUERY);
1826         }
1827     }
1828     else
1829     {
1830         const SwNodeIndex* pIdx = pFormat->GetCntnt().GetCntntIdx();
1831         DBG_ASSERT(pIdx, "where is the index?");
1832         SwNode const*const pNd =
1833             i_rUnoCrsr.GetDoc()->GetNodes()[ pIdx->GetIndex() + 1 ];
1834 
1835         const FlyCntType eType = (!pNd->IsNoTxtNode()) ? FLYCNTTYPE_FRM
1836             : ( (pNd->IsGrfNode()) ? FLYCNTTYPE_GRF : FLYCNTTYPE_OLE );
1837 
1838         const uno::Reference< container::XNamed >  xFrame =
1839             SwXFrames::GetObject(*pFormat, eType);
1840         o_rNextObject.set(xFrame, uno::UNO_QUERY);
1841     }
1842 
1843     return o_rNextObject.is();
1844 }
1845 
1846 /* -----------------------------03.04.00 10:15--------------------------------
1847     Description: Search for a FLYCNT text attribute at the cursor point
1848                 and fill the frame into the array
1849  ---------------------------------------------------------------------------*/
1850 static void
1851 lcl_FillFrame(SwClient & rEnum, SwUnoCrsr& rUnoCrsr,
1852         FrameDependList_t & rFrames)
1853 {
1854     // search for objects at the cursor - anchored at/as char
1855     SwTxtAttr const*const pTxtAttr =
1856         rUnoCrsr.GetNode()->GetTxtNode()->GetTxtAttrForCharAt(
1857             rUnoCrsr.GetPoint()->nContent.GetIndex(), RES_TXTATR_FLYCNT);
1858     if (pTxtAttr)
1859     {
1860         const SwFmtFlyCnt& rFlyCnt = pTxtAttr->GetFlyCnt();
1861         SwFrmFmt * const  pFrmFmt = rFlyCnt.GetFrmFmt();
1862         SwDepend * const pNewDepend = new SwDepend(&rEnum, pFrmFmt);
1863         rFrames.push_back( ::boost::shared_ptr<SwDepend>(pNewDepend) );
1864     }
1865 }
1866 
1867 SwXParaFrameEnumeration::SwXParaFrameEnumeration(
1868         const SwPaM& rPaM, const enum ParaFrameMode eParaFrameMode,
1869         SwFrmFmt *const pFmt)
1870     : m_pImpl( new SwXParaFrameEnumeration::Impl(rPaM) )
1871 {
1872     if (PARAFRAME_PORTION_PARAGRAPH == eParaFrameMode)
1873     {
1874         FrameDependSortList_t frames;
1875         ::CollectFrameAtNode(*m_pImpl.get(), rPaM.GetPoint()->nNode,
1876                 frames, false);
1877         ::std::transform(frames.begin(), frames.end(),
1878             ::std::back_inserter(m_pImpl->m_Frames),
1879             ::boost::bind(&FrameDependSortListEntry::pFrameDepend, _1));
1880     }
1881     else if (pFmt)
1882     {
1883         // create SwDepend for frame and insert into array
1884         SwDepend *const pNewDepend = new SwDepend(m_pImpl.get(), pFmt);
1885         m_pImpl->m_Frames.push_back(::boost::shared_ptr<SwDepend>(pNewDepend));
1886     }
1887     else if ((PARAFRAME_PORTION_CHAR == eParaFrameMode) ||
1888              (PARAFRAME_PORTION_TEXTRANGE == eParaFrameMode))
1889     {
1890         if (PARAFRAME_PORTION_TEXTRANGE == eParaFrameMode)
1891         {
1892             SwPosFlyFrms aFlyFrms;
1893             //get all frames that are bound at paragraph or at character
1894             rPaM.GetDoc()->GetAllFlyFmts(aFlyFrms, m_pImpl->GetCursor());
1895             for(sal_uInt16 i = 0; i < aFlyFrms.Count(); i++)
1896             {
1897                 SwPosFlyFrm* pPosFly = aFlyFrms[i];
1898                 SwFrmFmt *const pFrmFmt =
1899                     const_cast<SwFrmFmt*>(&pPosFly->GetFmt());
1900                 // create SwDepend for frame and insert into array
1901                 SwDepend *const pNewDepend =
1902                     new SwDepend(m_pImpl.get(), pFrmFmt);
1903                 m_pImpl->m_Frames.push_back(
1904                         ::boost::shared_ptr<SwDepend>(pNewDepend) );
1905             }
1906             //created from any text range
1907             if (m_pImpl->GetCursor()->HasMark())
1908             {
1909                 m_pImpl->GetCursor()->Normalize();
1910                 do
1911                 {
1912                     lcl_FillFrame(*m_pImpl.get(), *m_pImpl->GetCursor(),
1913                             m_pImpl->m_Frames);
1914                     m_pImpl->GetCursor()->Right(
1915                             1, CRSR_SKIP_CHARS, sal_False, sal_False);
1916                 }
1917                 while (*m_pImpl->GetCursor()->GetPoint() <
1918                         *m_pImpl->GetCursor()->GetMark());
1919             }
1920         }
1921         lcl_FillFrame(*m_pImpl.get(), *m_pImpl->GetCursor(), m_pImpl->m_Frames);
1922     }
1923 }
1924 
1925 SwXParaFrameEnumeration::~SwXParaFrameEnumeration()
1926 {
1927 }
1928 
1929 sal_Bool SAL_CALL
1930 SwXParaFrameEnumeration::hasMoreElements() throw (uno::RuntimeException)
1931 {
1932 	vos::OGuard aGuard(Application::GetSolarMutex());
1933 
1934     if (!m_pImpl->GetCursor())
1935         throw uno::RuntimeException();
1936 
1937     return (m_pImpl->m_xNextObject.is())
1938         ? sal_True
1939         : lcl_CreateNextObject(*m_pImpl->GetCursor(),
1940             m_pImpl->m_xNextObject, m_pImpl->m_Frames);
1941 }
1942 
1943 uno::Any SAL_CALL SwXParaFrameEnumeration::nextElement()
1944 throw (container::NoSuchElementException,
1945         lang::WrappedTargetException, uno::RuntimeException)
1946 {
1947 	vos::OGuard aGuard(Application::GetSolarMutex());
1948 
1949     if (!m_pImpl->GetCursor())
1950     {
1951         throw uno::RuntimeException();
1952     }
1953 
1954     if (!m_pImpl->m_xNextObject.is() && m_pImpl->m_Frames.size())
1955     {
1956         lcl_CreateNextObject(*m_pImpl->GetCursor(),
1957                 m_pImpl->m_xNextObject, m_pImpl->m_Frames);
1958     }
1959     if (!m_pImpl->m_xNextObject.is())
1960     {
1961         throw container::NoSuchElementException();
1962     }
1963     uno::Any aRet;
1964     aRet <<= m_pImpl->m_xNextObject;
1965     m_pImpl->m_xNextObject = 0;
1966     return aRet;
1967 }
1968 
1969 OUString SAL_CALL
1970 SwXParaFrameEnumeration::getImplementationName() throw (uno::RuntimeException)
1971 {
1972     return C2U("SwXParaFrameEnumeration");
1973 }
1974 
1975 static char const*const g_ServicesParaFrameEnum[] =
1976 {
1977     "com.sun.star.util.ContentEnumeration",
1978 };
1979 static const size_t g_nServicesParaFrameEnum(
1980     sizeof(g_ServicesParaFrameEnum)/sizeof(g_ServicesParaFrameEnum[0]));
1981 
1982 sal_Bool SAL_CALL
1983 SwXParaFrameEnumeration::supportsService(const OUString& rServiceName)
1984 throw (uno::RuntimeException)
1985 {
1986     return ::sw::SupportsServiceImpl(
1987             g_nServicesParaFrameEnum, g_ServicesParaFrameEnum, rServiceName);
1988 }
1989 
1990 uno::Sequence< OUString > SAL_CALL
1991 SwXParaFrameEnumeration::getSupportedServiceNames()
1992 throw (uno::RuntimeException)
1993 {
1994     return ::sw::GetSupportedServiceNamesImpl(
1995             g_nServicesParaFrameEnum, g_ServicesParaFrameEnum);
1996 }
1997 
1998