xref: /AOO41X/main/sw/source/core/unocore/unotext.cxx (revision 253f501c167aa653381b40e636f479c40401bebe)
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& )
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::XPropertyState >
2180                     xCellTextPropState(xCellCurs, uno::UNO_QUERY);
2181                 const beans::PropertyState state = xCellTextPropState->getPropertyState(rName);
2182                 if (state == beans::PropertyState_DEFAULT_VALUE)
2183                 {
2184                     const uno::Reference< beans::XPropertySet >
2185                         xCellTextProps(xCellCurs, uno::UNO_QUERY);
2186                     xCellTextProps->setPropertyValue(rName, rValue);
2187                 }
2188             }
2189         }
2190     }
2191 }
2192 
2193 static void
2194 lcl_MergeCells(::std::vector<VerticallyMergedCell> & rMergedCells)
2195 {
2196     if (rMergedCells.size())
2197     {
2198         std::vector<VerticallyMergedCell>::iterator aMergedIter =
2199             rMergedCells.begin();
2200         while (aMergedIter != rMergedCells.end())
2201         {
2202             sal_Int32 nCellCount =
2203                 static_cast<sal_Int32>(aMergedIter->aCells.size());
2204             std::vector<uno::Reference< beans::XPropertySet > >::iterator
2205                 aCellIter = aMergedIter->aCells.begin();
2206             bool bFirstCell = true;
2207             // the first of the cells gets the number of cells set as RowSpan
2208             // the others get the inverted number of remaining merged cells
2209             // (3,-2,-1)
2210             while (aCellIter != aMergedIter->aCells.end())
2211             {
2212                 (*aCellIter)->setPropertyValue(
2213                     C2U(SW_PROP_NAME_STR(UNO_NAME_ROW_SPAN)),
2214                     uno::makeAny(nCellCount));
2215                 if (bFirstCell)
2216                 {
2217                     nCellCount *= -1;
2218                     bFirstCell = false;
2219                 }
2220                 ++nCellCount;
2221                 ++aCellIter;
2222             }
2223             ++aMergedIter;
2224         }
2225     }
2226 }
2227 
2228 uno::Reference< text::XTextTable > SAL_CALL
2229 SwXText::convertToTable(
2230     const uno::Sequence< uno::Sequence< uno::Sequence<
2231         uno::Reference< text::XTextRange > > > >& rTableRanges,
2232     const uno::Sequence< uno::Sequence< uno::Sequence<
2233         beans::PropertyValue > > >& rCellProperties,
2234     const uno::Sequence< uno::Sequence< beans::PropertyValue > >&
2235         rRowProperties,
2236     const uno::Sequence< beans::PropertyValue >& rTableProperties)
2237 throw (lang::IllegalArgumentException, uno::RuntimeException)
2238 {
2239     vos::OGuard aGuard(Application::GetSolarMutex());
2240 
2241     if(!IsValid())
2242     {
2243         throw  uno::RuntimeException();
2244     }
2245 
2246     //at first collect the text ranges as SwPaMs
2247     const uno::Sequence< uno::Sequence< uno::Reference< text::XTextRange > > >*
2248         pTableRanges = rTableRanges.getConstArray();
2249     std::auto_ptr < SwPaM > pFirstPaM;
2250     std::vector< std::vector<SwNodeRange> > aTableNodes;
2251     bool bExcept = false;
2252     SwPaM aLastPaM(m_pImpl->m_pDoc->GetNodes());
2253     for (sal_Int32 nRow = 0; !bExcept && (nRow < rTableRanges.getLength());
2254             ++nRow)
2255     {
2256         std::vector<SwNodeRange> aRowNodes;
2257         const uno::Sequence< uno::Reference< text::XTextRange > >* pRow =
2258             pTableRanges[nRow].getConstArray();
2259         const sal_Int32 nCells(pTableRanges[nRow].getLength());
2260 
2261         for (sal_Int32 nCell = 0; nCell < nCells; ++nCell)
2262         {
2263             m_pImpl->ConvertCell((nCell == 0) && (nRow == 0), pRow[nCell],
2264                 aRowNodes, pFirstPaM, aLastPaM, bExcept);
2265         }
2266         aTableNodes.push_back(aRowNodes);
2267     }
2268 
2269     if(bExcept)
2270     {
2271         m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
2272         throw lang::IllegalArgumentException();
2273     }
2274 
2275     std::vector< TableColumnSeparators >
2276         aRowSeparators(rRowProperties.getLength());
2277     std::vector<VerticallyMergedCell> aMergedCells;
2278 
2279     SwTable const*const pTable = m_pImpl->m_pDoc->TextToTable( aTableNodes );
2280     SwXTextTable *const pTextTable = new SwXTextTable( *pTable->GetFrmFmt() );
2281     const uno::Reference< text::XTextTable > xRet = pTextTable;
2282     const uno::Reference< beans::XPropertySet > xPrSet = pTextTable;
2283     // set properties to the table
2284     // catch lang::WrappedTargetException and lang::IndexOutOfBoundsException
2285     try
2286     {
2287         //apply table properties
2288         const beans::PropertyValue* pTableProperties =
2289             rTableProperties.getConstArray();
2290         for (sal_Int32 nProperty = 0; nProperty < rTableProperties.getLength();
2291              ++nProperty)
2292         {
2293             try
2294             {
2295                 xPrSet->setPropertyValue( pTableProperties[nProperty].Name,
2296                         pTableProperties[nProperty].Value );
2297             }
2298             catch ( uno::Exception const& e )
2299             {
2300 #if DEBUG
2301                 std::clog << "Exception when setting property: ";
2302                 std::clog << rtl::OUStringToOString(
2303                     pTableProperties[nProperty].Name, RTL_TEXTENCODING_UTF8)
2304                     .getStr();
2305                 std::clog << ". Message: ";
2306                 std::clog << rtl::OUStringToOString( e.Message,
2307                     RTL_TEXTENCODING_UTF8 ).getStr();
2308                 std::clog << std::endl;
2309 #endif
2310             }
2311         }
2312 
2313         //apply row properties
2314         const uno::Reference< table::XTableRows >  xRows = xRet->getRows();
2315 
2316         const beans::PropertyValues* pRowProperties =
2317             rRowProperties.getConstArray();
2318         for (sal_Int32 nRow = 0; nRow < xRows->getCount(); ++nRow)
2319         {
2320             if( nRow >= rRowProperties.getLength())
2321             {
2322                 break;
2323             }
2324             lcl_ApplyRowProperties(pRowProperties[nRow],
2325                 xRows->getByIndex(nRow), aRowSeparators[nRow]);
2326         }
2327 
2328 #ifdef DEBUG
2329         lcl_DebugCellProperties(rCellProperties);
2330 #endif
2331 
2332         //apply cell properties
2333         for (sal_Int32 nRow = 0; nRow < rCellProperties.getLength(); ++nRow)
2334         {
2335             const uno::Sequence< beans::PropertyValues > aCurrentRow =
2336                 rCellProperties[nRow];
2337             sal_Int32 nCells = aCurrentRow.getLength();
2338             for (sal_Int32  nCell = 0; nCell < nCells; ++nCell)
2339             {
2340                 lcl_ApplyCellProperties(nCell,
2341                     aRowSeparators[nRow], aCurrentRow[nCell],
2342                     pTextTable->getCellByPosition(nCell, nRow),
2343                     aMergedCells);
2344             }
2345         }
2346         // now that the cell properties are set the vertical merge values
2347         // have to be applied
2348         lcl_MergeCells(aMergedCells);
2349     }
2350     catch( const lang::WrappedTargetException& rWrapped )
2351     {
2352         (void)rWrapped;
2353     }
2354     catch ( const lang::IndexOutOfBoundsException& rBounds )
2355     {
2356         (void)rBounds;
2357     }
2358 
2359     return xRet;
2360 }
2361 
2362 
2363 void SAL_CALL
2364 SwXText::copyText(
2365     const uno::Reference< text::XTextCopy >& xSource )
2366 throw (uno::RuntimeException)
2367 {
2368     vos::OGuard g(Application::GetSolarMutex());
2369 
2370     uno::Reference< text::XText > const xText(xSource, uno::UNO_QUERY_THROW);
2371     uno::Reference< text::XTextCursor > const xCursor =
2372         xText->createTextCursor();
2373     xCursor->gotoEnd( sal_True );
2374 
2375     uno::Reference< lang::XUnoTunnel > const xCursorTunnel(xCursor,
2376         uno::UNO_QUERY_THROW);
2377 
2378     OTextCursorHelper *const pCursor =
2379         ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xCursorTunnel);
2380     if (!pCursor)
2381     {
2382         throw uno::RuntimeException();
2383     }
2384 
2385     SwNodeIndex rNdIndex( *GetStartNode( ), 1 );
2386     SwPosition rPos( rNdIndex );
2387     m_pImpl->m_pDoc->CopyRange( *pCursor->GetPaM(), rPos, false );
2388 }
2389 
2390 
2391 /******************************************************************
2392  * SwXBodyText
2393  ******************************************************************/
2394 SwXBodyText::SwXBodyText(SwDoc *const pDoc)
2395     : SwXText(pDoc, CURSOR_BODY)
2396 {
2397 }
2398 
2399 /*-- 10.12.98 11:17:27---------------------------------------------------
2400 
2401   -----------------------------------------------------------------------*/
2402 SwXBodyText::~SwXBodyText()
2403 {
2404 
2405 }
2406 /* -----------------------------06.04.00 16:33--------------------------------
2407 
2408  ---------------------------------------------------------------------------*/
2409 OUString SAL_CALL
2410 SwXBodyText::getImplementationName() throw (uno::RuntimeException)
2411 {
2412 	return C2U("SwXBodyText");
2413 }
2414 /* -----------------------------06.04.00 16:33--------------------------------
2415 
2416  ---------------------------------------------------------------------------*/
2417 static char const*const g_ServicesBodyText[] =
2418 {
2419     "com.sun.star.text.Text",
2420 };
2421 static const size_t g_nServicesBodyText(
2422     sizeof(g_ServicesBodyText)/sizeof(g_ServicesBodyText[0]));
2423 
2424 sal_Bool SAL_CALL SwXBodyText::supportsService(const OUString& rServiceName)
2425 throw (uno::RuntimeException)
2426 {
2427     return ::sw::SupportsServiceImpl(
2428             g_nServicesBodyText, g_ServicesBodyText, rServiceName);
2429 }
2430 
2431 uno::Sequence< OUString > SAL_CALL
2432 SwXBodyText::getSupportedServiceNames() throw (uno::RuntimeException)
2433 {
2434     return ::sw::GetSupportedServiceNamesImpl(
2435             g_nServicesBodyText, g_ServicesBodyText);
2436 }
2437 
2438 /*-- 10.12.98 11:17:27---------------------------------------------------
2439 
2440   -----------------------------------------------------------------------*/
2441 uno::Any SAL_CALL
2442 SwXBodyText::queryAggregation(const uno::Type& rType)
2443 throw (uno::RuntimeException)
2444 {
2445 	uno::Any aRet;
2446     if (rType == container::XEnumerationAccess::static_type())
2447     {
2448         aRet <<= uno::Reference< container::XEnumerationAccess >(this);
2449     }
2450     else if (rType == container::XElementAccess::static_type())
2451     {
2452         aRet <<= uno::Reference< container::XElementAccess >(this);
2453     }
2454     else if (rType == lang::XServiceInfo::static_type())
2455     {
2456         aRet <<= uno::Reference< lang::XServiceInfo >(this);
2457     }
2458     else
2459     {
2460         aRet = SwXText::queryInterface( rType );
2461     }
2462 	if(aRet.getValueType() == ::getCppuVoidType())
2463     {
2464 		aRet = OWeakAggObject::queryAggregation( rType );
2465     }
2466 	return aRet;
2467 }
2468 
2469 /*-- 10.12.98 11:17:28---------------------------------------------------
2470 
2471   -----------------------------------------------------------------------*/
2472 uno::Sequence< uno::Type > SAL_CALL
2473 SwXBodyText::getTypes() throw (uno::RuntimeException)
2474 {
2475     const uno::Sequence< uno::Type > aTypes = SwXBodyText_Base::getTypes();
2476     const uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
2477     return ::comphelper::concatSequences(aTypes, aTextTypes);
2478 }
2479 /* -----------------------------21.03.00 15:39--------------------------------
2480 
2481  ---------------------------------------------------------------------------*/
2482 uno::Sequence< sal_Int8 > SAL_CALL
2483 SwXBodyText::getImplementationId() throw (uno::RuntimeException)
2484 {
2485     vos::OGuard aGuard(Application::GetSolarMutex());
2486     static uno::Sequence< sal_Int8 > aId( 16 );
2487     static sal_Bool bInit = sal_False;
2488     if(!bInit)
2489     {
2490         rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
2491         bInit = sal_True;
2492     }
2493     return aId;
2494 }
2495 /*-- 10.12.98 11:17:28---------------------------------------------------
2496 
2497   -----------------------------------------------------------------------*/
2498 uno::Any SAL_CALL
2499 SwXBodyText::queryInterface(const uno::Type& rType)
2500 throw (uno::RuntimeException)
2501 {
2502     const uno::Any ret = SwXText::queryInterface(rType);
2503     return (ret.getValueType() == ::getCppuVoidType())
2504         ?   SwXBodyText_Base::queryInterface(rType)
2505         :   ret;
2506 }
2507 /* -----------------------------05.01.00 11:07--------------------------------
2508 
2509  ---------------------------------------------------------------------------*/
2510 SwXTextCursor * SwXBodyText::CreateTextCursor(const bool bIgnoreTables)
2511 {
2512     if(!IsValid())
2513     {
2514         return 0;
2515     }
2516 
2517     // the cursor has to skip tables contained in this text
2518     SwPaM aPam(GetDoc()->GetNodes().GetEndOfContent());
2519     aPam.Move( fnMoveBackward, fnGoDoc );
2520     if (!bIgnoreTables)
2521     {
2522         SwTableNode * pTblNode = aPam.GetNode()->FindTableNode();
2523         SwCntntNode * pCont = 0;
2524         while (pTblNode)
2525         {
2526             aPam.GetPoint()->nNode = *pTblNode->EndOfSectionNode();
2527             pCont = GetDoc()->GetNodes().GoNext(&aPam.GetPoint()->nNode);
2528             pTblNode = pCont->FindTableNode();
2529         }
2530         if (pCont)
2531         {
2532             aPam.GetPoint()->nContent.Assign(pCont, 0);
2533         }
2534     }
2535     return new SwXTextCursor(*GetDoc(), this, CURSOR_BODY, *aPam.GetPoint());
2536 }
2537 
2538 /*-- 10.12.98 11:17:29---------------------------------------------------
2539 
2540   -----------------------------------------------------------------------*/
2541 uno::Reference< text::XTextCursor > SAL_CALL
2542 SwXBodyText::createTextCursor() throw (uno::RuntimeException)
2543 {
2544 	vos::OGuard aGuard(Application::GetSolarMutex());
2545 
2546     const uno::Reference< text::XTextCursor > xRef(
2547             static_cast<text::XWordCursor*>(CreateTextCursor(false)) );
2548     if (!xRef.is())
2549 	{
2550 		uno::RuntimeException aRuntime;
2551 		aRuntime.Message = C2U(cInvalidObject);
2552 		throw aRuntime;
2553 	}
2554 	return xRef;
2555 }
2556 /*-- 10.12.98 11:17:29---------------------------------------------------
2557 
2558   -----------------------------------------------------------------------*/
2559 uno::Reference< text::XTextCursor > SAL_CALL
2560 SwXBodyText::createTextCursorByRange(
2561     const uno::Reference< text::XTextRange > & xTextPosition)
2562 throw (uno::RuntimeException)
2563 {
2564 	vos::OGuard aGuard(Application::GetSolarMutex());
2565 
2566 	if(!IsValid())
2567 	{
2568 		uno::RuntimeException aRuntime;
2569 		aRuntime.Message = C2U(cInvalidObject);
2570 		throw aRuntime;
2571 	}
2572 
2573 	uno::Reference< text::XTextCursor >  aRef;
2574 	SwUnoInternalPaM aPam(*GetDoc());
2575     if (::sw::XTextRangeToSwPaM(aPam, xTextPosition))
2576 	{
2577 		SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
2578 
2579         SwStartNode* p1 = aPam.GetNode()->StartOfSectionNode();
2580 		//document starts with a section?
2581 		while(p1->IsSectionNode())
2582 		{
2583             p1 = p1->StartOfSectionNode();
2584 		}
2585         SwStartNode *const p2 = rNode.StartOfSectionNode();
2586 
2587 		if(p1 == p2)
2588         {
2589             aRef = static_cast<text::XWordCursor*>(
2590                     new SwXTextCursor(*GetDoc(), this, CURSOR_BODY,
2591                         *aPam.GetPoint(), aPam.GetMark()));
2592         }
2593 	}
2594 	if(!aRef.is())
2595     {
2596 		throw uno::RuntimeException();
2597     }
2598 	return aRef;
2599 }
2600 
2601 /*-- 10.12.98 11:17:30---------------------------------------------------
2602 
2603   -----------------------------------------------------------------------*/
2604 uno::Reference< container::XEnumeration > SAL_CALL
2605 SwXBodyText::createEnumeration()
2606 throw (uno::RuntimeException)
2607 {
2608 	vos::OGuard aGuard(Application::GetSolarMutex());
2609 
2610     if (!IsValid())
2611 	{
2612 		uno::RuntimeException aRuntime;
2613 		aRuntime.Message = C2U(cInvalidObject);
2614 		throw aRuntime;
2615 	}
2616 
2617     SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
2618     SwPosition aPos(rNode);
2619     ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
2620         GetDoc()->CreateUnoCrsr(aPos, sal_False));
2621     pUnoCursor->Move(fnMoveBackward, fnGoDoc);
2622     const uno::Reference< container::XEnumeration > xRet
2623         = new SwXParagraphEnumeration(this, pUnoCursor, CURSOR_BODY);
2624     return xRet;
2625 }
2626 
2627 /* -----------------18.12.98 13:36-------------------
2628  *
2629  * --------------------------------------------------*/
2630 uno::Type SAL_CALL
2631 SwXBodyText::getElementType() throw (uno::RuntimeException)
2632 {
2633     return text::XTextRange::static_type();
2634 }
2635 /* -----------------18.12.98 13:36-------------------
2636  *
2637  * --------------------------------------------------*/
2638 sal_Bool SAL_CALL
2639 SwXBodyText::hasElements() throw (uno::RuntimeException)
2640 {
2641 	vos::OGuard aGuard(Application::GetSolarMutex());
2642 
2643     if (!IsValid())
2644 	{
2645 		uno::RuntimeException aRuntime;
2646 		aRuntime.Message = C2U(cInvalidObject);
2647 		throw aRuntime;
2648 	}
2649 
2650     return sal_True;
2651 }
2652 
2653 /******************************************************************
2654  *	SwXHeadFootText
2655  ******************************************************************/
2656 
2657 class SwXHeadFootText::Impl
2658     : public SwClient
2659 {
2660 
2661 public:
2662 
2663     bool                        m_bIsHeader;
2664 
2665     Impl(   SwXHeadFootText & /*rThis*/,
2666             SwFrmFmt & rHeadFootFmt, const bool bIsHeader)
2667         : SwClient(& rHeadFootFmt)
2668         , m_bIsHeader(bIsHeader)
2669     {
2670     }
2671 
2672     SwFrmFmt * GetHeadFootFmt() const {
2673         return static_cast<SwFrmFmt*>(
2674                 const_cast<SwModify*>(GetRegisteredIn()));
2675     }
2676 
2677     SwFrmFmt & GetHeadFootFmtOrThrow() {
2678         SwFrmFmt *const pFmt( GetHeadFootFmt() );
2679         if (!pFmt) {
2680             throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
2681                     "SwXHeadFootText: disposed or invalid")), 0);
2682         }
2683         return *pFmt;
2684     }
2685 protected:
2686     // SwClient
2687     virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
2688 
2689 };
2690 
2691 /*-- 11.12.98 10:14:51---------------------------------------------------
2692 
2693   -----------------------------------------------------------------------*/
2694 void SwXHeadFootText::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
2695 {
2696     ClientModify(this, pOld, pNew);
2697 }
2698 
2699 bool SwXHeadFootText::IsXHeadFootText(SwClient *const pClient)
2700 {
2701     return 0 != dynamic_cast<SwXHeadFootText::Impl*>(pClient);
2702 }
2703 
2704 uno::Reference< text::XText >
2705 SwXHeadFootText::CreateXHeadFootText(
2706         SwFrmFmt & rHeadFootFmt, const bool bIsHeader)
2707 {
2708     // re-use existing SwXHeadFootText
2709     // #i105557#: do not iterate over the registered clients: race condition
2710     uno::Reference< text::XText > xText(rHeadFootFmt.GetXObject(),
2711             uno::UNO_QUERY);
2712     if (!xText.is())
2713     {
2714         SwXHeadFootText *const pXHFT(
2715                 new SwXHeadFootText(rHeadFootFmt, bIsHeader));
2716         xText.set(pXHFT);
2717         rHeadFootFmt.SetXObject(xText);
2718     }
2719     return xText;
2720 }
2721 
2722 /*-- 11.12.98 10:14:48---------------------------------------------------
2723 
2724   -----------------------------------------------------------------------*/
2725 SwXHeadFootText::SwXHeadFootText(SwFrmFmt & rHeadFootFmt, const bool bIsHeader)
2726     : SwXText(rHeadFootFmt.GetDoc(),
2727             (bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER)
2728     , m_pImpl( new SwXHeadFootText::Impl(*this, rHeadFootFmt, bIsHeader) )
2729 {
2730 }
2731 
2732 /*-- 11.12.98 10:14:48---------------------------------------------------
2733 
2734   -----------------------------------------------------------------------*/
2735 SwXHeadFootText::~SwXHeadFootText()
2736 {
2737 }
2738 
2739 /* -----------------------------06.04.00 16:40--------------------------------
2740 
2741  ---------------------------------------------------------------------------*/
2742 OUString SAL_CALL
2743 SwXHeadFootText::getImplementationName() throw (uno::RuntimeException)
2744 {
2745 	return C2U("SwXHeadFootText");
2746 }
2747 
2748 /* -----------------------------06.04.00 16:40--------------------------------
2749 
2750  ---------------------------------------------------------------------------*/
2751 static char const*const g_ServicesHeadFootText[] =
2752 {
2753     "com.sun.star.text.Text",
2754 };
2755 static const size_t g_nServicesHeadFootText(
2756     sizeof(g_ServicesHeadFootText)/sizeof(g_ServicesHeadFootText[0]));
2757 
2758 sal_Bool SAL_CALL SwXHeadFootText::supportsService(const OUString& rServiceName)
2759 throw (uno::RuntimeException)
2760 {
2761     return ::sw::SupportsServiceImpl(
2762             g_nServicesHeadFootText, g_ServicesHeadFootText, rServiceName);
2763 }
2764 
2765 uno::Sequence< OUString > SAL_CALL
2766 SwXHeadFootText::getSupportedServiceNames() throw (uno::RuntimeException)
2767 {
2768     return ::sw::GetSupportedServiceNamesImpl(
2769             g_nServicesHeadFootText, g_ServicesHeadFootText);
2770 }
2771 
2772 /*-- 11.12.98 10:14:49---------------------------------------------------
2773 
2774   -----------------------------------------------------------------------*/
2775 const SwStartNode *SwXHeadFootText::GetStartNode() const
2776 {
2777 	const SwStartNode *pSttNd = 0;
2778     SwFrmFmt *const pHeadFootFmt = m_pImpl->GetHeadFootFmt();
2779 	if(pHeadFootFmt)
2780 	{
2781 		const SwFmtCntnt& rFlyCntnt = pHeadFootFmt->GetCntnt();
2782 		if( rFlyCntnt.GetCntntIdx() )
2783         {
2784 			pSttNd = rFlyCntnt.GetCntntIdx()->GetNode().GetStartNode();
2785         }
2786 	}
2787 	return pSttNd;
2788 }
2789 
2790 uno::Reference< text::XTextCursor >
2791 SwXHeadFootText::CreateCursor() throw (uno::RuntimeException)
2792 {
2793 	return createTextCursor();
2794 }
2795 /* -----------------------------21.03.00 15:39--------------------------------
2796 
2797  ---------------------------------------------------------------------------*/
2798 uno::Sequence< uno::Type > SAL_CALL
2799 SwXHeadFootText::getTypes() throw (uno::RuntimeException)
2800 {
2801     const uno::Sequence< uno::Type > aTypes = SwXHeadFootText_Base::getTypes();
2802     const uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
2803     return ::comphelper::concatSequences(aTypes, aTextTypes);
2804 }
2805 
2806 /* -----------------------------21.03.00 15:39--------------------------------
2807 
2808  ---------------------------------------------------------------------------*/
2809 uno::Sequence< sal_Int8 > SAL_CALL
2810 SwXHeadFootText::getImplementationId() throw (uno::RuntimeException)
2811 {
2812     vos::OGuard aGuard(Application::GetSolarMutex());
2813     static uno::Sequence< sal_Int8 > aId( 16 );
2814     static sal_Bool bInit = sal_False;
2815     if(!bInit)
2816     {
2817         rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
2818         bInit = sal_True;
2819     }
2820     return aId;
2821 }
2822 /* -----------------------------21.03.00 15:46--------------------------------
2823 
2824  ---------------------------------------------------------------------------*/
2825 uno::Any SAL_CALL
2826 SwXHeadFootText::queryInterface(const uno::Type& rType)
2827 throw (uno::RuntimeException)
2828 {
2829     const uno::Any ret = SwXHeadFootText_Base::queryInterface(rType);
2830     return (ret.getValueType() == ::getCppuVoidType())
2831         ?   SwXText::queryInterface(rType)
2832         :   ret;
2833 }
2834 
2835 /*-- 11.12.98 10:14:50---------------------------------------------------
2836 
2837   -----------------------------------------------------------------------*/
2838 uno::Reference< text::XTextCursor > SAL_CALL
2839 SwXHeadFootText::createTextCursor() throw (uno::RuntimeException)
2840 {
2841 	vos::OGuard aGuard(Application::GetSolarMutex());
2842 
2843     SwFrmFmt & rHeadFootFmt( m_pImpl->GetHeadFootFmtOrThrow() );
2844 
2845     uno::Reference< text::XTextCursor > xRet;
2846     const SwFmtCntnt& rFlyCntnt = rHeadFootFmt.GetCntnt();
2847     const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
2848     SwPosition aPos(rNode);
2849     SwXTextCursor *const pXCursor = new SwXTextCursor(*GetDoc(), this,
2850             (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER, aPos);
2851     SwUnoCrsr *const pUnoCrsr = pXCursor->GetCursor();
2852     pUnoCrsr->Move(fnMoveForward, fnGoNode);
2853 
2854     // save current start node to be able to check if there is content
2855     // after the table - otherwise the cursor would be in the body text!
2856     SwStartNode const*const pOwnStartNode = rNode.FindSttNodeByType(
2857             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2858     // is there a table here?
2859     SwTableNode* pTblNode = pUnoCrsr->GetNode()->FindTableNode();
2860     SwCntntNode* pCont = 0;
2861     while (pTblNode)
2862     {
2863         pUnoCrsr->GetPoint()->nNode = *pTblNode->EndOfSectionNode();
2864         pCont = GetDoc()->GetNodes().GoNext(&pUnoCrsr->GetPoint()->nNode);
2865         pTblNode = pCont->FindTableNode();
2866     }
2867     if (pCont)
2868     {
2869         pUnoCrsr->GetPoint()->nContent.Assign(pCont, 0);
2870     }
2871     SwStartNode const*const pNewStartNode =
2872         pUnoCrsr->GetNode()->FindSttNodeByType(
2873             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2874     if (!pNewStartNode || (pNewStartNode != pOwnStartNode))
2875     {
2876         uno::RuntimeException aExcept;
2877         aExcept.Message = C2U("no text available");
2878         throw aExcept;
2879     }
2880     xRet = static_cast<text::XWordCursor*>(pXCursor);
2881 	return xRet;
2882 }
2883 
2884 /*-- 11.12.98 10:14:50---------------------------------------------------
2885 
2886   -----------------------------------------------------------------------*/
2887 uno::Reference< text::XTextCursor > SAL_CALL
2888 SwXHeadFootText::createTextCursorByRange(
2889     const uno::Reference< text::XTextRange > & xTextPosition)
2890 throw (uno::RuntimeException)
2891 {
2892 	vos::OGuard aGuard(Application::GetSolarMutex());
2893 
2894     SwFrmFmt & rHeadFootFmt( m_pImpl->GetHeadFootFmtOrThrow() );
2895 
2896 	SwUnoInternalPaM aPam(*GetDoc());
2897     if (!::sw::XTextRangeToSwPaM(aPam, xTextPosition))
2898     {
2899         uno::RuntimeException aRuntime;
2900         aRuntime.Message = C2U(cInvalidObject);
2901         throw aRuntime;
2902     }
2903 
2904 	uno::Reference< text::XTextCursor >  xRet;
2905     SwNode& rNode = rHeadFootFmt.GetCntnt().GetCntntIdx()->GetNode();
2906     SwPosition aPos(rNode);
2907     SwPaM aHFPam(aPos);
2908     aHFPam.Move(fnMoveForward, fnGoNode);
2909     SwStartNode *const pOwnStartNode = aHFPam.GetNode()->FindSttNodeByType(
2910             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2911     SwStartNode *const p1 = aPam.GetNode()->FindSttNodeByType(
2912             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2913     if (p1 == pOwnStartNode)
2914     {
2915         xRet = static_cast<text::XWordCursor*>(
2916                 new SwXTextCursor(*GetDoc(), this,
2917                     (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER,
2918                     *aPam.GetPoint(), aPam.GetMark()));
2919     }
2920 	return xRet;
2921 }
2922 
2923 /* -----------------19.03.99 15:44-------------------
2924  *
2925  * --------------------------------------------------*/
2926 uno::Reference< container::XEnumeration > SAL_CALL
2927 SwXHeadFootText::createEnumeration()
2928 throw (uno::RuntimeException)
2929 {
2930 	vos::OGuard aGuard(Application::GetSolarMutex());
2931 
2932     SwFrmFmt & rHeadFootFmt( m_pImpl->GetHeadFootFmtOrThrow() );
2933 
2934     uno::Reference< container::XEnumeration >  aRef;
2935     const SwFmtCntnt& rFlyCntnt = rHeadFootFmt.GetCntnt();
2936     const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
2937     SwPosition aPos(rNode);
2938     ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
2939         GetDoc()->CreateUnoCrsr(aPos, sal_False));
2940     pUnoCursor->Move(fnMoveForward, fnGoNode);
2941     aRef = new SwXParagraphEnumeration(this, pUnoCursor,
2942                 (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER);
2943 
2944 	return aRef;
2945 }
2946 
2947 /* -----------------19.03.99 15:50-------------------
2948  *
2949  * --------------------------------------------------*/
2950 uno::Type SAL_CALL
2951 SwXHeadFootText::getElementType() throw (uno::RuntimeException)
2952 {
2953     return text::XTextRange::static_type();
2954 }
2955 /* -----------------19.03.99 15:50-------------------
2956  *
2957  * --------------------------------------------------*/
2958 sal_Bool SAL_CALL SwXHeadFootText::hasElements() throw (uno::RuntimeException)
2959 {
2960 	return sal_True;
2961 }
2962 
2963