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