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