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