xref: /AOO41X/main/sw/source/core/unocore/unotext.cxx (revision 0aabba3ab117bd1ebf1560f23f52dfa1a54fd4c7)
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 <stdlib.h>
28 
29 #include <memory>
30 #include <iostream>
31 
32 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
33 #include <com/sun/star/text/ControlCharacter.hpp>
34 #include <com/sun/star/text/TableColumnSeparator.hpp>
35 
36 #include <rtl/uuid.h>
37 
38 #include <vos/mutex.hxx>
39 #include <vcl/svapp.hxx>
40 #include <comphelper/sequence.hxx>
41 
42 #include <cmdid.h>
43 #include <unotextbodyhf.hxx>
44 #include <unotext.hxx>
45 #include <unotextrange.hxx>
46 #include <unotextcursor.hxx>
47 #include <unosection.hxx>
48 #include <unobookmark.hxx>
49 #include <unorefmark.hxx>
50 #include <unoport.hxx>
51 #include <unotbl.hxx>
52 #include <unoidx.hxx>
53 #include <unoframe.hxx>
54 #include <unofield.hxx>
55 #include <unometa.hxx>
56 #include <unodraw.hxx>
57 #include <unoredline.hxx>
58 #include <unomap.hxx>
59 #include <unoprnms.hxx>
60 #include <unoparagraph.hxx>
61 #include <unocrsrhelper.hxx>
62 #include <docsh.hxx>
63 #include <docary.hxx>
64 #include <doc.hxx>
65 #include <IDocumentUndoRedo.hxx>
66 #include <redline.hxx>
67 #include <swundo.hxx>
68 #include <section.hxx>
69 #include <IMark.hxx>
70 #include <fmtanchr.hxx>
71 #include <fmtcntnt.hxx>
72 #include <crsskip.hxx>
73 #include <ndtxt.hxx>
74 
75 
76 using namespace ::com::sun::star;
77 using ::rtl::OUString;
78 
79 
80 const sal_Char cInvalidObject[] = "this object is invalid";
81 
82 /******************************************************************
83  * SwXText
84  ******************************************************************/
85 
86 class SwXText::Impl
87 {
88 
89 public:
90     SwXText &                   m_rThis;
91     SfxItemPropertySet const&   m_rPropSet;
92     const enum CursorType       m_eType;
93     SwDoc *                     m_pDoc;
94     bool                        m_bIsValid;
95 
96     Impl(   SwXText & rThis,
97             SwDoc *const pDoc, const enum CursorType eType)
98         : m_rThis(rThis)
99         , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT))
100         , m_eType(eType)
101         , m_pDoc(pDoc)
102         , m_bIsValid(0 != pDoc)
103     {
104     }
105 
106     uno::Reference< text::XTextRange >
107         finishOrAppendParagraph(
108             const bool bFinish,
109             const uno::Sequence< beans::PropertyValue >&
110                 rCharacterAndParagraphProperties)
111         throw (lang::IllegalArgumentException, uno::RuntimeException);
112 
113     sal_Int16 ComparePositions(
114             const uno::Reference<text::XTextRange>& xPos1,
115             const uno::Reference<text::XTextRange>& xPos2)
116         throw (lang::IllegalArgumentException, uno::RuntimeException);
117 
118     bool CheckForOwnMember(const SwPaM & rPaM)
119         throw (lang::IllegalArgumentException, uno::RuntimeException);
120 
121     void ConvertCell(
122             const bool bFirstCell,
123             const uno::Sequence< uno::Reference< text::XTextRange > > & rCell,
124             ::std::vector<SwNodeRange> & rRowNodes,
125             ::std::auto_ptr< SwPaM > & rpFirstPaM,
126             SwPaM & rLastPaM,
127             bool & rbExcept);
128 
129 };
130 
131 /* -----------------------------15.03.2002 12:39------------------------------
132 
133  ---------------------------------------------------------------------------*/
134 SwXText::SwXText(SwDoc *const pDoc, const enum CursorType eType)
135     : m_pImpl( new SwXText::Impl(*this, pDoc, eType) )
136 {
137 }
138 /*-- 09.12.98 12:43:55---------------------------------------------------
139 
140   -----------------------------------------------------------------------*/
141 SwXText::~SwXText()
142 {
143 }
144 
145 /*-- 09.12.98 12:44:07---------------------------------------------------
146 
147   -----------------------------------------------------------------------*/
148 
149 const SwDoc * SwXText::GetDoc() const
150 {
151     return m_pImpl->m_pDoc;
152 }
153       SwDoc * SwXText::GetDoc()
154 {
155     return m_pImpl->m_pDoc;
156 }
157 
158 bool SwXText::IsValid() const
159 {
160     return m_pImpl->m_bIsValid;
161 }
162 
163 void SwXText::Invalidate()
164 {
165     m_pImpl->m_bIsValid = false;
166 }
167 
168 void SwXText::SetDoc(SwDoc *const pDoc)
169 {
170     OSL_ENSURE(!m_pImpl->m_pDoc || !pDoc,
171         "SwXText::SetDoc: already have a doc?");
172     m_pImpl->m_pDoc = pDoc;
173     m_pImpl->m_bIsValid = (0 != pDoc);
174 }
175 
176 void
177 SwXText::PrepareForAttach(uno::Reference< text::XTextRange > &, const SwPaM &)
178 {
179 }
180 
181 bool SwXText::CheckForOwnMemberMeta(const SwPaM &, const bool)
182     throw (lang::IllegalArgumentException, uno::RuntimeException)
183 {
184     ASSERT(CURSOR_META != m_pImpl->m_eType, "should not be called!");
185     return false;
186 }
187 
188 const SwStartNode *SwXText::GetStartNode() const
189 {
190 	return GetDoc()->GetNodes().GetEndOfContent().StartOfSectionNode();
191 }
192 
193 uno::Reference< text::XTextCursor >
194 SwXText::CreateCursor() throw (uno::RuntimeException)
195 {
196 	uno::Reference< text::XTextCursor >  xRet;
197 	if(IsValid())
198 	{
199 		SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
200 		SwPosition aPos(rNode);
201         xRet = static_cast<text::XWordCursor*>(
202                 new SwXTextCursor(*GetDoc(), this, m_pImpl->m_eType, aPos));
203 		xRet->gotoStart(sal_False);
204 	}
205 	return xRet;
206 }
207 
208 /*-- 09.12.98 12:43:02---------------------------------------------------
209 
210   -----------------------------------------------------------------------*/
211 uno::Any SAL_CALL
212 SwXText::queryInterface(const uno::Type& rType) throw (uno::RuntimeException)
213 {
214 	uno::Any aRet;
215     if (rType == text::XText::static_type())
216     {
217         aRet <<= uno::Reference< text::XText >(this);
218     }
219     else if (rType == text::XSimpleText::static_type())
220     {
221         aRet <<= uno::Reference< text::XSimpleText >(this);
222     }
223     else if (rType == text::XTextRange::static_type())
224     {
225         aRet <<= uno::Reference< text::XTextRange>(this);
226     }
227     else if (rType == text::XTextRangeCompare::static_type())
228     {
229         aRet <<= uno::Reference< text::XTextRangeCompare >(this);
230     }
231     else if (rType == lang::XTypeProvider::static_type())
232     {
233         aRet <<= uno::Reference< lang::XTypeProvider >(this);
234     }
235     else if (rType == text::XRelativeTextContentInsert::static_type())
236     {
237         aRet <<= uno::Reference< text::XRelativeTextContentInsert >(this);
238     }
239     else if (rType == text::XRelativeTextContentRemove::static_type())
240     {
241         aRet <<= uno::Reference< text::XRelativeTextContentRemove >(this);
242     }
243     else if (rType == beans::XPropertySet::static_type())
244     {
245         aRet <<= uno::Reference< beans::XPropertySet >(this);
246     }
247     else if (rType == lang::XUnoTunnel::static_type())
248     {
249         aRet <<= uno::Reference< lang::XUnoTunnel >(this);
250     }
251     else if (rType == text::XTextAppendAndConvert::static_type())
252     {
253         aRet <<= uno::Reference< text::XTextAppendAndConvert >(this);
254     }
255     else if (rType == text::XTextAppend::static_type())
256     {
257         aRet <<= uno::Reference< text::XTextAppend >(this);
258     }
259     else if (rType == text::XTextPortionAppend::static_type())
260     {
261         aRet <<= uno::Reference< text::XTextPortionAppend >(this);
262     }
263     else if (rType == text::XParagraphAppend::static_type())
264     {
265         aRet <<= uno::Reference< text::XParagraphAppend >(this);
266     }
267     else if (rType == text::XTextConvert::static_type() )
268     {
269         aRet <<= uno::Reference< text::XTextConvert >(this);
270     }
271     else if (rType == text::XTextContentAppend::static_type())
272     {
273         aRet <<= uno::Reference< text::XTextContentAppend >(this);
274     }
275     else if(rType == text::XTextCopy::static_type())
276     {
277         aRet <<= uno::Reference< text::XTextCopy >( this );
278     }
279 	return aRet;
280 }
281 /* -----------------------------15.03.00 17:42--------------------------------
282 
283  ---------------------------------------------------------------------------*/
284 uno::Sequence< uno::Type > SAL_CALL
285 SwXText::getTypes() throw (uno::RuntimeException)
286 {
287     uno::Sequence< uno::Type > aRet(12);
288     uno::Type* pTypes = aRet.getArray();
289     pTypes[0] = text::XText::static_type();
290     pTypes[1] = text::XTextRangeCompare::static_type();
291     pTypes[2] = text::XRelativeTextContentInsert::static_type();
292     pTypes[3] = text::XRelativeTextContentRemove::static_type();
293     pTypes[4] = lang::XUnoTunnel::static_type();
294     pTypes[5] = beans::XPropertySet::static_type();
295     pTypes[6] = text::XTextPortionAppend::static_type();
296     pTypes[7] = text::XParagraphAppend::static_type();
297     pTypes[8] = text::XTextContentAppend::static_type();
298     pTypes[9] = text::XTextConvert::static_type();
299     pTypes[10] = text::XTextAppend::static_type();
300     pTypes[11] = text::XTextAppendAndConvert::static_type();
301 
302 	return aRet;
303 }
304 
305 // belongs the range in the text ? insert it then.
306 void SAL_CALL
307 SwXText::insertString(const uno::Reference< text::XTextRange >& xTextRange,
308     const OUString& rString, sal_Bool bAbsorb)
309 throw (uno::RuntimeException)
310 {
311     vos::OGuard aGuard(Application::GetSolarMutex());
312 
313     if (!xTextRange.is())
314     {
315         throw uno::RuntimeException();
316     }
317     if (!GetDoc())
318     {
319         throw uno::RuntimeException();
320     }
321     const uno::Reference<lang::XUnoTunnel> xRangeTunnel(xTextRange,
322             uno::UNO_QUERY);
323     SwXTextRange *const pRange =
324         ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
325     OTextCursorHelper *const pCursor =
326         ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
327     if ((!pRange  || pRange ->GetDoc() != GetDoc()) &&
328         (!pCursor || pCursor->GetDoc() != GetDoc()))
329     {
330         throw uno::RuntimeException();
331     }
332 
333     const SwStartNode *const pOwnStartNode = GetStartNode();
334     SwPaM aPam(GetDoc()->GetNodes());
335     const SwPaM * pPam(0);
336     if (pCursor)
337     {
338         pPam = pCursor->GetPaM();
339     }
340     else // pRange
341     {
342         if (pRange->GetPositions(aPam))
343         {
344             pPam = &aPam;
345         }
346     }
347     if (!pPam)
348     {
349         throw uno::RuntimeException();
350     }
351 
352     const SwStartNode* pTmp(pPam->GetNode()->StartOfSectionNode());
353     while (pTmp && pTmp->IsSectionNode())
354     {
355         pTmp = pTmp->StartOfSectionNode();
356     }
357     if (!pOwnStartNode || (pOwnStartNode != pTmp))
358     {
359         throw uno::RuntimeException();
360     }
361 
362     bool bForceExpandHints( false );
363     if (CURSOR_META == m_pImpl->m_eType)
364     {
365         try
366         {
367             bForceExpandHints = CheckForOwnMemberMeta(*pPam, bAbsorb);
368         }
369         catch (lang::IllegalArgumentException & iae)
370         {
371             // stupid method not allowed to throw iae
372             throw uno::RuntimeException(iae.Message, 0);
373         }
374     }
375     if (bAbsorb)
376     {
377         //!! scan for CR characters and inserting the paragraph breaks
378         //!! has to be done in the called function.
379         //!! Implemented in SwXTextRange::DeleteAndInsert
380         if (pCursor)
381         {
382             SwXTextCursor * const pTextCursor(
383                 dynamic_cast<SwXTextCursor*>(pCursor) );
384             if (pTextCursor)
385             {
386                 pTextCursor->DeleteAndInsert(rString, bForceExpandHints);
387             }
388             else
389             {
390                 xTextRange->setString(rString);
391             }
392         }
393         else
394         {
395             pRange->DeleteAndInsert(rString, bForceExpandHints);
396         }
397     }
398     else
399     {
400         // create a PaM positioned before the parameter PaM,
401         // so the text is inserted before
402         UnoActionContext aContext(GetDoc());
403         SwPaM aInsertPam(*pPam->Start());
404         ::sw::GroupUndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo());
405         SwUnoCursorHelper::DocInsertStringSplitCR(
406             *GetDoc(), aInsertPam, rString, bForceExpandHints );
407     }
408 }
409 
410 /*-- 09.12.98 12:43:16---------------------------------------------------
411 
412   -----------------------------------------------------------------------*/
413 void SAL_CALL
414 SwXText::insertControlCharacter(
415         const uno::Reference< text::XTextRange > & xTextRange,
416         sal_Int16 nControlCharacter, sal_Bool bAbsorb)
417 throw (lang::IllegalArgumentException, uno::RuntimeException)
418 {
419 	vos::OGuard aGuard(Application::GetSolarMutex());
420 
421     if (!xTextRange.is())
422     {
423         throw lang::IllegalArgumentException();
424     }
425     if (!GetDoc())
426     {
427         throw uno::RuntimeException();
428     }
429 
430     SwUnoInternalPaM aPam(*GetDoc());
431     if (!::sw::XTextRangeToSwPaM(aPam, xTextRange))
432     {
433         throw uno::RuntimeException();
434     }
435     const bool bForceExpandHints(CheckForOwnMemberMeta(aPam, bAbsorb));
436 
437     const enum IDocumentContentOperations::InsertFlags nInsertFlags =
438         (bForceExpandHints)
439         ? static_cast<IDocumentContentOperations::InsertFlags>(
440                 IDocumentContentOperations::INS_FORCEHINTEXPAND |
441                 IDocumentContentOperations::INS_EMPTYEXPAND)
442         : IDocumentContentOperations::INS_EMPTYEXPAND;
443 
444     SwPaM aTmp(*aPam.Start());
445     if (bAbsorb && aPam.HasMark())
446     {
447         m_pImpl->m_pDoc->DeleteAndJoin(aPam);
448     }
449 
450     sal_Unicode cIns = 0;
451     switch (nControlCharacter)
452     {
453         case text::ControlCharacter::PARAGRAPH_BREAK :
454             // a table cell now becomes an ordinary text cell!
455             m_pImpl->m_pDoc->ClearBoxNumAttrs( aTmp.GetPoint()->nNode );
456             m_pImpl->m_pDoc->SplitNode( *aTmp.GetPoint(), sal_False );
457             break;
458         case text::ControlCharacter::APPEND_PARAGRAPH:
459         {
460             m_pImpl->m_pDoc->ClearBoxNumAttrs( aTmp.GetPoint()->nNode );
461             m_pImpl->m_pDoc->AppendTxtNode( *aTmp.GetPoint() );
462 
463             const uno::Reference<lang::XUnoTunnel> xRangeTunnel(
464                     xTextRange, uno::UNO_QUERY);
465             SwXTextRange *const pRange =
466                 ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
467             OTextCursorHelper *const pCursor =
468                 ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(
469                             xRangeTunnel);
470             if (pRange)
471             {
472                 pRange->SetPositions(aTmp);
473             }
474             else if (pCursor)
475             {
476                 SwPaM *const pCrsr = pCursor->GetPaM();
477                 *pCrsr->GetPoint() = *aTmp.GetPoint();
478                 pCrsr->DeleteMark();
479             }
480         }
481         break;
482         case text::ControlCharacter::LINE_BREAK:  cIns = 10;              break;
483         case text::ControlCharacter::SOFT_HYPHEN: cIns = CHAR_SOFTHYPHEN; break;
484         case text::ControlCharacter::HARD_HYPHEN: cIns = CHAR_HARDHYPHEN; break;
485         case text::ControlCharacter::HARD_SPACE:  cIns = CHAR_HARDBLANK;  break;
486     }
487     if (cIns)
488     {
489         m_pImpl->m_pDoc->InsertString( aTmp, cIns, nInsertFlags );
490     }
491 
492     if (bAbsorb)
493     {
494         const uno::Reference<lang::XUnoTunnel> xRangeTunnel(
495                 xTextRange, uno::UNO_QUERY);
496         SwXTextRange *const pRange =
497             ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
498         OTextCursorHelper *const pCursor =
499             ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
500 
501         SwCursor aCrsr(*aTmp.GetPoint(),0,false);
502         SwUnoCursorHelper::SelectPam(aCrsr, true);
503         aCrsr.Left(1, CRSR_SKIP_CHARS, sal_False, sal_False);
504         //hier muss der uebergebene PaM umgesetzt werden:
505         if (pRange)
506         {
507             pRange->SetPositions(aCrsr);
508         }
509         else
510         {
511             SwPaM *const pUnoCrsr = pCursor->GetPaM();
512             *pUnoCrsr->GetPoint() = *aCrsr.GetPoint();
513             if (aCrsr.HasMark())
514             {
515                 pUnoCrsr->SetMark();
516                 *pUnoCrsr->GetMark() = *aCrsr.GetMark();
517             }
518             else
519             {
520                 pUnoCrsr->DeleteMark();
521             }
522         }
523     }
524 }
525 
526 /*-- 09.12.98 12:43:17---------------------------------------------------
527 
528   -----------------------------------------------------------------------*/
529 void SAL_CALL
530 SwXText::insertTextContent(
531         const uno::Reference< text::XTextRange > & xRange,
532         const uno::Reference< text::XTextContent > & xContent,
533         sal_Bool bAbsorb)
534 throw (lang::IllegalArgumentException, uno::RuntimeException)
535 {
536 	vos::OGuard aGuard(Application::GetSolarMutex());
537 
538     if (!xRange.is())
539     {
540         lang::IllegalArgumentException aIllegal;
541         aIllegal.Message = C2U("first parameter invalid;");
542         throw aIllegal;
543     }
544     if (!xContent.is())
545     {
546         lang::IllegalArgumentException aIllegal;
547         aIllegal.Message += C2U("second parameter invalid");
548         throw aIllegal;
549     }
550 	if(!GetDoc())
551 	{
552 		uno::RuntimeException aRuntime;
553 		aRuntime.Message = C2U(cInvalidObject);
554 		throw aRuntime;
555 	}
556 
557     SwUnoInternalPaM aPam(*GetDoc());
558     if (!::sw::XTextRangeToSwPaM(aPam, xRange))
559     {
560         lang::IllegalArgumentException aIllegal;
561         aIllegal.Message = C2U("first parameter invalid");
562         throw aIllegal;
563     }
564     // first test if the range is at the right position, then call
565     // xContent->attach
566     const SwStartNode* pOwnStartNode = GetStartNode();
567     SwStartNodeType eSearchNodeType = SwNormalStartNode;
568     switch (m_pImpl->m_eType)
569     {
570         case CURSOR_FRAME:      eSearchNodeType = SwFlyStartNode;       break;
571         case CURSOR_TBLTEXT:    eSearchNodeType = SwTableBoxStartNode;  break;
572         case CURSOR_FOOTNOTE:   eSearchNodeType = SwFootnoteStartNode;  break;
573         case CURSOR_HEADER:     eSearchNodeType = SwHeaderStartNode;    break;
574         case CURSOR_FOOTER:     eSearchNodeType = SwFooterStartNode;    break;
575         //case CURSOR_INVALID:
576         //case CURSOR_BODY:
577         default:
578             break;
579     }
580 
581     const SwStartNode* pTmp =
582         aPam.GetNode()->FindSttNodeByType(eSearchNodeType);
583 
584     // ignore SectionNodes
585     while (pTmp && pTmp->IsSectionNode())
586     {
587         pTmp = pTmp->StartOfSectionNode();
588     }
589     // if the document starts with a section
590     while (pOwnStartNode->IsSectionNode())
591     {
592         pOwnStartNode = pOwnStartNode->StartOfSectionNode();
593     }
594     // this checks if (this) and xRange are in the same text::XText interface
595     if (pOwnStartNode != pTmp)
596     {
597         uno::RuntimeException aRunException;
598         aRunException.Message = C2U("text interface and cursor not related");
599         throw aRunException;
600     }
601 
602     const bool bForceExpandHints(CheckForOwnMemberMeta(aPam, bAbsorb));
603 
604     // special treatment for Contents that do not replace the range, but
605     // instead are "overlaid"
606     const uno::Reference<lang::XUnoTunnel> xContentTunnel(xContent,
607             uno::UNO_QUERY);
608     if (!xContentTunnel.is())
609     {
610         lang::IllegalArgumentException aArgException;
611         aArgException.Message =
612             C2U("text content does not support lang::XUnoTunnel");
613         throw aArgException;
614     }
615     SwXDocumentIndexMark *const pDocumentIndexMark =
616         ::sw::UnoTunnelGetImplementation<SwXDocumentIndexMark>(xContentTunnel);
617     SwXTextSection *const pSection =
618         ::sw::UnoTunnelGetImplementation<SwXTextSection>(xContentTunnel);
619     SwXBookmark *const pBookmark =
620         ::sw::UnoTunnelGetImplementation<SwXBookmark>(xContentTunnel);
621     SwXReferenceMark *const pReferenceMark =
622         ::sw::UnoTunnelGetImplementation<SwXReferenceMark>(xContentTunnel);
623     SwXMeta *const pMeta =
624         ::sw::UnoTunnelGetImplementation<SwXMeta>(xContentTunnel);
625 
626     const bool bAttribute = pBookmark || pDocumentIndexMark
627         || pSection || pReferenceMark || pMeta;
628 
629     if (bAbsorb && !bAttribute)
630     {
631         xRange->setString(aEmptyStr);
632     }
633     uno::Reference< text::XTextRange > xTempRange =
634         (bAttribute && bAbsorb) ? xRange : xRange->getStart();
635     if (bForceExpandHints)
636     {
637         // if necessary, replace xTempRange with a new SwXTextCursor
638         PrepareForAttach(xTempRange, aPam);
639     }
640     xContent->attach(xTempRange);
641 }
642 
643 /* -----------------------------10.07.00 15:40--------------------------------
644 
645  ---------------------------------------------------------------------------*/
646 void SAL_CALL
647 SwXText::insertTextContentBefore(
648 	const uno::Reference< text::XTextContent>& xNewContent,
649 	const uno::Reference< text::XTextContent>& xSuccessor)
650 throw (lang::IllegalArgumentException, uno::RuntimeException)
651 {
652 	vos::OGuard aGuard(Application::GetSolarMutex());
653 
654 	if(!GetDoc())
655 	{
656 		uno::RuntimeException aRuntime;
657 		aRuntime.Message = C2U(cInvalidObject);
658 		throw aRuntime;
659 	}
660 
661     const uno::Reference<lang::XUnoTunnel> xParaTunnel(xNewContent,
662             uno::UNO_QUERY);
663     SwXParagraph *const pPara =
664             ::sw::UnoTunnelGetImplementation<SwXParagraph>(xParaTunnel);
665     if (!pPara || !pPara->IsDescriptor() || !xSuccessor.is())
666     {
667 		throw lang::IllegalArgumentException();
668     }
669 
670     sal_Bool bRet = sal_False;
671     const uno::Reference<lang::XUnoTunnel> xSuccTunnel(xSuccessor,
672             uno::UNO_QUERY);
673     SwXTextSection *const pXSection =
674             ::sw::UnoTunnelGetImplementation<SwXTextSection>(xSuccTunnel);
675     SwXTextTable *const pXTable =
676             ::sw::UnoTunnelGetImplementation<SwXTextTable>(xSuccTunnel);
677     SwFrmFmt *const pTableFmt = (pXTable) ? pXTable->GetFrmFmt() : 0;
678     SwTxtNode * pTxtNode = 0;
679 	if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
680     {
681         SwTable *const pTable = SwTable::FindTable( pTableFmt );
682         SwTableNode *const pTblNode = pTable->GetTableNode();
683 
684         const SwNodeIndex aTblIdx( *pTblNode, -1 );
685 		SwPosition aBefore(aTblIdx);
686 		bRet = GetDoc()->AppendTxtNode( aBefore );
687         pTxtNode = aBefore.nNode.GetNode().GetTxtNode();
688 	}
689     else if (pXSection && pXSection->GetFmt() &&
690 			pXSection->GetFmt()->GetDoc() == GetDoc())
691     {
692         SwSectionFmt *const pSectFmt = pXSection->GetFmt();
693         SwSectionNode *const pSectNode = pSectFmt->GetSectionNode();
694 
695         const SwNodeIndex aSectIdx( *pSectNode, -1 );
696 		SwPosition aBefore(aSectIdx);
697 		bRet = GetDoc()->AppendTxtNode( aBefore );
698         pTxtNode = aBefore.nNode.GetNode().GetTxtNode();
699 	}
700     if (!bRet || !pTxtNode)
701     {
702 		throw lang::IllegalArgumentException();
703     }
704     pPara->attachToText(*this, *pTxtNode);
705 }
706 
707 /* -----------------------------10.07.00 15:40--------------------------------
708 
709  ---------------------------------------------------------------------------*/
710 void SAL_CALL
711 SwXText::insertTextContentAfter(
712 	const uno::Reference< text::XTextContent>& xNewContent,
713 	const uno::Reference< text::XTextContent>& xPredecessor)
714 throw (lang::IllegalArgumentException, uno::RuntimeException)
715 {
716 	vos::OGuard aGuard(Application::GetSolarMutex());
717 
718 	if(!GetDoc())
719     {
720 		throw uno::RuntimeException();
721     }
722 
723     const uno::Reference<lang::XUnoTunnel> xParaTunnel(xNewContent,
724             uno::UNO_QUERY);
725     SwXParagraph *const pPara =
726             ::sw::UnoTunnelGetImplementation<SwXParagraph>(xParaTunnel);
727 	if(!pPara || !pPara->IsDescriptor() || !xPredecessor.is())
728     {
729 		throw lang::IllegalArgumentException();
730     }
731 
732     const uno::Reference<lang::XUnoTunnel> xPredTunnel(xPredecessor,
733             uno::UNO_QUERY);
734     SwXTextSection *const pXSection =
735             ::sw::UnoTunnelGetImplementation<SwXTextSection>(xPredTunnel);
736     SwXTextTable *const pXTable =
737             ::sw::UnoTunnelGetImplementation<SwXTextTable>(xPredTunnel);
738     SwFrmFmt *const pTableFmt = (pXTable) ? pXTable->GetFrmFmt() : 0;
739     sal_Bool bRet = sal_False;
740     SwTxtNode * pTxtNode = 0;
741 	if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
742 	{
743         SwTable *const pTable = SwTable::FindTable( pTableFmt );
744         SwTableNode *const pTblNode = pTable->GetTableNode();
745 
746         SwEndNode *const pTableEnd = pTblNode->EndOfSectionNode();
747 		SwPosition aTableEnd(*pTableEnd);
748 		bRet = GetDoc()->AppendTxtNode( aTableEnd );
749         pTxtNode = aTableEnd.nNode.GetNode().GetTxtNode();
750 	}
751 	else if (pXSection && pXSection->GetFmt() &&
752 			pXSection->GetFmt()->GetDoc() == GetDoc())
753     {
754         SwSectionFmt *const pSectFmt = pXSection->GetFmt();
755         SwSectionNode *const pSectNode = pSectFmt->GetSectionNode();
756         SwEndNode *const pEnd = pSectNode->EndOfSectionNode();
757 		SwPosition aEnd(*pEnd);
758 		bRet = GetDoc()->AppendTxtNode( aEnd );
759         pTxtNode = aEnd.nNode.GetNode().GetTxtNode();
760 	}
761     if (!bRet || !pTxtNode)
762     {
763 		throw lang::IllegalArgumentException();
764     }
765     pPara->attachToText(*this, *pTxtNode);
766 }
767 
768 /* -----------------------------10.07.00 15:40--------------------------------
769 
770  ---------------------------------------------------------------------------*/
771 void SAL_CALL
772 SwXText::removeTextContentBefore(
773 	const uno::Reference< text::XTextContent>& xSuccessor)
774 throw (lang::IllegalArgumentException, uno::RuntimeException)
775 {
776 	vos::OGuard aGuard(Application::GetSolarMutex());
777 
778 	if(!GetDoc())
779 	{
780 		uno::RuntimeException aRuntime;
781 		aRuntime.Message = C2U(cInvalidObject);
782 		throw aRuntime;
783 	}
784 
785     sal_Bool bRet = sal_False;
786     const uno::Reference<lang::XUnoTunnel> xSuccTunnel(xSuccessor,
787             uno::UNO_QUERY);
788     SwXTextSection *const pXSection =
789             ::sw::UnoTunnelGetImplementation<SwXTextSection>(xSuccTunnel);
790     SwXTextTable *const pXTable =
791             ::sw::UnoTunnelGetImplementation<SwXTextTable>(xSuccTunnel);
792     SwFrmFmt *const pTableFmt = (pXTable) ? pXTable->GetFrmFmt() : 0;
793 	if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
794     {
795         SwTable *const pTable = SwTable::FindTable( pTableFmt );
796         SwTableNode *const pTblNode = pTable->GetTableNode();
797 
798         const SwNodeIndex aTblIdx( *pTblNode, -1 );
799 		if(aTblIdx.GetNode().IsTxtNode())
800 		{
801 			SwPaM aBefore(aTblIdx);
802 			bRet = GetDoc()->DelFullPara( aBefore );
803 		}
804 	}
805     else if (pXSection && pXSection->GetFmt() &&
806 			pXSection->GetFmt()->GetDoc() == GetDoc())
807     {
808         SwSectionFmt *const pSectFmt = pXSection->GetFmt();
809         SwSectionNode *const pSectNode = pSectFmt->GetSectionNode();
810 
811         const SwNodeIndex aSectIdx(  *pSectNode, -1 );
812 		if(aSectIdx.GetNode().IsTxtNode())
813 		{
814 			SwPaM aBefore(aSectIdx);
815 			bRet = GetDoc()->DelFullPara( aBefore );
816 		}
817 	}
818 	if(!bRet)
819     {
820         throw lang::IllegalArgumentException();
821     }
822 }
823 
824 /* -----------------------------10.07.00 15:40--------------------------------
825 
826  ---------------------------------------------------------------------------*/
827 void SAL_CALL
828 SwXText::removeTextContentAfter(
829         const uno::Reference< text::XTextContent>& xPredecessor)
830 throw (lang::IllegalArgumentException, uno::RuntimeException)
831 {
832 	vos::OGuard aGuard(Application::GetSolarMutex());
833 
834 	if(!GetDoc())
835 	{
836 		uno::RuntimeException aRuntime;
837 		aRuntime.Message = C2U(cInvalidObject);
838 		throw aRuntime;
839 	}
840 
841     sal_Bool bRet = sal_False;
842     const uno::Reference<lang::XUnoTunnel> xPredTunnel(xPredecessor,
843             uno::UNO_QUERY);
844     SwXTextSection *const pXSection =
845             ::sw::UnoTunnelGetImplementation<SwXTextSection>(xPredTunnel);
846     SwXTextTable *const pXTable =
847             ::sw::UnoTunnelGetImplementation<SwXTextTable>(xPredTunnel);
848     SwFrmFmt *const pTableFmt = (pXTable) ? pXTable->GetFrmFmt() : 0;
849 	if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
850     {
851         SwTable *const pTable = SwTable::FindTable( pTableFmt );
852         SwTableNode *const pTblNode = pTable->GetTableNode();
853         SwEndNode *const pTableEnd = pTblNode->EndOfSectionNode();
854 
855         const SwNodeIndex aTblIdx( *pTableEnd, 1 );
856 		if(aTblIdx.GetNode().IsTxtNode())
857 		{
858 			SwPaM aPaM(aTblIdx);
859 			bRet = GetDoc()->DelFullPara( aPaM );
860 		}
861 	}
862     else if (pXSection && pXSection->GetFmt() &&
863 			pXSection->GetFmt()->GetDoc() == GetDoc())
864     {
865         SwSectionFmt *const pSectFmt = pXSection->GetFmt();
866         SwSectionNode *const pSectNode = pSectFmt->GetSectionNode();
867         SwEndNode *const pEnd = pSectNode->EndOfSectionNode();
868         const SwNodeIndex aSectIdx(  *pEnd, 1 );
869 		if(aSectIdx.GetNode().IsTxtNode())
870 		{
871 			SwPaM aAfter(aSectIdx);
872 			bRet = GetDoc()->DelFullPara( aAfter );
873 		}
874 	}
875 	if(!bRet)
876     {
877         throw lang::IllegalArgumentException();
878     }
879 }
880 
881 /*-- 09.12.98 12:43:19---------------------------------------------------
882 
883   -----------------------------------------------------------------------*/
884 void SAL_CALL
885 SwXText::removeTextContent(
886         const uno::Reference< text::XTextContent > & xContent)
887 throw (container::NoSuchElementException, uno::RuntimeException)
888 {
889     // forward: need no solar mutex here
890 	if(!xContent.is())
891 	{
892 		uno::RuntimeException aRuntime;
893 		aRuntime.Message = C2U("first parameter invalid");
894 		throw aRuntime;
895 	}
896     xContent->dispose();
897 }
898 
899 /*-- 09.12.98 12:43:22---------------------------------------------------
900 
901   -----------------------------------------------------------------------*/
902 uno::Reference< text::XText > SAL_CALL
903 SwXText::getText() throw (uno::RuntimeException)
904 {
905 	vos::OGuard aGuard(Application::GetSolarMutex());
906 
907     const uno::Reference< text::XText > xRet(this);
908 	return xRet;
909 }
910 
911 /*-- 09.12.98 12:43:24---------------------------------------------------
912 
913   -----------------------------------------------------------------------*/
914 uno::Reference< text::XTextRange > SAL_CALL
915 SwXText::getStart() throw (uno::RuntimeException)
916 {
917 	vos::OGuard aGuard(Application::GetSolarMutex());
918 
919     const uno::Reference< text::XTextCursor > xRef = CreateCursor();
920 	if(!xRef.is())
921 	{
922 		uno::RuntimeException aRuntime;
923 		aRuntime.Message = C2U(cInvalidObject);
924 		throw aRuntime;
925 	}
926 	xRef->gotoStart(sal_False);
927     const uno::Reference< text::XTextRange > xRet(xRef, uno::UNO_QUERY);
928 	return xRet;
929 }
930 /*-- 09.12.98 12:43:27---------------------------------------------------
931 
932   -----------------------------------------------------------------------*/
933 uno::Reference< text::XTextRange > SAL_CALL
934 SwXText::getEnd() throw (uno::RuntimeException)
935 {
936 	vos::OGuard aGuard(Application::GetSolarMutex());
937 
938     const uno::Reference< text::XTextCursor > xRef = CreateCursor();
939 	if(!xRef.is())
940 	{
941 		uno::RuntimeException aRuntime;
942 		aRuntime.Message = C2U(cInvalidObject);
943 		throw aRuntime;
944 	}
945     xRef->gotoEnd(sal_False);
946     const uno::Reference< text::XTextRange >  xRet(xRef, uno::UNO_QUERY);
947 	return xRet;
948 }
949 
950 /*-- 09.12.98 12:43:29---------------------------------------------------
951 
952   -----------------------------------------------------------------------*/
953 OUString SAL_CALL SwXText::getString() throw (uno::RuntimeException)
954 {
955 	vos::OGuard aGuard(Application::GetSolarMutex());
956 
957     const uno::Reference< text::XTextCursor > xRet = CreateCursor();
958 	if(!xRet.is())
959 	{
960 		uno::RuntimeException aRuntime;
961 		aRuntime.Message = C2U(cInvalidObject);
962 		throw aRuntime;
963 	}
964     xRet->gotoEnd(sal_True);
965 	return xRet->getString();
966 }
967 /*-- 09.12.98 12:43:30---------------------------------------------------
968 
969   -----------------------------------------------------------------------*/
970 void SAL_CALL
971 SwXText::setString(const OUString& rString) throw (uno::RuntimeException)
972 {
973 	vos::OGuard aGuard(Application::GetSolarMutex());
974 
975     if (!GetDoc())
976     {
977         uno::RuntimeException aRuntime;
978         aRuntime.Message = C2U(cInvalidObject);
979         throw aRuntime;
980     }
981 
982     const SwStartNode* pStartNode = GetStartNode();
983     if (!pStartNode)
984     {
985         throw uno::RuntimeException();
986     }
987 
988     GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_START, NULL);
989     //insert an empty paragraph at the start and at the end to ensure that
990     //all tables and sections can be removed by the selecting text::XTextCursor
991     if (CURSOR_META != m_pImpl->m_eType)
992     {
993         SwPosition aStartPos(*pStartNode);
994         const SwEndNode* pEnd = pStartNode->EndOfSectionNode();
995         SwNodeIndex aEndIdx(*pEnd);
996         aEndIdx--;
997         //the inserting of nodes should only be done if really necessary
998         //to prevent #97924# (removes paragraph attributes when setting the text
999         //e.g. of a table cell
1000         sal_Bool bInsertNodes = sal_False;
1001         SwNodeIndex aStartIdx(*pStartNode);
1002         do
1003         {
1004             aStartIdx++;
1005             SwNode& rCurrentNode = aStartIdx.GetNode();
1006             if(rCurrentNode.GetNodeType() == ND_SECTIONNODE
1007                 ||rCurrentNode.GetNodeType() == ND_TABLENODE)
1008             {
1009                 bInsertNodes = sal_True;
1010                 break;
1011             }
1012         }
1013         while(aStartIdx < aEndIdx);
1014         if(bInsertNodes)
1015         {
1016             GetDoc()->AppendTxtNode( aStartPos );
1017             SwPosition aEndPos(aEndIdx.GetNode());
1018             SwPaM aPam(aEndPos);
1019             GetDoc()->AppendTxtNode( *aPam.Start() );
1020         }
1021     }
1022 
1023     const uno::Reference< text::XTextCursor > xRet = CreateCursor();
1024     if(!xRet.is())
1025     {
1026         GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
1027         uno::RuntimeException aRuntime;
1028         aRuntime.Message = C2U(cInvalidObject);
1029         throw aRuntime;
1030     }
1031     xRet->gotoEnd(sal_True);
1032     xRet->setString(rString);
1033     GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
1034 }
1035 
1036 //FIXME why is CheckForOwnMember duplicated in some insert methods?
1037 //	Description: Checks if pRange/pCursor are member of the same text interface.
1038 //				Only one of the pointers has to be set!
1039 bool SwXText::Impl::CheckForOwnMember(
1040     const SwPaM & rPaM)
1041 throw (lang::IllegalArgumentException, uno::RuntimeException)
1042 {
1043     const uno::Reference<text::XTextCursor> xOwnCursor(m_rThis.CreateCursor());
1044 
1045     const uno::Reference<lang::XUnoTunnel> xTunnel(xOwnCursor, uno::UNO_QUERY);
1046     OTextCursorHelper *const pOwnCursor =
1047             ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xTunnel);
1048     DBG_ASSERT(pOwnCursor, "OTextCursorHelper::getUnoTunnelId() ??? ");
1049     const SwStartNode* pOwnStartNode =
1050         pOwnCursor->GetPaM()->GetNode()->StartOfSectionNode();
1051     SwStartNodeType eSearchNodeType = SwNormalStartNode;
1052     switch (m_eType)
1053     {
1054         case CURSOR_FRAME:      eSearchNodeType = SwFlyStartNode;       break;
1055         case CURSOR_TBLTEXT:    eSearchNodeType = SwTableBoxStartNode;  break;
1056         case CURSOR_FOOTNOTE:   eSearchNodeType = SwFootnoteStartNode;  break;
1057         case CURSOR_HEADER:     eSearchNodeType = SwHeaderStartNode;    break;
1058         case CURSOR_FOOTER:     eSearchNodeType = SwFooterStartNode;    break;
1059         //case CURSOR_INVALID:
1060         //case CURSOR_BODY:
1061         default:
1062             ;
1063     }
1064 
1065     SwNode const*const pSrcNode(rPaM.GetNode());
1066     if (!pSrcNode) { return false; }
1067     const SwStartNode* pTmp = pSrcNode->FindSttNodeByType(eSearchNodeType);
1068 
1069     //SectionNodes ueberspringen
1070     while(pTmp && pTmp->IsSectionNode())
1071     {
1072         pTmp = pTmp->StartOfSectionNode();
1073     }
1074 
1075     //if the document starts with a section
1076     while(pOwnStartNode->IsSectionNode())
1077     {
1078         pOwnStartNode = pOwnStartNode->StartOfSectionNode();
1079     }
1080 
1081     //this checks if (this) and xRange are in the same text::XText interface
1082     return (pOwnStartNode == pTmp);
1083 }
1084 
1085 sal_Int16
1086 SwXText::Impl::ComparePositions(
1087     const uno::Reference<text::XTextRange>& xPos1,
1088     const uno::Reference<text::XTextRange>& xPos2)
1089 throw (lang::IllegalArgumentException, uno::RuntimeException)
1090 {
1091     SwUnoInternalPaM aPam1(*m_pDoc);
1092     SwUnoInternalPaM aPam2(*m_pDoc);
1093 
1094     if (!::sw::XTextRangeToSwPaM(aPam1, xPos1) ||
1095         !::sw::XTextRangeToSwPaM(aPam2, xPos2))
1096     {
1097         throw lang::IllegalArgumentException();
1098     }
1099     if (!CheckForOwnMember(aPam1) || !CheckForOwnMember(aPam2))
1100     {
1101         throw lang::IllegalArgumentException();
1102     }
1103 
1104     sal_Int16 nCompare = 0;
1105     SwPosition const*const pStart1 = aPam1.Start();
1106     SwPosition const*const pStart2 = aPam2.Start();
1107     if (*pStart1 < *pStart2)
1108     {
1109         nCompare = 1;
1110     }
1111     else if (*pStart1 > *pStart2)
1112     {
1113         nCompare = -1;
1114     }
1115     else
1116     {
1117         DBG_ASSERT(*pStart1 == *pStart2,
1118                 "SwPositions should be equal here");
1119         nCompare = 0;
1120     }
1121 
1122     return nCompare;
1123 }
1124 
1125 /*-- 28.03.00 10:37:22---------------------------------------------------
1126 
1127   -----------------------------------------------------------------------*/
1128 sal_Int16 SAL_CALL
1129 SwXText::compareRegionStarts(
1130     const uno::Reference<text::XTextRange>& xRange1,
1131     const uno::Reference<text::XTextRange>& xRange2)
1132 throw (lang::IllegalArgumentException, uno::RuntimeException)
1133 {
1134 	vos::OGuard aGuard(Application::GetSolarMutex());
1135 
1136     if (!xRange1.is() || !xRange2.is())
1137     {
1138 		throw lang::IllegalArgumentException();
1139     }
1140     const uno::Reference<text::XTextRange> xStart1 = xRange1->getStart();
1141     const uno::Reference<text::XTextRange> xStart2 = xRange2->getStart();
1142 
1143     return m_pImpl->ComparePositions(xStart1, xStart2);
1144 }
1145 /*-- 28.03.00 10:37:25---------------------------------------------------
1146 
1147   -----------------------------------------------------------------------*/
1148 sal_Int16 SAL_CALL
1149 SwXText::compareRegionEnds(
1150 	const uno::Reference<text::XTextRange>& xRange1,
1151 	const uno::Reference<text::XTextRange>& xRange2)
1152 throw (lang::IllegalArgumentException, uno::RuntimeException)
1153 {
1154 	vos::OGuard aGuard(Application::GetSolarMutex());
1155 
1156     if (!xRange1.is() || !xRange2.is())
1157     {
1158 		throw lang::IllegalArgumentException();
1159     }
1160     uno::Reference<text::XTextRange> xEnd1 = xRange1->getEnd();
1161     uno::Reference<text::XTextRange> xEnd2 = xRange2->getEnd();
1162 
1163     return m_pImpl->ComparePositions(xEnd1, xEnd2);
1164 }
1165 
1166 /*-- 15.03.2002 12:30:40---------------------------------------------------
1167 
1168   -----------------------------------------------------------------------*/
1169 uno::Reference< beans::XPropertySetInfo > SAL_CALL
1170 SwXText::getPropertySetInfo() throw(uno::RuntimeException)
1171 {
1172     vos::OGuard g(Application::GetSolarMutex());
1173 
1174     static uno::Reference< beans::XPropertySetInfo > xInfo =
1175         m_pImpl->m_rPropSet.getPropertySetInfo();
1176     return xInfo;
1177 }
1178 
1179 /*-- 15.03.2002 12:30:42---------------------------------------------------
1180 
1181   -----------------------------------------------------------------------*/
1182 void SAL_CALL
1183 SwXText::setPropertyValue(const ::rtl::OUString& /*aPropertyName*/,
1184         const uno::Any& /*aValue*/)
1185 throw (beans::UnknownPropertyException, beans::PropertyVetoException,
1186     lang::IllegalArgumentException, lang::WrappedTargetException,
1187     uno::RuntimeException)
1188 {
1189     throw lang::IllegalArgumentException();
1190 }
1191 /*-- 15.03.2002 12:30:42---------------------------------------------------
1192 
1193   -----------------------------------------------------------------------*/
1194 uno::Any SAL_CALL
1195 SwXText::getPropertyValue(
1196     const ::rtl::OUString& rPropertyName)
1197 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1198         uno::RuntimeException)
1199 {
1200     vos::OGuard aGuard(Application::GetSolarMutex());
1201 
1202     if(!IsValid())
1203     {
1204         throw  uno::RuntimeException();
1205     }
1206 
1207     SfxItemPropertySimpleEntry const*const pEntry =
1208         m_pImpl->m_rPropSet.getPropertyMap()->getByName(rPropertyName);
1209     if (!pEntry)
1210     {
1211         beans::UnknownPropertyException aExcept;
1212         aExcept.Message = C2U("Unknown property: ");
1213         aExcept.Message += rPropertyName;
1214         throw aExcept;
1215     }
1216 
1217     uno::Any aRet;
1218     switch (pEntry->nWID)
1219     {
1220 //          no code necessary - the redline is always located at the end node
1221 //            case FN_UNO_REDLINE_NODE_START:
1222 //            break;
1223         case FN_UNO_REDLINE_NODE_END:
1224         {
1225             const SwRedlineTbl& rRedTbl = GetDoc()->GetRedlineTbl();
1226             const sal_uInt16 nRedTblCount = rRedTbl.Count();
1227             if (nRedTblCount > 0)
1228             {
1229                 SwStartNode const*const pStartNode = GetStartNode();
1230                 const sal_uLong nOwnIndex = pStartNode->EndOfSectionIndex();
1231                 for (sal_uInt16 nRed = 0; nRed < nRedTblCount; nRed++)
1232                 {
1233                     SwRedline const*const pRedline = rRedTbl[nRed];
1234                     SwPosition const*const pRedStart = pRedline->Start();
1235                     const SwNodeIndex nRedNode = pRedStart->nNode;
1236                     if (nOwnIndex == nRedNode.GetIndex())
1237                     {
1238                         aRet <<= SwXRedlinePortion::CreateRedlineProperties(
1239                                 *pRedline, sal_True);
1240                         break;
1241                     }
1242                 }
1243             }
1244         }
1245         break;
1246     }
1247 	return aRet;
1248 }
1249 
1250 /*-- 15.03.2002 12:30:42---------------------------------------------------
1251 
1252   -----------------------------------------------------------------------*/
1253 void SAL_CALL
1254 SwXText::addPropertyChangeListener(
1255         const ::rtl::OUString& /*rPropertyName*/,
1256         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1257 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1258     uno::RuntimeException)
1259 {
1260     OSL_ENSURE(false,
1261         "SwXText::addPropertyChangeListener(): not implemented");
1262 }
1263 /*-- 15.03.2002 12:30:43---------------------------------------------------
1264 
1265   -----------------------------------------------------------------------*/
1266 void SAL_CALL
1267 SwXText::removePropertyChangeListener(
1268         const ::rtl::OUString& /*rPropertyName*/,
1269         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1270 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1271     uno::RuntimeException)
1272 {
1273     OSL_ENSURE(false,
1274         "SwXText::removePropertyChangeListener(): not implemented");
1275 }
1276 /*-- 15.03.2002 12:30:43---------------------------------------------------
1277 
1278   -----------------------------------------------------------------------*/
1279 void SAL_CALL
1280 SwXText::addVetoableChangeListener(
1281         const ::rtl::OUString& /*rPropertyName*/,
1282         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1283 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1284     uno::RuntimeException)
1285 {
1286     OSL_ENSURE(false,
1287         "SwXText::addVetoableChangeListener(): not implemented");
1288 }
1289 /*-- 15.03.2002 12:30:43---------------------------------------------------
1290 
1291   -----------------------------------------------------------------------*/
1292 void SAL_CALL
1293 SwXText::removeVetoableChangeListener(
1294         const ::rtl::OUString& /*rPropertyName*/,
1295         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1296 throw (beans::UnknownPropertyException, lang::WrappedTargetException,
1297         uno::RuntimeException)
1298 {
1299     OSL_ENSURE(false,
1300         "SwXText::removeVetoableChangeListener(): not implemented");
1301 }
1302 
1303 /* -----------------------------08.01.01 09:07--------------------------------
1304 
1305  ---------------------------------------------------------------------------*/
1306 const uno::Sequence< sal_Int8 > & SwXText::getUnoTunnelId()
1307 {
1308     static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
1309 	return aSeq;
1310 }
1311 /* -----------------------------08.01.01 09:07--------------------------------
1312 
1313  ---------------------------------------------------------------------------*/
1314 sal_Int64 SAL_CALL
1315 SwXText::getSomething(const uno::Sequence< sal_Int8 >& rId)
1316 throw (uno::RuntimeException)
1317 {
1318     return ::sw::UnoTunnelImpl<SwXText>(rId, this);
1319 }
1320 
1321 /*-- 23.06.2006 08:56:30---------------------------------------------------
1322 
1323   -----------------------------------------------------------------------*/
1324 uno::Reference< text::XTextRange > SAL_CALL
1325 SwXText::appendParagraph(
1326         const uno::Sequence< beans::PropertyValue > & rProperties)
1327 throw (lang::IllegalArgumentException, uno::RuntimeException)
1328 {
1329     vos::OGuard g(Application::GetSolarMutex());
1330 
1331     return m_pImpl->finishOrAppendParagraph(false, rProperties);
1332 }
1333 /*-- 23.06.2006 08:56:22---------------------------------------------------
1334 
1335   -----------------------------------------------------------------------*/
1336 uno::Reference< text::XTextRange > SAL_CALL
1337 SwXText::finishParagraph(
1338         const uno::Sequence< beans::PropertyValue > & rProperties)
1339 throw (lang::IllegalArgumentException, uno::RuntimeException)
1340 {
1341     vos::OGuard g(Application::GetSolarMutex());
1342 
1343     return m_pImpl->finishOrAppendParagraph(true, rProperties);
1344 }
1345 
1346 /*-- 08.05.2006 13:26:26---------------------------------------------------
1347 
1348   -----------------------------------------------------------------------*/
1349 uno::Reference< text::XTextRange >
1350 SwXText::Impl::finishOrAppendParagraph(
1351         const bool bFinish,
1352         const uno::Sequence< beans::PropertyValue > & rProperties)
1353 throw (lang::IllegalArgumentException, uno::RuntimeException)
1354 {
1355     if (!m_bIsValid)
1356     {
1357         throw  uno::RuntimeException();
1358     }
1359 
1360     const SwStartNode* pStartNode = m_rThis.GetStartNode();
1361     if(!pStartNode)
1362     {
1363         throw  uno::RuntimeException();
1364     }
1365 
1366     uno::Reference< text::XTextRange > xRet;
1367     bool bIllegalException = false;
1368     bool bRuntimeException = false;
1369     ::rtl::OUString sMessage;
1370     m_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_START , NULL);
1371     // find end node, go backward - don't skip tables because the new
1372     // paragraph has to be the last node
1373     //aPam.Move( fnMoveBackward, fnGoNode );
1374     SwPosition aInsertPosition(
1375             SwNodeIndex( *pStartNode->EndOfSectionNode(), -1 ) );
1376     SwPaM aPam(aInsertPosition);
1377     m_pDoc->AppendTxtNode( *aPam.GetPoint() );
1378     // remove attributes from the previous paragraph
1379     m_pDoc->ResetAttrs(aPam);
1380     // in case of finishParagraph the PaM needs to be moved to the
1381     // previous paragraph
1382     if (bFinish)
1383     {
1384         aPam.Move( fnMoveBackward, fnGoNode );
1385     }
1386     if (rProperties.getLength())
1387     {
1388         // now set the properties
1389         SfxItemPropertySet const*const pParaPropSet =
1390             aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH);
1391         SfxItemPropertyMap const*const pParagraphMap =
1392             pParaPropSet->getPropertyMap();
1393 
1394         const beans::PropertyValue* pValues = rProperties.getConstArray();
1395 
1396         for (sal_Int32 nProp = 0; nProp < rProperties.getLength(); ++nProp)
1397         {
1398             if (!pParagraphMap->getByName(pValues[nProp].Name))
1399             {
1400                 bIllegalException = true;
1401                 break;
1402             }
1403             try
1404             {
1405                 SwUnoCursorHelper::SetPropertyValue(aPam, *pParaPropSet,
1406                     pValues[nProp].Name, pValues[nProp].Value);
1407             }
1408             catch (lang::IllegalArgumentException& rIllegal)
1409             {
1410                 sMessage = rIllegal.Message;
1411                 bIllegalException = true;
1412                 break;
1413             }
1414             catch (uno::RuntimeException& rRuntime)
1415             {
1416                 sMessage = rRuntime.Message;
1417                 bRuntimeException = true;
1418                 break;
1419             }
1420         }
1421     }
1422     m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
1423     if (bIllegalException || bRuntimeException)
1424     {
1425         m_pDoc->GetIDocumentUndoRedo().Undo();
1426         if (bIllegalException)
1427         {
1428             lang::IllegalArgumentException aEx;
1429             aEx.Message = sMessage;
1430             throw aEx;
1431         }
1432         else // if(bRuntimeException)
1433         {
1434             uno::RuntimeException aEx;
1435             aEx.Message = sMessage;
1436             throw aEx;
1437         }
1438     }
1439     SwTxtNode *const pTxtNode( aPam.Start()->nNode.GetNode().GetTxtNode() );
1440     OSL_ENSURE(pTxtNode, "no SwTxtNode?");
1441     if (pTxtNode)
1442     {
1443         xRet.set(SwXParagraph::CreateXParagraph(*m_pDoc, *pTxtNode, &m_rThis),
1444                 uno::UNO_QUERY);
1445     }
1446 
1447     return xRet;
1448 }
1449 
1450 /*-- 08.05.2006 13:28:26---------------------------------------------------
1451     Append text portions at the end of the last paragraph of the text
1452     interface. Support of import filters.
1453   -----------------------------------------------------------------------*/
1454 uno::Reference< text::XTextRange > SAL_CALL
1455 SwXText::appendTextPortion(
1456         const ::rtl::OUString& rText,
1457         const uno::Sequence< beans::PropertyValue > &
1458             rCharacterAndParagraphProperties)
1459 throw (lang::IllegalArgumentException, uno::RuntimeException)
1460 {
1461     vos::OGuard aGuard(Application::GetSolarMutex());
1462 
1463     if(!IsValid())
1464     {
1465         throw  uno::RuntimeException();
1466     }
1467     uno::Reference< text::XTextRange > xRet;
1468     const uno::Reference< text::XTextCursor > xTextCursor = CreateCursor();
1469     xTextCursor->gotoEnd(sal_False);
1470 
1471     const uno::Reference< lang::XUnoTunnel > xRangeTunnel(
1472             xTextCursor, uno::UNO_QUERY_THROW );
1473     SwXTextCursor *const pTextCursor =
1474         ::sw::UnoTunnelGetImplementation<SwXTextCursor>(xRangeTunnel);
1475 
1476     bool bIllegalException = false;
1477     bool bRuntimeException = false;
1478     ::rtl::OUString sMessage;
1479     m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
1480 
1481 //        SwPaM aPam(*pStartNode->EndOfSectionNode());
1482     //aPam.Move( fnMoveBackward, fnGoNode );
1483     SwUnoCrsr *const pCursor = pTextCursor->GetCursor();
1484     pCursor->MovePara( fnParaCurr, fnParaEnd );
1485     m_pImpl->m_pDoc->DontExpandFmt( *pCursor->Start() );
1486 
1487     if (rText.getLength())
1488     {
1489         const xub_StrLen nContentPos = pCursor->GetPoint()->nContent.GetIndex();
1490         SwUnoCursorHelper::DocInsertStringSplitCR(
1491             *m_pImpl->m_pDoc, *pCursor, rText, false);
1492         SwUnoCursorHelper::SelectPam(*pCursor, true);
1493         pCursor->GetPoint()->nContent = nContentPos;
1494     }
1495 
1496     if (rCharacterAndParagraphProperties.getLength())
1497     {
1498         SfxItemPropertyMap const*const pCursorMap =
1499             aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR)
1500                 ->getPropertyMap();
1501         beans::PropertyValue const*const pValues =
1502             rCharacterAndParagraphProperties.getConstArray();
1503         SfxItemPropertySet const*const pCursorPropSet =
1504             aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR);
1505         const sal_Int32 nLen(rCharacterAndParagraphProperties.getLength());
1506         for (sal_Int32 nProp = 0; nProp < nLen; ++nProp)
1507         {
1508             if (!pCursorMap->getByName( pValues[nProp].Name ))
1509             {
1510                 bIllegalException = true;
1511                 break;
1512             }
1513             try
1514             {
1515                 SwUnoCursorHelper::SetPropertyValue(
1516                     *pCursor, *pCursorPropSet,
1517                     pValues[nProp].Name, pValues[nProp].Value,
1518                     nsSetAttrMode::SETATTR_NOFORMATATTR);
1519             }
1520             catch( lang::IllegalArgumentException& rIllegal )
1521             {
1522                 sMessage = rIllegal.Message;
1523                 bIllegalException = true;
1524                 break;
1525             }
1526             catch( uno::RuntimeException& rRuntime )
1527             {
1528                 sMessage = rRuntime.Message;
1529                 bRuntimeException = true;
1530                 break;
1531             }
1532         }
1533     }
1534     m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
1535     if (bIllegalException || bRuntimeException)
1536     {
1537         m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
1538         if (bIllegalException)
1539         {
1540             lang::IllegalArgumentException aEx;
1541             aEx.Message = sMessage;
1542             throw aEx;
1543         }
1544         else //if(bRuntimeException)
1545         {
1546             uno::RuntimeException aEx;
1547             aEx.Message = sMessage;
1548             throw aEx;
1549         }
1550     }
1551     xRet = new SwXTextRange(*pCursor, this);
1552     return xRet;
1553 }
1554 
1555 /*-- 11.05.2006 15:46:26---------------------------------------------------
1556     enable appending text contents like graphic objects, shapes and so on
1557     to support import filters
1558   -----------------------------------------------------------------------*/
1559 uno::Reference< text::XTextRange > SAL_CALL
1560 SwXText::appendTextContent(
1561     const uno::Reference< text::XTextContent >& xTextContent,
1562     const uno::Sequence< beans::PropertyValue >&
1563         rCharacterAndParagraphProperties)
1564 throw (lang::IllegalArgumentException, uno::RuntimeException)
1565 {
1566     vos::OGuard aGuard(Application::GetSolarMutex());
1567 
1568     if (!IsValid())
1569     {
1570         throw  uno::RuntimeException();
1571     }
1572     SwStartNode const*const pStartNode = GetStartNode();
1573     if(!pStartNode)
1574     {
1575         throw  uno::RuntimeException();
1576     }
1577 
1578     uno::Reference< text::XTextRange > xRet;
1579     m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
1580     // find end node, go backward - don't skip tables because the
1581     // new paragraph has to be the last node
1582     SwPaM aPam(*pStartNode->EndOfSectionNode());
1583     aPam.Move( fnMoveBackward, fnGoNode );
1584     // set cursor to the end of the last text node
1585     SwCursor aCursor( *aPam.Start(), 0, false );
1586     xRet = new SwXTextRange(aCursor, this);
1587     aCursor.MovePara( fnParaCurr, fnParaEnd );
1588     m_pImpl->m_pDoc->DontExpandFmt( *aCursor.Start() );
1589     // now attach the text content here
1590     insertTextContent( xRet, xTextContent, false );
1591     // now apply the properties to the anchor
1592     if (rCharacterAndParagraphProperties.getLength())
1593     {
1594         try
1595         {
1596             const sal_Int32 nLen(rCharacterAndParagraphProperties.getLength());
1597             const uno::Reference< beans::XPropertySet > xAnchor(
1598                 xTextContent->getAnchor(), uno::UNO_QUERY);
1599             if (xAnchor.is())
1600             {
1601                 for (sal_Int32 nElement = 0; nElement < nLen; ++nElement)
1602                 {
1603                     xAnchor->setPropertyValue(
1604                         rCharacterAndParagraphProperties[nElement].Name,
1605                         rCharacterAndParagraphProperties[nElement].Value);
1606                 }
1607             }
1608         }
1609         catch (const uno::Exception&)
1610         {
1611             throw uno::RuntimeException();
1612         }
1613     }
1614     m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
1615     return xRet;
1616 }
1617 
1618 // move previously appended paragraphs into a text frames
1619 // to support import filters
1620 uno::Reference< text::XTextContent > SAL_CALL
1621 SwXText::convertToTextFrame(
1622     const uno::Reference< text::XTextRange >& xStart,
1623     const uno::Reference< text::XTextRange >& xEnd,
1624     const uno::Sequence< beans::PropertyValue >& rFrameProperties)
1625 throw (lang::IllegalArgumentException, uno::RuntimeException)
1626 {
1627     vos::OGuard aGuard(Application::GetSolarMutex());
1628 
1629     if(!IsValid())
1630     {
1631         throw  uno::RuntimeException();
1632     }
1633     uno::Reference< text::XTextContent > xRet;
1634     SwUnoInternalPaM aStartPam(*GetDoc());
1635     std::auto_ptr< SwUnoInternalPaM > pEndPam(new SwUnoInternalPaM(*GetDoc()));
1636     if (!::sw::XTextRangeToSwPaM(aStartPam, xStart) ||
1637         !::sw::XTextRangeToSwPaM(*pEndPam, xEnd))
1638     {
1639         throw lang::IllegalArgumentException();
1640     }
1641 
1642     const uno::Reference<lang::XUnoTunnel> xStartRangeTunnel(xStart,
1643             uno::UNO_QUERY);
1644     SwXTextRange *const pStartRange =
1645         ::sw::UnoTunnelGetImplementation<SwXTextRange>(xStartRangeTunnel);
1646     const uno::Reference<lang::XUnoTunnel> xEndRangeTunnel(xEnd,
1647             uno::UNO_QUERY);
1648     SwXTextRange *const pEndRange   =
1649         ::sw::UnoTunnelGetImplementation<SwXTextRange>(xEndRangeTunnel);
1650     // bookmarks have to be removed before the referenced text node
1651     // is deleted in DelFullPara
1652     if (pStartRange)
1653     {
1654         pStartRange->Invalidate();
1655     }
1656     if (pEndRange)
1657     {
1658         pEndRange->Invalidate();
1659     }
1660 
1661     m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
1662     bool bIllegalException = false;
1663     bool bRuntimeException = false;
1664     ::rtl::OUString sMessage;
1665     SwStartNode* pStartStartNode = aStartPam.GetNode()->StartOfSectionNode();
1666     while (pStartStartNode && pStartStartNode->IsSectionNode())
1667     {
1668         pStartStartNode = pStartStartNode->StartOfSectionNode();
1669     }
1670     SwStartNode* pEndStartNode = pEndPam->GetNode()->StartOfSectionNode();
1671     while (pEndStartNode && pEndStartNode->IsSectionNode())
1672     {
1673         pEndStartNode = pEndStartNode->StartOfSectionNode();
1674     }
1675     bool bParaAfterInserted = false;
1676     bool bParaBeforeInserted = false;
1677     if (pStartStartNode != pEndStartNode || pStartStartNode != GetStartNode())
1678     {
1679         // todo: if the start/end is in a table then insert a paragraph
1680         // before/after, move the start/end nodes, then convert and
1681         // remove the addtional paragraphs in the end
1682         if (pStartStartNode->GetStartNodeType() == SwTableBoxStartNode)
1683         {
1684             SwTableNode *const pSartTableNode(pStartStartNode->FindTableNode());
1685             const SwNodeIndex aTblIdx(  *pSartTableNode, -1 );
1686             SwPosition aBefore(aTblIdx);
1687             bParaBeforeInserted = GetDoc()->AppendTxtNode( aBefore );
1688             aStartPam.DeleteMark();
1689             *aStartPam.GetPoint() = aBefore;
1690             pStartStartNode = aStartPam.GetNode()->StartOfSectionNode();
1691         }
1692         if (pEndStartNode->GetStartNodeType() == SwTableBoxStartNode)
1693         {
1694             SwTableNode *const pEndTableNode = pEndStartNode->FindTableNode();
1695             SwEndNode *const pTableEnd = pEndTableNode->EndOfSectionNode();
1696             SwPosition aTableEnd(*pTableEnd);
1697             bParaAfterInserted = GetDoc()->AppendTxtNode( aTableEnd );
1698             pEndPam->DeleteMark();
1699             *pEndPam->GetPoint() = aTableEnd;
1700             pEndStartNode = pEndPam->GetNode()->StartOfSectionNode();
1701         }
1702         // now we should have the positions in the same hierarchy
1703         if ((pStartStartNode != pEndStartNode) ||
1704             (pStartStartNode != GetStartNode()))
1705         {
1706             // if not - remove the additional paragraphs and throw
1707             if (bParaBeforeInserted)
1708             {
1709                 SwCursor aDelete(*aStartPam.GetPoint(), 0, false);
1710                 aDelete.MovePara(fnParaCurr, fnParaStart);
1711                 aDelete.SetMark();
1712                 aDelete.MovePara(fnParaCurr, fnParaEnd);
1713                 GetDoc()->DelFullPara(aDelete);
1714             }
1715             if (bParaAfterInserted)
1716             {
1717                 SwCursor aDelete(*pEndPam->GetPoint(), 0, false);
1718                 aDelete.MovePara(fnParaCurr, fnParaStart);
1719                 aDelete.SetMark();
1720                 aDelete.MovePara(fnParaCurr, fnParaEnd);
1721                 GetDoc()->DelFullPara(aDelete);
1722             }
1723             throw lang::IllegalArgumentException();
1724         }
1725     }
1726 
1727     // make a selection from aStartPam to a EndPam
1728     SwSelBoxes aBoxes;
1729     SfxItemSet aFrameItemSet(m_pImpl->m_pDoc->GetAttrPool(),
1730                     RES_FRMATR_BEGIN, RES_FRMATR_END-1,
1731                     0 );
1732 
1733     aStartPam.SetMark();
1734     *aStartPam.End() = *pEndPam->End();
1735     pEndPam.reset(0);
1736 
1737     SwXTextFrame *const pNewFrame = new SwXTextFrame(m_pImpl->m_pDoc);
1738     const uno::Reference< text::XTextFrame > xNewFrame = pNewFrame;
1739     pNewFrame->SetSelection( aStartPam );
1740     try
1741     {
1742         const beans::PropertyValue* pValues = rFrameProperties.getConstArray();
1743         for (sal_Int32 nProp = 0; nProp < rFrameProperties.getLength(); ++nProp)
1744         {
1745             pNewFrame->SwXFrame::setPropertyValue(
1746                     pValues[nProp].Name, pValues[nProp].Value);
1747         }
1748 
1749         {   // has to be in a block to remove the SwIndexes before
1750             // DelFullPara is called
1751             const uno::Reference< text::XTextRange> xInsertTextRange =
1752                 new SwXTextRange(aStartPam, this);
1753             aStartPam.DeleteMark(); // mark position node may be deleted!
1754             pNewFrame->attach( xInsertTextRange );
1755             pNewFrame->setName(m_pImpl->m_pDoc->GetUniqueFrameName());
1756         }
1757 
1758         SwTxtNode *const pTxtNode(aStartPam.GetNode()->GetTxtNode());
1759         OSL_ASSERT(pTxtNode);
1760         if (!pTxtNode || !pTxtNode->Len()) // don't remove if it contains text!
1761         {
1762             {   // has to be in a block to remove the SwIndexes before
1763                 // DelFullPara is called
1764                 SwPaM aMovePam( *aStartPam.GetNode() );
1765                 if (aMovePam.Move( fnMoveForward, fnGoCntnt ))
1766                 {
1767                     // move the anchor to the next paragraph
1768                     SwFmtAnchor aNewAnchor(pNewFrame->GetFrmFmt()->GetAnchor());
1769                     aNewAnchor.SetAnchor( aMovePam.Start() );
1770                     m_pImpl->m_pDoc->SetAttr(
1771                         aNewAnchor, *pNewFrame->GetFrmFmt() );
1772                 }
1773             }
1774             m_pImpl->m_pDoc->DelFullPara(aStartPam);
1775         }
1776     }
1777     catch (lang::IllegalArgumentException& rIllegal)
1778     {
1779         sMessage = rIllegal.Message;
1780         bIllegalException = true;
1781     }
1782     catch (uno::RuntimeException& rRuntime)
1783     {
1784         sMessage = rRuntime.Message;
1785         bRuntimeException = true;
1786     }
1787     xRet = pNewFrame;
1788     if (bParaBeforeInserted || bParaAfterInserted)
1789     {
1790         const uno::Reference<text::XTextCursor> xFrameTextCursor =
1791             pNewFrame->createTextCursor();
1792         const uno::Reference<XUnoTunnel> xTunnel(xFrameTextCursor,
1793                 uno::UNO_QUERY);
1794         SwXTextCursor *const pFrameCursor =
1795             ::sw::UnoTunnelGetImplementation<SwXTextCursor>(xTunnel);
1796         if (bParaBeforeInserted)
1797         {
1798             // todo: remove paragraph before frame
1799             m_pImpl->m_pDoc->DelFullPara(*pFrameCursor->GetPaM());
1800         }
1801         if (bParaAfterInserted)
1802         {
1803             xFrameTextCursor->gotoEnd(sal_False);
1804             m_pImpl->m_pDoc->DelFullPara(*pFrameCursor->GetPaM());
1805         }
1806     }
1807 
1808     m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
1809     if (bIllegalException || bRuntimeException)
1810     {
1811         m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
1812         if (bIllegalException)
1813         {
1814             lang::IllegalArgumentException aEx;
1815             aEx.Message = sMessage;
1816             throw aEx;
1817         }
1818         else //if(bRuntimeException)
1819         {
1820             uno::RuntimeException aEx;
1821             aEx.Message = sMessage;
1822             throw aEx;
1823         }
1824     }
1825     return xRet;
1826 }
1827 
1828 /*-- 11.05.2006 15:46:26---------------------------------------------------
1829     Move previously imported paragraphs into a new text table.
1830 
1831   -----------------------------------------------------------------------*/
1832 struct VerticallyMergedCell
1833 {
1834     std::vector<uno::Reference< beans::XPropertySet > > aCells;
1835     sal_Int32                                           nLeftPosition;
1836     bool                                                bOpen;
1837 
1838     VerticallyMergedCell(uno::Reference< beans::XPropertySet > const& rxCell,
1839             const sal_Int32 nLeft)
1840         : nLeftPosition( nLeft )
1841         , bOpen( true )
1842     {
1843         aCells.push_back( rxCell );
1844     }
1845 };
1846 #define COL_POS_FUZZY 2
1847 static bool lcl_SimilarPosition( const sal_Int32 nPos1, const sal_Int32 nPos2 )
1848 {
1849     return abs( nPos1 - nPos2 ) < COL_POS_FUZZY;
1850 }
1851 
1852 void SwXText::Impl::ConvertCell(
1853     const bool bFirstCell,
1854     const uno::Sequence< uno::Reference< text::XTextRange > > & rCell,
1855     ::std::vector<SwNodeRange> & rRowNodes,
1856     ::std::auto_ptr< SwPaM > & rpFirstPaM,
1857     SwPaM & rLastPaM,
1858     bool & rbExcept)
1859 {
1860     if (rCell.getLength() != 2)
1861     {
1862         throw lang::IllegalArgumentException();
1863     }
1864     const uno::Reference<text::XTextRange> xStartRange = rCell[0];
1865     const uno::Reference<text::XTextRange> xEndRange = rCell[1];
1866     SwUnoInternalPaM aStartCellPam(*m_pDoc);
1867     SwUnoInternalPaM aEndCellPam(*m_pDoc);
1868 
1869     // !!! TODO - PaMs in tables and sections do not work here -
1870     //     the same applies to PaMs in frames !!!
1871 
1872     if (!::sw::XTextRangeToSwPaM(aStartCellPam, xStartRange) ||
1873         !::sw::XTextRangeToSwPaM(aEndCellPam, xEndRange))
1874     {
1875         throw lang::IllegalArgumentException();
1876     }
1877 
1878     SwNodeRange aTmpRange(aStartCellPam.Start()->nNode,
1879                           aEndCellPam.End()->nNode);
1880     SwNodeRange * pCorrectedRange =
1881         m_pDoc->GetNodes().ExpandRangeForTableBox(aTmpRange);
1882 
1883     if (pCorrectedRange != NULL)
1884     {
1885         SwPaM aNewStartPaM(pCorrectedRange->aStart, 0);
1886         aStartCellPam = aNewStartPaM;
1887 
1888         xub_StrLen nEndLen = 0;
1889         SwTxtNode * pTxtNode = pCorrectedRange->aEnd.GetNode().GetTxtNode();
1890         if (pTxtNode != NULL)
1891             nEndLen = pTxtNode->Len();
1892 
1893         SwPaM aNewEndPaM(pCorrectedRange->aEnd, nEndLen);
1894         aEndCellPam = aNewEndPaM;
1895     }
1896 
1897     /** check the nodes between start and end
1898         it is allowed to have pairs of StartNode/EndNodes
1899      */
1900     if (aStartCellPam.Start()->nNode < aEndCellPam.End()->nNode)
1901     {
1902         // increment on each StartNode and decrement on each EndNode
1903         // we must reach zero at the end and must not go below zero
1904         long nOpenNodeBlock = 0;
1905         SwNodeIndex aCellIndex = aStartCellPam.Start()->nNode;
1906         while (aCellIndex < aEndCellPam.End()->nNode.GetIndex())
1907         {
1908             if (aCellIndex.GetNode().IsStartNode())
1909             {
1910                 ++nOpenNodeBlock;
1911             }
1912             else if (aCellIndex.GetNode().IsEndNode())
1913             {
1914                 --nOpenNodeBlock;
1915             }
1916             if (nOpenNodeBlock < 0)
1917             {
1918                 rbExcept = true;
1919                 break;
1920             }
1921             ++aCellIndex;
1922         }
1923         if (nOpenNodeBlock != 0)
1924         {
1925             rbExcept = true;
1926             return;
1927         }
1928     }
1929 
1930     /** The vector<vector> NodeRanges has to contain consecutive nodes.
1931         In rTableRanges the ranges don't need to be full paragraphs but
1932         they have to follow each other. To process the ranges they
1933         have to be aligned on paragraph borders by inserting paragraph
1934         breaks. Non-consecutive ranges must initiate an exception.
1935      */
1936     if (bFirstCell)
1937     {
1938         // align the beginning - if necessary
1939         if (aStartCellPam.Start()->nContent.GetIndex())
1940         {
1941             m_pDoc->SplitNode(*aStartCellPam.Start(), sal_False);
1942         }
1943     }
1944     else
1945     {
1946         // check the predecessor
1947         const sal_uLong nLastNodeIndex = rLastPaM.End()->nNode.GetIndex();
1948         const sal_uLong nStartCellNodeIndex =
1949             aStartCellPam.Start()->nNode.GetIndex();
1950         const sal_uLong nLastNodeEndIndex = rLastPaM.End()->nNode.GetIndex();
1951         if (nLastNodeIndex == nStartCellNodeIndex)
1952         {
1953             // same node as predecessor then equal nContent?
1954             if (rLastPaM.End()->nContent != aStartCellPam.Start()->nContent)
1955             {
1956                 rbExcept = true;
1957             }
1958             else
1959             {
1960                 m_pDoc->SplitNode(*aStartCellPam.Start(), sal_False);
1961             }
1962         }
1963         else if (nStartCellNodeIndex == (nLastNodeEndIndex + 1))
1964         {
1965             // next paragraph - now the content index of the new should be 0
1966             // and of the old one should be equal to the text length
1967             // but if it isn't we don't care - the cell is being inserted on
1968             // the node border anyway
1969         }
1970         else
1971         {
1972             rbExcept = true;
1973         }
1974     }
1975     // now check if there's a need to insert another paragraph break
1976     if (aEndCellPam.End()->nContent.GetIndex() <
1977             aEndCellPam.End()->nNode.GetNode().GetTxtNode()->Len())
1978     {
1979         m_pDoc->SplitNode(*aEndCellPam.End(), sal_False);
1980         // take care that the new start/endcell is moved to the right position
1981         // aStartCellPam has to point to the start of the new (previous) node
1982         // aEndCellPam has to point to the end of the new (previous) node
1983         aStartCellPam.DeleteMark();
1984         aStartCellPam.Move(fnMoveBackward, fnGoNode);
1985         aStartCellPam.GetPoint()->nContent = 0;
1986         aEndCellPam.DeleteMark();
1987         aEndCellPam.Move(fnMoveBackward, fnGoNode);
1988         aEndCellPam.GetPoint()->nContent =
1989             aEndCellPam.GetNode()->GetTxtNode()->Len();
1990     }
1991 
1992     *rLastPaM.GetPoint() = *aEndCellPam.Start();
1993     if (aStartCellPam.HasMark())
1994     {
1995         rLastPaM.SetMark();
1996         *rLastPaM.GetMark() = *aEndCellPam.End();
1997     }
1998     else
1999     {
2000         rLastPaM.DeleteMark();
2001     }
2002 
2003     SwNodeRange aCellRange(aStartCellPam.Start()->nNode,
2004             aEndCellPam.End()->nNode);
2005     rRowNodes.push_back(aCellRange);
2006     if (bFirstCell)
2007     {
2008         rpFirstPaM.reset(new SwPaM(*aStartCellPam.Start()));
2009     }
2010 }
2011 
2012 typedef uno::Sequence< text::TableColumnSeparator > TableColumnSeparators;
2013 
2014 static void
2015 lcl_ApplyRowProperties(
2016     uno::Sequence<beans::PropertyValue> const& rRowProperties,
2017     uno::Any const& rRow,
2018     TableColumnSeparators & rRowSeparators)
2019 {
2020     uno::Reference< beans::XPropertySet > xRow;
2021     rRow >>= xRow;
2022     const beans::PropertyValue* pProperties = rRowProperties.getConstArray();
2023     for (sal_Int32 nProperty = 0; nProperty < rRowProperties.getLength();
2024          ++nProperty)
2025     {
2026         if (pProperties[ nProperty ].Name.equalsAsciiL(
2027                 RTL_CONSTASCII_STRINGPARAM("TableColumnSeparators")))
2028         {
2029             // add the separators to access the cell's positions
2030             // for vertical merging later
2031             TableColumnSeparators aSeparators;
2032             pProperties[ nProperty ].Value >>= aSeparators;
2033             rRowSeparators = aSeparators;
2034         }
2035         xRow->setPropertyValue(
2036             pProperties[ nProperty ].Name, pProperties[ nProperty ].Value);
2037     }
2038 }
2039 
2040 #ifdef DEBUG
2041 //-->debug cell properties of all rows
2042 static void
2043 lcl_DebugCellProperties(
2044     const uno::Sequence< uno::Sequence< uno::Sequence<
2045         beans::PropertyValue > > >& rCellProperties)
2046 {
2047     ::rtl::OUString sNames;
2048     for (sal_Int32  nDebugRow = 0; nDebugRow < rCellProperties.getLength();
2049          ++nDebugRow)
2050     {
2051         const uno::Sequence< beans::PropertyValues > aDebugCurrentRow =
2052             rCellProperties[nDebugRow];
2053         sal_Int32 nDebugCells = aDebugCurrentRow.getLength();
2054         (void) nDebugCells;
2055         for (sal_Int32  nDebugCell = 0; nDebugCell < nDebugCells;
2056              ++nDebugCell)
2057         {
2058             const uno::Sequence< beans::PropertyValue >&
2059                 rDebugCellProperties = aDebugCurrentRow[nDebugCell];
2060             const sal_Int32 nDebugCellProperties =
2061                 rDebugCellProperties.getLength();
2062             for (sal_Int32  nDebugProperty = 0;
2063                  nDebugProperty < nDebugCellProperties; ++nDebugProperty)
2064             {
2065                 const ::rtl::OUString sName =
2066                     rDebugCellProperties[nDebugProperty].Name;
2067                 sNames += sName;
2068                 sNames += ::rtl::OUString('-');
2069             }
2070             sNames += ::rtl::OUString('+');
2071         }
2072         sNames += ::rtl::OUString('|');
2073     }
2074     (void)sNames;
2075 }
2076 //--<
2077 #endif
2078 
2079 
2080 static void
2081 lcl_ApplyCellProperties(
2082     const sal_Int32 nCell,
2083     TableColumnSeparators const& rRowSeparators,
2084     const uno::Sequence< beans::PropertyValue >& rCellProperties,
2085     uno::Reference< uno::XInterface > xCell,
2086     ::std::vector<VerticallyMergedCell> & rMergedCells)
2087 {
2088     const sal_Int32 nCellProperties = rCellProperties.getLength();
2089     const uno::Reference< beans::XPropertySet > xCellPS(xCell, uno::UNO_QUERY);
2090     for (sal_Int32 nProperty = 0; nProperty < nCellProperties; ++nProperty)
2091     {
2092         const OUString & rName  = rCellProperties[nProperty].Name;
2093         const uno::Any & rValue = rCellProperties[nProperty].Value;
2094         if (rName.equalsAscii("VerticalMerge"))
2095         {
2096             // determine left border position
2097             // add the cell to a queue of merged cells
2098             sal_Bool bMerge = sal_False;
2099             rValue >>= bMerge;
2100             sal_Int32 nLeftPos = -1;
2101             if (!nCell)
2102             {
2103                 nLeftPos = 0;
2104             }
2105             else if (rRowSeparators.getLength() >= nCell)
2106             {
2107                 const text::TableColumnSeparator* pSeparators =
2108                     rRowSeparators.getConstArray();
2109                 nLeftPos = pSeparators[nCell - 1].Position;
2110             }
2111             if (bMerge)
2112             {
2113                 // 'close' all the cell with the same left position
2114                 // if separate vertical merges in the same column exist
2115                 if (rMergedCells.size())
2116                 {
2117                     std::vector<VerticallyMergedCell>::iterator aMergedIter =
2118                         rMergedCells.begin();
2119                     while (aMergedIter != rMergedCells.end())
2120                     {
2121                         if (lcl_SimilarPosition(aMergedIter->nLeftPosition,
2122                                     nLeftPos))
2123                         {
2124                             aMergedIter->bOpen = false;
2125                         }
2126                         ++aMergedIter;
2127                     }
2128                 }
2129                 // add the new group of merged cells
2130                 rMergedCells.push_back(VerticallyMergedCell(xCellPS, nLeftPos));
2131             }
2132             else
2133             {
2134                 // find the cell that
2135                 DBG_ASSERT(rMergedCells.size(),
2136                         "the first merged cell is missing");
2137                 if (rMergedCells.size())
2138                 {
2139                     std::vector<VerticallyMergedCell>::iterator aMergedIter =
2140                         rMergedCells.begin();
2141 #if OSL_DEBUG_LEVEL > 1
2142                     bool bDbgFound = false;
2143 #endif
2144                     while (aMergedIter != rMergedCells.end())
2145                     {
2146                         if (aMergedIter->bOpen &&
2147                             lcl_SimilarPosition(aMergedIter->nLeftPosition,
2148                                 nLeftPos))
2149                         {
2150                             aMergedIter->aCells.push_back( xCellPS );
2151 #if OSL_DEBUG_LEVEL > 1
2152                             bDbgFound = true;
2153 #endif
2154                         }
2155                         ++aMergedIter;
2156                     }
2157 #if OSL_DEBUG_LEVEL > 1
2158                     DBG_ASSERT( bDbgFound,
2159                             "couldn't find first vertically merged cell" );
2160 #endif
2161                 }
2162             }
2163         }
2164         else
2165         {
2166             try
2167             {
2168                 xCellPS->setPropertyValue(rName, rValue);
2169             }
2170             catch (uno::Exception const& e)
2171             {
2172                 // Apply the paragraph and char properties to the cell's content
2173                 const uno::Reference< text::XText > xCellText(xCell,
2174                         uno::UNO_QUERY);
2175                 const uno::Reference< text::XTextCursor > xCellCurs =
2176                     xCellText->createTextCursor();
2177                 xCellCurs->gotoStart( sal_False );
2178                 xCellCurs->gotoEnd( sal_True );
2179                 const uno::Reference< beans::XPropertySet > xCellTextProps(
2180                         xCellCurs, uno::UNO_QUERY);
2181                 xCellTextProps->setPropertyValue(rName, rValue);
2182             }
2183         }
2184     }
2185 }
2186 
2187 static void
2188 lcl_MergeCells(::std::vector<VerticallyMergedCell> & rMergedCells)
2189 {
2190     if (rMergedCells.size())
2191     {
2192         std::vector<VerticallyMergedCell>::iterator aMergedIter =
2193             rMergedCells.begin();
2194         while (aMergedIter != rMergedCells.end())
2195         {
2196             sal_Int32 nCellCount =
2197                 static_cast<sal_Int32>(aMergedIter->aCells.size());
2198             std::vector<uno::Reference< beans::XPropertySet > >::iterator
2199                 aCellIter = aMergedIter->aCells.begin();
2200             bool bFirstCell = true;
2201             // the first of the cells gets the number of cells set as RowSpan
2202             // the others get the inverted number of remaining merged cells
2203             // (3,-2,-1)
2204             while (aCellIter != aMergedIter->aCells.end())
2205             {
2206                 (*aCellIter)->setPropertyValue(
2207                     C2U(SW_PROP_NAME_STR(UNO_NAME_ROW_SPAN)),
2208                     uno::makeAny(nCellCount));
2209                 if (bFirstCell)
2210                 {
2211                     nCellCount *= -1;
2212                     bFirstCell = false;
2213                 }
2214                 ++nCellCount;
2215                 ++aCellIter;
2216             }
2217             ++aMergedIter;
2218         }
2219     }
2220 }
2221 
2222 uno::Reference< text::XTextTable > SAL_CALL
2223 SwXText::convertToTable(
2224     const uno::Sequence< uno::Sequence< uno::Sequence<
2225         uno::Reference< text::XTextRange > > > >& rTableRanges,
2226     const uno::Sequence< uno::Sequence< uno::Sequence<
2227         beans::PropertyValue > > >& rCellProperties,
2228     const uno::Sequence< uno::Sequence< beans::PropertyValue > >&
2229         rRowProperties,
2230     const uno::Sequence< beans::PropertyValue >& rTableProperties)
2231 throw (lang::IllegalArgumentException, uno::RuntimeException)
2232 {
2233     vos::OGuard aGuard(Application::GetSolarMutex());
2234 
2235     if(!IsValid())
2236     {
2237         throw  uno::RuntimeException();
2238     }
2239 
2240     //at first collect the text ranges as SwPaMs
2241     const uno::Sequence< uno::Sequence< uno::Reference< text::XTextRange > > >*
2242         pTableRanges = rTableRanges.getConstArray();
2243     std::auto_ptr < SwPaM > pFirstPaM;
2244     std::vector< std::vector<SwNodeRange> > aTableNodes;
2245     bool bExcept = false;
2246     SwPaM aLastPaM(m_pImpl->m_pDoc->GetNodes());
2247     for (sal_Int32 nRow = 0; !bExcept && (nRow < rTableRanges.getLength());
2248             ++nRow)
2249     {
2250         std::vector<SwNodeRange> aRowNodes;
2251         const uno::Sequence< uno::Reference< text::XTextRange > >* pRow =
2252             pTableRanges[nRow].getConstArray();
2253         const sal_Int32 nCells(pTableRanges[nRow].getLength());
2254 
2255         for (sal_Int32 nCell = 0; nCell < nCells; ++nCell)
2256         {
2257             m_pImpl->ConvertCell((nCell == 0) && (nRow == 0), pRow[nCell],
2258                 aRowNodes, pFirstPaM, aLastPaM, bExcept);
2259         }
2260         aTableNodes.push_back(aRowNodes);
2261     }
2262 
2263     if(bExcept)
2264     {
2265         m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
2266         throw lang::IllegalArgumentException();
2267     }
2268 
2269     std::vector< TableColumnSeparators >
2270         aRowSeparators(rRowProperties.getLength());
2271     std::vector<VerticallyMergedCell> aMergedCells;
2272 
2273     SwTable const*const pTable = m_pImpl->m_pDoc->TextToTable( aTableNodes );
2274     SwXTextTable *const pTextTable = new SwXTextTable( *pTable->GetFrmFmt() );
2275     const uno::Reference< text::XTextTable > xRet = pTextTable;
2276     const uno::Reference< beans::XPropertySet > xPrSet = pTextTable;
2277     // set properties to the table
2278     // catch lang::WrappedTargetException and lang::IndexOutOfBoundsException
2279     try
2280     {
2281         //apply table properties
2282         const beans::PropertyValue* pTableProperties =
2283             rTableProperties.getConstArray();
2284         for (sal_Int32 nProperty = 0; nProperty < rTableProperties.getLength();
2285              ++nProperty)
2286         {
2287             try
2288             {
2289                 xPrSet->setPropertyValue( pTableProperties[nProperty].Name,
2290                         pTableProperties[nProperty].Value );
2291             }
2292             catch ( uno::Exception const& e )
2293             {
2294 #if DEBUG
2295                 std::clog << "Exception when setting property: ";
2296                 std::clog << rtl::OUStringToOString(
2297                     pTableProperties[nProperty].Name, RTL_TEXTENCODING_UTF8)
2298                     .getStr();
2299                 std::clog << ". Message: ";
2300                 std::clog << rtl::OUStringToOString( e.Message,
2301                     RTL_TEXTENCODING_UTF8 ).getStr();
2302                 std::clog << std::endl;
2303 #endif
2304             }
2305         }
2306 
2307         //apply row properties
2308         const uno::Reference< table::XTableRows >  xRows = xRet->getRows();
2309 
2310         const beans::PropertyValues* pRowProperties =
2311             rRowProperties.getConstArray();
2312         for (sal_Int32 nRow = 0; nRow < xRows->getCount(); ++nRow)
2313         {
2314             if( nRow >= rRowProperties.getLength())
2315             {
2316                 break;
2317             }
2318             lcl_ApplyRowProperties(pRowProperties[nRow],
2319                 xRows->getByIndex(nRow), aRowSeparators[nRow]);
2320         }
2321 
2322 #ifdef DEBUG
2323         lcl_DebugCellProperties(rCellProperties);
2324 #endif
2325 
2326         //apply cell properties
2327         for (sal_Int32 nRow = 0; nRow < rCellProperties.getLength(); ++nRow)
2328         {
2329             const uno::Sequence< beans::PropertyValues > aCurrentRow =
2330                 rCellProperties[nRow];
2331             sal_Int32 nCells = aCurrentRow.getLength();
2332             for (sal_Int32  nCell = 0; nCell < nCells; ++nCell)
2333             {
2334                 lcl_ApplyCellProperties(nCell,
2335                     aRowSeparators[nRow], aCurrentRow[nCell],
2336                     pTextTable->getCellByPosition(nCell, nRow),
2337                     aMergedCells);
2338             }
2339         }
2340         // now that the cell properties are set the vertical merge values
2341         // have to be applied
2342         lcl_MergeCells(aMergedCells);
2343     }
2344     catch( const lang::WrappedTargetException& rWrapped )
2345     {
2346         (void)rWrapped;
2347     }
2348     catch ( const lang::IndexOutOfBoundsException& rBounds )
2349     {
2350         (void)rBounds;
2351     }
2352 
2353     return xRet;
2354 }
2355 
2356 
2357 void SAL_CALL
2358 SwXText::copyText(
2359     const uno::Reference< text::XTextCopy >& xSource )
2360 throw (uno::RuntimeException)
2361 {
2362     vos::OGuard g(Application::GetSolarMutex());
2363 
2364     uno::Reference< text::XText > const xText(xSource, uno::UNO_QUERY_THROW);
2365     uno::Reference< text::XTextCursor > const xCursor =
2366         xText->createTextCursor();
2367     xCursor->gotoEnd( sal_True );
2368 
2369     uno::Reference< lang::XUnoTunnel > const xCursorTunnel(xCursor,
2370         uno::UNO_QUERY_THROW);
2371 
2372     OTextCursorHelper *const pCursor =
2373         ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xCursorTunnel);
2374     if (!pCursor)
2375     {
2376         throw uno::RuntimeException();
2377     }
2378 
2379     SwNodeIndex rNdIndex( *GetStartNode( ), 1 );
2380     SwPosition rPos( rNdIndex );
2381     m_pImpl->m_pDoc->CopyRange( *pCursor->GetPaM(), rPos, false );
2382 }
2383 
2384 
2385 /******************************************************************
2386  * SwXBodyText
2387  ******************************************************************/
2388 SwXBodyText::SwXBodyText(SwDoc *const pDoc)
2389     : SwXText(pDoc, CURSOR_BODY)
2390 {
2391 }
2392 
2393 /*-- 10.12.98 11:17:27---------------------------------------------------
2394 
2395   -----------------------------------------------------------------------*/
2396 SwXBodyText::~SwXBodyText()
2397 {
2398 
2399 }
2400 /* -----------------------------06.04.00 16:33--------------------------------
2401 
2402  ---------------------------------------------------------------------------*/
2403 OUString SAL_CALL
2404 SwXBodyText::getImplementationName() throw (uno::RuntimeException)
2405 {
2406 	return C2U("SwXBodyText");
2407 }
2408 /* -----------------------------06.04.00 16:33--------------------------------
2409 
2410  ---------------------------------------------------------------------------*/
2411 static char const*const g_ServicesBodyText[] =
2412 {
2413     "com.sun.star.text.Text",
2414 };
2415 static const size_t g_nServicesBodyText(
2416     sizeof(g_ServicesBodyText)/sizeof(g_ServicesBodyText[0]));
2417 
2418 sal_Bool SAL_CALL SwXBodyText::supportsService(const OUString& rServiceName)
2419 throw (uno::RuntimeException)
2420 {
2421     return ::sw::SupportsServiceImpl(
2422             g_nServicesBodyText, g_ServicesBodyText, rServiceName);
2423 }
2424 
2425 uno::Sequence< OUString > SAL_CALL
2426 SwXBodyText::getSupportedServiceNames() throw (uno::RuntimeException)
2427 {
2428     return ::sw::GetSupportedServiceNamesImpl(
2429             g_nServicesBodyText, g_ServicesBodyText);
2430 }
2431 
2432 /*-- 10.12.98 11:17:27---------------------------------------------------
2433 
2434   -----------------------------------------------------------------------*/
2435 uno::Any SAL_CALL
2436 SwXBodyText::queryAggregation(const uno::Type& rType)
2437 throw (uno::RuntimeException)
2438 {
2439 	uno::Any aRet;
2440     if (rType == container::XEnumerationAccess::static_type())
2441     {
2442         aRet <<= uno::Reference< container::XEnumerationAccess >(this);
2443     }
2444     else if (rType == container::XElementAccess::static_type())
2445     {
2446         aRet <<= uno::Reference< container::XElementAccess >(this);
2447     }
2448     else if (rType == lang::XServiceInfo::static_type())
2449     {
2450         aRet <<= uno::Reference< lang::XServiceInfo >(this);
2451     }
2452     else
2453     {
2454         aRet = SwXText::queryInterface( rType );
2455     }
2456 	if(aRet.getValueType() == ::getCppuVoidType())
2457     {
2458 		aRet = OWeakAggObject::queryAggregation( rType );
2459     }
2460 	return aRet;
2461 }
2462 
2463 /*-- 10.12.98 11:17:28---------------------------------------------------
2464 
2465   -----------------------------------------------------------------------*/
2466 uno::Sequence< uno::Type > SAL_CALL
2467 SwXBodyText::getTypes() throw (uno::RuntimeException)
2468 {
2469     const uno::Sequence< uno::Type > aTypes = SwXBodyText_Base::getTypes();
2470     const uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
2471     return ::comphelper::concatSequences(aTypes, aTextTypes);
2472 }
2473 /* -----------------------------21.03.00 15:39--------------------------------
2474 
2475  ---------------------------------------------------------------------------*/
2476 uno::Sequence< sal_Int8 > SAL_CALL
2477 SwXBodyText::getImplementationId() throw (uno::RuntimeException)
2478 {
2479     vos::OGuard aGuard(Application::GetSolarMutex());
2480     static uno::Sequence< sal_Int8 > aId( 16 );
2481     static sal_Bool bInit = sal_False;
2482     if(!bInit)
2483     {
2484         rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
2485         bInit = sal_True;
2486     }
2487     return aId;
2488 }
2489 /*-- 10.12.98 11:17:28---------------------------------------------------
2490 
2491   -----------------------------------------------------------------------*/
2492 uno::Any SAL_CALL
2493 SwXBodyText::queryInterface(const uno::Type& rType)
2494 throw (uno::RuntimeException)
2495 {
2496     const uno::Any ret = SwXText::queryInterface(rType);
2497     return (ret.getValueType() == ::getCppuVoidType())
2498         ?   SwXBodyText_Base::queryInterface(rType)
2499         :   ret;
2500 }
2501 /* -----------------------------05.01.00 11:07--------------------------------
2502 
2503  ---------------------------------------------------------------------------*/
2504 SwXTextCursor * SwXBodyText::CreateTextCursor(const bool bIgnoreTables)
2505 {
2506     if(!IsValid())
2507     {
2508         return 0;
2509     }
2510 
2511     // the cursor has to skip tables contained in this text
2512     SwPaM aPam(GetDoc()->GetNodes().GetEndOfContent());
2513     aPam.Move( fnMoveBackward, fnGoDoc );
2514     if (!bIgnoreTables)
2515     {
2516         SwTableNode * pTblNode = aPam.GetNode()->FindTableNode();
2517         SwCntntNode * pCont = 0;
2518         while (pTblNode)
2519         {
2520             aPam.GetPoint()->nNode = *pTblNode->EndOfSectionNode();
2521             pCont = GetDoc()->GetNodes().GoNext(&aPam.GetPoint()->nNode);
2522             pTblNode = pCont->FindTableNode();
2523         }
2524         if (pCont)
2525         {
2526             aPam.GetPoint()->nContent.Assign(pCont, 0);
2527         }
2528     }
2529     return new SwXTextCursor(*GetDoc(), this, CURSOR_BODY, *aPam.GetPoint());
2530 }
2531 
2532 /*-- 10.12.98 11:17:29---------------------------------------------------
2533 
2534   -----------------------------------------------------------------------*/
2535 uno::Reference< text::XTextCursor > SAL_CALL
2536 SwXBodyText::createTextCursor() throw (uno::RuntimeException)
2537 {
2538 	vos::OGuard aGuard(Application::GetSolarMutex());
2539 
2540     const uno::Reference< text::XTextCursor > xRef(
2541             static_cast<text::XWordCursor*>(CreateTextCursor(false)) );
2542     if (!xRef.is())
2543 	{
2544 		uno::RuntimeException aRuntime;
2545 		aRuntime.Message = C2U(cInvalidObject);
2546 		throw aRuntime;
2547 	}
2548 	return xRef;
2549 }
2550 /*-- 10.12.98 11:17:29---------------------------------------------------
2551 
2552   -----------------------------------------------------------------------*/
2553 uno::Reference< text::XTextCursor > SAL_CALL
2554 SwXBodyText::createTextCursorByRange(
2555     const uno::Reference< text::XTextRange > & xTextPosition)
2556 throw (uno::RuntimeException)
2557 {
2558 	vos::OGuard aGuard(Application::GetSolarMutex());
2559 
2560 	if(!IsValid())
2561 	{
2562 		uno::RuntimeException aRuntime;
2563 		aRuntime.Message = C2U(cInvalidObject);
2564 		throw aRuntime;
2565 	}
2566 
2567 	uno::Reference< text::XTextCursor >  aRef;
2568 	SwUnoInternalPaM aPam(*GetDoc());
2569     if (::sw::XTextRangeToSwPaM(aPam, xTextPosition))
2570 	{
2571 		SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
2572 
2573         SwStartNode* p1 = aPam.GetNode()->StartOfSectionNode();
2574 		//document starts with a section?
2575 		while(p1->IsSectionNode())
2576 		{
2577             p1 = p1->StartOfSectionNode();
2578 		}
2579         SwStartNode *const p2 = rNode.StartOfSectionNode();
2580 
2581 		if(p1 == p2)
2582         {
2583             aRef = static_cast<text::XWordCursor*>(
2584                     new SwXTextCursor(*GetDoc(), this, CURSOR_BODY,
2585                         *aPam.GetPoint(), aPam.GetMark()));
2586         }
2587 	}
2588 	if(!aRef.is())
2589     {
2590 		throw uno::RuntimeException();
2591     }
2592 	return aRef;
2593 }
2594 
2595 /*-- 10.12.98 11:17:30---------------------------------------------------
2596 
2597   -----------------------------------------------------------------------*/
2598 uno::Reference< container::XEnumeration > SAL_CALL
2599 SwXBodyText::createEnumeration()
2600 throw (uno::RuntimeException)
2601 {
2602 	vos::OGuard aGuard(Application::GetSolarMutex());
2603 
2604     if (!IsValid())
2605 	{
2606 		uno::RuntimeException aRuntime;
2607 		aRuntime.Message = C2U(cInvalidObject);
2608 		throw aRuntime;
2609 	}
2610 
2611     SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
2612     SwPosition aPos(rNode);
2613     ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
2614         GetDoc()->CreateUnoCrsr(aPos, sal_False));
2615     pUnoCursor->Move(fnMoveBackward, fnGoDoc);
2616     const uno::Reference< container::XEnumeration > xRet
2617         = new SwXParagraphEnumeration(this, pUnoCursor, CURSOR_BODY);
2618     return xRet;
2619 }
2620 
2621 /* -----------------18.12.98 13:36-------------------
2622  *
2623  * --------------------------------------------------*/
2624 uno::Type SAL_CALL
2625 SwXBodyText::getElementType() throw (uno::RuntimeException)
2626 {
2627     return text::XTextRange::static_type();
2628 }
2629 /* -----------------18.12.98 13:36-------------------
2630  *
2631  * --------------------------------------------------*/
2632 sal_Bool SAL_CALL
2633 SwXBodyText::hasElements() throw (uno::RuntimeException)
2634 {
2635 	vos::OGuard aGuard(Application::GetSolarMutex());
2636 
2637     if (!IsValid())
2638 	{
2639 		uno::RuntimeException aRuntime;
2640 		aRuntime.Message = C2U(cInvalidObject);
2641 		throw aRuntime;
2642 	}
2643 
2644     return sal_True;
2645 }
2646 
2647 /******************************************************************
2648  *	SwXHeadFootText
2649  ******************************************************************/
2650 
2651 class SwXHeadFootText::Impl
2652     : public SwClient
2653 {
2654 
2655 public:
2656 
2657     bool                        m_bIsHeader;
2658 
2659     Impl(   SwXHeadFootText & /*rThis*/,
2660             SwFrmFmt & rHeadFootFmt, const bool bIsHeader)
2661         : SwClient(& rHeadFootFmt)
2662         , m_bIsHeader(bIsHeader)
2663     {
2664     }
2665 
2666     SwFrmFmt * GetHeadFootFmt() const {
2667         return static_cast<SwFrmFmt*>(
2668                 const_cast<SwModify*>(GetRegisteredIn()));
2669     }
2670 
2671     SwFrmFmt & GetHeadFootFmtOrThrow() {
2672         SwFrmFmt *const pFmt( GetHeadFootFmt() );
2673         if (!pFmt) {
2674             throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
2675                     "SwXHeadFootText: disposed or invalid")), 0);
2676         }
2677         return *pFmt;
2678     }
2679 protected:
2680     // SwClient
2681     virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
2682 
2683 };
2684 
2685 /*-- 11.12.98 10:14:51---------------------------------------------------
2686 
2687   -----------------------------------------------------------------------*/
2688 void SwXHeadFootText::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
2689 {
2690     ClientModify(this, pOld, pNew);
2691 }
2692 
2693 bool SwXHeadFootText::IsXHeadFootText(SwClient *const pClient)
2694 {
2695     return 0 != dynamic_cast<SwXHeadFootText::Impl*>(pClient);
2696 }
2697 
2698 uno::Reference< text::XText >
2699 SwXHeadFootText::CreateXHeadFootText(
2700         SwFrmFmt & rHeadFootFmt, const bool bIsHeader)
2701 {
2702     // re-use existing SwXHeadFootText
2703     // #i105557#: do not iterate over the registered clients: race condition
2704     uno::Reference< text::XText > xText(rHeadFootFmt.GetXObject(),
2705             uno::UNO_QUERY);
2706     if (!xText.is())
2707     {
2708         SwXHeadFootText *const pXHFT(
2709                 new SwXHeadFootText(rHeadFootFmt, bIsHeader));
2710         xText.set(pXHFT);
2711         rHeadFootFmt.SetXObject(xText);
2712     }
2713     return xText;
2714 }
2715 
2716 /*-- 11.12.98 10:14:48---------------------------------------------------
2717 
2718   -----------------------------------------------------------------------*/
2719 SwXHeadFootText::SwXHeadFootText(SwFrmFmt & rHeadFootFmt, const bool bIsHeader)
2720     : SwXText(rHeadFootFmt.GetDoc(),
2721             (bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER)
2722     , m_pImpl( new SwXHeadFootText::Impl(*this, rHeadFootFmt, bIsHeader) )
2723 {
2724 }
2725 
2726 /*-- 11.12.98 10:14:48---------------------------------------------------
2727 
2728   -----------------------------------------------------------------------*/
2729 SwXHeadFootText::~SwXHeadFootText()
2730 {
2731 }
2732 
2733 /* -----------------------------06.04.00 16:40--------------------------------
2734 
2735  ---------------------------------------------------------------------------*/
2736 OUString SAL_CALL
2737 SwXHeadFootText::getImplementationName() throw (uno::RuntimeException)
2738 {
2739 	return C2U("SwXHeadFootText");
2740 }
2741 
2742 /* -----------------------------06.04.00 16:40--------------------------------
2743 
2744  ---------------------------------------------------------------------------*/
2745 static char const*const g_ServicesHeadFootText[] =
2746 {
2747     "com.sun.star.text.Text",
2748 };
2749 static const size_t g_nServicesHeadFootText(
2750     sizeof(g_ServicesHeadFootText)/sizeof(g_ServicesHeadFootText[0]));
2751 
2752 sal_Bool SAL_CALL SwXHeadFootText::supportsService(const OUString& rServiceName)
2753 throw (uno::RuntimeException)
2754 {
2755     return ::sw::SupportsServiceImpl(
2756             g_nServicesHeadFootText, g_ServicesHeadFootText, rServiceName);
2757 }
2758 
2759 uno::Sequence< OUString > SAL_CALL
2760 SwXHeadFootText::getSupportedServiceNames() throw (uno::RuntimeException)
2761 {
2762     return ::sw::GetSupportedServiceNamesImpl(
2763             g_nServicesHeadFootText, g_ServicesHeadFootText);
2764 }
2765 
2766 /*-- 11.12.98 10:14:49---------------------------------------------------
2767 
2768   -----------------------------------------------------------------------*/
2769 const SwStartNode *SwXHeadFootText::GetStartNode() const
2770 {
2771 	const SwStartNode *pSttNd = 0;
2772     SwFrmFmt *const pHeadFootFmt = m_pImpl->GetHeadFootFmt();
2773 	if(pHeadFootFmt)
2774 	{
2775 		const SwFmtCntnt& rFlyCntnt = pHeadFootFmt->GetCntnt();
2776 		if( rFlyCntnt.GetCntntIdx() )
2777         {
2778 			pSttNd = rFlyCntnt.GetCntntIdx()->GetNode().GetStartNode();
2779         }
2780 	}
2781 	return pSttNd;
2782 }
2783 
2784 uno::Reference< text::XTextCursor >
2785 SwXHeadFootText::CreateCursor() throw (uno::RuntimeException)
2786 {
2787 	return createTextCursor();
2788 }
2789 /* -----------------------------21.03.00 15:39--------------------------------
2790 
2791  ---------------------------------------------------------------------------*/
2792 uno::Sequence< uno::Type > SAL_CALL
2793 SwXHeadFootText::getTypes() throw (uno::RuntimeException)
2794 {
2795     const uno::Sequence< uno::Type > aTypes = SwXHeadFootText_Base::getTypes();
2796     const uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
2797     return ::comphelper::concatSequences(aTypes, aTextTypes);
2798 }
2799 
2800 /* -----------------------------21.03.00 15:39--------------------------------
2801 
2802  ---------------------------------------------------------------------------*/
2803 uno::Sequence< sal_Int8 > SAL_CALL
2804 SwXHeadFootText::getImplementationId() throw (uno::RuntimeException)
2805 {
2806     vos::OGuard aGuard(Application::GetSolarMutex());
2807     static uno::Sequence< sal_Int8 > aId( 16 );
2808     static sal_Bool bInit = sal_False;
2809     if(!bInit)
2810     {
2811         rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
2812         bInit = sal_True;
2813     }
2814     return aId;
2815 }
2816 /* -----------------------------21.03.00 15:46--------------------------------
2817 
2818  ---------------------------------------------------------------------------*/
2819 uno::Any SAL_CALL
2820 SwXHeadFootText::queryInterface(const uno::Type& rType)
2821 throw (uno::RuntimeException)
2822 {
2823     const uno::Any ret = SwXHeadFootText_Base::queryInterface(rType);
2824     return (ret.getValueType() == ::getCppuVoidType())
2825         ?   SwXText::queryInterface(rType)
2826         :   ret;
2827 }
2828 
2829 /*-- 11.12.98 10:14:50---------------------------------------------------
2830 
2831   -----------------------------------------------------------------------*/
2832 uno::Reference< text::XTextCursor > SAL_CALL
2833 SwXHeadFootText::createTextCursor() throw (uno::RuntimeException)
2834 {
2835 	vos::OGuard aGuard(Application::GetSolarMutex());
2836 
2837     SwFrmFmt & rHeadFootFmt( m_pImpl->GetHeadFootFmtOrThrow() );
2838 
2839     uno::Reference< text::XTextCursor > xRet;
2840     const SwFmtCntnt& rFlyCntnt = rHeadFootFmt.GetCntnt();
2841     const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
2842     SwPosition aPos(rNode);
2843     SwXTextCursor *const pXCursor = new SwXTextCursor(*GetDoc(), this,
2844             (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER, aPos);
2845     SwUnoCrsr *const pUnoCrsr = pXCursor->GetCursor();
2846     pUnoCrsr->Move(fnMoveForward, fnGoNode);
2847 
2848     // save current start node to be able to check if there is content
2849     // after the table - otherwise the cursor would be in the body text!
2850     SwStartNode const*const pOwnStartNode = rNode.FindSttNodeByType(
2851             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2852     // is there a table here?
2853     SwTableNode* pTblNode = pUnoCrsr->GetNode()->FindTableNode();
2854     SwCntntNode* pCont = 0;
2855     while (pTblNode)
2856     {
2857         pUnoCrsr->GetPoint()->nNode = *pTblNode->EndOfSectionNode();
2858         pCont = GetDoc()->GetNodes().GoNext(&pUnoCrsr->GetPoint()->nNode);
2859         pTblNode = pCont->FindTableNode();
2860     }
2861     if (pCont)
2862     {
2863         pUnoCrsr->GetPoint()->nContent.Assign(pCont, 0);
2864     }
2865     SwStartNode const*const pNewStartNode =
2866         pUnoCrsr->GetNode()->FindSttNodeByType(
2867             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2868     if (!pNewStartNode || (pNewStartNode != pOwnStartNode))
2869     {
2870         uno::RuntimeException aExcept;
2871         aExcept.Message = S2U("no text available");
2872         throw aExcept;
2873     }
2874     xRet = static_cast<text::XWordCursor*>(pXCursor);
2875 	return xRet;
2876 }
2877 
2878 /*-- 11.12.98 10:14:50---------------------------------------------------
2879 
2880   -----------------------------------------------------------------------*/
2881 uno::Reference< text::XTextCursor > SAL_CALL
2882 SwXHeadFootText::createTextCursorByRange(
2883     const uno::Reference< text::XTextRange > & xTextPosition)
2884 throw (uno::RuntimeException)
2885 {
2886 	vos::OGuard aGuard(Application::GetSolarMutex());
2887 
2888     SwFrmFmt & rHeadFootFmt( m_pImpl->GetHeadFootFmtOrThrow() );
2889 
2890 	SwUnoInternalPaM aPam(*GetDoc());
2891     if (!::sw::XTextRangeToSwPaM(aPam, xTextPosition))
2892     {
2893         uno::RuntimeException aRuntime;
2894         aRuntime.Message = C2U(cInvalidObject);
2895         throw aRuntime;
2896     }
2897 
2898 	uno::Reference< text::XTextCursor >  xRet;
2899     SwNode& rNode = rHeadFootFmt.GetCntnt().GetCntntIdx()->GetNode();
2900     SwPosition aPos(rNode);
2901     SwPaM aHFPam(aPos);
2902     aHFPam.Move(fnMoveForward, fnGoNode);
2903     SwStartNode *const pOwnStartNode = aHFPam.GetNode()->FindSttNodeByType(
2904             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2905     SwStartNode *const p1 = aPam.GetNode()->FindSttNodeByType(
2906             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2907     if (p1 == pOwnStartNode)
2908     {
2909         xRet = static_cast<text::XWordCursor*>(
2910                 new SwXTextCursor(*GetDoc(), this,
2911                     (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER,
2912                     *aPam.GetPoint(), aPam.GetMark()));
2913     }
2914 	return xRet;
2915 }
2916 
2917 /* -----------------19.03.99 15:44-------------------
2918  *
2919  * --------------------------------------------------*/
2920 uno::Reference< container::XEnumeration > SAL_CALL
2921 SwXHeadFootText::createEnumeration()
2922 throw (uno::RuntimeException)
2923 {
2924 	vos::OGuard aGuard(Application::GetSolarMutex());
2925 
2926     SwFrmFmt & rHeadFootFmt( m_pImpl->GetHeadFootFmtOrThrow() );
2927 
2928     uno::Reference< container::XEnumeration >  aRef;
2929     const SwFmtCntnt& rFlyCntnt = rHeadFootFmt.GetCntnt();
2930     const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
2931     SwPosition aPos(rNode);
2932     ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
2933         GetDoc()->CreateUnoCrsr(aPos, sal_False));
2934     pUnoCursor->Move(fnMoveForward, fnGoNode);
2935     aRef = new SwXParagraphEnumeration(this, pUnoCursor,
2936                 (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER);
2937 
2938 	return aRef;
2939 }
2940 
2941 /* -----------------19.03.99 15:50-------------------
2942  *
2943  * --------------------------------------------------*/
2944 uno::Type SAL_CALL
2945 SwXHeadFootText::getElementType() throw (uno::RuntimeException)
2946 {
2947     return text::XTextRange::static_type();
2948 }
2949 /* -----------------19.03.99 15:50-------------------
2950  *
2951  * --------------------------------------------------*/
2952 sal_Bool SAL_CALL SwXHeadFootText::hasElements() throw (uno::RuntimeException)
2953 {
2954 	return sal_True;
2955 }
2956 
2957