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