LibreOffice Module sw (master) 1
unotext.cxx
Go to the documentation of this file.
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 <set>
24
25#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
26#include <com/sun/star/text/ControlCharacter.hpp>
27#include <com/sun/star/text/TableColumnSeparator.hpp>
28#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
29#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
30
31#include <svl/listener.hxx>
32#include <vcl/svapp.hxx>
38#include <sal/log.hxx>
40
41#include <cmdid.h>
42#include <unotextbodyhf.hxx>
43#include <unotext.hxx>
44#include <unotextrange.hxx>
45#include <unotextcursor.hxx>
46#include <unosection.hxx>
47#include <unobookmark.hxx>
48#include <unorefmark.hxx>
49#include <unoport.hxx>
50#include <unotbl.hxx>
51#include <unoidx.hxx>
52#include <unocoll.hxx>
53#include <unoframe.hxx>
54#include <unofield.hxx>
55#include <unometa.hxx>
56#include <unomap.hxx>
57#include <unoprnms.hxx>
58#include <unoparagraph.hxx>
59#include <unocrsrhelper.hxx>
60#include <docary.hxx>
61#include <doc.hxx>
63#include <IDocumentUndoRedo.hxx>
64#include <bookmark.hxx>
65#include <redline.hxx>
66#include <swundo.hxx>
67#include <section.hxx>
68#include <fmtanchr.hxx>
69#include <fmtcntnt.hxx>
70#include <ndtxt.hxx>
71#include <SwRewriter.hxx>
72#include <strings.hrc>
73#include <frameformats.hxx>
74#include <unocontentcontrol.hxx>
75
76using namespace ::com::sun::star;
77
78constexpr OUStringLiteral cInvalidObject = u"this object is invalid";
79
81{
82
83public:
89
90 Impl( SwXText & rThis,
91 SwDoc *const pDoc, const CursorType eType)
92 : m_rThis(rThis)
94 , m_eType(eType)
95 , m_pDoc(pDoc)
96 , m_bIsValid(nullptr != pDoc)
97 {
98 }
99
102 uno::Reference< text::XTextRange >
104 const uno::Sequence< beans::PropertyValue >&
105 rCharacterAndParagraphProperties,
106 const uno::Reference< text::XTextRange >& xInsertPosition);
107
110 sal_Int16 ComparePositions(
111 const uno::Reference<text::XTextRange>& xPos1,
112 const uno::Reference<text::XTextRange>& xPos2);
113
116 bool CheckForOwnMember(const SwPaM & rPaM);
117
118 void ConvertCell(
119 const uno::Sequence< uno::Reference< text::XTextRange > > & rCell,
120 std::vector<SwNodeRange> & rRowNodes,
121 SwNodeRange *const pLastCell);
122
123};
124
125SwXText::SwXText(SwDoc *const pDoc, const CursorType eType)
126 : m_pImpl( new SwXText::Impl(*this, pDoc, eType) )
127{
128}
129
131{
132}
133
134const SwDoc * SwXText::GetDoc() const
135{
136 return m_pImpl->m_pDoc;
137}
138
140{
141 return m_pImpl->m_pDoc;
142}
143
145{
146 return m_pImpl->m_bIsValid;
147}
148
150{
151 m_pImpl->m_bIsValid = false;
152}
153
154void SwXText::SetDoc(SwDoc *const pDoc)
155{
156 OSL_ENSURE(!m_pImpl->m_pDoc || !pDoc,
157 "SwXText::SetDoc: already have a doc?");
158 m_pImpl->m_pDoc = pDoc;
159 m_pImpl->m_bIsValid = (nullptr != pDoc);
160}
161
162void
163SwXText::PrepareForAttach(uno::Reference< text::XTextRange > &, const SwPaM &)
164{
165}
166
167bool SwXText::CheckForOwnMemberMeta(const SwPaM &, const bool)
168{
169 OSL_ENSURE(CursorType::Meta != m_pImpl->m_eType, "should not be called!");
170 return false;
171}
172
174{
176}
177
178uno::Reference< text::XTextCursor > SAL_CALL SwXText::createTextCursor()
179{
180 SolarMutexGuard aGuard;
182 if (!xCursor.is())
183 {
184 uno::RuntimeException aRuntime;
185 aRuntime.Message = cInvalidObject;
186 throw aRuntime;
187 }
188 return static_cast<text::XWordCursor*>(xCursor.get());
189}
190
193{
195 if(IsValid())
196 {
197 SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
198 SwPosition aPos(rNode);
199 xRet = new SwXTextCursor(*GetDoc(), this, m_pImpl->m_eType, aPos);
200 xRet->gotoStart(false);
201 }
202 return xRet;
203}
204
205css::uno::Reference< css::text::XTextCursor > SAL_CALL SwXText::createTextCursorByRange(
206 const ::css::uno::Reference< ::css::text::XTextRange >& aTextPosition )
207{
208 SolarMutexGuard aGuard;
209 return static_cast<text::XWordCursor*>(createXTextCursorByRange(aTextPosition).get());
210}
211
212
213uno::Any SAL_CALL
215{
216 uno::Any aRet;
217 if (rType == cppu::UnoType<text::XText>::get())
218 {
219 aRet <<= uno::Reference< text::XText >(this);
220 }
221 else if (rType == cppu::UnoType<text::XSimpleText>::get())
222 {
223 aRet <<= uno::Reference< text::XSimpleText >(this);
224 }
225 else if (rType == cppu::UnoType<text::XTextRange>::get())
226 {
227 aRet <<= uno::Reference< text::XTextRange>(this);
228 }
230 {
231 aRet <<= uno::Reference< text::XTextRangeCompare >(this);
232 }
233 else if (rType == cppu::UnoType<lang::XTypeProvider>::get())
234 {
235 aRet <<= uno::Reference< lang::XTypeProvider >(this);
236 }
238 {
239 aRet <<= uno::Reference< text::XRelativeTextContentInsert >(this);
240 }
242 {
243 aRet <<= uno::Reference< text::XRelativeTextContentRemove >(this);
244 }
245 else if (rType == cppu::UnoType<beans::XPropertySet>::get())
246 {
247 aRet <<= uno::Reference< beans::XPropertySet >(this);
248 }
250 {
251 aRet <<= uno::Reference< text::XTextAppendAndConvert >(this);
252 }
253 else if (rType == cppu::UnoType<text::XTextAppend>::get())
254 {
255 aRet <<= uno::Reference< text::XTextAppend >(this);
256 }
258 {
259 aRet <<= uno::Reference< text::XTextPortionAppend >(this);
260 }
262 {
263 aRet <<= uno::Reference< text::XParagraphAppend >(this);
264 }
265 else if (rType == cppu::UnoType<text::XTextConvert>::get() )
266 {
267 aRet <<= uno::Reference< text::XTextConvert >(this);
268 }
270 {
271 aRet <<= uno::Reference< text::XTextContentAppend >(this);
272 }
273 else if(rType == cppu::UnoType<text::XTextCopy>::get())
274 {
275 aRet <<= uno::Reference< text::XTextCopy >( this );
276 }
277 return aRet;
278}
279
280uno::Sequence< uno::Type > SAL_CALL
282{
283 static const uno::Sequence< uno::Type > aTypes {
296 };
297 return aTypes;
298}
299
300// belongs the range in the text ? insert it then.
301void SAL_CALL
302SwXText::insertString(const uno::Reference< text::XTextRange >& xTextRange,
303 const OUString& rString, sal_Bool bAbsorb)
304{
305 SolarMutexGuard aGuard;
306 comphelper::ProfileZone aZone("SwXText::insertString");
307
308 if (!xTextRange.is())
309 {
310 throw uno::RuntimeException();
311 }
312 if (!GetDoc())
313 {
314 throw uno::RuntimeException();
315 }
316 SwXTextRange *const pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
317 OTextCursorHelper *const pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
318 if ((!pRange || &pRange ->GetDoc() != GetDoc()) &&
319 (!pCursor || pCursor->GetDoc() != GetDoc()))
320 {
321 throw uno::RuntimeException();
322 }
323
324 const SwStartNode *const pOwnStartNode = GetStartNode();
325 SwPaM aPam(GetDoc()->GetNodes());
326 const SwPaM * pPam(nullptr);
327 if (pCursor)
328 {
329 pPam = pCursor->GetPaM();
330 }
331 else // pRange
332 {
333 if (pRange->GetPositions(aPam))
334 {
335 pPam = &aPam;
336 }
337 }
338 if (!pPam)
339 {
340 throw uno::RuntimeException();
341 }
342
343 const SwStartNode* pTmp(pPam->GetPointNode().StartOfSectionNode());
344 while (pTmp && pTmp->IsSectionNode())
345 {
346 pTmp = pTmp->StartOfSectionNode();
347 }
348 if (!pOwnStartNode || (pOwnStartNode != pTmp))
349 {
350 throw uno::RuntimeException();
351 }
352
353 bool bForceExpandHints( false );
354 if (CursorType::Meta == m_pImpl->m_eType)
355 {
356 try
357 {
358 bForceExpandHints = CheckForOwnMemberMeta(*pPam, bAbsorb);
359 }
360 catch (const lang::IllegalArgumentException& iae)
361 {
362 // stupid method not allowed to throw iae
363 css::uno::Any anyEx = cppu::getCaughtException();
364 throw lang::WrappedTargetRuntimeException( iae.Message,
365 uno::Reference< uno::XInterface >(), anyEx );
366 }
367 }
368 if (bAbsorb)
369 {
373 if (pCursor)
374 {
375 SwXTextCursor * const pTextCursor(
376 dynamic_cast<SwXTextCursor*>(pCursor) );
377 if (pTextCursor)
378 {
379 pTextCursor->DeleteAndInsert(rString, ::sw::DeleteAndInsertMode::ForceReplace
380 | (bForceExpandHints ? ::sw::DeleteAndInsertMode::ForceExpandHints : ::sw::DeleteAndInsertMode::Default));
381 }
382 else
383 {
384 xTextRange->setString(rString);
385 }
386 }
387 else
388 {
389 pRange->DeleteAndInsert(rString, ::sw::DeleteAndInsertMode::ForceReplace
390 | (bForceExpandHints ? ::sw::DeleteAndInsertMode::ForceExpandHints : ::sw::DeleteAndInsertMode::Default));
391 }
392 }
393 else
394 {
395 // create a PaM positioned before the parameter PaM,
396 // so the text is inserted before
397 UnoActionContext aContext(GetDoc());
398 SwPaM aInsertPam(*pPam->Start());
399 ::sw::GroupUndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo());
401 *GetDoc(), aInsertPam, rString, bForceExpandHints );
402 }
403}
404
405void SAL_CALL
407 const uno::Reference< text::XTextRange > & xTextRange,
408 sal_Int16 nControlCharacter, sal_Bool bAbsorb)
409{
410 SolarMutexGuard aGuard;
411
412 if (!xTextRange.is())
413 {
414 throw lang::IllegalArgumentException();
415 }
416 if (!GetDoc())
417 {
418 throw uno::RuntimeException();
419 }
420
421 SwUnoInternalPaM aPam(*GetDoc());
422 if (!::sw::XTextRangeToSwPaM(aPam, xTextRange))
423 {
424 throw uno::RuntimeException();
425 }
426 const bool bForceExpandHints(CheckForOwnMemberMeta(aPam, bAbsorb));
427
428 const SwInsertFlags nInsertFlags =
429 bForceExpandHints
432
433 if (bAbsorb && aPam.HasMark())
434 {
435 m_pImpl->m_pDoc->getIDocumentContentOperations().DeleteAndJoin(aPam);
436 aPam.DeleteMark();
437 }
438
439 sal_Unicode cIns = 0;
440 switch (nControlCharacter)
441 {
442 case text::ControlCharacter::PARAGRAPH_BREAK :
443 // a table cell now becomes an ordinary text cell!
444 m_pImpl->m_pDoc->ClearBoxNumAttrs(aPam.GetPoint()->GetNode());
445 m_pImpl->m_pDoc->getIDocumentContentOperations().SplitNode(*aPam.GetPoint(), false);
446 break;
447 case text::ControlCharacter::APPEND_PARAGRAPH:
448 {
449 m_pImpl->m_pDoc->ClearBoxNumAttrs(aPam.GetPoint()->GetNode());
450 m_pImpl->m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPam.GetPoint());
451
452 SwXTextRange *const pRange =
453 dynamic_cast<SwXTextRange*>(xTextRange.get());
454 OTextCursorHelper *const pCursor =
455 dynamic_cast<OTextCursorHelper*>(xTextRange.get());
456 if (pRange)
457 {
458 pRange->SetPositions(aPam);
459 }
460 else if (pCursor)
461 {
462 SwPaM *const pCursorPam = pCursor->GetPaM();
463 *pCursorPam->GetPoint() = *aPam.GetPoint();
464 pCursorPam->DeleteMark();
465 }
466 }
467 break;
468 case text::ControlCharacter::LINE_BREAK: cIns = 10; break;
469 case text::ControlCharacter::SOFT_HYPHEN: cIns = CHAR_SOFTHYPHEN; break;
470 case text::ControlCharacter::HARD_HYPHEN: cIns = CHAR_HARDHYPHEN; break;
471 case text::ControlCharacter::HARD_SPACE: cIns = CHAR_HARDBLANK; break;
472 }
473 if (cIns)
474 {
475 m_pImpl->m_pDoc->getIDocumentContentOperations().InsertString(
476 aPam, OUString(cIns), nInsertFlags);
477 }
478
479 if (!bAbsorb)
480 return;
481
482 SwXTextRange *const pRange =
483 dynamic_cast<SwXTextRange*>(xTextRange.get());
484 OTextCursorHelper *const pCursor =
485 dynamic_cast<OTextCursorHelper*>(xTextRange.get());
486
487 SwCursor aCursor(*aPam.GetPoint(), nullptr);
488 SwUnoCursorHelper::SelectPam(aCursor, true);
489 aCursor.Left(1);
490 // here, the PaM needs to be moved:
491 if (pRange)
492 {
493 pRange->SetPositions(aCursor);
494 }
495 else
496 {
497 SwPaM *const pUnoCursor = pCursor->GetPaM();
498 *pUnoCursor->GetPoint() = *aCursor.GetPoint();
499 if (aCursor.HasMark())
500 {
501 pUnoCursor->SetMark();
502 *pUnoCursor->GetMark() = *aCursor.GetMark();
503 }
504 else
505 {
506 pUnoCursor->DeleteMark();
507 }
508 }
509}
510
511void SAL_CALL
513 const uno::Reference< text::XTextRange > & xRange,
514 const uno::Reference< text::XTextContent > & xContent,
515 sal_Bool bAbsorb)
516{
517 SolarMutexGuard aGuard;
518 comphelper::ProfileZone aZone("SwXText::insertTextContent");
519
520 if (!xRange.is())
521 {
522 lang::IllegalArgumentException aIllegal;
523 aIllegal.Message = "first parameter invalid;";
524 throw aIllegal;
525 }
526 if (!xContent.is())
527 {
528 lang::IllegalArgumentException aIllegal;
529 aIllegal.Message = "second parameter invalid";
530 throw aIllegal;
531 }
532 if(!GetDoc())
533 {
534 uno::RuntimeException aRuntime;
535 aRuntime.Message = cInvalidObject;
536 throw aRuntime;
537 }
538
539 SwUnoInternalPaM aPam(*GetDoc());
540 if (!::sw::XTextRangeToSwPaM(aPam, xRange))
541 {
542 lang::IllegalArgumentException aIllegal;
543 aIllegal.Message = "first parameter invalid";
544 throw aIllegal;
545 }
546
547 // first test if the range is at the right position, then call
548 // xContent->attach
549 const SwStartNode* pOwnStartNode = GetStartNode();
550 SwStartNodeType eSearchNodeType = SwNormalStartNode;
551 switch (m_pImpl->m_eType)
552 {
553 case CursorType::Frame: eSearchNodeType = SwFlyStartNode; break;
554 case CursorType::TableText: eSearchNodeType = SwTableBoxStartNode; break;
555 case CursorType::Footnote: eSearchNodeType = SwFootnoteStartNode; break;
556 case CursorType::Header: eSearchNodeType = SwHeaderStartNode; break;
557 case CursorType::Footer: eSearchNodeType = SwFooterStartNode; break;
558 //case CURSOR_INVALID:
559 //case CursorType::Body:
560 default:
561 break;
562 }
563
564 const SwStartNode* pTmp =
565 aPam.GetPointNode().FindSttNodeByType(eSearchNodeType);
566
567 // ignore SectionNodes
568 while (pTmp && pTmp->IsSectionNode())
569 {
570 pTmp = pTmp->StartOfSectionNode();
571 }
572 // if the document starts with a section
573 while (pOwnStartNode && pOwnStartNode->IsSectionNode())
574 {
575 pOwnStartNode = pOwnStartNode->StartOfSectionNode();
576 }
577 // this checks if (this) and xRange are in the same text::XText interface
578 if (pOwnStartNode != pTmp)
579 {
580 uno::RuntimeException aRunException;
581 aRunException.Message = "text interface and cursor not related";
582 throw aRunException;
583 }
584
585 const bool bForceExpandHints(CheckForOwnMemberMeta(aPam, bAbsorb));
586
587 // special treatment for Contents that do not replace the range, but
588 // instead are "overlaid"
589 SwXDocumentIndexMark *const pDocumentIndexMark =
590 dynamic_cast<SwXDocumentIndexMark*>(xContent.get());
591 SwXTextSection *const pSection =
592 dynamic_cast<SwXTextSection*>(xContent.get());
593 SwXBookmark *const pBookmark =
594 dynamic_cast<SwXBookmark*>(xContent.get());
595 SwXReferenceMark *const pReferenceMark =
596 dynamic_cast<SwXReferenceMark*>(xContent.get());
597 SwXMeta *const pMeta = dynamic_cast<SwXMeta*>(xContent.get());
598 auto* pContentControl = dynamic_cast<SwXContentControl*>(xContent.get());
599 SwXTextField* pTextField = dynamic_cast<SwXTextField*>(xContent.get());
600 if (pTextField && pTextField->GetServiceId() != SwServiceType::FieldTypeAnnotation)
601 pTextField = nullptr;
602
603 const bool bAttribute = pBookmark || pDocumentIndexMark
604 || pSection || pReferenceMark || pMeta || pContentControl || pTextField;
605
606 if (bAbsorb && !bAttribute)
607 {
608 if (SwXTextRange *const pRange = dynamic_cast<SwXTextRange*>(xRange.get()))
609 {
610 pRange->DeleteAndInsert(u"", ::sw::DeleteAndInsertMode::ForceReplace
611 | (bForceExpandHints ? ::sw::DeleteAndInsertMode::ForceExpandHints : ::sw::DeleteAndInsertMode::Default));
612 }
613 else if (SwXTextCursor *const pCursor = dynamic_cast<SwXTextCursor*>(dynamic_cast<OTextCursorHelper*>(xRange.get())))
614 {
615 pCursor->DeleteAndInsert(u"", ::sw::DeleteAndInsertMode::ForceReplace
616 | (bForceExpandHints ? ::sw::DeleteAndInsertMode::ForceExpandHints : ::sw::DeleteAndInsertMode::Default));
617 }
618 else
619 {
620 xRange->setString(OUString());
621 }
622 }
623 uno::Reference< text::XTextRange > xTempRange =
624 (bAttribute && bAbsorb) ? xRange : xRange->getStart();
625 if (bForceExpandHints)
626 {
627 // if necessary, replace xTempRange with a new SwXTextCursor
628 PrepareForAttach(xTempRange, aPam);
629 }
630 xContent->attach(xTempRange);
631}
632
633void SAL_CALL
635 const uno::Reference< text::XTextContent>& xNewContent,
636 const uno::Reference< text::XTextContent>& xSuccessor)
637{
638 SolarMutexGuard aGuard;
639
640 if(!GetDoc())
641 {
642 uno::RuntimeException aRuntime;
643 aRuntime.Message = cInvalidObject;
644 throw aRuntime;
645 }
646
647 SwXParagraph *const pPara = dynamic_cast<SwXParagraph*>(xNewContent.get());
648 if (!pPara || !pPara->IsDescriptor() || !xSuccessor.is())
649 {
650 throw lang::IllegalArgumentException();
651 }
652
653 bool bRet = false;
654 SwXTextSection *const pXSection = dynamic_cast<SwXTextSection*>(xSuccessor.get());
655 SwXTextTable *const pXTable = dynamic_cast<SwXTextTable*>(xSuccessor.get());
656 SwFrameFormat *const pTableFormat = pXTable ? pXTable->GetFrameFormat() : nullptr;
657 SwTextNode * pTextNode = nullptr;
658 if(pTableFormat && pTableFormat->GetDoc() == GetDoc())
659 {
660 SwTable *const pTable = SwTable::FindTable( pTableFormat );
661 SwTableNode *const pTableNode = pTable->GetTableNode();
662
663 const SwNodeIndex aTableIdx( *pTableNode, -1 );
664 SwPosition aBefore(aTableIdx);
666 pTextNode = aBefore.GetNode().GetTextNode();
667 }
668 else if (pXSection && pXSection->GetFormat() &&
669 pXSection->GetFormat()->GetDoc() == GetDoc())
670 {
671 SwSectionFormat *const pSectFormat = pXSection->GetFormat();
672 SwSectionNode *const pSectNode = pSectFormat->GetSectionNode();
673
674 const SwNodeIndex aSectIdx( *pSectNode, -1 );
675 SwPosition aBefore(aSectIdx);
677 pTextNode = aBefore.GetNode().GetTextNode();
678 }
679 if (!bRet || !pTextNode)
680 {
681 throw lang::IllegalArgumentException();
682 }
683 pPara->attachToText(*this, *pTextNode);
684}
685
686void SAL_CALL
688 const uno::Reference< text::XTextContent>& xNewContent,
689 const uno::Reference< text::XTextContent>& xPredecessor)
690{
691 SolarMutexGuard aGuard;
692
693 if(!GetDoc())
694 {
695 throw uno::RuntimeException();
696 }
697
698 SwXParagraph *const pPara = dynamic_cast<SwXParagraph*>(xNewContent.get());
699 if(!pPara || !pPara->IsDescriptor() || !xPredecessor.is())
700 {
701 throw lang::IllegalArgumentException();
702 }
703
704 SwXTextSection *const pXSection = dynamic_cast<SwXTextSection*>(xPredecessor.get());
705 SwXTextTable *const pXTable = dynamic_cast<SwXTextTable*>(xPredecessor.get());
706 SwFrameFormat *const pTableFormat = pXTable ? pXTable->GetFrameFormat() : nullptr;
707 bool bRet = false;
708 SwTextNode * pTextNode = nullptr;
709 if(pTableFormat && pTableFormat->GetDoc() == GetDoc())
710 {
711 SwTable *const pTable = SwTable::FindTable( pTableFormat );
712 SwTableNode *const pTableNode = pTable->GetTableNode();
713
714 SwEndNode *const pTableEnd = pTableNode->EndOfSectionNode();
715 SwPosition aTableEnd(*pTableEnd);
716 bRet = GetDoc()->getIDocumentContentOperations().AppendTextNode( aTableEnd );
717 pTextNode = aTableEnd.GetNode().GetTextNode();
718 }
719 else if (pXSection && pXSection->GetFormat() &&
720 pXSection->GetFormat()->GetDoc() == GetDoc())
721 {
722 SwSectionFormat *const pSectFormat = pXSection->GetFormat();
723 SwSectionNode *const pSectNode = pSectFormat->GetSectionNode();
724 SwEndNode *const pEnd = pSectNode->EndOfSectionNode();
725 SwPosition aEnd(*pEnd);
727 pTextNode = aEnd.GetNode().GetTextNode();
728 }
729 if (!bRet || !pTextNode)
730 {
731 throw lang::IllegalArgumentException();
732 }
733 pPara->attachToText(*this, *pTextNode);
734}
735
736void SAL_CALL
738 const uno::Reference< text::XTextContent>& xSuccessor)
739{
740 SolarMutexGuard aGuard;
741
742 if(!GetDoc())
743 {
744 uno::RuntimeException aRuntime;
745 aRuntime.Message = cInvalidObject;
746 throw aRuntime;
747 }
748
749 bool bRet = false;
750 SwXTextSection *const pXSection = dynamic_cast<SwXTextSection*>(xSuccessor.get());
751 SwXTextTable *const pXTable = dynamic_cast<SwXTextTable*>(xSuccessor.get());
752 SwFrameFormat *const pTableFormat = pXTable ? pXTable->GetFrameFormat() : nullptr;
753 if(pTableFormat && pTableFormat->GetDoc() == GetDoc())
754 {
755 SwTable *const pTable = SwTable::FindTable( pTableFormat );
756 SwTableNode *const pTableNode = pTable->GetTableNode();
757
758 const SwNodeIndex aTableIdx( *pTableNode, -1 );
759 if(aTableIdx.GetNode().IsTextNode())
760 {
761 SwPaM aBefore(aTableIdx);
762 bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( aBefore );
763 }
764 }
765 else if (pXSection && pXSection->GetFormat() &&
766 pXSection->GetFormat()->GetDoc() == GetDoc())
767 {
768 SwSectionFormat *const pSectFormat = pXSection->GetFormat();
769 SwSectionNode *const pSectNode = pSectFormat->GetSectionNode();
770
771 const SwNodeIndex aSectIdx( *pSectNode, -1 );
772 if(aSectIdx.GetNode().IsTextNode())
773 {
774 SwPaM aBefore(aSectIdx);
775 bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( aBefore );
776 }
777 }
778 if(!bRet)
779 {
780 throw lang::IllegalArgumentException();
781 }
782}
783
784void SAL_CALL
786 const uno::Reference< text::XTextContent>& xPredecessor)
787{
788 SolarMutexGuard aGuard;
789
790 if(!GetDoc())
791 {
792 uno::RuntimeException aRuntime;
793 aRuntime.Message = cInvalidObject;
794 throw aRuntime;
795 }
796
797 bool bRet = false;
798 SwXTextSection *const pXSection = dynamic_cast<SwXTextSection*>(xPredecessor.get());
799 SwXTextTable *const pXTable = dynamic_cast<SwXTextTable*>(xPredecessor.get());
800 SwFrameFormat *const pTableFormat = pXTable ? pXTable->GetFrameFormat() : nullptr;
801 if(pTableFormat && pTableFormat->GetDoc() == GetDoc())
802 {
803 SwTable *const pTable = SwTable::FindTable( pTableFormat );
804 SwTableNode *const pTableNode = pTable->GetTableNode();
805 SwEndNode *const pTableEnd = pTableNode->EndOfSectionNode();
806
807 const SwNodeIndex aTableIdx( *pTableEnd, 1 );
808 if(aTableIdx.GetNode().IsTextNode())
809 {
810 SwPaM aPaM(aTableIdx);
812 }
813 }
814 else if (pXSection && pXSection->GetFormat() &&
815 pXSection->GetFormat()->GetDoc() == GetDoc())
816 {
817 SwSectionFormat *const pSectFormat = pXSection->GetFormat();
818 SwSectionNode *const pSectNode = pSectFormat->GetSectionNode();
819 SwEndNode *const pEnd = pSectNode->EndOfSectionNode();
820 const SwNodeIndex aSectIdx( *pEnd, 1 );
821 if(aSectIdx.GetNode().IsTextNode())
822 {
823 SwPaM aAfter(aSectIdx);
825 }
826 }
827 if(!bRet)
828 {
829 throw lang::IllegalArgumentException();
830 }
831}
832
833void SAL_CALL
835 const uno::Reference< text::XTextContent > & xContent)
836{
837 // forward: need no solar mutex here
838 if(!xContent.is())
839 {
840 uno::RuntimeException aRuntime;
841 aRuntime.Message = "first parameter invalid";
842 throw aRuntime;
843 }
844 xContent->dispose();
845}
846
847uno::Reference< text::XText > SAL_CALL
849{
850 SolarMutexGuard aGuard;
851 comphelper::ProfileZone aZone("SwXText::getText");
852
853 const uno::Reference< text::XText > xRet(this);
854 return xRet;
855}
856
857uno::Reference< text::XTextRange > SAL_CALL
859{
860 SolarMutexGuard aGuard;
861
863 if(!xRef.is())
864 {
865 uno::RuntimeException aRuntime;
866 aRuntime.Message = cInvalidObject;
867 throw aRuntime;
868 }
869 xRef->gotoStart(false);
870 return static_cast<text::XWordCursor*>(xRef.get());
871}
872
873uno::Reference< text::XTextRange > SAL_CALL
875{
876 SolarMutexGuard aGuard;
877
879 if(!xRef.is())
880 {
881 uno::RuntimeException aRuntime;
882 aRuntime.Message = cInvalidObject;
883 throw aRuntime;
884 }
885 xRef->gotoEnd(false);
886 return static_cast<text::XWordCursor*>(xRef.get());
887}
888
889OUString SAL_CALL SwXText::getString()
890{
891 SolarMutexGuard aGuard;
892
894 if(!xRet.is())
895 {
896 SAL_WARN("sw.uno", "cursor was not created in getString() call. Returning empty string.");
897 return OUString();
898 }
899 xRet->gotoEnd(true);
900 return xRet->getString();
901}
902
903void SAL_CALL
904SwXText::setString(const OUString& rString)
905{
906 SolarMutexGuard aGuard;
907
908 if (!GetDoc())
909 {
910 uno::RuntimeException aRuntime;
911 aRuntime.Message = cInvalidObject;
912 throw aRuntime;
913 }
914
915 const SwStartNode* pStartNode = GetStartNode();
916 if (!pStartNode)
917 {
918 throw uno::RuntimeException();
919 }
920
921 GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::START, nullptr);
922 //insert an empty paragraph at the start and at the end to ensure that
923 //all tables and sections can be removed by the selecting text::XTextCursor
924 if (CursorType::Meta != m_pImpl->m_eType)
925 {
926 SwPosition aStartPos(*pStartNode);
927 const SwEndNode* pEnd = pStartNode->EndOfSectionNode();
928 SwNodeIndex aEndIdx(*pEnd);
929 --aEndIdx;
930 //the inserting of nodes should only be done if really necessary
931 //to prevent #97924# (removes paragraph attributes when setting the text
932 //e.g. of a table cell
933 bool bInsertNodes = false;
934 SwNodeIndex aStartIdx(*pStartNode);
935 do
936 {
937 ++aStartIdx;
938 SwNode& rCurrentNode = aStartIdx.GetNode();
939 if(rCurrentNode.GetNodeType() == SwNodeType::Section
940 ||rCurrentNode.GetNodeType() == SwNodeType::Table)
941 {
942 bInsertNodes = true;
943 break;
944 }
945 }
946 while(aStartIdx < aEndIdx);
947 if(bInsertNodes)
948 {
950 SwPaM aPam(aEndIdx.GetNode());
952 }
953 }
954
956 if(!xRet.is())
957 {
958 GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::END, nullptr);
959 uno::RuntimeException aRuntime;
960 aRuntime.Message = cInvalidObject;
961 throw aRuntime;
962 }
963 xRet->gotoEnd(true);
964 xRet->setString(rString);
965 GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::END, nullptr);
966}
967
968//FIXME why is CheckForOwnMember duplicated in some insert methods?
969// Description: Checks if pRange/pCursor are member of the same text interface.
970// Only one of the pointers has to be set!
972 const SwPaM & rPaM)
973{
975 const SwStartNode* pOwnStartNode =
976 xOwnCursor->GetPaM()->GetPointNode().StartOfSectionNode();
977 SwStartNodeType eSearchNodeType = SwNormalStartNode;
978 switch (m_eType)
979 {
980 case CursorType::Frame: eSearchNodeType = SwFlyStartNode; break;
981 case CursorType::TableText: eSearchNodeType = SwTableBoxStartNode; break;
982 case CursorType::Footnote: eSearchNodeType = SwFootnoteStartNode; break;
983 case CursorType::Header: eSearchNodeType = SwHeaderStartNode; break;
984 case CursorType::Footer: eSearchNodeType = SwFooterStartNode; break;
985 //case CURSOR_INVALID:
986 //case CursorType::Body:
987 default:
988 ;
989 }
990
991 const SwNode& rSrcNode = rPaM.GetPointNode();
992 const SwStartNode* pTmp = rSrcNode.FindSttNodeByType(eSearchNodeType);
993
994 // skip SectionNodes / TableNodes to be able to compare across table/section boundaries
995 while (pTmp
996 && (pTmp->IsSectionNode() || pTmp->IsTableNode()
999 {
1000 pTmp = pTmp->StartOfSectionNode();
1001 }
1002
1003 while (pOwnStartNode->IsSectionNode() || pOwnStartNode->IsTableNode()
1005 && pOwnStartNode->GetStartNodeType() == SwTableBoxStartNode))
1006 {
1007 pOwnStartNode = pOwnStartNode->StartOfSectionNode();
1008 }
1009
1010 //this checks if (this) and xRange are in the same text::XText interface
1011 return (pOwnStartNode == pTmp);
1012}
1013
1014sal_Int16
1016 const uno::Reference<text::XTextRange>& xPos1,
1017 const uno::Reference<text::XTextRange>& xPos2)
1018{
1019 SwUnoInternalPaM aPam1(*m_pDoc);
1020 SwUnoInternalPaM aPam2(*m_pDoc);
1021
1022 if (!::sw::XTextRangeToSwPaM(aPam1, xPos1) ||
1023 !::sw::XTextRangeToSwPaM(aPam2, xPos2))
1024 {
1025 throw lang::IllegalArgumentException();
1026 }
1027 if (!CheckForOwnMember(aPam1) || !CheckForOwnMember(aPam2))
1028 {
1029 throw lang::IllegalArgumentException();
1030 }
1031
1032 sal_Int16 nCompare = 0;
1033 SwPosition const*const pStart1 = aPam1.Start();
1034 SwPosition const*const pStart2 = aPam2.Start();
1035 if (*pStart1 < *pStart2)
1036 {
1037 nCompare = 1;
1038 }
1039 else if (*pStart1 > *pStart2)
1040 {
1041 nCompare = -1;
1042 }
1043 else
1044 {
1045 OSL_ENSURE(*pStart1 == *pStart2,
1046 "SwPositions should be equal here");
1047 nCompare = 0;
1048 }
1049
1050 return nCompare;
1051}
1052
1053sal_Int16 SAL_CALL
1055 const uno::Reference<text::XTextRange>& xRange1,
1056 const uno::Reference<text::XTextRange>& xRange2)
1057{
1058 SolarMutexGuard aGuard;
1059
1060 if (!xRange1.is() || !xRange2.is())
1061 {
1062 throw lang::IllegalArgumentException();
1063 }
1064 const uno::Reference<text::XTextRange> xStart1 = xRange1->getStart();
1065 const uno::Reference<text::XTextRange> xStart2 = xRange2->getStart();
1066
1067 return m_pImpl->ComparePositions(xStart1, xStart2);
1068}
1069
1070sal_Int16 SAL_CALL
1072 const uno::Reference<text::XTextRange>& xRange1,
1073 const uno::Reference<text::XTextRange>& xRange2)
1074{
1075 SolarMutexGuard aGuard;
1076
1077 if (!xRange1.is() || !xRange2.is())
1078 {
1079 throw lang::IllegalArgumentException();
1080 }
1081 uno::Reference<text::XTextRange> xEnd1 = xRange1->getEnd();
1082 uno::Reference<text::XTextRange> xEnd2 = xRange2->getEnd();
1083
1084 return m_pImpl->ComparePositions(xEnd1, xEnd2);
1085}
1086
1087uno::Reference< beans::XPropertySetInfo > SAL_CALL
1089{
1091
1092 static uno::Reference< beans::XPropertySetInfo > xInfo =
1093 m_pImpl->m_rPropSet.getPropertySetInfo();
1094 return xInfo;
1095}
1096
1097void SAL_CALL
1098SwXText::setPropertyValue(const OUString& /*aPropertyName*/,
1099 const uno::Any& /*aValue*/)
1100{
1101 throw lang::IllegalArgumentException();
1102}
1103
1104uno::Any SAL_CALL
1106 const OUString& rPropertyName)
1107{
1108 SolarMutexGuard aGuard;
1109
1110 if(!IsValid())
1111 {
1112 throw uno::RuntimeException();
1113 }
1114
1115 SfxItemPropertyMapEntry const*const pEntry =
1116 m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
1117 if (!pEntry)
1118 {
1119 beans::UnknownPropertyException aExcept;
1120 aExcept.Message = "Unknown property: " + rPropertyName;
1121 throw aExcept;
1122 }
1123
1124 uno::Any aRet;
1125 switch (pEntry->nWID)
1126 {
1127// no code necessary - the redline is always located at the end node
1128// case FN_UNO_REDLINE_NODE_START:
1129// break;
1131 {
1133 const size_t nRedTableCount = rRedTable.size();
1134 if (nRedTableCount > 0)
1135 {
1136 SwStartNode const*const pStartNode = GetStartNode();
1137 const SwNode& rOwnIndex = *pStartNode->EndOfSectionNode();
1138 for (size_t nRed = 0; nRed < nRedTableCount; ++nRed)
1139 {
1140 SwRangeRedline const*const pRedline = rRedTable[nRed];
1141 SwPosition const*const pRedStart = pRedline->Start();
1142 const SwNode& rRedNode = pRedStart->GetNode();
1143 if (rOwnIndex == rRedNode)
1144 {
1146 *pRedline, true);
1147 break;
1148 }
1149 }
1150 }
1151 }
1152 break;
1153 }
1154 return aRet;
1155}
1156
1157void SAL_CALL
1159 const OUString& /*rPropertyName*/,
1160 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1161{
1162 OSL_FAIL("SwXText::addPropertyChangeListener(): not implemented");
1163}
1164
1165void SAL_CALL
1167 const OUString& /*rPropertyName*/,
1168 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
1169{
1170 OSL_FAIL("SwXText::removePropertyChangeListener(): not implemented");
1171}
1172
1173void SAL_CALL
1175 const OUString& /*rPropertyName*/,
1176 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1177{
1178 OSL_FAIL("SwXText::addVetoableChangeListener(): not implemented");
1179}
1180
1181void SAL_CALL
1183 const OUString& /*rPropertyName*/,
1184 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
1185{
1186 OSL_FAIL("SwXText::removeVetoableChangeListener(): not implemented");
1187}
1188
1189namespace
1190{
1191}
1192
1193uno::Reference< text::XTextRange > SAL_CALL
1195 const uno::Sequence< beans::PropertyValue > & rProperties)
1196{
1198
1199 return m_pImpl->finishOrAppendParagraph(rProperties, uno::Reference< text::XTextRange >());
1200}
1201
1202uno::Reference< text::XTextRange > SAL_CALL
1204 const uno::Sequence< beans::PropertyValue > & rProperties,
1205 const uno::Reference< text::XTextRange >& xInsertPosition)
1206{
1208
1209 return m_pImpl->finishOrAppendParagraph(rProperties, xInsertPosition);
1210}
1211
1212uno::Reference< text::XTextRange >
1214 const uno::Sequence< beans::PropertyValue > & rProperties,
1215 const uno::Reference< text::XTextRange >& xInsertPosition)
1216{
1217 if (!m_bIsValid)
1218 {
1219 throw uno::RuntimeException();
1220 }
1221
1222 const SwStartNode* pStartNode = m_rThis.GetStartNode();
1223 if(!pStartNode)
1224 {
1225 throw uno::RuntimeException();
1226 }
1227
1228 uno::Reference< text::XTextRange > xRet;
1229 bool bIllegalException = false;
1230 bool bRuntimeException = false;
1231 OUString sMessage;
1232 m_pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::START , nullptr);
1233 // find end node, go backward - don't skip tables because the new
1234 // paragraph has to be the last node
1235 //aPam.Move( fnMoveBackward, GoInNode );
1236 SwPaM aPam(*pStartNode->EndOfSectionNode(), SwNodeOffset(-1));
1237 // If we got a position reference, then the insert point is not the end of
1238 // the document.
1239 if (xInsertPosition.is())
1240 {
1241 SwUnoInternalPaM aStartPam(*m_rThis.GetDoc());
1242 ::sw::XTextRangeToSwPaM(aStartPam, xInsertPosition);
1243 aPam = aStartPam;
1244 aPam.SetMark();
1245 }
1246 m_pDoc->getIDocumentContentOperations().AppendTextNode( *aPam.GetPoint() );
1247 // remove attributes from the previous paragraph
1248 m_pDoc->ResetAttrs(aPam);
1249 // in case of finishParagraph the PaM needs to be moved to the
1250 // previous paragraph
1251 aPam.Move( fnMoveBackward, GoInNode );
1252
1253 try
1254 {
1255 SfxItemPropertySet const*const pParaPropSet =
1257
1258 SwUnoCursorHelper::SetPropertyValues(aPam, *pParaPropSet, rProperties);
1259
1260 // tdf#127616 keep direct character formatting of empty paragraphs,
1261 // if character style of the paragraph sets also the same attributes
1262 if (aPam.Start()->GetNode().GetTextNode()->Len() == 0)
1263 {
1264 auto itCharStyle = std::find_if(rProperties.begin(), rProperties.end(), [](const beans::PropertyValue& rValue)
1265 {
1266 return rValue.Name == "CharStyleName";
1267 });
1268 if ( itCharStyle != rProperties.end() )
1269 {
1270 for (const auto& rValue : rProperties)
1271 {
1272 if ( rValue != *itCharStyle && rValue.Name.startsWith("Char") )
1273 {
1274 SwUnoCursorHelper::SetPropertyValue(aPam, *pParaPropSet, rValue.Name, rValue.Value);
1275 }
1276 }
1277 }
1278 }
1279 }
1280 catch (const lang::IllegalArgumentException& rIllegal)
1281 {
1282 sMessage = rIllegal.Message;
1283 bIllegalException = true;
1284 }
1285 catch (const uno::RuntimeException& rRuntime)
1286 {
1287 sMessage = rRuntime.Message;
1288 bRuntimeException = true;
1289 }
1290 catch (const uno::Exception& rEx)
1291 {
1292 sMessage = rEx.Message;
1293 bRuntimeException = true;
1294 }
1295
1296 m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::END, nullptr);
1297 if (bIllegalException || bRuntimeException)
1298 {
1299 m_pDoc->GetIDocumentUndoRedo().Undo();
1300 if (bIllegalException)
1301 {
1302 lang::IllegalArgumentException aEx;
1303 aEx.Message = sMessage;
1304 throw aEx;
1305 }
1306 else
1307 {
1308 uno::RuntimeException aEx;
1309 aEx.Message = sMessage;
1310 throw aEx;
1311 }
1312 }
1313 SwTextNode *const pTextNode( aPam.Start()->GetNode().GetTextNode() );
1314 OSL_ENSURE(pTextNode, "no SwTextNode?");
1315 if (pTextNode)
1316 {
1317 xRet = SwXParagraph::CreateXParagraph(*m_pDoc, pTextNode, &m_rThis);
1318 }
1319
1320 return xRet;
1321}
1322
1323uno::Reference< text::XTextRange > SAL_CALL
1325 const OUString& rText,
1326 const uno::Sequence< beans::PropertyValue > &
1327 rCharacterAndParagraphProperties,
1328 const uno::Reference<text::XTextRange>& xInsertPosition)
1329{
1330 SolarMutexGuard aGuard;
1331
1332 if(!IsValid())
1333 {
1334 throw uno::RuntimeException();
1335 }
1336 uno::Reference< text::XTextRange > xRet;
1337 const rtl::Reference<SwXTextCursor> xTextCursor = createXTextCursorByRange(xInsertPosition);
1338
1339 bool bIllegalException = false;
1340 bool bRuntimeException = false;
1341 OUString sMessage;
1342 m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, nullptr);
1343
1344 auto& rCursor(xTextCursor->GetCursor());
1345 m_pImpl->m_pDoc->DontExpandFormat( *rCursor.Start() );
1346
1347 if (!rText.isEmpty())
1348 {
1349 SwNodeIndex const nodeIndex(rCursor.GetPoint()->GetNode(), -1);
1350 const sal_Int32 nContentPos = rCursor.GetPoint()->GetContentIndex();
1352 *m_pImpl->m_pDoc, rCursor, rText, false);
1353 SwUnoCursorHelper::SelectPam(rCursor, true);
1354 rCursor.GetPoint()->Assign(nodeIndex.GetNode(), SwNodeOffset(+1), nContentPos);
1355 }
1356
1357 try
1358 {
1359 SfxItemPropertySet const*const pCursorPropSet =
1361 SwUnoCursorHelper::SetPropertyValues(rCursor, *pCursorPropSet,
1362 rCharacterAndParagraphProperties,
1364 }
1365 catch (const lang::IllegalArgumentException& rIllegal)
1366 {
1367 sMessage = rIllegal.Message;
1368 bIllegalException = true;
1369 }
1370 catch (const uno::RuntimeException& rRuntime)
1371 {
1372 sMessage = rRuntime.Message;
1373 bRuntimeException = true;
1374 }
1375 m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, nullptr);
1376 if (bIllegalException || bRuntimeException)
1377 {
1378 m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
1379 if (bIllegalException)
1380 {
1381 lang::IllegalArgumentException aEx;
1382 aEx.Message = sMessage;
1383 throw aEx;
1384 }
1385 else
1386 {
1387 uno::RuntimeException aEx;
1388 aEx.Message = sMessage;
1389 throw aEx;
1390 }
1391 }
1392 xRet = new SwXTextRange(rCursor, this);
1393 return xRet;
1394}
1395
1396// Append text portions at the end of the last paragraph of the text interface.
1397// Support of import filters.
1398uno::Reference< text::XTextRange > SAL_CALL
1400 const OUString& rText,
1401 const uno::Sequence< beans::PropertyValue > &
1402 rCharacterAndParagraphProperties)
1403{
1404 // Right now this doesn't need a guard, as it's just calling the insert
1405 // version, that has it already.
1406 uno::Reference<text::XTextRange> xInsertPosition = getEnd();
1407 return insertTextPortion(rText, rCharacterAndParagraphProperties, xInsertPosition);
1408}
1409
1410// enable inserting/appending text contents like graphic objects, shapes and so on to
1411// support import filters
1412uno::Reference< text::XTextRange > SAL_CALL
1414 const uno::Reference< text::XTextContent >& xTextContent,
1415 const uno::Sequence< beans::PropertyValue >&
1416 rCharacterAndParagraphProperties,
1417 const uno::Reference< text::XTextRange >& xInsertPosition)
1418{
1419 SolarMutexGuard aGuard;
1420
1421 if (!IsValid())
1422 {
1423 throw uno::RuntimeException();
1424 }
1425
1426 SwUnoInternalPaM aPam(*GetDoc());
1427 if (!::sw::XTextRangeToSwPaM(aPam, xInsertPosition))
1428 {
1429 throw lang::IllegalArgumentException("invalid position", nullptr, 2);
1430 }
1431
1432 SwRewriter aRewriter;
1433 aRewriter.AddRule(UndoArg1, SwResId(STR_UNDO_INSERT_TEXTBOX));
1434
1435 m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, &aRewriter);
1436
1437 // Any direct formatting ending at the insert position (xRange) should not
1438 // be expanded to cover the inserted content (xContent)
1439 // (insertTextContent() shouldn't do this, only ...WithProperties()!)
1440 GetDoc()->DontExpandFormat( *aPam.Start() );
1441
1442 // now attach the text content here
1443 insertTextContent( xInsertPosition, xTextContent, false );
1444 // now apply the properties to the anchor
1445 if (rCharacterAndParagraphProperties.hasElements())
1446 {
1447 try
1448 {
1449 const uno::Reference< beans::XPropertySet > xAnchor(
1450 xTextContent->getAnchor(), uno::UNO_QUERY);
1451 if (xAnchor.is())
1452 {
1453 for (const auto& rProperty : rCharacterAndParagraphProperties)
1454 {
1455 xAnchor->setPropertyValue(rProperty.Name, rProperty.Value);
1456 }
1457 }
1458 }
1459 catch (const uno::Exception& e)
1460 {
1461 css::uno::Any anyEx = cppu::getCaughtException();
1462 m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, &aRewriter);
1463 throw lang::WrappedTargetRuntimeException( e.Message,
1464 uno::Reference< uno::XInterface >(), anyEx );
1465 }
1466 }
1467 m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT, &aRewriter);
1468 return xInsertPosition;
1469}
1470
1471uno::Reference< text::XTextRange > SAL_CALL
1473 const uno::Reference< text::XTextContent >& xTextContent,
1474 const uno::Sequence< beans::PropertyValue >& rCharacterAndParagraphProperties
1475 )
1476{
1477 // Right now this doesn't need a guard, as it's just calling the insert
1478 // version, that has it already.
1479 uno::Reference<text::XTextRange> xInsertPosition = getEnd();
1480 return insertTextContentWithProperties(xTextContent, rCharacterAndParagraphProperties, xInsertPosition);
1481}
1482
1483// determine whether SwFrameFormat is a graphic node
1484static bool isGraphicNode(const SwFrameFormat* pFrameFormat)
1485{
1486 // safety
1487 if( !pFrameFormat->GetContent().GetContentIdx() )
1488 {
1489 return false;
1490 }
1491 auto index = *pFrameFormat->GetContent().GetContentIdx();
1492 // consider the next node -> there is the graphic stored
1493 ++index;
1494 return index.GetNode().IsGrfNode();
1495}
1496
1498static bool IsAtParaMatch(const SwPaM& rAnchorCheckPam, const SwFormatAnchor& rAnchor)
1499{
1500 if (rAnchor.GetAnchorId() != RndStdIds::FLY_AT_PARA)
1501 {
1502 return false;
1503 }
1504
1505 if (rAnchorCheckPam.Start()->GetNode() == *rAnchor.GetAnchorNode())
1506 {
1507 return true;
1508 }
1509
1510 if (rAnchorCheckPam.End()->GetNode() == *rAnchor.GetAnchorNode())
1511 {
1512 SwTextNode* pEndTextNode = rAnchorCheckPam.End()->GetNode().GetTextNode();
1513 if (pEndTextNode && rAnchorCheckPam.End()->GetContentIndex() == pEndTextNode->Len())
1514 {
1515 // rAnchorCheckPam covers the entire last text node, rAnchor is at-para, consider this
1516 // as "inside pam" rather than "at the end of pam".
1517 return false;
1518 }
1519 return true;
1520 }
1521
1522 return false;
1523}
1524
1525// move previously appended paragraphs into a text frames
1526// to support import filters
1527uno::Reference< text::XTextContent > SAL_CALL
1529 const uno::Reference< text::XTextRange >& xStart,
1530 const uno::Reference< text::XTextRange >& xEnd,
1531 const uno::Sequence< beans::PropertyValue >& rFrameProperties)
1532{
1533 SolarMutexGuard aGuard;
1534
1535 if(!IsValid())
1536 {
1537 throw uno::RuntimeException();
1538 }
1539 // tdf#143384 recognize dummy property, that was set to make createTextCursor
1540 // to not ignore tables.
1541 // It is enough to use this hack only for the range start,
1542 // because as far as I know, the range cannot end with table when this property is set.
1543 ::sw::TextRangeMode eMode = ::sw::TextRangeMode::RequireTextNode;
1544 for (const auto& rCellProperty : rFrameProperties)
1545 {
1546 if (rCellProperty.Name == "CursorNotIgnoreTables")
1547 {
1548 bool bAllowNonTextNode = false;
1549 rCellProperty.Value >>= bAllowNonTextNode;
1550 if (bAllowNonTextNode)
1551 eMode = ::sw::TextRangeMode::AllowTableNode;
1552 break;
1553 }
1554 }
1555 uno::Reference< text::XTextContent > xRet;
1556 std::optional<SwUnoInternalPaM> pTempStartPam(*GetDoc());
1557 std::optional<SwUnoInternalPaM> pEndPam(*GetDoc());
1558 if (!::sw::XTextRangeToSwPaM(*pTempStartPam, xStart, eMode)
1559 || !::sw::XTextRangeToSwPaM(*pEndPam, xEnd))
1560 {
1561 throw lang::IllegalArgumentException();
1562 }
1563
1564 auto pStartPam(GetDoc()->CreateUnoCursor(*pTempStartPam->GetPoint()));
1565 if (pTempStartPam->HasMark())
1566 {
1567 pStartPam->SetMark();
1568 *pStartPam->GetMark() = *pTempStartPam->GetMark();
1569 }
1570 pTempStartPam.reset();
1571
1572 SwXTextRange *const pStartRange = dynamic_cast<SwXTextRange*>(xStart.get());
1573 SwXTextRange *const pEndRange = dynamic_cast<SwXTextRange*>(xEnd.get());
1574 // bookmarks have to be removed before the referenced text node
1575 // is deleted in DelFullPara
1576 if (pStartRange)
1577 {
1578 pStartRange->Invalidate();
1579 }
1580 if (pEndRange)
1581 {
1582 pEndRange->Invalidate();
1583 }
1584
1585 m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
1586 bool bIllegalException = false;
1587 bool bRuntimeException = false;
1588 OUString sMessage;
1589 SwStartNode* pStartStartNode = pStartPam->GetPointNode().StartOfSectionNode();
1590 while (pStartStartNode && pStartStartNode->IsSectionNode())
1591 {
1592 pStartStartNode = pStartStartNode->StartOfSectionNode();
1593 }
1594 SwStartNode* pEndStartNode = pEndPam->GetPointNode().StartOfSectionNode();
1595 while (pEndStartNode && pEndStartNode->IsSectionNode())
1596 {
1597 pEndStartNode = pEndStartNode->StartOfSectionNode();
1598 }
1599 bool bParaAfterInserted = false;
1600 bool bParaBeforeInserted = false;
1601 ::std::optional<SwPaM> oAnchorCheckPam;
1602 oAnchorCheckPam.emplace(*pStartPam->Start(), *pEndPam->End());
1603 if (
1604 pStartStartNode && pEndStartNode &&
1605 (pStartStartNode != pEndStartNode || pStartStartNode != GetStartNode())
1606 )
1607 {
1608 // todo: if the start/end is in a table then insert a paragraph
1609 // before/after, move the start/end nodes, then convert and
1610 // remove the additional paragraphs in the end
1611 SwTableNode * pStartTableNode(nullptr);
1612 if (pStartStartNode->GetStartNodeType() == SwTableBoxStartNode)
1613 {
1614 pStartTableNode = pStartStartNode->FindTableNode();
1615 // Is it the same table start node than the end?
1616 SwTableNode *const pEndStartTableNode(pEndStartNode->FindTableNode());
1617 while (pEndStartTableNode && pStartTableNode &&
1618 pEndStartTableNode->GetIndex() < pStartTableNode->GetIndex())
1619 {
1620 SwStartNode* pStartStartTableNode = pStartTableNode->StartOfSectionNode();
1621 pStartTableNode = pStartStartTableNode->FindTableNode();
1622 }
1623 }
1624 if (pStartTableNode)
1625 {
1626 const SwNodeIndex aTableIdx( *pStartTableNode, -1 );
1627 SwPosition aBefore(aTableIdx);
1628 bParaBeforeInserted = GetDoc()->getIDocumentContentOperations().AppendTextNode( aBefore );
1629 pStartPam->DeleteMark();
1630 *pStartPam->GetPoint() = aBefore;
1631 pStartStartNode = pStartPam->GetPointNode().StartOfSectionNode();
1632 }
1633 if (pEndStartNode->GetStartNodeType() == SwTableBoxStartNode)
1634 {
1635 SwTableNode *const pEndTableNode = pEndStartNode->FindTableNode();
1636 SwEndNode *const pTableEnd = pEndTableNode->EndOfSectionNode();
1637 SwPosition aTableEnd(*pTableEnd);
1638 bParaAfterInserted = GetDoc()->getIDocumentContentOperations().AppendTextNode( aTableEnd );
1639 pEndPam->DeleteMark();
1640 *pEndPam->GetPoint() = aTableEnd;
1641 pEndStartNode = pEndPam->GetPointNode().StartOfSectionNode();
1642 }
1643 // now we should have the positions in the same hierarchy
1644 if ((pStartStartNode != pEndStartNode) ||
1645 (pStartStartNode != GetStartNode()))
1646 {
1647 // if not - remove the additional paragraphs and throw
1648 if (bParaBeforeInserted)
1649 {
1650 SwCursor aDelete(*pStartPam->GetPoint(), nullptr);
1651 *pStartPam->GetPoint() = // park it because node is deleted
1652 SwPosition(GetDoc()->GetNodes().GetEndOfContent());
1654 aDelete.SetMark();
1655 aDelete.MovePara(GoCurrPara, fnParaEnd);
1657 }
1658 if (bParaAfterInserted)
1659 {
1660 SwCursor aDelete(*pEndPam->GetPoint(), nullptr);
1661 *pEndPam->GetPoint() = // park it because node is deleted
1662 SwPosition(GetDoc()->GetNodes().GetEndOfContent());
1664 aDelete.SetMark();
1665 aDelete.MovePara(GoCurrPara, fnParaEnd);
1667 }
1668 throw lang::IllegalArgumentException();
1669 }
1670 }
1671
1672 // make a selection from pStartPam to pEndPam
1673 // If there is no content in the frame the shape is in
1674 // it gets deleted in the DelFullPara call below,
1675 // In this case insert a tmp text node ( we delete it later )
1676 if (pStartPam->Start()->GetNode() == pEndPam->Start()->GetNode()
1677 && pStartPam->End()->GetNode() == pEndPam->End()->GetNode())
1678 {
1679 SwPosition aEnd(*pStartPam->End());
1680 bParaAfterInserted = GetDoc()->getIDocumentContentOperations().AppendTextNode( aEnd );
1681 pEndPam->DeleteMark();
1682 *pEndPam->GetPoint() = aEnd;
1683 *oAnchorCheckPam->End() = aEnd;
1684 }
1685 pStartPam->SetMark();
1686 *pStartPam->End() = *pEndPam->End();
1687 pEndPam.reset();
1688
1689 // see if there are frames already anchored to this node
1690 // we have to work with the SdrObjects, as unique name is not guaranteed in their frame format
1691 // tdf#115094: do nothing if we have a graphic node
1692 o3tl::sorted_vector<const SdrObject*> aAnchoredObjectsByPtr;
1693 std::set<OUString> aAnchoredObjectsByName;
1694 for (size_t i = 0; i < m_pImpl->m_pDoc->GetSpzFrameFormats()->size(); ++i)
1695 {
1696 const SwFrameFormat* pFrameFormat = (*m_pImpl->m_pDoc->GetSpzFrameFormats())[i];
1697 const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
1698 // note: Word can do at-char anchors in text frames - sometimes!
1699 // see testFlyInFly for why this checks only the edges of the selection,
1700 // and testFloatingTablesAnchor for why it excludes pre/post table
1701 // added nodes
1702 if (!isGraphicNode(pFrameFormat)
1703 && (IsAtParaMatch(*oAnchorCheckPam, rAnchor)
1704 || (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId()
1705 && ( *oAnchorCheckPam->Start() == *rAnchor.GetContentAnchor()
1706 || *oAnchorCheckPam->End() == *rAnchor.GetContentAnchor()))))
1707 {
1708 if (pFrameFormat->GetName().isEmpty())
1709 {
1710 aAnchoredObjectsByPtr.insert(pFrameFormat->FindSdrObject());
1711 }
1712 else
1713 {
1714 aAnchoredObjectsByName.insert(pFrameFormat->GetName());
1715 }
1716 }
1717 }
1718 oAnchorCheckPam.reset(); // clear SwIndex before deleting nodes
1719
1720 const uno::Reference<text::XTextFrame> xNewFrame(
1721 SwXTextFrame::CreateXTextFrame(*m_pImpl->m_pDoc, nullptr));
1722 SwXTextFrame& rNewFrame = dynamic_cast<SwXTextFrame&>(*xNewFrame);
1723 try
1724 {
1725 for (const beans::PropertyValue& rValue : rFrameProperties)
1726 {
1727 rNewFrame.SwXFrame::setPropertyValue(rValue.Name, rValue.Value);
1728 }
1729
1730 { // has to be in a block to remove the SwIndexes before
1731 // DelFullPara is called
1732 const uno::Reference< text::XTextRange> xInsertTextRange =
1733 new SwXTextRange(*pStartPam, this);
1734 assert(rNewFrame.IsDescriptor());
1735 rNewFrame.attachToRange(xInsertTextRange, pStartPam.get());
1736 assert(!rNewFrame.getName().isEmpty());
1737 }
1738
1739 SwTextNode *const pTextNode(pStartPam->GetPointNode().GetTextNode());
1740 assert(pTextNode);
1741 if (!pTextNode || !pTextNode->Len()) // don't remove if it contains text!
1742 {
1743 { // has to be in a block to remove the SwIndexes before
1744 // DelFullPara is called
1745 SwPaM aMovePam( pStartPam->GetPointNode() );
1746 if (aMovePam.Move( fnMoveForward, GoInContent ))
1747 {
1748 // move the anchor to the next paragraph
1749 SwFormatAnchor aNewAnchor(rNewFrame.GetFrameFormat()->GetAnchor());
1750 aNewAnchor.SetAnchor( aMovePam.Start() );
1751 m_pImpl->m_pDoc->SetAttr(
1752 aNewAnchor, *rNewFrame.GetFrameFormat() );
1753
1754 // also move frames anchored to us
1755 for (size_t i = 0; i < m_pImpl->m_pDoc->GetSpzFrameFormats()->size(); ++i)
1756 {
1757 SwFrameFormat* pFrameFormat = (*m_pImpl->m_pDoc->GetSpzFrameFormats())[i];
1758 if ((!pFrameFormat->GetName().isEmpty() && aAnchoredObjectsByName.find(pFrameFormat->GetName()) != aAnchoredObjectsByName.end() ) ||
1759 ( pFrameFormat->GetName().isEmpty() && aAnchoredObjectsByPtr.find(pFrameFormat->FindSdrObject()) != aAnchoredObjectsByPtr.end()) )
1760 {
1761 // copy the anchor to the next paragraph
1762 SwFormatAnchor aAnchor(pFrameFormat->GetAnchor());
1763 aAnchor.SetAnchor(aMovePam.Start());
1764 m_pImpl->m_pDoc->SetAttr(aAnchor, *pFrameFormat);
1765 }
1766 else
1767 {
1768 // if this frame is a textbox of a shape anchored to us, move this textbox too.
1769 const auto& pTextBoxes = pFrameFormat->GetOtherTextBoxFormats();
1770 if (pFrameFormat->Which() == RES_FLYFRMFMT && pTextBoxes
1771 && pTextBoxes->GetOwnerShape())
1772 {
1773 const auto& rShapeAnchor = pTextBoxes->GetOwnerShape()->GetAnchor();
1774 if (rShapeAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR
1775 && rShapeAnchor.GetContentAnchor() && pFrameFormat->GetAnchor().GetContentAnchor()
1776 && pStartPam->ContainsPosition(*pFrameFormat->GetAnchor().GetContentAnchor()))
1777 {
1778 const SwNode& rAnchorNode
1779 = *pFrameFormat->GetAnchor().GetAnchorNode();
1780 if (!(rAnchorNode.FindFooterStartNode() || rAnchorNode.FindHeaderStartNode()))
1781 {
1782 SwFormatAnchor aAnchor(pFrameFormat->GetAnchor());
1783 aAnchor.SetAnchor(aMovePam.Start());
1784 m_pImpl->m_pDoc->SetAttr(aAnchor, *pFrameFormat);
1785 }
1786 }
1787 }
1788 }
1789 }
1790 }
1791 }
1792 m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*pStartPam);
1793 }
1794 }
1795 catch (const lang::IllegalArgumentException& rIllegal)
1796 {
1797 sMessage = rIllegal.Message;
1798 bIllegalException = true;
1799 }
1800 catch (const uno::RuntimeException& rRuntime)
1801 {
1802 sMessage = rRuntime.Message;
1803 bRuntimeException = true;
1804 }
1805 xRet = xNewFrame;
1806 if (bParaBeforeInserted || bParaAfterInserted)
1807 {
1808 const rtl::Reference<SwXTextCursor> xFrameTextCursor =
1809 rNewFrame.createXTextCursor();
1810 if (bParaBeforeInserted)
1811 {
1812 // todo: remove paragraph before frame
1813 m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*xFrameTextCursor->GetPaM());
1814 }
1815 if (bParaAfterInserted)
1816 {
1817 xFrameTextCursor->gotoEnd(false);
1818 if (!bParaBeforeInserted)
1819 m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*xFrameTextCursor->GetPaM());
1820 else
1821 {
1822 // In case the frame has a table only, the cursor points to the end of the first cell of the table.
1823 SwPaM aPaM(*xFrameTextCursor->GetPaM()->GetPointNode().FindSttNodeByType(SwFlyStartNode)->EndOfSectionNode());
1824 // Now we have the end of the frame -- the node before that will be the paragraph we want to remove.
1825 aPaM.GetPoint()->Adjust(SwNodeOffset(-1));
1826 m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(aPaM);
1827 }
1828 }
1829 }
1830
1831 m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::END, nullptr);
1832 if (bIllegalException || bRuntimeException)
1833 {
1834 m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
1835 if (bIllegalException)
1836 {
1837 lang::IllegalArgumentException aEx;
1838 aEx.Message = sMessage;
1839 throw aEx;
1840 }
1841 else
1842 {
1843 uno::RuntimeException aEx;
1844 aEx.Message = sMessage;
1845 throw aEx;
1846 }
1847 }
1848 return xRet;
1849}
1850
1851namespace {
1852
1853// Move previously imported paragraphs into a new text table.
1854struct VerticallyMergedCell
1855{
1856 std::vector<uno::Reference< beans::XPropertySet > > aCells;
1857 sal_Int32 nLeftPosition;
1858 bool bOpen;
1859
1860 VerticallyMergedCell(uno::Reference< beans::XPropertySet > const& rxCell,
1861 const sal_Int32 nLeft)
1862 : nLeftPosition( nLeft )
1863 , bOpen( true )
1864 {
1865 aCells.push_back( rxCell );
1866 }
1867};
1868
1869}
1870
1871#define COL_POS_FUZZY 2
1872
1873static bool lcl_SimilarPosition( const sal_Int32 nPos1, const sal_Int32 nPos2 )
1874{
1875 return abs( nPos1 - nPos2 ) < COL_POS_FUZZY;
1876}
1877
1879 const uno::Sequence< uno::Reference< text::XTextRange > > & rCell,
1880 std::vector<SwNodeRange> & rRowNodes,
1881 SwNodeRange *const pLastCell)
1882{
1883 if (rCell.getLength() != 2)
1884 {
1885 throw lang::IllegalArgumentException(
1886 "rCell needs to contain 2 elements",
1887 uno::Reference< text::XTextCopy >( &m_rThis ), sal_Int16( 2 ) );
1888 }
1889 const uno::Reference<text::XTextRange> xStartRange = rCell[0];
1890 const uno::Reference<text::XTextRange> xEndRange = rCell[1];
1891 SwUnoInternalPaM aStartCellPam(*m_pDoc);
1892 SwUnoInternalPaM aEndCellPam(*m_pDoc);
1893
1894 // !!! TODO - PaMs in tables and sections do not work here -
1895 // the same applies to PaMs in frames !!!
1896
1897 if (!::sw::XTextRangeToSwPaM(aStartCellPam, xStartRange) ||
1898 !::sw::XTextRangeToSwPaM(aEndCellPam, xEndRange))
1899 {
1900 throw lang::IllegalArgumentException(
1901 "Start or End range cannot be resolved to a SwPaM",
1902 uno::Reference< text::XTextCopy >( &m_rThis ), sal_Int16( 2 ) );
1903 }
1904
1905 SwNodeRange aTmpRange(aStartCellPam.Start()->GetNode(),
1906 aEndCellPam.End()->GetNode());
1907 std::optional<SwNodeRange> oCorrectedRange;
1908 m_pDoc->GetNodes().ExpandRangeForTableBox(aTmpRange, oCorrectedRange);
1909
1910 if (oCorrectedRange)
1911 {
1912 SwPaM aNewStartPaM(oCorrectedRange->aStart, 0);
1913 aStartCellPam = aNewStartPaM;
1914
1915 sal_Int32 nEndLen = 0;
1916 SwTextNode * pTextNode = oCorrectedRange->aEnd.GetNode().GetTextNode();
1917 if (pTextNode != nullptr)
1918 nEndLen = pTextNode->Len();
1919
1920 SwPaM aNewEndPaM(oCorrectedRange->aEnd, nEndLen);
1921 aEndCellPam = aNewEndPaM;
1922
1923 oCorrectedRange.reset();
1924 }
1925
1929 if (aStartCellPam.Start()->GetNode() < aEndCellPam.End()->GetNode())
1930 {
1931 // increment on each StartNode and decrement on each EndNode
1932 // we must reach zero at the end and must not go below zero
1933 tools::Long nOpenNodeBlock = 0;
1934 SwNodeIndex aCellIndex(aStartCellPam.Start()->GetNode());
1935 while (aCellIndex < aEndCellPam.End()->GetNodeIndex())
1936 {
1937 if (aCellIndex.GetNode().IsStartNode())
1938 {
1939 ++nOpenNodeBlock;
1940 }
1941 else if (aCellIndex.GetNode().IsEndNode())
1942 {
1943 --nOpenNodeBlock;
1944 }
1945 if (nOpenNodeBlock < 0)
1946 {
1947 throw lang::IllegalArgumentException();
1948 }
1949 ++aCellIndex;
1950 }
1951 if (nOpenNodeBlock != 0)
1952 {
1953 throw lang::IllegalArgumentException();
1954 }
1955 }
1956
1963 if (!pLastCell) // first cell?
1964 {
1965 // align the beginning - if necessary
1966 if (aStartCellPam.Start()->GetContentIndex())
1967 {
1968 m_pDoc->getIDocumentContentOperations().SplitNode(*aStartCellPam.Start(), false);
1969 }
1970 }
1971 else
1972 {
1973 // check the predecessor
1974 const SwNodeOffset nStartCellNodeIndex =
1975 aStartCellPam.Start()->GetNodeIndex();
1976 const SwNodeOffset nLastNodeEndIndex = pLastCell->aEnd.GetIndex();
1977 if (nLastNodeEndIndex == nStartCellNodeIndex)
1978 {
1979 // same node as predecessor then equal nContent?
1980 if (0 != aStartCellPam.Start()->GetContentIndex())
1981 {
1982 throw lang::IllegalArgumentException();
1983 }
1984
1985 m_pDoc->getIDocumentContentOperations().SplitNode(*aStartCellPam.Start(), false);
1986 SwNodeOffset const nNewIndex(aStartCellPam.Start()->GetNodeIndex());
1987 if (nNewIndex != nStartCellNodeIndex)
1988 {
1989 // aStartCellPam now points to the 2nd node
1990 // the last cell may *also* point to 2nd node now - fix it!
1991 assert(nNewIndex == nStartCellNodeIndex + 1);
1992 if (pLastCell->aEnd.GetIndex() == nNewIndex)
1993 {
1994 --pLastCell->aEnd;
1995 if (pLastCell->aStart.GetIndex() == nNewIndex)
1996 {
1997 --pLastCell->aStart;
1998 }
1999 }
2000 }
2001 }
2002 else if (nStartCellNodeIndex == (nLastNodeEndIndex + 1))
2003 {
2004 // next paragraph - now the content index of the new should be 0
2005 // and of the old one should be equal to the text length
2006 // but if it isn't we don't care - the cell is being inserted on
2007 // the node border anyway
2008 }
2009 else
2010 {
2011 throw lang::IllegalArgumentException();
2012 }
2013 }
2014 // now check if there's a need to insert another paragraph break
2015 if (aEndCellPam.End()->GetContentIndex() <
2016 aEndCellPam.End()->GetNode().GetTextNode()->Len())
2017 {
2018 m_pDoc->getIDocumentContentOperations().SplitNode(*aEndCellPam.End(), false);
2019 // take care that the new start/endcell is moved to the right position
2020 // aStartCellPam has to point to the start of the new (previous) node
2021 // aEndCellPam has to point to the end of the new (previous) node
2022 aStartCellPam.DeleteMark();
2023 aStartCellPam.Move(fnMoveBackward, GoInNode);
2024 aStartCellPam.GetPoint()->SetContent(0);
2025 aEndCellPam.DeleteMark();
2026 aEndCellPam.Move(fnMoveBackward, GoInNode);
2027 aEndCellPam.GetPoint()->SetContent(
2028 aEndCellPam.GetPointNode().GetTextNode()->Len() );
2029 }
2030
2031 assert(aStartCellPam.Start()->GetContentIndex() == 0);
2032 assert(aEndCellPam.End()->GetContentIndex() == aEndCellPam.End()->GetNode().GetTextNode()->Len());
2033 SwNodeRange aCellRange(aStartCellPam.Start()->GetNode(),
2034 aEndCellPam.End()->GetNode());
2035 rRowNodes.push_back(aCellRange); // note: invalidates pLastCell!
2036
2037 // tdf#149649 delete any fieldmarks overlapping the cell
2038 IDocumentMarkAccess & rIDMA(*m_pDoc->getIDocumentMarkAccess());
2039 while (sw::mark::IFieldmark *const pMark = rIDMA.getInnerFieldmarkFor(*aStartCellPam.Start()))
2040 {
2041 if (pMark->GetMarkEnd() <= *aEndCellPam.End())
2042 {
2043 if (pMark->GetMarkStart() < *aStartCellPam.Start())
2044 {
2045 SAL_INFO("sw.uno", "deleting fieldmark overlapping table cell");
2046 rIDMA.deleteMark(pMark);
2047 }
2048 else
2049 {
2050 break;
2051 }
2052 }
2053 else
2054 {
2055 SwPosition const sepPos(::sw::mark::FindFieldSep(*pMark));
2056 if (*aStartCellPam.Start() <= sepPos && sepPos <= *aEndCellPam.End())
2057 {
2058 SAL_INFO("sw.uno", "deleting fieldmark with separator in table cell");
2059 rIDMA.deleteMark(pMark);
2060 }
2061 else
2062 {
2063 break;
2064 }
2065 }
2066 }
2067 while (sw::mark::IFieldmark *const pMark = rIDMA.getInnerFieldmarkFor(*aEndCellPam.End()))
2068 {
2069 if (*aStartCellPam.Start() <= pMark->GetMarkStart())
2070 {
2071 if (*aEndCellPam.End() < pMark->GetMarkEnd())
2072 {
2073 SAL_INFO("sw.uno", "deleting fieldmark overlapping table cell");
2074 rIDMA.deleteMark(pMark);
2075 }
2076 else
2077 {
2078 break;
2079 }
2080 }
2081 else
2082 {
2083 SwPosition const sepPos(::sw::mark::FindFieldSep(*pMark));
2084 if (*aStartCellPam.Start() <= sepPos && sepPos <= *aEndCellPam.End())
2085 {
2086 SAL_INFO("sw.uno", "deleting fieldmark with separator in table cell");
2087 rIDMA.deleteMark(pMark);
2088 }
2089 else
2090 {
2091 break;
2092 }
2093 }
2094 }
2095}
2096
2097typedef uno::Sequence< text::TableColumnSeparator > TableColumnSeparators;
2098
2099static void
2101 uno::Sequence<beans::PropertyValue> const& rRowProperties,
2102 uno::Any const& rRow,
2103 TableColumnSeparators & rRowSeparators)
2104{
2105 uno::Reference< beans::XPropertySet > xRow;
2106 rRow >>= xRow;
2107 for (const beans::PropertyValue& rProperty : rRowProperties)
2108 {
2109 if ( rProperty.Name == "TableColumnSeparators" )
2110 {
2111 // add the separators to access the cell's positions
2112 // for vertical merging later
2113 TableColumnSeparators aSeparators;
2114 rProperty.Value >>= aSeparators;
2115 rRowSeparators = aSeparators;
2116 }
2117 xRow->setPropertyValue(rProperty.Name, rProperty.Value);
2118 }
2119}
2120
2121static sal_Int32 lcl_GetLeftPos(sal_Int32 nCell, TableColumnSeparators const& rRowSeparators)
2122{
2123 if(!nCell)
2124 return 0;
2125 if (rRowSeparators.getLength() < nCell)
2126 return -1;
2127 return rRowSeparators[nCell - 1].Position;
2128}
2129
2130static void
2132 const sal_Int32 nLeftPos,
2133 const uno::Sequence< beans::PropertyValue >& rCellProperties,
2134 const uno::Reference< uno::XInterface >& xCell,
2135 std::vector<VerticallyMergedCell> & rMergedCells)
2136{
2137 const uno::Reference< beans::XPropertySet > xCellPS(xCell, uno::UNO_QUERY);
2138 for (const auto& rCellProperty : rCellProperties)
2139 {
2140 const OUString & rName = rCellProperty.Name;
2141 const uno::Any & rValue = rCellProperty.Value;
2142 if ( rName == "VerticalMerge" )
2143 {
2144 // determine left border position
2145 // add the cell to a queue of merged cells
2146 bool bMerge = false;
2147 rValue >>= bMerge;
2148 if (bMerge)
2149 {
2150 // 'close' all the cell with the same left position
2151 // if separate vertical merges in the same column exist
2152 for(auto& aMergedCell : rMergedCells)
2153 {
2154 if(lcl_SimilarPosition(aMergedCell.nLeftPosition, nLeftPos))
2155 {
2156 aMergedCell.bOpen = false;
2157 }
2158 }
2159 // add the new group of merged cells
2160 rMergedCells.emplace_back(xCellPS, nLeftPos);
2161 }
2162 else
2163 {
2164 bool bFound = false;
2165 SAL_WARN_IF(rMergedCells.empty(), "sw.uno", "the first merged cell is missing");
2166 for(auto& aMergedCell : rMergedCells)
2167 {
2168 if (aMergedCell.bOpen && lcl_SimilarPosition(aMergedCell.nLeftPosition, nLeftPos))
2169 {
2170 aMergedCell.aCells.push_back( xCellPS );
2171 bFound = true;
2172 }
2173 }
2174 SAL_WARN_IF(!bFound, "sw.uno", "couldn't find first vertically merged cell" );
2175 }
2176 }
2177 else
2178 {
2179 try
2180 {
2181 static const std::initializer_list<std::u16string_view> vDenylist = {
2182 u"LeftMargin",
2183 };
2184 if (std::find(vDenylist.begin(), vDenylist.end(), rName) == vDenylist.end())
2185 {
2186 xCellPS->setPropertyValue(rName, rValue);
2187 }
2188 }
2189 catch (const uno::Exception&)
2190 {
2191 TOOLS_WARN_EXCEPTION( "sw.uno", "Exception when setting cell property " << rName );
2192 }
2193 }
2194 }
2195}
2196
2197static void
2198lcl_MergeCells(std::vector<VerticallyMergedCell> & rMergedCells)
2199{
2200 for(auto& aMergedCell : rMergedCells)
2201 {
2202 // the first of the cells gets the number of cells set as RowSpan
2203 // the others get the inverted number of remaining merged cells
2204 // (3,-2,-1)
2205 sal_Int32 nCellCount = static_cast<sal_Int32>(aMergedCell.aCells.size());
2206 if(nCellCount<2)
2207 {
2208 SAL_WARN("sw.uno", "incomplete vertical cell merge");
2209 continue;
2210 }
2211 aMergedCell.aCells.front()->setPropertyValue(UNO_NAME_ROW_SPAN, uno::Any(nCellCount--));
2212 nCellCount*=-1;
2213 for(auto pxPSet = aMergedCell.aCells.begin()+1; nCellCount<0; ++pxPSet, ++nCellCount)
2214 {
2215 (*pxPSet)->setPropertyValue(UNO_NAME_ROW_SPAN, uno::Any(nCellCount));
2216 (*pxPSet)->setPropertyValue("VerticalMerge", uno::Any(true));
2217 }
2218 }
2219}
2220
2221uno::Reference< text::XTextTable > SAL_CALL
2223 const uno::Sequence< uno::Sequence< uno::Sequence<
2224 uno::Reference< text::XTextRange > > > >& rTableRanges,
2225 const uno::Sequence< uno::Sequence< uno::Sequence<
2226 beans::PropertyValue > > >& rCellProperties,
2227 const uno::Sequence< uno::Sequence< beans::PropertyValue > >&
2228 rRowProperties,
2229 const uno::Sequence< beans::PropertyValue >& rTableProperties)
2230{
2231 SolarMutexGuard aGuard;
2232
2233 if(!IsValid())
2234 {
2235 throw uno::RuntimeException();
2236 }
2237
2238 IDocumentRedlineAccess & rIDRA(m_pImpl->m_pDoc->getIDocumentRedlineAccess());
2240 {
2241 throw uno::RuntimeException(
2242 "cannot convertToTable if tracked changes are hidden!");
2243 }
2244
2245 //at first collect the text ranges as SwPaMs
2246 const uno::Sequence< uno::Sequence< uno::Reference< text::XTextRange > > >*
2247 pTableRanges = rTableRanges.getConstArray();
2248 std::vector< std::vector<SwNodeRange> > aTableNodes;
2249 for (sal_Int32 nRow = 0; nRow < rTableRanges.getLength(); ++nRow)
2250 {
2251 std::vector<SwNodeRange> aRowNodes;
2252 const uno::Sequence< uno::Reference< text::XTextRange > >* pRow =
2253 pTableRanges[nRow].getConstArray();
2254 const sal_Int32 nCells(pTableRanges[nRow].getLength());
2255
2256 if (0 == nCells) // this would lead to no pLastCell below
2257 { // and make it impossible to detect node gaps
2258 throw lang::IllegalArgumentException();
2259 }
2260
2261 for (sal_Int32 nCell = 0; nCell < nCells; ++nCell)
2262 {
2263 SwNodeRange *const pLastCell(
2264 (nCell == 0)
2265 ? ((nRow == 0)
2266 ? nullptr
2267 : &*aTableNodes.rbegin()->rbegin())
2268 : &*aRowNodes.rbegin());
2269 m_pImpl->ConvertCell(pRow[nCell], aRowNodes, pLastCell);
2270 }
2271 assert(!aRowNodes.empty());
2272 aTableNodes.push_back(aRowNodes);
2273 }
2274
2275 std::vector< TableColumnSeparators >
2276 aRowSeparators(rRowProperties.getLength());
2277 std::vector<VerticallyMergedCell> aMergedCells;
2278
2279 SwTable const*const pTable = m_pImpl->m_pDoc->TextToTable( aTableNodes );
2280
2281 if (!pTable)
2282 return uno::Reference< text::XTextTable >();
2283
2284 uno::Reference<text::XTextTable> const xRet =
2286 uno::Reference<beans::XPropertySet> const xPrSet(xRet, uno::UNO_QUERY);
2287 // set properties to the table
2288 // catch lang::WrappedTargetException and lang::IndexOutOfBoundsException
2289 try
2290 {
2291 //apply table properties
2292 for(const auto& rTableProperty : rTableProperties)
2293 {
2294 try
2295 {
2296 static const std::initializer_list<std::u16string_view> vDenylist = {
2297 u"BottomBorder",
2298 u"CharAutoKerning",
2299 u"CharFontName",
2300 u"CharFontNameAsian",
2301 u"CharFontNameComplex",
2302 u"CharHeight",
2303 u"CharHeightAsian",
2304 u"CharHeightComplex",
2305 u"CharInteropGrabBag",
2306 u"CharLocale",
2307 u"CharLocaleAsian",
2308 u"CharLocaleComplex",
2309 u"HorizontalBorder",
2310 u"LeftBorder",
2311 u"ParaAdjust",
2312 u"ParaBottomMargin",
2313 u"ParaIsHyphenation",
2314 u"ParaLineSpacing",
2315 u"ParaOrphans",
2316 u"ParaTopMargin",
2317 u"ParaWidows",
2318 u"RightBorder",
2319 u"TopBorder",
2320 u"VerticalBorder",
2321 };
2322 if (std::find(vDenylist.begin(), vDenylist.end(), rTableProperty.Name) == vDenylist.end())
2323 {
2324 xPrSet->setPropertyValue(rTableProperty.Name, rTableProperty.Value);
2325 }
2326 }
2327 catch (const uno::Exception&)
2328 {
2329 TOOLS_WARN_EXCEPTION( "sw.uno", "Exception when setting property: " << rTableProperty.Name );
2330 }
2331 }
2332
2333 //apply row properties
2334 const auto xRows = xRet->getRows();
2335 const sal_Int32 nLast = std::min(xRows->getCount(), rRowProperties.getLength());
2336 SAL_WARN_IF(nLast != rRowProperties.getLength(), "sw.uno", "not enough rows for properties");
2337 for(sal_Int32 nCnt = 0; nCnt < nLast; ++nCnt)
2338 lcl_ApplyRowProperties(rRowProperties[nCnt], xRows->getByIndex(nCnt), aRowSeparators[nCnt]);
2339
2340 uno::Reference<table::XCellRange> const xCR(xRet, uno::UNO_QUERY_THROW);
2341 //apply cell properties
2342 sal_Int32 nRow = 0;
2343 for(const auto& rCellPropertiesForRow : rCellProperties)
2344 {
2345 sal_Int32 nCell = 0;
2346 for(const auto& rCellProps : rCellPropertiesForRow)
2347 {
2348 lcl_ApplyCellProperties(lcl_GetLeftPos(nCell, aRowSeparators[nRow]),
2349 rCellProps,
2350 xCR->getCellByPosition(nCell, nRow),
2351 aMergedCells);
2352 ++nCell;
2353 }
2354 ++nRow;
2355 }
2356
2357 // now that the cell properties are set the vertical merge values
2358 // have to be applied
2359 lcl_MergeCells(aMergedCells);
2360 }
2361 catch (const lang::WrappedTargetException&)
2362 {
2363 }
2364 catch (const lang::IndexOutOfBoundsException&)
2365 {
2366 }
2367
2368 assert(SwTable::FindTable(pTable->GetFrameFormat()) == pTable);
2369 assert(pTable->GetFrameFormat() ==
2370 dynamic_cast<SwXTextTable&>(*xRet).GetFrameFormat());
2371 return xRet;
2372}
2373
2374void SAL_CALL
2376 const uno::Reference< text::XTextCopy >& xSource )
2377{
2378 SolarMutexGuard aGuard;
2379
2380 SwXText const* const pSource(dynamic_cast<SwXText*>(xSource.get()));
2381
2382 uno::Reference< text::XText > const xText(xSource, uno::UNO_QUERY_THROW);
2383 uno::Reference< text::XTextCursor > const xCursor =
2384 xText->createTextCursor();
2385 xCursor->gotoEnd( true );
2386
2387 OTextCursorHelper *const pCursor = dynamic_cast<OTextCursorHelper*>(xCursor.get());
2388 if (!pCursor)
2389 {
2390 throw uno::RuntimeException();
2391 }
2392
2393 SwNodeIndex rNdIndex( *GetStartNode( ), 1 );
2394 SwPosition rPos( rNdIndex );
2395 // tdf#112202 need SwXText because cursor cannot select table at the start
2396 if (pSource)
2397 {
2398 SwTextNode * pFirstNode;
2399 {
2400 SwPaM temp(*pSource->GetStartNode(), *pSource->GetStartNode()->EndOfSectionNode(), SwNodeOffset(+1), SwNodeOffset(-1));
2401 pFirstNode = temp.GetMark()->GetNode().GetTextNode();
2402 if (pFirstNode)
2403 {
2404 temp.GetMark()->AssignStartIndex(*pFirstNode);
2405 }
2406 if (SwTextNode *const pNode = temp.GetPoint()->GetNode().GetTextNode())
2407 {
2408 temp.GetPoint()->AssignEndIndex(*pNode);
2409 }
2410 // Explicitly request copy text mode, so
2411 // sw::DocumentContentOperationsManager::CopyFlyInFlyImpl() will copy shapes anchored to
2412 // us, even if we have only a single paragraph.
2413 m_pImpl->m_pDoc->getIDocumentContentOperations().CopyRange(temp, rPos, SwCopyFlags::CheckPosInFly);
2414 }
2415 if (!pFirstNode)
2416 { // the node at rPos was split; get rid of the first empty one so
2417 // that the pasted table is first
2418 auto pDelCursor(m_pImpl->m_pDoc->CreateUnoCursor(SwPosition(*GetStartNode(), SwNodeOffset(1))));
2419 m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*pDelCursor);
2420 }
2421 }
2422 else
2423 {
2424 m_pImpl->m_pDoc->getIDocumentContentOperations().CopyRange(*pCursor->GetPaM(), rPos, SwCopyFlags::CheckPosInFly);
2425 }
2426
2427}
2428
2430 : SwXText(pDoc, CursorType::Body)
2431{
2432}
2433
2435{
2436}
2437
2438OUString SAL_CALL
2440{
2441 return "SwXBodyText";
2442}
2443
2444sal_Bool SAL_CALL SwXBodyText::supportsService(const OUString& rServiceName)
2445{
2446 return cppu::supportsService(this, rServiceName);
2447}
2448
2449uno::Sequence< OUString > SAL_CALL
2451{
2452 return { "com.sun.star.text.Text" };
2453}
2454
2455uno::Sequence< uno::Type > SAL_CALL
2457{
2458 const uno::Sequence< uno::Type > aTypes = SwXBodyText_Base::getTypes();
2459 const uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
2460 return ::comphelper::concatSequences(aTypes, aTextTypes);
2461}
2462
2463uno::Sequence< sal_Int8 > SAL_CALL
2465{
2466 return css::uno::Sequence<sal_Int8>();
2467}
2468
2469uno::Any SAL_CALL
2471{
2472 const uno::Any ret = SwXText::queryInterface(rType);
2473 return (ret.getValueType() == cppu::UnoType<void>::get())
2474 ? SwXBodyText_Base::queryInterface(rType)
2475 : ret;
2476}
2477
2479{
2480 if(!IsValid())
2481 {
2482 return nullptr;
2483 }
2484
2485 // the cursor has to skip tables contained in this text
2486 SwPaM aPam(GetDoc()->GetNodes().GetEndOfContent());
2487 aPam.Move( fnMoveBackward, GoInDoc );
2488 if (!bIgnoreTables)
2489 {
2490 SwTableNode * pTableNode = aPam.GetPointNode().FindTableNode();
2491 while (pTableNode)
2492 {
2493 aPam.GetPoint()->Assign( *pTableNode->EndOfSectionNode() );
2494 SwContentNode* pCont = GetDoc()->GetNodes().GoNext(aPam.GetPoint());
2495 pTableNode = pCont->FindTableNode();
2496 }
2497 }
2498 return new SwXTextCursor(*GetDoc(), this, CursorType::Body, *aPam.GetPoint());
2499}
2500
2503{
2504 return CreateTextCursor();
2505}
2506
2509 const uno::Reference< text::XTextRange > & xTextPosition)
2510{
2511 if(!IsValid())
2512 {
2513 uno::RuntimeException aRuntime;
2514 aRuntime.Message = cInvalidObject;
2515 throw aRuntime;
2516 }
2517
2519 SwUnoInternalPaM aPam(*GetDoc());
2520 if (::sw::XTextRangeToSwPaM(aPam, xTextPosition))
2521 {
2522 if ( !aPam.GetPointNode().GetTextNode() )
2523 throw uno::RuntimeException("Invalid text range" );
2524
2525 SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
2526
2528 //document starts with a section?
2529 while(p1->IsSectionNode())
2530 {
2531 p1 = p1->StartOfSectionNode();
2532 }
2533 SwStartNode *const p2 = rNode.StartOfSectionNode();
2534
2535 if(p1 == p2)
2536 {
2537 aRef = new SwXTextCursor(*GetDoc(), this, CursorType::Body,
2538 *aPam.GetPoint(), aPam.GetMark());
2539 }
2540 }
2541 if(!aRef.is())
2542 {
2543 throw uno::RuntimeException( "End of content node doesn't have the proper start node",
2544 uno::Reference< uno::XInterface >( *this ) );
2545 }
2546 return aRef;
2547}
2548
2549uno::Reference< container::XEnumeration > SAL_CALL
2551{
2553}
2554
2557{
2558 SolarMutexGuard aGuard;
2559
2560 if (!IsValid())
2561 {
2562 uno::RuntimeException aRuntime;
2563 aRuntime.Message = cInvalidObject;
2564 throw aRuntime;
2565 }
2566
2567 SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
2568 SwPosition aPos(rNode);
2569 auto pUnoCursor(GetDoc()->CreateUnoCursor(aPos));
2570 pUnoCursor->Move(fnMoveBackward, GoInDoc);
2571 return SwXParagraphEnumeration::Create(this, pUnoCursor, CursorType::Body);
2572}
2573
2574uno::Type SAL_CALL
2576{
2578}
2579
2580sal_Bool SAL_CALL
2582{
2583 SolarMutexGuard aGuard;
2584
2585 if (!IsValid())
2586 {
2587 uno::RuntimeException aRuntime;
2588 aRuntime.Message = cInvalidObject;
2589 throw aRuntime;
2590 }
2591
2592 return true;
2593}
2594
2596 : public SvtListener
2597{
2598 public:
2601
2602 Impl(SwFrameFormat& rHeadFootFormat, const bool bIsHeader)
2603 : m_pHeadFootFormat(&rHeadFootFormat)
2604 , m_bIsHeader(bIsHeader)
2605 {
2606 StartListening(m_pHeadFootFormat->GetNotifier());
2607 }
2608
2610 return m_pHeadFootFormat;
2611 }
2612
2614 if (!m_pHeadFootFormat) {
2615 throw uno::RuntimeException("SwXHeadFootText: disposed or invalid", nullptr);
2616 }
2617 return *m_pHeadFootFormat;
2618 }
2619 protected:
2620 virtual void Notify(const SfxHint& rHint) override
2621 {
2622 if(rHint.GetId() == SfxHintId::Dying)
2623 m_pHeadFootFormat = nullptr;
2624 }
2625};
2626
2627uno::Reference<text::XText> SwXHeadFootText::CreateXHeadFootText(
2628 SwFrameFormat& rHeadFootFormat,
2629 const bool bIsHeader)
2630{
2631 // re-use existing SwXHeadFootText
2632 // #i105557#: do not iterate over the registered clients: race condition
2633 uno::Reference<text::XText> xText(rHeadFootFormat.GetXObject(), uno::UNO_QUERY);
2634 if(!xText.is())
2635 {
2636 xText = new SwXHeadFootText(rHeadFootFormat, bIsHeader);
2637 rHeadFootFormat.SetXObject(xText);
2638 }
2639 return xText;
2640}
2641
2642SwXHeadFootText::SwXHeadFootText(SwFrameFormat& rHeadFootFormat, const bool bIsHeader)
2643 : SwXText(
2644 rHeadFootFormat.GetDoc(),
2645 bIsHeader ? CursorType::Header : CursorType::Footer)
2646 , m_pImpl(new SwXHeadFootText::Impl(rHeadFootFormat, bIsHeader))
2647{
2648}
2649
2651{ }
2652
2653OUString SAL_CALL
2655{
2656 return {"SwXHeadFootText"};
2657}
2658
2659sal_Bool SAL_CALL SwXHeadFootText::supportsService(const OUString& rServiceName)
2660{
2661 return cppu::supportsService(this, rServiceName);
2662}
2663
2664uno::Sequence<OUString> SAL_CALL
2666{
2667 return {"com.sun.star.text.Text"};
2668}
2669
2671{
2672 const SwStartNode* pSttNd = nullptr;
2673 SwFrameFormat* const pHeadFootFormat = m_pImpl->GetHeadFootFormat();
2674 if(pHeadFootFormat)
2675 {
2676 const SwFormatContent& rFlyContent = pHeadFootFormat->GetContent();
2677 if(rFlyContent.GetContentIdx())
2678 {
2679 pSttNd = rFlyContent.GetContentIdx()->GetNode().GetStartNode();
2680 }
2681 }
2682 return pSttNd;
2683}
2684
2685uno::Sequence<uno::Type> SAL_CALL SwXHeadFootText::getTypes()
2686{
2687 return ::comphelper::concatSequences(
2688 SwXHeadFootText_Base::getTypes(),
2690}
2691
2692uno::Sequence<sal_Int8> SAL_CALL SwXHeadFootText::getImplementationId()
2693{
2694 return css::uno::Sequence<sal_Int8>();
2695}
2696
2698{
2699 const uno::Any ret = SwXHeadFootText_Base::queryInterface(rType);
2700 return (ret.getValueType() == cppu::UnoType<void>::get())
2702 : ret;
2703}
2704
2706{
2707 SwFrameFormat & rHeadFootFormat( m_pImpl->GetHeadFootFormatOrThrow() );
2708
2709 const SwFormatContent& rFlyContent = rHeadFootFormat.GetContent();
2710 const SwNode& rNode = rFlyContent.GetContentIdx()->GetNode();
2711 SwPosition aPos(rNode);
2712 rtl::Reference<SwXTextCursor> pXCursor = new SwXTextCursor(*GetDoc(), this,
2713 (m_pImpl->m_bIsHeader) ? CursorType::Header : CursorType::Footer, aPos);
2714 auto& rUnoCursor(pXCursor->GetCursor());
2715 rUnoCursor.Move(fnMoveForward, GoInNode);
2716
2717 // save current start node to be able to check if there is content
2718 // after the table - otherwise the cursor would be in the body text!
2719 SwStartNode const*const pOwnStartNode = rNode.FindSttNodeByType(
2720 (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2721
2722 if (!bIgnoreTables)
2723 {
2724 // is there a table here?
2725 SwTableNode* pTableNode = rUnoCursor.GetPointNode().FindTableNode();
2726 while (pTableNode)
2727 {
2728 rUnoCursor.GetPoint()->Assign(*pTableNode->EndOfSectionNode());
2729 SwContentNode* pCont = GetDoc()->GetNodes().GoNext(rUnoCursor.GetPoint());
2730 pTableNode = pCont->FindTableNode();
2731 }
2732 }
2733 SwStartNode const*const pNewStartNode = rUnoCursor.GetPointNode().FindSttNodeByType(
2734 (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2735 if (!pNewStartNode || (pNewStartNode != pOwnStartNode))
2736 {
2737 uno::RuntimeException aExcept;
2738 aExcept.Message = "no text available";
2739 throw aExcept;
2740 }
2741 return pXCursor;
2742}
2743
2746{
2747 return CreateTextCursor(false);
2748}
2749
2751 const uno::Reference<text::XTextRange>& xTextPosition)
2752{
2753 SwFrameFormat& rHeadFootFormat( m_pImpl->GetHeadFootFormatOrThrow() );
2754
2755 SwUnoInternalPaM aPam(*GetDoc());
2756 if (!sw::XTextRangeToSwPaM(aPam, xTextPosition))
2757 {
2758 uno::RuntimeException aRuntime;
2759 aRuntime.Message = cInvalidObject;
2760 throw aRuntime;
2761 }
2762
2763 SwNode& rNode = rHeadFootFormat.GetContent().GetContentIdx()->GetNode();
2764 SwPosition aPos(rNode);
2765 SwPaM aHFPam(aPos);
2766 aHFPam.Move(fnMoveForward, GoInNode);
2767 SwStartNode* const pOwnStartNode = aHFPam.GetPointNode().FindSttNodeByType(
2768 (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2769 SwStartNode* const p1 = aPam.GetPointNode().FindSttNodeByType(
2770 (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
2771 if (p1 == pOwnStartNode)
2772 {
2773 return new SwXTextCursor(
2774 *GetDoc(),
2775 this,
2777 *aPam.GetPoint(), aPam.GetMark());
2778 }
2779 return nullptr;
2780}
2781
2782uno::Reference<container::XEnumeration> SAL_CALL SwXHeadFootText::createEnumeration()
2783{
2784 SolarMutexGuard aGuard;
2785 SwFrameFormat& rHeadFootFormat(m_pImpl->GetHeadFootFormatOrThrow());
2786
2787 const SwFormatContent& rFlyContent = rHeadFootFormat.GetContent();
2788 const SwNode& rNode = rFlyContent.GetContentIdx()->GetNode();
2789 SwPosition aPos(rNode);
2790 auto pUnoCursor(GetDoc()->CreateUnoCursor(aPos));
2791 pUnoCursor->Move(fnMoveForward, GoInNode);
2793 this,
2794 pUnoCursor,
2795 (m_pImpl->m_bIsHeader)
2798}
2799
2802
2804 { return true; }
2805
2806/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@ CheckPosInFly
check if target position is in fly anchored at source range
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
@ UndoArg1
Definition: SwRewriter.hxx:29
virtual bool AppendTextNode(SwPosition &rPos)=0
virtual bool DelFullPara(SwPaM &)=0
Delete full paragraphs.
Provides access to the marks of a document.
virtual sw::mark::IFieldmark * getInnerFieldmarkFor(const SwPosition &pos) const =0
virtual std::unique_ptr< ILazyDeleter > deleteMark(const IDocumentMarkAccess::const_iterator_t &ppMark, bool isMoveNodes)=0
Deletes a mark.
static bool IsShowChanges(const RedlineFlags eM)
virtual const SwRedlineTable & GetRedlineTable() const =0
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
SfxHintId GetId() const
bool StartListening(SvtBroadcaster &rBroadcaster)
bool Left(sal_uInt16 nCnt)
Definition: swcrsr.hxx:172
bool MovePara(SwWhichPara, SwMoveFnCollection const &)
Definition: swcrsr.cxx:2290
Definition: doc.hxx:197
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:329
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:158
SwNodes & GetNodes()
Definition: doc.hxx:422
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:349
bool DontExpandFormat(const SwPosition &rPos, bool bFlag=true)
Definition: docfmt.cxx:1722
Ends a section of nodes in the document model.
Definition: node.hxx:378
FlyAnchors.
Definition: fmtanchr.hxx:37
void SetAnchor(const SwPosition *pPos)
Definition: atrfrm.cxx:1593
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:67
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:74
SwNode * GetAnchorNode() const
Definition: atrfrm.cxx:1614
Content, content of frame (header, footer, fly).
Definition: fmtcntnt.hxx:32
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:139
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:82
const OUString & GetName() const
Definition: format.hxx:131
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:88
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
Style of a layout element.
Definition: frmfmt.hxx:72
SAL_DLLPRIVATE css::uno::WeakReference< css::uno::XInterface > const & GetXObject() const
Definition: frmfmt.hxx:183
SAL_DLLPRIVATE void SetXObject(css::uno::Reference< css::uno::XInterface > const &xObject)
Definition: frmfmt.hxx:185
const std::shared_ptr< SwTextBoxNode > & GetOtherTextBoxFormats() const
Definition: frmfmt.hxx:118
SdrObject * FindSdrObject()
Definition: frmfmt.hxx:153
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
SwNodeIndex aStart
Definition: ndindex.hxx:136
SwNodeIndex aEnd
Definition: ndindex.hxx:137
Base class of the Writer document model elements.
Definition: node.hxx:98
SwStartNode * GetStartNode()
Definition: node.hxx:642
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwNodeOffset GetIndex() const
Definition: node.hxx:312
const SwStartNode * FindFooterStartNode() const
Definition: node.hxx:226
const SwStartNode * FindHeaderStartNode() const
Definition: node.hxx:224
bool IsEndNode() const
Definition: node.hxx:189
bool IsStartNode() const
Definition: node.hxx:187
bool IsSectionNode() const
Definition: node.hxx:192
bool IsTableNode() const
Definition: node.hxx:191
bool IsTextNode() const
Definition: node.hxx:190
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:380
SwStartNode * FindSttNodeByType(SwStartNodeType eTyp)
Definition: node.cxx:782
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwNodeType GetNodeType() const
Definition: node.hxx:166
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:695
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:165
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1299
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
const SwPosition * GetMark() const
Definition: pam.hxx:255
SwNode & GetPointNode() const
Definition: pam.hxx:275
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:643
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:657
const SwPosition * End() const
Definition: pam.hxx:263
void DeleteMark()
Definition: pam.hxx:232
const SwPosition * GetPoint() const
Definition: pam.hxx:253
const SwPosition * Start() const
Definition: pam.hxx:258
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:251
size_type size() const
Definition: docary.hxx:268
void AddRule(SwUndoArg eWhat, const OUString &rWith)
Definition: SwRewriter.cxx:25
SwSectionNode * GetSectionNode()
Definition: section.cxx:923
A section node represents the start of a section on the UI, i.e.
Definition: node.hxx:575
Starts a section of nodes in the document model.
Definition: node.hxx:348
SwStartNodeType GetStartNodeType() const
Definition: node.hxx:364
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:113
SwTableNode * GetTableNode() const
Definition: swtable.cxx:2315
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:209
static SwTable * FindTable(SwFrameFormat const *const pFormat)
Definition: swtable.cxx:2308
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:291
const SfxItemPropertySet * GetPropertySet(sal_uInt16 PropertyId)
Definition: unomap1.cxx:1111
SwXBodyText(SwDoc *const pDoc)
Definition: unotext.cxx:2429
virtual rtl::Reference< SwXTextCursor > createXTextCursor() override
Definition: unotext.cxx:2502
virtual sal_Bool SAL_CALL supportsService(const OUString &rServiceName) override
Definition: unotext.cxx:2444
virtual sal_Bool SAL_CALL hasElements() override
Definition: unotext.cxx:2581
virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override
Definition: unotext.cxx:2550
virtual css::uno::Type SAL_CALL getElementType() override
Definition: unotext.cxx:2575
virtual rtl::Reference< SwXTextCursor > createXTextCursorByRange(const ::css::uno::Reference< ::css::text::XTextRange > &aTextPosition) override
Definition: unotext.cxx:2508
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unotext.cxx:2450
virtual OUString SAL_CALL getImplementationName() override
Definition: unotext.cxx:2439
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
Definition: unotext.cxx:2470
rtl::Reference< SwXTextCursor > CreateTextCursor(const bool bIgnoreTables=false)
Definition: unotext.cxx:2478
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
Definition: unotext.cxx:2456
rtl::Reference< SwXParagraphEnumeration > createParagraphEnumeration()
Definition: unotext.cxx:2556
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
Definition: unotext.cxx:2464
virtual ~SwXBodyText() override
Definition: unotext.cxx:2434
UNO API wrapper around an internal sw::mark::IMark.
Definition: unobookmark.hxx:51
UNO API wrapper around an SwContentControl, exposed as the com.sun.star.text.ContentControl service.
Impl(SwFrameFormat &rHeadFootFormat, const bool bIsHeader)
Definition: unotext.cxx:2602
SwFrameFormat & GetHeadFootFormatOrThrow()
Definition: unotext.cxx:2613
virtual void Notify(const SfxHint &rHint) override
Definition: unotext.cxx:2620
SwFrameFormat * GetHeadFootFormat() const
Definition: unotext.cxx:2609
SwFrameFormat * m_pHeadFootFormat
Definition: unotext.cxx:2599
virtual sal_Bool SAL_CALL hasElements() override
Definition: unotext.cxx:2803
virtual const SwStartNode * GetStartNode() const override
Definition: unotext.cxx:2670
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unotext.cxx:2665
virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override
Definition: unotext.cxx:2782
::sw::UnoImplPtr< Impl > m_pImpl
virtual ~SwXHeadFootText() override
Definition: unotext.cxx:2650
virtual rtl::Reference< SwXTextCursor > createXTextCursorByRange(const ::css::uno::Reference< ::css::text::XTextRange > &aTextPosition) override
Definition: unotext.cxx:2750
SwXHeadFootText(SwFrameFormat &rHeadFootFormat, const bool bIsHeader)
Definition: unotext.cxx:2642
static css::uno::Reference< css::text::XText > CreateXHeadFootText(SwFrameFormat &rHeadFootFormat, const bool bIsHeader)
Definition: unotext.cxx:2627
virtual sal_Bool SAL_CALL supportsService(const OUString &rServiceName) override
Definition: unotext.cxx:2659
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
Definition: unotext.cxx:2685
virtual css::uno::Type SAL_CALL getElementType() override
Definition: unotext.cxx:2800
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
Definition: unotext.cxx:2697
virtual rtl::Reference< SwXTextCursor > createXTextCursor() override
Definition: unotext.cxx:2745
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
Definition: unotext.cxx:2692
virtual OUString SAL_CALL getImplementationName() override
Definition: unotext.cxx:2654
rtl::Reference< SwXTextCursor > CreateTextCursor(const bool bIgnoreTables=false)
Definition: unotext.cxx:2705
void attachToText(SwXText &rParent, SwTextNode &rTextNode)
for SwXText
bool IsDescriptor() const
static rtl::Reference< SwXParagraph > CreateXParagraph(SwDoc &rDoc, SwTextNode *pTextNode, css::uno::Reference< css::text::XText > const &xParentText=nullptr, const sal_Int32 nSelStart=-1, const sal_Int32 nSelEnd=- 1)
static css::uno::Sequence< css::beans::PropertyValue > CreateRedlineProperties(SwRangeRedline const &rRedline, bool const bIsStart)
Definition: unoredline.cxx:284
void DeleteAndInsert(std::u16string_view aText, ::sw::DeleteAndInsertMode eMode)
Definition: unoobj.cxx:729
UNO wrapper around an SwFormatField, i.e.
Definition: unofield.hxx:120
SwServiceType GetServiceId() const
Definition: unofield.cxx:1221
virtual rtl::Reference< SwXTextCursor > createXTextCursor() override
Definition: unoframe.cxx:3293
static SW_DLLPUBLIC rtl::Reference< SwXTextFrame > CreateXTextFrame(SwDoc &rDoc, SwFrameFormat *pFrameFormat)
Definition: unoframe.cxx:3234
void SetPositions(SwPaM const &rPam)
Definition: unoobj2.cxx:777
bool GetPositions(SwPaM &rToFill, ::sw::TextRangeMode eMode=::sw::TextRangeMode::RequireTextNode) const
Definition: unoobj2.cxx:1050
void Invalidate()
Definition: unoobj2.cxx:772
void DeleteAndInsert(std::u16string_view aText, ::sw::DeleteAndInsertMode eMode)
Definition: unoobj2.cxx:798
SwSectionFormat * GetFormat() const
Definition: unosect.cxx:188
static rtl::Reference< SwXTextTable > CreateXTextTable(SwFrameFormat *pFrameFormat)
Definition: unotbl.cxx:1953
SwFrameFormat * GetFrameFormat()
Definition: unotbl.cxx:1968
uno::Reference< text::XTextRange > finishOrAppendParagraph(const uno::Sequence< beans::PropertyValue > &rCharacterAndParagraphProperties, const uno::Reference< text::XTextRange > &xInsertPosition)
Definition: unotext.cxx:1213
const CursorType m_eType
Definition: unotext.cxx:86
SwXText & m_rThis
Definition: unotext.cxx:84
bool CheckForOwnMember(const SwPaM &rPaM)
Definition: unotext.cxx:971
bool m_bIsValid
Definition: unotext.cxx:88
SfxItemPropertySet const & m_rPropSet
Definition: unotext.cxx:85
SwDoc * m_pDoc
Definition: unotext.cxx:87
sal_Int16 ComparePositions(const uno::Reference< text::XTextRange > &xPos1, const uno::Reference< text::XTextRange > &xPos2)
Definition: unotext.cxx:1015
void ConvertCell(const uno::Sequence< uno::Reference< text::XTextRange > > &rCell, std::vector< SwNodeRange > &rRowNodes, SwNodeRange *const pLastCell)
Definition: unotext.cxx:1878
Impl(SwXText &rThis, SwDoc *const pDoc, const CursorType eType)
Definition: unotext.cxx:90
virtual void SAL_CALL removeTextContent(const css::uno::Reference< css::text::XTextContent > &xContent) override
Definition: unotext.cxx:834
const SwDoc * GetDoc() const
Definition: unotext.cxx:134
virtual css::uno::Reference< css::text::XTextRange > SAL_CALL finishParagraphInsert(const css::uno::Sequence< css::beans::PropertyValue > &rCharacterAndParagraphProperties, const css::uno::Reference< css::text::XTextRange > &xInsertPosition) override
Definition: unotext.cxx:1203
virtual rtl::Reference< SwXTextCursor > createXTextCursorByRange(const ::css::uno::Reference< ::css::text::XTextRange > &aTextPosition)=0
bool IsValid() const
Definition: unotext.cxx:144
void SetDoc(SwDoc *const pDoc)
Definition: unotext.cxx:154
virtual void SAL_CALL removePropertyChangeListener(const OUString &rPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &xListener) override
Definition: unotext.cxx:1166
::sw::UnoImplPtr< Impl > m_pImpl
Definition: unotext.hxx:57
virtual css::uno::Reference< css::text::XTextContent > SAL_CALL convertToTextFrame(const css::uno::Reference< css::text::XTextRange > &xStart, const css::uno::Reference< css::text::XTextRange > &xEnd, const css::uno::Sequence< css::beans::PropertyValue > &xFrameProperties) override
Definition: unotext.cxx:1528
virtual void SAL_CALL removeVetoableChangeListener(const OUString &rPropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &xListener) override
Definition: unotext.cxx:1182
void Invalidate()
Definition: unotext.cxx:149
virtual css::uno::Reference< css::text::XTextRange > SAL_CALL appendTextPortion(const OUString &rText, const css::uno::Sequence< css::beans::PropertyValue > &rCharacterAndParagraphProperties) override
Definition: unotext.cxx:1399
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
Definition: unotext.cxx:1088
virtual css::uno::Reference< css::text::XTextRange > SAL_CALL appendTextContent(const css::uno::Reference< css::text::XTextContent > &xTextContent, const css::uno::Sequence< css::beans::PropertyValue > &rCharacterAndParagraphProperties) override
Definition: unotext.cxx:1472
virtual void SAL_CALL addPropertyChangeListener(const OUString &rPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &xListener) override
Definition: unotext.cxx:1158
virtual void SAL_CALL addVetoableChangeListener(const OUString &rPropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &xListener) override
Definition: unotext.cxx:1174
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
Definition: unotext.cxx:214
virtual css::uno::Reference< css::text::XTextRange > SAL_CALL insertTextContentWithProperties(const css::uno::Reference< css::text::XTextContent > &xTextContent, const css::uno::Sequence< css::beans::PropertyValue > &rCharacterAndParagraphProperties, const css::uno::Reference< css::text::XTextRange > &xInsertPosition) override
Definition: unotext.cxx:1413
virtual void SAL_CALL removeTextContentBefore(const css::uno::Reference< css::text::XTextContent > &xSuccessor) override
Definition: unotext.cxx:737
virtual css::uno::Reference< css::text::XTextCursor > SAL_CALL createTextCursorByRange(const ::css::uno::Reference< ::css::text::XTextRange > &aTextPosition) override final
Definition: unotext.cxx:205
SwXText(SwDoc *const pDoc, const CursorType eType)
Definition: unotext.cxx:125
virtual bool CheckForOwnMemberMeta(const SwPaM &rPam, const bool bAbsorb)
Definition: unotext.cxx:167
virtual void SAL_CALL removeTextContentAfter(const css::uno::Reference< css::text::XTextContent > &xPredecessor) override
Definition: unotext.cxx:785
virtual css::uno::Any SAL_CALL getPropertyValue(const OUString &rPropertyName) override
Definition: unotext.cxx:1105
virtual rtl::Reference< SwXTextCursor > createXTextCursor()=0
Definition: unotext.cxx:192
virtual OUString SAL_CALL getString() override
Definition: unotext.cxx:889
virtual css::uno::Reference< css::text::XTextCursor > SAL_CALL createTextCursor() override final
Definition: unotext.cxx:178
virtual css::uno::Reference< css::text::XTextTable > SAL_CALL convertToTable(css::uno::Sequence< css::uno::Sequence< css::uno::Sequence< css::uno::Reference< css::text::XTextRange > > > > const &rTableRanges, css::uno::Sequence< css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > > const &rCellProperties, css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > const &rRowProperties, css::uno::Sequence< css::beans::PropertyValue > const &rTableProperties) override
Definition: unotext.cxx:2222
sal_Int16 SAL_CALL compareRegionStarts(const css::uno::Reference< css::text::XTextRange > &xR1, const css::uno::Reference< css::text::XTextRange > &xR2) override
Definition: unotext.cxx:1054
virtual css::uno::Reference< css::text::XTextRange > SAL_CALL getEnd() override
Definition: unotext.cxx:874
virtual css::uno::Reference< css::text::XTextRange > SAL_CALL insertTextPortion(const OUString &rText, const css::uno::Sequence< css::beans::PropertyValue > &rCharacterAndParagraphProperties, const css::uno::Reference< css::text::XTextRange > &rTextRange) override
Definition: unotext.cxx:1324
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
Definition: unotext.cxx:281
sal_Int16 SAL_CALL compareRegionEnds(const css::uno::Reference< css::text::XTextRange > &xR1, const css::uno::Reference< css::text::XTextRange > &xR2) override
Definition: unotext.cxx:1071
virtual void SAL_CALL insertTextContentAfter(const css::uno::Reference< css::text::XTextContent > &xNewContent, const css::uno::Reference< css::text::XTextContent > &xPredecessor) override
Definition: unotext.cxx:687
virtual void SAL_CALL insertTextContent(const css::uno::Reference< css::text::XTextRange > &xRange, const css::uno::Reference< css::text::XTextContent > &xContent, sal_Bool bAbsorb) override
Definition: unotext.cxx:512
virtual css::uno::Reference< css::text::XTextRange > SAL_CALL getStart() override
Definition: unotext.cxx:858
virtual ~SwXText()
Definition: unotext.cxx:130
virtual void SAL_CALL insertString(const css::uno::Reference< css::text::XTextRange > &xRange, const OUString &aString, sal_Bool bAbsorb) override
Definition: unotext.cxx:302
virtual void SAL_CALL setString(const OUString &rString) override
Definition: unotext.cxx:904
virtual css::uno::Reference< css::text::XText > SAL_CALL getText() override
Definition: unotext.cxx:848
virtual const SwStartNode * GetStartNode() const
Definition: unotext.cxx:173
virtual void SAL_CALL insertTextContentBefore(const css::uno::Reference< css::text::XTextContent > &xNewContent, const css::uno::Reference< css::text::XTextContent > &xSuccessor) override
Definition: unotext.cxx:634
virtual void PrepareForAttach(css::uno::Reference< css::text::XTextRange > &xRange, SwPaM const &rPam)
Definition: unotext.cxx:163
virtual void SAL_CALL copyText(const css::uno::Reference< css::text::XTextCopy > &xSource) override
Definition: unotext.cxx:2375
virtual css::uno::Reference< css::text::XTextRange > SAL_CALL finishParagraph(const css::uno::Sequence< css::beans::PropertyValue > &rCharacterAndParagraphProperties) override
Definition: unotext.cxx:1194
virtual void SAL_CALL insertControlCharacter(const css::uno::Reference< css::text::XTextRange > &xRange, sal_Int16 nControlCharacter, sal_Bool bAbsorb) override
Definition: unotext.cxx:406
virtual void SAL_CALL setPropertyValue(const OUString &rPropertyName, const css::uno::Any &rValue) override
Definition: unotext.cxx:1098
css::uno::Type const & get()
const_iterator find(const Value &x) const
const_iterator end() const
std::pair< const_iterator, bool > insert(Value &&x)
Blocks grouping undo actions together into an SfxListUndoAction.
#define FN_UNO_REDLINE_NODE_END
Definition: cmdid.h:605
#define TOOLS_WARN_EXCEPTION(area, stream)
float u
DocumentType eType
constexpr TypedWhichId< SwFlyFrameFormat > RES_FLYFRMFMT(162)
Mode eMode
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
void SetPropertyValue(SwPaM &rPaM, const SfxItemPropertySet &rPropSet, const OUString &rPropertyName, const css::uno::Any &rValue, const SetAttrMode nAttrMode=SetAttrMode::DEFAULT)
void SetPropertyValues(SwPaM &rPaM, const SfxItemPropertySet &rPropSet, const css::uno::Sequence< css::beans::PropertyValue > &rPropertyValues, const SetAttrMode nAttrMode=SetAttrMode::DEFAULT)
bool DocInsertStringSplitCR(SwDoc &rDoc, const SwPaM &rNewCursor, std::u16string_view rText, const bool bForceExpandHints)
void SelectPam(SwPaM &rPam, const bool bExpand)
Definition: unoobj.cxx:120
double getLength(const B2DPolygon &rCandidate)
size
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Any SAL_CALL getCaughtException()
int i
index
Header
Footer
SwPosition FindFieldSep(IFieldmark const &rMark)
return position of the CH_TXT_ATR_FIELDSEP for rMark
bool XTextRangeToSwPaM(SwUnoInternalPaM &rToFill, const uno::Reference< text::XTextRange > &xTextRange, ::sw::TextRangeMode const eMode)
Definition: unoobj2.cxx:1108
TextRangeMode
long Long
SwStartNodeType
Definition: ndtyp.hxx:51
@ SwNormalStartNode
Definition: ndtyp.hxx:52
@ SwHeaderStartNode
Definition: ndtyp.hxx:56
@ SwFooterStartNode
Definition: ndtyp.hxx:57
@ SwFlyStartNode
Definition: ndtyp.hxx:54
@ SwTableBoxStartNode
Definition: ndtyp.hxx:53
@ SwFootnoteStartNode
Definition: ndtyp.hxx:55
@ Table
SwTableNode is derived from SwStartNode.
@ Section
SwSectionNode is derived from SwStartNode.
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
bool GoCurrPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1248
bool GoInNode(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1194
bool GoInDoc(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1182
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1203
SwMoveFnCollection const & fnParaStart
Definition: paminit.cxx:48
SwMoveFnCollection const & fnParaEnd
Definition: paminit.cxx:49
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:60
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:61
OUString sMessage
Marks a position in the document model.
Definition: pam.hxx:38
void Adjust(SwNodeOffset nDelta)
Adjust node position, and resets content position to zero.
Definition: pam.cxx:257
SwNode & GetNode() const
Definition: pam.hxx:81
void SetMark(const sw::mark::IMark *pMark)
Definition: pam.hxx:86
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:231
void AssignEndIndex(const SwContentNode &rNd)
Set nNode to rNd, and nContent to the end of rNd.
Definition: pam.cxx:277
void SetContent(sal_Int32 nContentIndex)
Set content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:267
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:78
void AssignStartIndex(const SwContentNode &rNd)
Set nNode to rNd, and nContent to the beginning of rNd.
Definition: pam.cxx:272
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
static rtl::Reference< SwXParagraphEnumeration > Create(css::uno::Reference< css::text::XText > const &xParent, const std::shared_ptr< SwUnoCursor > &pCursor, const CursorType eType, SwTableBox const *const pTableBox=nullptr)
Definition: unoobj2.cxx:445
Object Value
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:168
#define CHAR_HARDBLANK
Definition: swtypes.hxx:173
#define CHAR_SOFTHYPHEN
Definition: swtypes.hxx:175
#define CHAR_HARDHYPHEN
Definition: swtypes.hxx:174
css::uno::Reference< css::i18n::XExtendedTransliteration > Body
unsigned char sal_Bool
sal_uInt16 sal_Unicode
CursorType
SwUnoPropertyMapProvider aSwMapProvider
Definition: unomap1.cxx:88
#define PROPERTY_MAP_TEXT_CURSOR
Definition: unomap.hxx:28
#define PROPERTY_MAP_PARAGRAPH
Definition: unomap.hxx:62
#define PROPERTY_MAP_TEXT
Definition: unomap.hxx:113
constexpr OUStringLiteral UNO_NAME_ROW_SPAN
Definition: unoprnms.hxx:826
constexpr OUStringLiteral cInvalidObject
Definition: unotext.cxx:78
static bool isGraphicNode(const SwFrameFormat *pFrameFormat)
Definition: unotext.cxx:1484
static bool IsAtParaMatch(const SwPaM &rAnchorCheckPam, const SwFormatAnchor &rAnchor)
Determines if the at-para rAnchor is anchored at the start or end of rAnchorCheckPam.
Definition: unotext.cxx:1498
static void lcl_MergeCells(std::vector< VerticallyMergedCell > &rMergedCells)
Definition: unotext.cxx:2198
static void lcl_ApplyRowProperties(uno::Sequence< beans::PropertyValue > const &rRowProperties, uno::Any const &rRow, TableColumnSeparators &rRowSeparators)
Definition: unotext.cxx:2100
#define COL_POS_FUZZY
Definition: unotext.cxx:1871
uno::Sequence< text::TableColumnSeparator > TableColumnSeparators
Definition: unotext.cxx:2097
static sal_Int32 lcl_GetLeftPos(sal_Int32 nCell, TableColumnSeparators const &rRowSeparators)
Definition: unotext.cxx:2121
static void lcl_ApplyCellProperties(const sal_Int32 nLeftPos, const uno::Sequence< beans::PropertyValue > &rCellProperties, const uno::Reference< uno::XInterface > &xCell, std::vector< VerticallyMergedCell > &rMergedCells)
Definition: unotext.cxx:2131
static bool lcl_SimilarPosition(const sal_Int32 nPos1, const sal_Int32 nPos2)
Definition: unotext.cxx:1873
const SvXMLTokenMapEntry aTypes[]