xref: /trunk/main/sw/source/core/unocore/unoobj2.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 protected:
519     // SwClient
520     virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
521 
522 };
523 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)524 void SwXParagraphEnumeration::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
525 {
526     ClientModify(this, pOld, pNew);
527 }
528 
SwXParagraphEnumeration(uno::Reference<text::XText> const & xParent,::std::auto_ptr<SwUnoCrsr> pCursor,const CursorType eType,SwStartNode const * const pStartNode,SwTable const * const pTable)529 SwXParagraphEnumeration::SwXParagraphEnumeration(
530         uno::Reference< text::XText > const& xParent,
531         ::std::auto_ptr<SwUnoCrsr> pCursor,
532         const CursorType eType,
533         SwStartNode const*const pStartNode, SwTable const*const pTable)
534     : m_pImpl( new SwXParagraphEnumeration::Impl(xParent, pCursor, eType,
535                     pStartNode, pTable) )
536 {
537 }
538 
~SwXParagraphEnumeration()539 SwXParagraphEnumeration::~SwXParagraphEnumeration()
540 {
541 }
542 
543 OUString SAL_CALL
getImplementationName()544 SwXParagraphEnumeration::getImplementationName()
545 {
546     return C2U("SwXParagraphEnumeration");
547 }
548 
549 static char const*const g_ServicesParagraphEnum[] =
550 {
551     "com.sun.star.text.ParagraphEnumeration",
552 };
553 static const size_t g_nServicesParagraphEnum(
554     sizeof(g_ServicesParagraphEnum)/sizeof(g_ServicesParagraphEnum[0]));
555 
556 sal_Bool SAL_CALL
supportsService(const OUString & rServiceName)557 SwXParagraphEnumeration::supportsService(const OUString& rServiceName)
558 {
559     return ::sw::SupportsServiceImpl(
560             g_nServicesParagraphEnum, g_ServicesParagraphEnum, rServiceName);
561 }
562 
563 uno::Sequence< OUString > SAL_CALL
getSupportedServiceNames()564 SwXParagraphEnumeration::getSupportedServiceNames()
565 {
566     return ::sw::GetSupportedServiceNamesImpl(
567             g_nServicesParagraphEnum, g_ServicesParagraphEnum);
568 }
569 
570 sal_Bool SAL_CALL
hasMoreElements()571 SwXParagraphEnumeration::hasMoreElements()
572 {
573     vos::OGuard aGuard(Application::GetSolarMutex());
574 
575     return (m_pImpl->m_bFirstParagraph) ? sal_True : m_pImpl->m_xNextPara.is();
576 }
577 
578 //!! compare to SwShellTableCrsr::FillRects() in viscrs.cxx
579 static SwTableNode *
lcl_FindTopLevelTable(SwTableNode * const pTblNode,SwTable const * const pOwnTable)580 lcl_FindTopLevelTable(
581         SwTableNode *const pTblNode, SwTable const*const pOwnTable)
582 {
583     // find top-most table in current context (section) level
584 
585     SwTableNode * pLast = pTblNode;
586     for (SwTableNode* pTmp = pLast;
587          pTmp != NULL  &&  &pTmp->GetTable() != pOwnTable;  /* we must not go up higher than the own table! */
588          pTmp = pTmp->StartOfSectionNode()->FindTableNode() )
589     {
590         pLast = pTmp;
591     }
592     return pLast;
593 }
594 
595 
596 static bool
lcl_CursorIsInSection(SwUnoCrsr const * const pUnoCrsr,SwStartNode const * const pOwnStartNode)597 lcl_CursorIsInSection(
598         SwUnoCrsr const*const pUnoCrsr, SwStartNode const*const pOwnStartNode)
599 {
600     // returns true if the cursor is in the section (or in a sub section!)
601     // represented by pOwnStartNode
602 
603     bool bRes = true;
604     if (pUnoCrsr && pOwnStartNode)
605     {
606         const SwEndNode * pOwnEndNode = pOwnStartNode->EndOfSectionNode();
607         bRes = pOwnStartNode->GetIndex() <= pUnoCrsr->Start()->nNode.GetIndex() &&
608                pUnoCrsr->End()->nNode.GetIndex() <= pOwnEndNode->GetIndex();
609     }
610     return bRes;
611 }
612 
613 
614 uno::Reference< text::XTextContent >
NextElement_Impl()615 SwXParagraphEnumeration::Impl::NextElement_Impl()
616 {
617     SwUnoCrsr *const pUnoCrsr = GetCursor();
618     if (!pUnoCrsr)
619     {
620         throw uno::RuntimeException();
621     }
622 
623     // check for exceeding selections
624     if (!m_bFirstParagraph &&
625         ((CURSOR_SELECTION == m_eCursorType) ||
626          (CURSOR_SELECTION_IN_TABLE == m_eCursorType)))
627     {
628         SwPosition* pStart = pUnoCrsr->Start();
629         const ::std::auto_ptr<SwUnoCrsr> aNewCrsr(
630             pUnoCrsr->GetDoc()->CreateUnoCrsr(*pStart, sal_False) );
631         // one may also go into tables here
632         if ((CURSOR_TBLTEXT != m_eCursorType) &&
633             (CURSOR_SELECTION_IN_TABLE != m_eCursorType))
634         {
635             aNewCrsr->SetRemainInSection( sal_False );
636         }
637 
638         // os 2005-01-14: This part is only necessary to detect movements out
639         // of a selection; if there is no selection we don't have to care
640         SwTableNode *const pTblNode = aNewCrsr->GetNode()->FindTableNode();
641         if (((CURSOR_TBLTEXT != m_eCursorType) &&
642             (CURSOR_SELECTION_IN_TABLE != m_eCursorType)) && pTblNode)
643         {
644             aNewCrsr->GetPoint()->nNode = pTblNode->EndOfSectionIndex();
645             aNewCrsr->Move(fnMoveForward, fnGoNode);
646         }
647         else
648         {
649             aNewCrsr->MovePara(fnParaNext, fnParaStart);
650         }
651         if (m_nEndIndex < aNewCrsr->Start()->nNode.GetIndex())
652         {
653             return 0;
654         }
655     }
656 
657     sal_Bool bInTable = sal_False;
658     if (!m_bFirstParagraph)
659     {
660         pUnoCrsr->SetRemainInSection( sal_False );
661         // what to do if already in a table?
662         SwTableNode * pTblNode = pUnoCrsr->GetNode()->FindTableNode();
663         pTblNode = lcl_FindTopLevelTable( pTblNode, m_pOwnTable );
664         if (pTblNode && (&pTblNode->GetTable() != m_pOwnTable))
665         {
666             // this is a foreign table: go to end
667             pUnoCrsr->GetPoint()->nNode = pTblNode->EndOfSectionIndex();
668             if (!pUnoCrsr->Move(fnMoveForward, fnGoNode))
669             {
670                 return 0;
671             }
672             bInTable = sal_True;
673         }
674     }
675 
676     uno::Reference< text::XTextContent >  xRef;
677     // the cursor must remain in the current section or a subsection
678     // before AND after the movement...
679     if (lcl_CursorIsInSection( pUnoCrsr, m_pOwnStartNode ) &&
680         (m_bFirstParagraph || bInTable ||
681         (pUnoCrsr->MovePara(fnParaNext, fnParaStart) &&
682             lcl_CursorIsInSection( pUnoCrsr, m_pOwnStartNode ))))
683     {
684         SwPosition* pStart = pUnoCrsr->Start();
685         const sal_Int32 nFirstContent =
686             (m_bFirstParagraph) ? m_nFirstParaStart : -1;
687         const sal_Int32 nLastContent =
688             (m_nEndIndex == pStart->nNode.GetIndex()) ? m_nLastParaEnd : -1;
689 
690         // position in a table, or in a simple paragraph?
691         SwTableNode * pTblNode = pUnoCrsr->GetNode()->FindTableNode();
692         pTblNode = lcl_FindTopLevelTable( pTblNode, m_pOwnTable );
693         if (/*CURSOR_TBLTEXT != eCursorType && CURSOR_SELECTION_IN_TABLE != eCursorType && */
694             pTblNode && (&pTblNode->GetTable() != m_pOwnTable))
695         {
696             // this is a foreign table
697             SwFrmFmt* pTableFmt =
698                 static_cast<SwFrmFmt*>(pTblNode->GetTable().GetFrmFmt());
699             text::XTextTable *const pTable =
700                 SwXTextTables::GetObject( *pTableFmt );
701             xRef = static_cast<text::XTextContent*>(
702                     static_cast<SwXTextTable*>(pTable));
703         }
704         else
705         {
706             text::XText *const pText = m_xParentText.get();
707             xRef = SwXParagraph::CreateXParagraph(*pUnoCrsr->GetDoc(),
708                 *pStart->nNode.GetNode().GetTxtNode(),
709                 static_cast<SwXText*>(pText), nFirstContent, nLastContent);
710         }
711     }
712 
713     return xRef;
714 }
715 
nextElement()716 uno::Any SAL_CALL SwXParagraphEnumeration::nextElement()
717 {
718     vos::OGuard aGuard(Application::GetSolarMutex());
719 
720     if (m_pImpl->m_bFirstParagraph)
721     {
722         m_pImpl->m_xNextPara = m_pImpl->NextElement_Impl();
723         m_pImpl->m_bFirstParagraph = false;
724     }
725     const uno::Reference< text::XTextContent > xRef = m_pImpl->m_xNextPara;
726     if (!xRef.is())
727     {
728         throw container::NoSuchElementException();
729     }
730     m_pImpl->m_xNextPara = m_pImpl->NextElement_Impl();
731 
732     uno::Any aRet;
733     aRet <<= xRef;
734     return aRet;
735 }
736 
737 /******************************************************************
738  * SwXTextRange
739  ******************************************************************/
740 
741 class SwXTextRange::Impl
742     : public SwClient
743 {
744 
745 public:
746 
747     const SfxItemPropertySet &  m_rPropSet;
748     const enum RangePosition    m_eRangePosition;
749     SwDoc &                     m_rDoc;
750     uno::Reference<text::XText> m_xParentText;
751     SwDepend            m_ObjectDepend; // register at format of table or frame
752     ::sw::mark::IMark * m_pMark;
753 
Impl(SwDoc & rDoc,const enum RangePosition eRange,SwFrmFmt * const pTblFmt=0,const uno::Reference<text::XText> & xParent=0)754     Impl(   SwDoc & rDoc, const enum RangePosition eRange,
755             SwFrmFmt *const pTblFmt = 0,
756             const uno::Reference< text::XText > & xParent = 0)
757         : SwClient()
758         , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
759         , m_eRangePosition(eRange)
760         , m_rDoc(rDoc)
761         , m_xParentText(xParent)
762         , m_ObjectDepend(this, pTblFmt)
763         , m_pMark(0)
764     {
765     }
766 
~Impl()767     ~Impl()
768     {
769         // Impl owns the bookmark; delete it here: SolarMutex is locked
770         Invalidate();
771     }
772 
Invalidate()773     void Invalidate()
774     {
775         if (m_pMark)
776         {
777             m_rDoc.getIDocumentMarkAccess()->deleteMark(m_pMark);
778             m_pMark = 0;
779         }
780     }
781 
GetBookmark() const782     const ::sw::mark::IMark * GetBookmark() const { return m_pMark; }
783 protected:
784     // SwClient
785     virtual void    Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
786 
787 };
788 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)789 void SwXTextRange::Impl::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
790 {
791     const bool bAlreadyRegistered = 0 != GetRegisteredIn();
792     ClientModify(this, pOld, pNew);
793     if (m_ObjectDepend.GetRegisteredIn())
794     {
795         ClientModify(&m_ObjectDepend, pOld, pNew);
796         // if the depend was removed then the range must be removed too
797         if (!m_ObjectDepend.GetRegisteredIn() && GetRegisteredIn())
798         {
799             const_cast<SwModify*>(GetRegisteredIn())->Remove(this);
800         }
801         // or if the range has been removed but the depend ist still
802         // connected then the depend must be removed
803         else if (bAlreadyRegistered && !GetRegisteredIn() &&
804                     m_ObjectDepend.GetRegisteredIn())
805         {
806             const_cast<SwModify*>(m_ObjectDepend.GetRegisteredIn())
807                 ->Remove(& m_ObjectDepend);
808         }
809     }
810     if (!GetRegisteredIn())
811     {
812         m_pMark = 0;
813     }
814 }
815 
816 
SwXTextRange(SwPaM & rPam,const uno::Reference<text::XText> & xParent,const enum RangePosition eRange)817 SwXTextRange::SwXTextRange(SwPaM& rPam,
818         const uno::Reference< text::XText > & xParent,
819         const enum RangePosition eRange)
820     : m_pImpl( new SwXTextRange::Impl(*rPam.GetDoc(), eRange, 0, xParent) )
821 {
822     SetPositions(rPam);
823 }
824 
SwXTextRange(SwFrmFmt & rTblFmt)825 SwXTextRange::SwXTextRange(SwFrmFmt& rTblFmt)
826     : m_pImpl(
827         new SwXTextRange::Impl(*rTblFmt.GetDoc(), RANGE_IS_TABLE, &rTblFmt) )
828 {
829     SwTable *const pTable = SwTable::FindTable( &rTblFmt );
830     SwTableNode *const pTblNode = pTable->GetTableNode();
831     SwPosition aPosition( *pTblNode );
832     SwPaM aPam( aPosition );
833 
834     SetPositions( aPam );
835 }
836 
~SwXTextRange()837 SwXTextRange::~SwXTextRange()
838 {
839 }
840 
GetDoc() const841 const SwDoc * SwXTextRange::GetDoc() const
842 {
843     return & m_pImpl->m_rDoc;
844 }
845 
GetDoc()846 SwDoc * SwXTextRange::GetDoc()
847 {
848     return & m_pImpl->m_rDoc;
849 }
850 
851 
Invalidate()852 void SwXTextRange::Invalidate()
853 {
854     m_pImpl->Invalidate();
855 }
856 
SetPositions(const SwPaM & rPam)857 void SwXTextRange::SetPositions(const SwPaM& rPam)
858 {
859     m_pImpl->Invalidate();
860     IDocumentMarkAccess* const pMA = m_pImpl->m_rDoc.getIDocumentMarkAccess();
861     m_pImpl->m_pMark = pMA->makeMark(rPam, ::rtl::OUString(),
862                 IDocumentMarkAccess::UNO_BOOKMARK);
863     m_pImpl->m_pMark->Add(m_pImpl.get());
864 }
865 
DeleteAndInsert(const::rtl::OUString & rText,const bool bForceExpandHints)866 void SwXTextRange::DeleteAndInsert(
867         const ::rtl::OUString& rText, const bool bForceExpandHints)
868 {
869     if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
870     {
871         // setString on table not allowed
872         throw uno::RuntimeException();
873     }
874 
875     const SwPosition aPos(GetDoc()->GetNodes().GetEndOfContent());
876     SwCursor aCursor(aPos, 0, false);
877     if (GetPositions(aCursor))
878     {
879         UnoActionContext aAction(& m_pImpl->m_rDoc);
880         m_pImpl->m_rDoc.GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
881         if (aCursor.HasMark())
882         {
883             m_pImpl->m_rDoc.DeleteAndJoin(aCursor);
884         }
885 
886         if (rText.getLength())
887         {
888             SwUnoCursorHelper::DocInsertStringSplitCR(
889                     m_pImpl->m_rDoc, aCursor, rText, bForceExpandHints);
890 
891             SwUnoCursorHelper::SelectPam(aCursor, true);
892             aCursor.Left(rText.getLength(), CRSR_SKIP_CHARS, sal_False, sal_False);
893         }
894         SetPositions(aCursor);
895         m_pImpl->m_rDoc.GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
896     }
897 }
898 
getUnoTunnelId()899 const uno::Sequence< sal_Int8 > & SwXTextRange::getUnoTunnelId()
900 {
901     static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
902     return aSeq;
903 }
904 
905 // XUnoTunnel
906 sal_Int64 SAL_CALL
getSomething(const uno::Sequence<sal_Int8> & rId)907 SwXTextRange::getSomething(const uno::Sequence< sal_Int8 >& rId)
908 {
909     return ::sw::UnoTunnelImpl<SwXTextRange>(rId, this);
910 }
911 
912 OUString SAL_CALL
getImplementationName()913 SwXTextRange::getImplementationName()
914 {
915     return OUString::createFromAscii("SwXTextRange");
916 }
917 
918 static char const*const g_ServicesTextRange[] =
919 {
920     "com.sun.star.text.TextRange",
921     "com.sun.star.style.CharacterProperties",
922     "com.sun.star.style.CharacterPropertiesAsian",
923     "com.sun.star.style.CharacterPropertiesComplex",
924     "com.sun.star.style.ParagraphProperties",
925     "com.sun.star.style.ParagraphPropertiesAsian",
926     "com.sun.star.style.ParagraphPropertiesComplex",
927 };
928 static const size_t g_nServicesTextRange(
929     sizeof(g_ServicesTextRange)/sizeof(g_ServicesTextRange[0]));
930 
supportsService(const OUString & rServiceName)931 sal_Bool SAL_CALL SwXTextRange::supportsService(const OUString& rServiceName)
932 {
933     return ::sw::SupportsServiceImpl(
934             g_nServicesTextRange, g_ServicesTextRange, rServiceName);
935 }
936 
937 uno::Sequence< OUString > SAL_CALL
getSupportedServiceNames()938 SwXTextRange::getSupportedServiceNames()
939 {
940     return ::sw::GetSupportedServiceNamesImpl(
941             g_nServicesTextRange, g_ServicesTextRange);
942 }
943 
944 uno::Reference< text::XText > SAL_CALL
getText()945 SwXTextRange::getText()
946 {
947     vos::OGuard aGuard(Application::GetSolarMutex());
948 
949     if (!m_pImpl->m_xParentText.is())
950     {
951         if (m_pImpl->m_eRangePosition == RANGE_IS_TABLE &&
952             m_pImpl->m_ObjectDepend.GetRegisteredIn())
953         {
954             SwFrmFmt const*const pTblFmt = static_cast<SwFrmFmt const*>(
955                     m_pImpl->m_ObjectDepend.GetRegisteredIn());
956             SwTable const*const pTable = SwTable::FindTable( pTblFmt );
957             SwTableNode const*const pTblNode = pTable->GetTableNode();
958             const SwPosition aPosition( *pTblNode );
959             m_pImpl->m_xParentText =
960                 ::sw::CreateParentXText(m_pImpl->m_rDoc, aPosition);
961         }
962     }
963     OSL_ENSURE(m_pImpl->m_xParentText.is(), "SwXTextRange::getText: no text");
964     return m_pImpl->m_xParentText;
965 }
966 
967 uno::Reference< text::XTextRange > SAL_CALL
getStart()968 SwXTextRange::getStart()
969 {
970     vos::OGuard aGuard(Application::GetSolarMutex());
971 
972     uno::Reference< text::XTextRange >  xRet;
973     ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
974     if (!m_pImpl->m_xParentText.is())
975     {
976         getText();
977     }
978     if(pBkmk)
979     {
980         SwPaM aPam(pBkmk->GetMarkStart());
981         xRet = new SwXTextRange(aPam, m_pImpl->m_xParentText);
982     }
983     else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
984     {
985         // start and end are this, if its a table
986         xRet = this;
987     }
988     else
989     {
990         throw uno::RuntimeException();
991     }
992     return xRet;
993 }
994 
995 uno::Reference< text::XTextRange > SAL_CALL
getEnd()996 SwXTextRange::getEnd()
997 {
998     vos::OGuard aGuard(Application::GetSolarMutex());
999 
1000     uno::Reference< text::XTextRange >  xRet;
1001     ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
1002     if (!m_pImpl->m_xParentText.is())
1003     {
1004         getText();
1005     }
1006     if(pBkmk)
1007     {
1008         SwPaM aPam(pBkmk->GetMarkEnd());
1009         xRet = new SwXTextRange(aPam, m_pImpl->m_xParentText);
1010     }
1011     else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
1012     {
1013         // start and end are this, if its a table
1014         xRet = this;
1015     }
1016     else
1017     {
1018         throw uno::RuntimeException();
1019     }
1020     return xRet;
1021 }
1022 
getString()1023 OUString SAL_CALL SwXTextRange::getString()
1024 {
1025     vos::OGuard aGuard(Application::GetSolarMutex());
1026 
1027     OUString sRet;
1028     // for tables there is no bookmark, thus also no text
1029     // one could export the table as ASCII here maybe?
1030     SwPaM aPaM(GetDoc()->GetNodes());
1031     if (GetPositions(aPaM) && aPaM.HasMark())
1032     {
1033         SwUnoCursorHelper::GetTextFromPam(aPaM, sRet);
1034     }
1035     return sRet;
1036 }
1037 
setString(const OUString & rString)1038 void SAL_CALL SwXTextRange::setString(const OUString& rString)
1039 {
1040     vos::OGuard aGuard(Application::GetSolarMutex());
1041 
1042     DeleteAndInsert(rString, false);
1043 }
1044 
GetPositions(SwPaM & rToFill) const1045 bool SwXTextRange::GetPositions(SwPaM& rToFill) const
1046 {
1047     ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
1048     if(pBkmk)
1049     {
1050         *rToFill.GetPoint() = pBkmk->GetMarkPos();
1051         if(pBkmk->IsExpanded())
1052         {
1053             rToFill.SetMark();
1054             *rToFill.GetMark() = pBkmk->GetOtherMarkPos();
1055         }
1056         else
1057         {
1058             rToFill.DeleteMark();
1059         }
1060         return true;
1061     }
1062     return false;
1063 }
1064 
1065 namespace sw {
1066 
XTextRangeToSwPaM(SwUnoInternalPaM & rToFill,const uno::Reference<text::XTextRange> & xTextRange)1067 bool XTextRangeToSwPaM( SwUnoInternalPaM & rToFill,
1068         const uno::Reference< text::XTextRange > & xTextRange)
1069 {
1070     bool bRet = false;
1071 
1072     uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
1073     SwXTextRange* pRange = 0;
1074     OTextCursorHelper* pCursor = 0;
1075     SwXTextPortion* pPortion = 0;
1076     SwXText* pText = 0;
1077     SwXParagraph* pPara = 0;
1078     if(xRangeTunnel.is())
1079     {
1080         pRange  = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
1081         pCursor =
1082             ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
1083         pPortion=
1084             ::sw::UnoTunnelGetImplementation<SwXTextPortion>(xRangeTunnel);
1085         pText   = ::sw::UnoTunnelGetImplementation<SwXText>(xRangeTunnel);
1086         pPara   = ::sw::UnoTunnelGetImplementation<SwXParagraph>(xRangeTunnel);
1087     }
1088 
1089     // if it's a text then create a temporary cursor there and re-use
1090     // the pCursor variable
1091     // #i108489#: Reference in outside scope to keep cursor alive
1092     uno::Reference< text::XTextCursor > xTextCursor;
1093     if (pText)
1094     {
1095         xTextCursor.set( pText->CreateCursor() );
1096         xTextCursor->gotoEnd(sal_True);
1097         const uno::Reference<lang::XUnoTunnel> xCrsrTunnel(
1098                 xTextCursor, uno::UNO_QUERY);
1099         pCursor =
1100             ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xCrsrTunnel);
1101     }
1102     if(pRange && pRange->GetDoc() == rToFill.GetDoc())
1103     {
1104         bRet = pRange->GetPositions(rToFill);
1105     }
1106     else
1107     {
1108         if (pPara)
1109         {
1110             bRet = pPara->SelectPaM(rToFill);
1111         }
1112         else
1113         {
1114             SwDoc* const pDoc = (pCursor) ? pCursor->GetDoc()
1115                 : ((pPortion) ? pPortion->GetCursor()->GetDoc() : 0);
1116             const SwPaM* const pUnoCrsr = (pCursor) ? pCursor->GetPaM()
1117                 : ((pPortion) ? pPortion->GetCursor() : 0);
1118             if (pUnoCrsr && pDoc == rToFill.GetDoc())
1119             {
1120                 DBG_ASSERT((SwPaM*)pUnoCrsr->GetNext() == pUnoCrsr,
1121                         "what to do about rings?");
1122                 bRet = true;
1123                 *rToFill.GetPoint() = *pUnoCrsr->GetPoint();
1124                 if (pUnoCrsr->HasMark())
1125                 {
1126                     rToFill.SetMark();
1127                     *rToFill.GetMark() = *pUnoCrsr->GetMark();
1128                 }
1129                 else
1130                     rToFill.DeleteMark();
1131             }
1132         }
1133     }
1134     return bRet;
1135 }
1136 
1137 static bool
lcl_IsStartNodeInFormat(const bool bHeader,SwStartNode * const pSttNode,SwFrmFmt const * const pFrmFmt,SwFrmFmt * & rpFormat)1138 lcl_IsStartNodeInFormat(const bool bHeader, SwStartNode *const pSttNode,
1139     SwFrmFmt const*const pFrmFmt, SwFrmFmt*& rpFormat)
1140 {
1141     bool bRet = false;
1142     const SfxItemSet& rSet = pFrmFmt->GetAttrSet();
1143     const SfxPoolItem* pItem;
1144     if (SFX_ITEM_SET == rSet.GetItemState(
1145             static_cast<sal_uInt16>(bHeader ? RES_HEADER : RES_FOOTER),
1146             sal_True, &pItem))
1147     {
1148         SfxPoolItem *const pItemNonConst(const_cast<SfxPoolItem *>(pItem));
1149         SwFrmFmt *const pHeadFootFmt = (bHeader) ?
1150             static_cast<SwFmtHeader*>(pItemNonConst)->GetHeaderFmt() :
1151             static_cast<SwFmtFooter*>(pItemNonConst)->GetFooterFmt();
1152         if (pHeadFootFmt)
1153         {
1154             const SwFmtCntnt& rFlyCntnt = pHeadFootFmt->GetCntnt();
1155             const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
1156             SwStartNode const*const pCurSttNode = rNode.FindSttNodeByType(
1157                 (bHeader) ? SwHeaderStartNode : SwFooterStartNode);
1158             if (pCurSttNode && (pCurSttNode == pSttNode))
1159             {
1160                 rpFormat = pHeadFootFmt;
1161                 bRet = true;
1162             }
1163         }
1164     }
1165     return bRet;
1166 }
1167 
1168 } // namespace sw
1169 
1170 uno::Reference< text::XTextRange >
CreateXTextRange(SwDoc & rDoc,const SwPosition & rPos,const SwPosition * const pMark)1171 SwXTextRange::CreateXTextRange(
1172     SwDoc & rDoc, const SwPosition& rPos, const SwPosition *const pMark)
1173 {
1174     const uno::Reference<text::XText> xParentText(
1175             ::sw::CreateParentXText(rDoc, rPos));
1176     const ::std::auto_ptr<SwUnoCrsr> pNewCrsr(
1177             rDoc.CreateUnoCrsr(rPos, sal_False));
1178     if(pMark)
1179     {
1180         pNewCrsr->SetMark();
1181         *pNewCrsr->GetMark() = *pMark;
1182     }
1183     const bool isCell( dynamic_cast<SwXCell*>(xParentText.get()) );
1184     const uno::Reference< text::XTextRange > xRet(
1185         new SwXTextRange(*pNewCrsr, xParentText,
1186             isCell ? RANGE_IN_CELL : RANGE_IN_TEXT) );
1187     return xRet;
1188 }
1189 
1190 namespace sw {
1191 
1192 uno::Reference< text::XText >
CreateParentXText(SwDoc & rDoc,const SwPosition & rPos)1193 CreateParentXText(SwDoc & rDoc, const SwPosition& rPos)
1194 {
1195     uno::Reference< text::XText > xParentText;
1196     SwStartNode* pSttNode = rPos.nNode.GetNode().StartOfSectionNode();
1197     while(pSttNode && pSttNode->IsSectionNode())
1198     {
1199         pSttNode = pSttNode->StartOfSectionNode();
1200     }
1201     SwStartNodeType eType = pSttNode->GetStartNodeType();
1202     switch(eType)
1203     {
1204         case SwTableBoxStartNode:
1205         {
1206             SwTableNode const*const pTblNode = pSttNode->FindTableNode();
1207             SwFrmFmt *const pTableFmt =
1208                 static_cast<SwFrmFmt*>(pTblNode->GetTable().GetFrmFmt());
1209             SwTableBox *const  pBox = pSttNode->GetTblBox();
1210 
1211             xParentText = (pBox)
1212                 ? SwXCell::CreateXCell( pTableFmt, pBox )
1213                 : new SwXCell( pTableFmt, *pSttNode );
1214         }
1215         break;
1216         case SwFlyStartNode:
1217         {
1218             SwFrmFmt *const pFmt = pSttNode->GetFlyFmt();
1219             if (0 != pFmt)
1220             {
1221                 SwXTextFrame* pFrame = SwIterator<SwXTextFrame,SwFmt>::FirstElement( *pFmt );
1222                 xParentText = pFrame ? pFrame : new SwXTextFrame( *pFmt );
1223             }
1224         }
1225         break;
1226         case SwHeaderStartNode:
1227         case SwFooterStartNode:
1228         {
1229             const bool bHeader = (SwHeaderStartNode == eType);
1230             const sal_uInt16 nPDescCount = rDoc.GetPageDescCnt();
1231             for(sal_uInt16 i = 0; i < nPDescCount; i++)
1232             {
1233                 const SwPageDesc& rDesc =
1234                     // C++ is retarded
1235                     const_cast<SwDoc const&>(rDoc).GetPageDesc( i );
1236                 const SwFrmFmt* pFrmFmtMaster = &rDesc.GetMaster();
1237                 const SwFrmFmt* pFrmFmtLeft = &rDesc.GetLeft();
1238 
1239                 SwFrmFmt* pHeadFootFmt = 0;
1240                 if (!lcl_IsStartNodeInFormat(bHeader, pSttNode, pFrmFmtMaster,
1241                             pHeadFootFmt))
1242                 {
1243                     lcl_IsStartNodeInFormat(bHeader, pSttNode, pFrmFmtLeft,
1244                             pHeadFootFmt);
1245                 }
1246 
1247                 if (pHeadFootFmt)
1248                 {
1249                     xParentText = SwXHeadFootText::CreateXHeadFootText(
1250                             *pHeadFootFmt, bHeader);
1251                 }
1252             }
1253         }
1254         break;
1255         case SwFootnoteStartNode:
1256         {
1257             const sal_uInt16 nFtnCnt = rDoc.GetFtnIdxs().Count();
1258             uno::Reference< text::XFootnote >  xRef;
1259             for (sal_uInt16 n = 0; n < nFtnCnt; ++n )
1260             {
1261                 const SwTxtFtn* pTxtFtn = rDoc.GetFtnIdxs()[ n ];
1262                 const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
1263                 pTxtFtn = rFtn.GetTxtFtn();
1264 #if OSL_DEBUG_LEVEL > 1
1265                 const SwStartNode* pTmpSttNode =
1266                         pTxtFtn->GetStartNode()->GetNode().
1267                                 FindSttNodeByType(SwFootnoteStartNode);
1268                 (void)pTmpSttNode;
1269 #endif
1270 
1271                 if (pSttNode == pTxtFtn->GetStartNode()->GetNode().
1272                                     FindSttNodeByType(SwFootnoteStartNode))
1273                 {
1274                     xParentText = SwXFootnote::CreateXFootnote(rDoc, rFtn);
1275                     break;
1276                 }
1277             }
1278         }
1279         break;
1280         default:
1281         {
1282             // then it is the body text
1283             const uno::Reference<frame::XModel> xModel =
1284                 rDoc.GetDocShell()->GetBaseModel();
1285             const uno::Reference< text::XTextDocument > xDoc(
1286                 xModel, uno::UNO_QUERY);
1287             xParentText = xDoc->getText();
1288         }
1289     }
1290     OSL_ENSURE(xParentText.is(), "no parent text?");
1291     return xParentText;
1292 }
1293 
1294 } // namespace sw
1295 
1296 uno::Reference< container::XEnumeration > SAL_CALL
createContentEnumeration(const OUString & rServiceName)1297 SwXTextRange::createContentEnumeration(const OUString& rServiceName)
1298 {
1299     vos::OGuard g(Application::GetSolarMutex());
1300 
1301     if (!rServiceName.equalsAscii("com.sun.star.text.TextContent"))
1302     {
1303         throw uno::RuntimeException();
1304     }
1305 
1306     if (!GetDoc() || !m_pImpl->GetBookmark())
1307     {
1308         throw uno::RuntimeException();
1309     }
1310     const SwPosition aPos(GetDoc()->GetNodes().GetEndOfContent());
1311     const ::std::auto_ptr<SwUnoCrsr> pNewCrsr(
1312             m_pImpl->m_rDoc.CreateUnoCrsr(aPos, sal_False));
1313     if (!GetPositions(*pNewCrsr))
1314     {
1315         throw uno::RuntimeException();
1316     }
1317 
1318     const uno::Reference< container::XEnumeration > xRet =
1319         new SwXParaFrameEnumeration(*pNewCrsr, PARAFRAME_PORTION_TEXTRANGE);
1320     return xRet;
1321 }
1322 
1323 uno::Reference< container::XEnumeration > SAL_CALL
createEnumeration()1324 SwXTextRange::createEnumeration()
1325 {
1326     vos::OGuard g(Application::GetSolarMutex());
1327 
1328     if (!GetDoc() || !m_pImpl->GetBookmark())
1329     {
1330         throw uno::RuntimeException();
1331     }
1332     const SwPosition aPos(GetDoc()->GetNodes().GetEndOfContent());
1333     ::std::auto_ptr<SwUnoCrsr> pNewCrsr(
1334             m_pImpl->m_rDoc.CreateUnoCrsr(aPos, sal_False));
1335     if (!GetPositions(*pNewCrsr))
1336     {
1337         throw uno::RuntimeException();
1338     }
1339     if (!m_pImpl->m_xParentText.is())
1340     {
1341         getText();
1342     }
1343 
1344     const CursorType eSetType = (RANGE_IN_CELL == m_pImpl->m_eRangePosition)
1345             ? CURSOR_SELECTION_IN_TABLE : CURSOR_SELECTION;
1346     const uno::Reference< container::XEnumeration > xRet =
1347         new SwXParagraphEnumeration(m_pImpl->m_xParentText, pNewCrsr, eSetType);
1348     return xRet;
1349 }
1350 
getElementType()1351 uno::Type SAL_CALL SwXTextRange::getElementType()
1352 {
1353     return text::XTextRange::static_type();
1354 }
1355 
hasElements()1356 sal_Bool SAL_CALL SwXTextRange::hasElements()
1357 {
1358     return sal_True;
1359 }
1360 
1361 uno::Sequence< OUString > SAL_CALL
getAvailableServiceNames()1362 SwXTextRange::getAvailableServiceNames()
1363 {
1364     uno::Sequence< OUString > aRet(1);
1365     OUString* pArray = aRet.getArray();
1366     pArray[0] = OUString::createFromAscii("com.sun.star.text.TextContent");
1367     return aRet;
1368 }
1369 
1370 uno::Reference< beans::XPropertySetInfo > SAL_CALL
getPropertySetInfo()1371 SwXTextRange::getPropertySetInfo()
1372 {
1373     vos::OGuard aGuard(Application::GetSolarMutex());
1374 
1375     static uno::Reference< beans::XPropertySetInfo > xRef =
1376         m_pImpl->m_rPropSet.getPropertySetInfo();
1377     return xRef;
1378 }
1379 
1380 void SAL_CALL
setPropertyValue(const OUString & rPropertyName,const uno::Any & rValue)1381 SwXTextRange::setPropertyValue(
1382         const OUString& rPropertyName, const uno::Any& rValue)
1383 {
1384     vos::OGuard aGuard(Application::GetSolarMutex());
1385 
1386     if (!GetDoc() || !m_pImpl->GetBookmark())
1387     {
1388         throw uno::RuntimeException();
1389     }
1390     SwPaM aPaM(GetDoc()->GetNodes());
1391     GetPositions(aPaM);
1392     SwUnoCursorHelper::SetPropertyValue(aPaM, m_pImpl->m_rPropSet,
1393             rPropertyName, rValue);
1394 }
1395 
1396 uno::Any SAL_CALL
getPropertyValue(const OUString & rPropertyName)1397 SwXTextRange::getPropertyValue(const OUString& rPropertyName)
1398 {
1399     vos::OGuard aGuard(Application::GetSolarMutex());
1400 
1401     if (!GetDoc() || !m_pImpl->GetBookmark())
1402     {
1403         throw uno::RuntimeException();
1404     }
1405     SwPaM aPaM(GetDoc()->GetNodes());
1406     GetPositions(aPaM);
1407     return SwUnoCursorHelper::GetPropertyValue(aPaM, m_pImpl->m_rPropSet,
1408             rPropertyName);
1409 }
1410 
1411 void SAL_CALL
addPropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)1412 SwXTextRange::addPropertyChangeListener(
1413         const ::rtl::OUString& /*rPropertyName*/,
1414         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1415 {
1416     OSL_ENSURE(false,
1417         "SwXTextRange::addPropertyChangeListener(): not implemented");
1418 }
1419 
1420 void SAL_CALL
removePropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)1421 SwXTextRange::removePropertyChangeListener(
1422         const ::rtl::OUString& /*rPropertyName*/,
1423         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1424 {
1425     OSL_ENSURE(false,
1426         "SwXTextRange::removePropertyChangeListener(): not implemented");
1427 }
1428 
1429 void SAL_CALL
addVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)1430 SwXTextRange::addVetoableChangeListener(
1431         const ::rtl::OUString& /*rPropertyName*/,
1432         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1433 {
1434     OSL_ENSURE(false,
1435         "SwXTextRange::addVetoableChangeListener(): not implemented");
1436 }
1437 
1438 void SAL_CALL
removeVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)1439 SwXTextRange::removeVetoableChangeListener(
1440         const ::rtl::OUString& /*rPropertyName*/,
1441         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1442 {
1443     OSL_ENSURE(false,
1444         "SwXTextRange::removeVetoableChangeListener(): not implemented");
1445 }
1446 
1447 beans::PropertyState SAL_CALL
getPropertyState(const OUString & rPropertyName)1448 SwXTextRange::getPropertyState(const OUString& rPropertyName)
1449 {
1450     vos::OGuard aGuard(Application::GetSolarMutex());
1451 
1452     if (!GetDoc() || !m_pImpl->GetBookmark())
1453     {
1454         throw uno::RuntimeException();
1455     }
1456     SwPaM aPaM(GetDoc()->GetNodes());
1457     GetPositions(aPaM);
1458     return SwUnoCursorHelper::GetPropertyState(aPaM, m_pImpl->m_rPropSet,
1459             rPropertyName);
1460 }
1461 
1462 uno::Sequence< beans::PropertyState > SAL_CALL
getPropertyStates(const uno::Sequence<OUString> & rPropertyName)1463 SwXTextRange::getPropertyStates(const uno::Sequence< OUString >& rPropertyName)
1464 {
1465     vos::OGuard g(Application::GetSolarMutex());
1466 
1467     if (!GetDoc() || !m_pImpl->GetBookmark())
1468     {
1469         throw uno::RuntimeException();
1470     }
1471     SwPaM aPaM(GetDoc()->GetNodes());
1472     GetPositions(aPaM);
1473     return SwUnoCursorHelper::GetPropertyStates(aPaM, m_pImpl->m_rPropSet,
1474             rPropertyName);
1475 }
1476 
setPropertyToDefault(const OUString & rPropertyName)1477 void SAL_CALL SwXTextRange::setPropertyToDefault(const OUString& rPropertyName)
1478 {
1479     vos::OGuard aGuard(Application::GetSolarMutex());
1480 
1481     if (!GetDoc() || !m_pImpl->GetBookmark())
1482     {
1483         throw uno::RuntimeException();
1484     }
1485     SwPaM aPaM(GetDoc()->GetNodes());
1486     GetPositions(aPaM);
1487     SwUnoCursorHelper::SetPropertyToDefault(aPaM, m_pImpl->m_rPropSet,
1488             rPropertyName);
1489 }
1490 
1491 uno::Any SAL_CALL
getPropertyDefault(const OUString & rPropertyName)1492 SwXTextRange::getPropertyDefault(const OUString& rPropertyName)
1493 {
1494     vos::OGuard aGuard(Application::GetSolarMutex());
1495 
1496     if (!GetDoc() || !m_pImpl->GetBookmark())
1497     {
1498         throw uno::RuntimeException();
1499     }
1500     SwPaM aPaM(GetDoc()->GetNodes());
1501     GetPositions(aPaM);
1502     return SwUnoCursorHelper::GetPropertyDefault(aPaM, m_pImpl->m_rPropSet,
1503             rPropertyName);
1504 }
1505 
1506 void SAL_CALL
makeRedline(const::rtl::OUString & rRedlineType,const uno::Sequence<beans::PropertyValue> & rRedlineProperties)1507 SwXTextRange::makeRedline(
1508     const ::rtl::OUString& rRedlineType,
1509     const uno::Sequence< beans::PropertyValue >& rRedlineProperties )
1510 {
1511     vos::OGuard aGuard(Application::GetSolarMutex());
1512 
1513     if (!GetDoc() || !m_pImpl->GetBookmark())
1514     {
1515         throw uno::RuntimeException();
1516     }
1517     SwPaM aPaM(GetDoc()->GetNodes());
1518     SwXTextRange::GetPositions(aPaM);
1519     SwUnoCursorHelper::makeRedline( aPaM, rRedlineType, rRedlineProperties );
1520 }
1521 
1522 /******************************************************************
1523  * SwXTextRanges
1524  ******************************************************************/
1525 
1526 class SwXTextRanges::Impl
1527     : public SwClient
1528 {
1529 
1530 public:
1531 
1532     ::std::vector< uno::Reference< text::XTextRange > > m_Ranges;
1533 
Impl(SwPaM * const pPaM)1534     Impl(SwPaM *const pPaM)
1535         : SwClient( (pPaM)
1536             ? pPaM->GetDoc()->CreateUnoCrsr(*pPaM->GetPoint())
1537             : 0 )
1538     {
1539         if (pPaM)
1540         {
1541             ::sw::DeepCopyPaM(*pPaM, *GetCursor());
1542         }
1543         MakeRanges();
1544     }
1545 
~Impl()1546     ~Impl() {
1547         // Impl owns the cursor; delete it here: SolarMutex is locked
1548         delete GetRegisteredIn();
1549     }
1550 
GetCursor()1551     SwUnoCrsr * GetCursor() {
1552         return static_cast<SwUnoCrsr*>(
1553                 const_cast<SwModify*>(GetRegisteredIn()));
1554     }
1555 
1556     void MakeRanges();
1557 protected:
1558     // SwClient
1559     virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
1560 
1561 };
1562 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)1563 void SwXTextRanges::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
1564 {
1565     ClientModify(this, pOld, pNew);
1566 }
1567 
MakeRanges()1568 void SwXTextRanges::Impl::MakeRanges()
1569 {
1570     SwUnoCrsr *const pCursor = GetCursor();
1571     if (pCursor)
1572     {
1573         SwPaM *pTmpCursor = pCursor;
1574         do {
1575             const uno::Reference< text::XTextRange > xRange(
1576                     SwXTextRange::CreateXTextRange(
1577                         *pTmpCursor->GetDoc(),
1578                         *pTmpCursor->GetPoint(), pTmpCursor->GetMark()));
1579             if (xRange.is())
1580             {
1581                 m_Ranges.push_back(xRange);
1582             }
1583             pTmpCursor = static_cast<SwPaM*>(pTmpCursor->GetNext());
1584         }
1585         while (pTmpCursor != pCursor);
1586     }
1587 }
1588 
GetCursor() const1589 const SwUnoCrsr* SwXTextRanges::GetCursor() const
1590 {
1591     return m_pImpl->GetCursor();
1592 }
1593 
SwXTextRanges(SwPaM * const pPaM)1594 SwXTextRanges::SwXTextRanges(SwPaM *const pPaM)
1595     : m_pImpl( new SwXTextRanges::Impl(pPaM) )
1596 {
1597 }
1598 
~SwXTextRanges()1599 SwXTextRanges::~SwXTextRanges()
1600 {
1601 }
1602 
getUnoTunnelId()1603 const uno::Sequence< sal_Int8 > & SwXTextRanges::getUnoTunnelId()
1604 {
1605     static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
1606     return aSeq;
1607 }
1608 
1609 sal_Int64 SAL_CALL
getSomething(const uno::Sequence<sal_Int8> & rId)1610 SwXTextRanges::getSomething(const uno::Sequence< sal_Int8 >& rId)
1611 {
1612     return ::sw::UnoTunnelImpl<SwXTextRanges>(rId, this);
1613 }
1614 
1615 /****************************************************************************
1616  *  Text positions
1617  *  Bis zum ersten Zugriff auf eine TextPosition wird ein SwCursor gehalten,
1618  * danach wird ein Array mit uno::Reference< XTextPosition >  angelegt
1619  *
1620 ****************************************************************************/
1621 OUString SAL_CALL
getImplementationName()1622 SwXTextRanges::getImplementationName()
1623 {
1624     return C2U("SwXTextRanges");
1625 }
1626 
1627 static char const*const g_ServicesTextRanges[] =
1628 {
1629     "com.sun.star.text.TextRanges",
1630 };
1631 static const size_t g_nServicesTextRanges(
1632     sizeof(g_ServicesTextRanges)/sizeof(g_ServicesTextRanges[0]));
1633 
supportsService(const OUString & rServiceName)1634 sal_Bool SAL_CALL SwXTextRanges::supportsService(const OUString& rServiceName)
1635 {
1636     return ::sw::SupportsServiceImpl(
1637             g_nServicesTextRanges, g_ServicesTextRanges, rServiceName);
1638 }
1639 
1640 uno::Sequence< OUString > SAL_CALL
getSupportedServiceNames()1641 SwXTextRanges::getSupportedServiceNames()
1642 {
1643     return ::sw::GetSupportedServiceNamesImpl(
1644             g_nServicesTextRanges, g_ServicesTextRanges);
1645 }
1646 
getCount()1647 sal_Int32 SAL_CALL SwXTextRanges::getCount()
1648 {
1649     vos::OGuard aGuard(Application::GetSolarMutex());
1650 
1651     return static_cast<sal_Int32>(m_pImpl->m_Ranges.size());
1652 }
1653 
getByIndex(sal_Int32 nIndex)1654 uno::Any SAL_CALL SwXTextRanges::getByIndex(sal_Int32 nIndex)
1655 {
1656     vos::OGuard aGuard(Application::GetSolarMutex());
1657 
1658     if ((nIndex < 0) ||
1659         (static_cast<size_t>(nIndex) >= m_pImpl->m_Ranges.size()))
1660     {
1661         throw lang::IndexOutOfBoundsException();
1662     }
1663     uno::Any ret;
1664     ret <<= (m_pImpl->m_Ranges.at(nIndex));
1665     return ret;
1666 }
1667 
1668 uno::Type SAL_CALL
getElementType()1669 SwXTextRanges::getElementType()
1670 {
1671     return text::XTextRange::static_type();
1672 }
1673 
hasElements()1674 sal_Bool SAL_CALL SwXTextRanges::hasElements()
1675 {
1676     // no mutex necessary: getCount() does locking
1677     return getCount() > 0;
1678 }
1679 
SetString(SwCursor & rCursor,const OUString & rString)1680 void SwUnoCursorHelper::SetString(SwCursor & rCursor, const OUString& rString)
1681 {
1682     // Start/EndAction
1683     SwDoc *const pDoc = rCursor.GetDoc();
1684     UnoActionContext aAction(pDoc);
1685     pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
1686     if (rCursor.HasMark())
1687     {
1688         pDoc->DeleteAndJoin(rCursor);
1689     }
1690     if (rString.getLength())
1691     {
1692         String aText(rString);
1693         const bool bSuccess( SwUnoCursorHelper::DocInsertStringSplitCR(
1694                     *pDoc, rCursor, aText, false ) );
1695         DBG_ASSERT( bSuccess, "DocInsertStringSplitCR" );
1696         (void) bSuccess;
1697         SwUnoCursorHelper::SelectPam(rCursor, true);
1698         rCursor.Left(rString.getLength(), CRSR_SKIP_CHARS, sal_False, sal_False);
1699     }
1700     pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
1701 }
1702 
1703 /******************************************************************
1704  * SwXParaFrameEnumeration
1705  ******************************************************************/
1706 
1707 class SwXParaFrameEnumeration::Impl
1708     : public SwClient
1709 {
1710 
1711 public:
1712 
1713     // created by hasMoreElements
1714     uno::Reference< text::XTextContent > m_xNextObject;
1715     FrameDependList_t m_Frames;
1716 
Impl(SwPaM const & rPaM)1717     Impl(SwPaM const & rPaM)
1718         : SwClient(rPaM.GetDoc()->CreateUnoCrsr(*rPaM.GetPoint(), sal_False))
1719     {
1720         if (rPaM.HasMark())
1721         {
1722             GetCursor()->SetMark();
1723             *GetCursor()->GetMark() = *rPaM.GetMark();
1724         }
1725     }
1726 
~Impl()1727     ~Impl() {
1728         // Impl owns the cursor; delete it here: SolarMutex is locked
1729         delete GetRegisteredIn();
1730     }
1731 
GetCursor()1732     SwUnoCrsr * GetCursor() {
1733         return static_cast<SwUnoCrsr*>(
1734                 const_cast<SwModify*>(GetRegisteredIn()));
1735     }
1736 protected:
1737     // SwClient
1738     virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
1739 
1740 };
1741 
1742 struct InvalidFrameDepend {
operator ()InvalidFrameDepend1743     bool operator() (::boost::shared_ptr<SwDepend> const & rEntry)
1744     { return !rEntry->GetRegisteredIn(); }
1745 };
1746 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)1747 void SwXParaFrameEnumeration::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
1748 {
1749     ClientModify(this, pOld, pNew);
1750     if(!GetRegisteredIn())
1751     {
1752         m_Frames.clear();
1753         m_xNextObject = 0;
1754     }
1755     else
1756     {
1757         // check if any frame went away...
1758         FrameDependList_t::iterator const iter =
1759             ::std::remove_if(m_Frames.begin(), m_Frames.end(),
1760                     InvalidFrameDepend());
1761         m_Frames.erase(iter, m_Frames.end());
1762     }
1763 }
1764 
1765 static sal_Bool
lcl_CreateNextObject(SwUnoCrsr & i_rUnoCrsr,uno::Reference<text::XTextContent> & o_rNextObject,FrameDependList_t & i_rFrames)1766 lcl_CreateNextObject(SwUnoCrsr& i_rUnoCrsr,
1767         uno::Reference<text::XTextContent> & o_rNextObject,
1768         FrameDependList_t & i_rFrames)
1769 {
1770     if (!i_rFrames.size())
1771         return sal_False;
1772 
1773     SwFrmFmt *const pFormat = static_cast<SwFrmFmt*>(const_cast<SwModify*>(
1774                 i_rFrames.front()->GetRegisteredIn()));
1775     i_rFrames.pop_front();
1776     // the format should be valid here, otherwise the client
1777     // would have been removed in ::Modify
1778     // check for a shape first
1779     SwDrawContact* const pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement( *pFormat );
1780     if (pContact)
1781     {
1782         SdrObject * const pSdr = pContact->GetMaster();
1783         if (pSdr)
1784         {
1785             o_rNextObject.set(pSdr->getUnoShape(), uno::UNO_QUERY);
1786         }
1787     }
1788     else
1789     {
1790         const SwNodeIndex* pIdx = pFormat->GetCntnt().GetCntntIdx();
1791         DBG_ASSERT(pIdx, "where is the index?");
1792         SwNode const*const pNd =
1793             i_rUnoCrsr.GetDoc()->GetNodes()[ pIdx->GetIndex() + 1 ];
1794 
1795         const FlyCntType eType = (!pNd->IsNoTxtNode()) ? FLYCNTTYPE_FRM
1796             : ( (pNd->IsGrfNode()) ? FLYCNTTYPE_GRF : FLYCNTTYPE_OLE );
1797 
1798         const uno::Reference< container::XNamed >  xFrame =
1799             SwXFrames::GetObject(*pFormat, eType);
1800         o_rNextObject.set(xFrame, uno::UNO_QUERY);
1801     }
1802 
1803     return o_rNextObject.is();
1804 }
1805 
1806 /* -----------------------------03.04.00 10:15--------------------------------
1807     Description: Search for a FLYCNT text attribute at the cursor point
1808                 and fill the frame into the array
1809  ---------------------------------------------------------------------------*/
1810 static void
lcl_FillFrame(SwClient & rEnum,SwUnoCrsr & rUnoCrsr,FrameDependList_t & rFrames)1811 lcl_FillFrame(SwClient & rEnum, SwUnoCrsr& rUnoCrsr,
1812         FrameDependList_t & rFrames)
1813 {
1814     // search for objects at the cursor - anchored at/as char
1815     SwTxtAttr const*const pTxtAttr =
1816         rUnoCrsr.GetNode()->GetTxtNode()->GetTxtAttrForCharAt(
1817             rUnoCrsr.GetPoint()->nContent.GetIndex(), RES_TXTATR_FLYCNT);
1818     if (pTxtAttr)
1819     {
1820         const SwFmtFlyCnt& rFlyCnt = pTxtAttr->GetFlyCnt();
1821         SwFrmFmt * const  pFrmFmt = rFlyCnt.GetFrmFmt();
1822         SwDepend * const pNewDepend = new SwDepend(&rEnum, pFrmFmt);
1823         rFrames.push_back( ::boost::shared_ptr<SwDepend>(pNewDepend) );
1824     }
1825 }
1826 
SwXParaFrameEnumeration(const SwPaM & rPaM,const enum ParaFrameMode eParaFrameMode,SwFrmFmt * const pFmt)1827 SwXParaFrameEnumeration::SwXParaFrameEnumeration(
1828         const SwPaM& rPaM, const enum ParaFrameMode eParaFrameMode,
1829         SwFrmFmt *const pFmt)
1830     : m_pImpl( new SwXParaFrameEnumeration::Impl(rPaM) )
1831 {
1832     if (PARAFRAME_PORTION_PARAGRAPH == eParaFrameMode)
1833     {
1834         FrameDependSortList_t frames;
1835         ::CollectFrameAtNode(*m_pImpl.get(), rPaM.GetPoint()->nNode,
1836                 frames, false);
1837         ::std::transform(frames.begin(), frames.end(),
1838             ::std::back_inserter(m_pImpl->m_Frames),
1839             ::boost::bind(&FrameDependSortListEntry::pFrameDepend, _1));
1840     }
1841     else if (pFmt)
1842     {
1843         // create SwDepend for frame and insert into array
1844         SwDepend *const pNewDepend = new SwDepend(m_pImpl.get(), pFmt);
1845         m_pImpl->m_Frames.push_back(::boost::shared_ptr<SwDepend>(pNewDepend));
1846     }
1847     else if ((PARAFRAME_PORTION_CHAR == eParaFrameMode) ||
1848              (PARAFRAME_PORTION_TEXTRANGE == eParaFrameMode))
1849     {
1850         if (PARAFRAME_PORTION_TEXTRANGE == eParaFrameMode)
1851         {
1852             //get all frames that are bound at paragraph or at character
1853             SwPosFlyFrms aFlyFrms(rPaM.GetDoc()->GetAllFlyFmts(m_pImpl->GetCursor()));
1854 
1855             for(SwPosFlyFrms::const_iterator aIter(aFlyFrms.begin()); aIter != aFlyFrms.end(); aIter++)
1856             {
1857                 SwFrmFmt *const pFrmFmt = const_cast<SwFrmFmt*>(&((*aIter)->GetFmt()));
1858 
1859                 // create SwDepend for frame and insert into array
1860                 SwDepend *const pNewDepend = new SwDepend(m_pImpl.get(), pFrmFmt);
1861                 m_pImpl->m_Frames.push_back(::boost::shared_ptr<SwDepend>(pNewDepend));
1862             }
1863 
1864             //created from any text range
1865             if (m_pImpl->GetCursor()->HasMark())
1866             {
1867                 m_pImpl->GetCursor()->Normalize();
1868                 do
1869                 {
1870                     lcl_FillFrame(*m_pImpl.get(), *m_pImpl->GetCursor(),
1871                             m_pImpl->m_Frames);
1872                     m_pImpl->GetCursor()->Right(
1873                             1, CRSR_SKIP_CHARS, sal_False, sal_False);
1874                 }
1875                 while (*m_pImpl->GetCursor()->GetPoint() <
1876                         *m_pImpl->GetCursor()->GetMark());
1877             }
1878         }
1879 
1880         lcl_FillFrame(*m_pImpl.get(), *m_pImpl->GetCursor(), m_pImpl->m_Frames);
1881     }
1882 }
1883 
~SwXParaFrameEnumeration()1884 SwXParaFrameEnumeration::~SwXParaFrameEnumeration()
1885 {
1886 }
1887 
1888 sal_Bool SAL_CALL
hasMoreElements()1889 SwXParaFrameEnumeration::hasMoreElements()
1890 {
1891     vos::OGuard aGuard(Application::GetSolarMutex());
1892 
1893     if (!m_pImpl->GetCursor())
1894         throw uno::RuntimeException();
1895 
1896     return (m_pImpl->m_xNextObject.is())
1897         ? sal_True
1898         : lcl_CreateNextObject(*m_pImpl->GetCursor(),
1899             m_pImpl->m_xNextObject, m_pImpl->m_Frames);
1900 }
1901 
nextElement()1902 uno::Any SAL_CALL SwXParaFrameEnumeration::nextElement()
1903 {
1904     vos::OGuard aGuard(Application::GetSolarMutex());
1905 
1906     if (!m_pImpl->GetCursor())
1907     {
1908         throw uno::RuntimeException();
1909     }
1910 
1911     if (!m_pImpl->m_xNextObject.is() && m_pImpl->m_Frames.size())
1912     {
1913         lcl_CreateNextObject(*m_pImpl->GetCursor(),
1914                 m_pImpl->m_xNextObject, m_pImpl->m_Frames);
1915     }
1916     if (!m_pImpl->m_xNextObject.is())
1917     {
1918         throw container::NoSuchElementException();
1919     }
1920     uno::Any aRet;
1921     aRet <<= m_pImpl->m_xNextObject;
1922     m_pImpl->m_xNextObject = 0;
1923     return aRet;
1924 }
1925 
1926 OUString SAL_CALL
getImplementationName()1927 SwXParaFrameEnumeration::getImplementationName()
1928 {
1929     return C2U("SwXParaFrameEnumeration");
1930 }
1931 
1932 static char const*const g_ServicesParaFrameEnum[] =
1933 {
1934     "com.sun.star.util.ContentEnumeration",
1935 };
1936 static const size_t g_nServicesParaFrameEnum(
1937     sizeof(g_ServicesParaFrameEnum)/sizeof(g_ServicesParaFrameEnum[0]));
1938 
1939 sal_Bool SAL_CALL
supportsService(const OUString & rServiceName)1940 SwXParaFrameEnumeration::supportsService(const OUString& rServiceName)
1941 {
1942     return ::sw::SupportsServiceImpl(
1943             g_nServicesParaFrameEnum, g_ServicesParaFrameEnum, rServiceName);
1944 }
1945 
1946 uno::Sequence< OUString > SAL_CALL
getSupportedServiceNames()1947 SwXParaFrameEnumeration::getSupportedServiceNames()
1948 {
1949     return ::sw::GetSupportedServiceNamesImpl(
1950             g_nServicesParaFrameEnum, g_ServicesParaFrameEnum);
1951 }
1952