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