1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <unocrsrhelper.hxx>
26 #include <com/sun/star/beans/NamedValue.hpp>
27 #include <com/sun/star/beans/PropertyAttribute.hpp>
28 #include <com/sun/star/beans/PropertyState.hpp>
29 #include <com/sun/star/embed/ElementModes.hpp>
30 #include <com/sun/star/embed/XStorage.hpp>
31 #include <com/sun/star/io/IOException.hpp>
32 #include <com/sun/star/text/XTextSection.hpp>
33 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
35 #include <svx/unoshape.hxx>
38 #include <hintids.hxx>
39 #include <unotextrange.hxx>
40 #include <unodraw.hxx>
41 #include <unofootnote.hxx>
42 #include <unobookmark.hxx>
44 #include <unorefmark.hxx>
46 #include <unofield.hxx>
48 #include <unosett.hxx>
49 #include <unoframe.hxx>
50 #include <unocrsr.hxx>
52 #include <IDocumentUndoRedo.hxx>
53 #include <IDocumentRedlineAccess.hxx>
54 #include <IDocumentLayoutAccess.hxx>
56 #include <charfmt.hxx>
57 #include <pagedesc.hxx>
58 #include <docstyle.hxx>
61 #include <section.hxx>
62 #include <shellio.hxx>
66 #include <pagefrm.hxx>
67 #include <svl/eitem.hxx>
68 #include <svl/lngmisc.hxx>
69 #include <swtable.hxx>
72 #include <fchrfmt.hxx>
73 #include <editeng/editids.hrc>
74 #include <editeng/flstitem.hxx>
75 #include <editeng/prntitem.hxx>
76 #include <vcl/metric.hxx>
77 #include <svtools/ctrltool.hxx>
78 #include <sfx2/docfilt.hxx>
79 #include <sfx2/docfile.hxx>
80 #include <sfx2/fcontnr.hxx>
81 #include <svl/stritem.hxx>
82 #include <SwStyleNameMapper.hxx>
83 #include <redline.hxx>
84 #include <numrule.hxx>
85 #include <comphelper/storagehelper.hxx>
86 #include <unotools/mediadescriptor.hxx>
87 #include <comphelper/sequenceashashmap.hxx>
88 #include <SwNodeNum.hxx>
89 #include <fmtmeta.hxx>
91 #include <unoparagraph.hxx>
92 #include <poolfmt.hxx>
94 #include <sal/log.hxx>
96 using namespace ::com::sun::star
;
97 using namespace ::com::sun::star::uno
;
98 using namespace ::com::sun::star::beans
;
99 using namespace ::com::sun::star::text
;
100 using namespace ::com::sun::star::table
;
101 using namespace ::com::sun::star::container
;
102 using namespace ::com::sun::star::lang
;
104 namespace SwUnoCursorHelper
107 static SwPaM
* lcl_createPamCopy(const SwPaM
& rPam
)
109 SwPaM
*const pRet
= new SwPaM(*rPam
.GetPoint());
110 ::sw::DeepCopyPaM(rPam
, *pRet
);
114 void GetSelectableFromAny(uno::Reference
<uno::XInterface
> const& xIfc
,
116 SwPaM
*& o_rpPaM
, std::pair
<OUString
, FlyCntType
> & o_rFrame
,
117 OUString
& o_rTableName
, SwUnoTableCursor
const*& o_rpTableCursor
,
118 ::sw::mark::IMark
const*& o_rpMark
,
119 std::vector
<SdrObject
*> & o_rSdrObjects
)
121 uno::Reference
<drawing::XShapes
> const xShapes(xIfc
, UNO_QUERY
);
124 sal_Int32
nShapes(xShapes
->getCount());
125 for (sal_Int32 i
= 0; i
< nShapes
; ++i
)
127 uno::Reference
<lang::XUnoTunnel
> xShape
;
128 xShapes
->getByIndex(i
) >>= xShape
;
131 SvxShape
*const pSvxShape(
132 comphelper::getFromUnoTunnel
<SvxShape
>(xShape
));
135 SdrObject
*const pSdrObject
= pSvxShape
->GetSdrObject();
137 { // hmm... needs view to verify it's in right doc...
138 o_rSdrObjects
.push_back(pSdrObject
);
146 uno::Reference
<lang::XUnoTunnel
> const xTunnel(xIfc
, UNO_QUERY
);
148 SwXShape
*const pShape(comphelper::getFromUnoTunnel
<SwXShape
>(xTunnel
));
151 uno::Reference
<uno::XAggregation
> const xAgg(
152 pShape
->GetAggregationInterface());
155 SvxShape
*const pSvxShape(
156 comphelper::getFromUnoTunnel
<SvxShape
>(xTunnel
));
159 SdrObject
*const pSdrObject
= pSvxShape
->GetSdrObject();
161 { // hmm... needs view to verify it's in right doc...
162 o_rSdrObjects
.push_back(pSdrObject
);
169 OTextCursorHelper
*const pCursor(
170 dynamic_cast<OTextCursorHelper
*>(xIfc
.get()));
173 if (pCursor
->GetDoc() == &rTargetDoc
)
175 o_rpPaM
= lcl_createPamCopy(*pCursor
->GetPaM());
180 SwXTextRanges
* const pRanges
= dynamic_cast<SwXTextRanges
*>(xIfc
.get());
183 SwUnoCursor
const* pUnoCursor
= pRanges
->GetCursor();
184 if (pUnoCursor
&& &pUnoCursor
->GetDoc() == &rTargetDoc
)
186 o_rpPaM
= lcl_createPamCopy(*pUnoCursor
);
191 // check these before Range to prevent misinterpretation of text frames
192 // and cells also implement XTextRange
193 SwXFrame
*const pFrame
= dynamic_cast<SwXFrame
*>(xIfc
.get());
196 const SwFrameFormat
*const pFrameFormat(pFrame
->GetFrameFormat());
197 if (pFrameFormat
&& pFrameFormat
->GetDoc() == &rTargetDoc
)
199 o_rFrame
= std::make_pair(pFrameFormat
->GetName(), pFrame
->GetFlyCntType());
204 SwXTextTable
*const pTextTable
= dynamic_cast<SwXTextTable
*>(xIfc
.get());
207 SwFrameFormat
*const pFrameFormat(pTextTable
->GetFrameFormat());
208 if (pFrameFormat
&& pFrameFormat
->GetDoc() == &rTargetDoc
)
210 o_rTableName
= pFrameFormat
->GetName();
215 SwXCell
*const pCell
= dynamic_cast<SwXCell
*>(xIfc
.get());
218 SwFrameFormat
*const pFrameFormat(pCell
->GetFrameFormat());
219 if (pFrameFormat
&& pFrameFormat
->GetDoc() == &rTargetDoc
)
221 SwTableBox
* pBox
= pCell
->GetTableBox();
222 SwTable
*const pTable
= SwTable::FindTable(pFrameFormat
);
223 // ??? what's the benefit of setting pBox in this convoluted way?
224 pBox
= pCell
->FindBox(pTable
, pBox
);
227 SwPaM
aPam(*pBox
->GetSttNd());
228 aPam
.Move(fnMoveForward
, GoInNode
);
229 o_rpPaM
= lcl_createPamCopy(aPam
);
235 uno::Reference
<text::XTextRange
> const xTextRange(xTunnel
, UNO_QUERY
);
238 SwUnoInternalPaM
aPam(rTargetDoc
);
239 if (::sw::XTextRangeToSwPaM(aPam
, xTextRange
))
241 o_rpPaM
= lcl_createPamCopy(aPam
);
246 SwXCellRange
*const pCellRange
= dynamic_cast<SwXCellRange
*>(xIfc
.get());
249 SwUnoCursor
const*const pUnoCursor(pCellRange
->GetTableCursor());
250 if (pUnoCursor
&& &pUnoCursor
->GetDoc() == &rTargetDoc
)
252 // probably can't copy it to o_rpPaM for this since it's
254 o_rpTableCursor
= dynamic_cast<SwUnoTableCursor
const*>(pUnoCursor
);
259 ::sw::mark::IMark
const*const pMark
=
260 SwXBookmark::GetBookmarkInDoc(& rTargetDoc
, xIfc
);
268 uno::Reference
<text::XTextContent
>
269 GetNestedTextContent(SwTextNode
const & rTextNode
, sal_Int32
const nIndex
,
272 // these should be unambiguous because of the dummy character
273 auto const eMode( bParent
274 ? ::sw::GetTextAttrMode::Parent
: ::sw::GetTextAttrMode::Expand
);
275 SwTextAttr
*const pMetaTextAttr
=
276 rTextNode
.GetTextAttrAt(nIndex
, RES_TXTATR_META
, eMode
);
277 SwTextAttr
*const pMetaFieldTextAttr
=
278 rTextNode
.GetTextAttrAt(nIndex
, RES_TXTATR_METAFIELD
, eMode
);
279 // which is innermost?
280 SwTextAttr
*const pTextAttr
= pMetaTextAttr
281 ? (pMetaFieldTextAttr
282 ? ((pMetaFieldTextAttr
->GetStart() >
283 pMetaTextAttr
->GetStart())
284 ? pMetaFieldTextAttr
: pMetaTextAttr
)
286 : pMetaFieldTextAttr
;
287 uno::Reference
<XTextContent
> xRet
;
290 ::sw::Meta
*const pMeta(
291 static_cast<SwFormatMeta
&>(pTextAttr
->GetAttr()).GetMeta());
293 xRet
.set(pMeta
->MakeUnoObject(), uno::UNO_QUERY
);
298 static uno::Any
GetParaListAutoFormat(SwTextNode
const& rNode
)
300 SwFormatAutoFormat
const*const pFormat(
301 rNode
.GetSwAttrSet().GetItem
<SwFormatAutoFormat
>(RES_PARATR_LIST_AUTOFMT
, false));
306 const auto pSet(pFormat
->GetStyleHandle());
309 SfxItemPropertySet
const& rPropSet(*aSwMapProvider
.GetPropertySet(PROPERTY_MAP_CHAR_AUTO_STYLE
));
310 SfxItemPropertyMap
const& rMap(rPropSet
.getPropertyMap());
311 std::vector
<beans::NamedValue
> props
;
312 // have to iterate the map, not the item set?
313 for (auto const pEntry
: rMap
.getPropertyEntries())
315 if (rPropSet
.getPropertyState(*pEntry
, *pSet
) == PropertyState_DIRECT_VALUE
)
318 rPropSet
.getPropertyValue(*pEntry
, *pSet
, value
);
319 props
.emplace_back(pEntry
->aName
, value
);
322 return uno::Any(comphelper::containerToSequence(props
));
325 // Read the special properties of the cursor
326 bool getCursorPropertyValue(const SfxItemPropertyMapEntry
& rEntry
329 , PropertyState
& eState
330 , const SwTextNode
* pNode
)
332 PropertyState eNewState
= PropertyState_DIRECT_VALUE
;
336 case FN_UNO_PARA_CONT_PREV_SUBTREE
:
339 const SwTextNode
* pTmpNode
= pNode
;
342 pTmpNode
= rPam
.GetPointNode().GetTextNode();
347 pTmpNode
->GetNum() &&
348 pTmpNode
->GetNum()->IsContinueingPreviousSubTree() )
356 case FN_UNO_PARA_NUM_STRING
:
359 const SwTextNode
* pTmpNode
= pNode
;
362 pTmpNode
= rPam
.GetPointNode().GetTextNode();
365 if ( pTmpNode
&& pTmpNode
->GetNum() )
367 sRet
= pTmpNode
->GetNumString();
373 case RES_PARATR_OUTLINELEVEL
:
376 const SwTextNode
* pTmpNode
= pNode
;
379 pTmpNode
= rPam
.GetPointNode().GetTextNode();
383 nRet
= sal::static_int_cast
< sal_Int16
>( pTmpNode
->GetAttrOutlineLevel() );
388 case FN_UNO_PARA_CONDITIONAL_STYLE_NAME
:
389 case FN_UNO_PARA_STYLE
:
391 SwFormatColl
* pFormat
= nullptr;
393 pFormat
= FN_UNO_PARA_CONDITIONAL_STYLE_NAME
== rEntry
.nWID
394 ? pNode
->GetFormatColl() : &pNode
->GetAnyFormatColl();
397 pFormat
= SwUnoCursorHelper::GetCurTextFormatColl(rPam
,
398 FN_UNO_PARA_CONDITIONAL_STYLE_NAME
== rEntry
.nWID
);
405 SwStyleNameMapper::FillProgName(pFormat
->GetName(), sVal
, SwGetPoolIdFromName::TxtColl
);
410 eNewState
= PropertyState_AMBIGUOUS_VALUE
;
413 case FN_UNO_PAGE_STYLE
:
416 GetCurPageStyle(rPam
, sVal
);
420 eNewState
= PropertyState_AMBIGUOUS_VALUE
;
423 case FN_UNO_NUM_START_VALUE
:
426 sal_Int16 nValue
= IsNodeNumStart(rPam
, eNewState
);
430 case FN_UNO_NUM_LEVEL
:
431 case FN_UNO_IS_NUMBER
:
434 case FN_NUMBER_NEWSTART
:
435 case FN_UNO_PARA_NUM_AUTO_FORMAT
:
441 // a multi selection is not considered
442 const SwTextNode
* pTextNd
= rPam
.GetPointNode().GetTextNode();
443 if ( pTextNd
&& pTextNd
->IsInList() )
447 case FN_UNO_NUM_LEVEL
:
449 *pAny
<<= static_cast<sal_Int16
>(pTextNd
->GetActualListLevel());
452 case FN_UNO_IS_NUMBER
:
454 *pAny
<<= pTextNd
->IsCountedInList();
460 *pAny
<<= pTextNd
->GetListId();
463 case FN_NUMBER_NEWSTART
:
465 *pAny
<<= pTextNd
->IsListRestart();
468 case FN_UNO_PARA_NUM_AUTO_FORMAT
:
470 *pAny
= GetParaListAutoFormat(*pTextNd
);
479 eNewState
= PropertyState_DEFAULT_VALUE
;
481 // #i30838# set default values for default properties
484 case FN_UNO_NUM_LEVEL
:
486 *pAny
<<= static_cast<sal_Int16
>( 0 );
489 case FN_UNO_IS_NUMBER
:
497 *pAny
<<= OUString();
500 case FN_NUMBER_NEWSTART
:
505 case FN_UNO_PARA_NUM_AUTO_FORMAT
:
513 //PROPERTY_MAYBEVOID!
516 case FN_UNO_NUM_RULES
:
518 getNumberingProperty(rPam
, eNewState
, pAny
);
521 if( !SwDoc::GetNumRuleAtPos( *rPam
.GetPoint() ) )
522 eNewState
= PropertyState_DEFAULT_VALUE
;
525 case FN_UNO_DOCUMENT_INDEX_MARK
:
527 std::vector
<SwTextAttr
*> marks
;
528 if (rPam
.GetPointNode().IsTextNode())
530 marks
= rPam
.GetPointNode().GetTextNode()->GetTextAttrsAt(
531 rPam
.GetPoint()->GetContentIndex(), RES_TXTATR_TOXMARK
);
536 { // hmm... can only return 1 here
538 static_cast<SwTOXMark
&>((*marks
.begin())->GetAttr());
539 const uno::Reference
< text::XDocumentIndexMark
> xRef
=
540 SwXDocumentIndexMark::CreateXDocumentIndexMark(
541 rPam
.GetDoc(), &rMark
);
546 //also here - indistinguishable
547 eNewState
= PropertyState_DEFAULT_VALUE
;
550 case FN_UNO_DOCUMENT_INDEX
:
552 SwTOXBase
* pBase
= SwDoc::GetCurTOX(
558 const uno::Reference
< text::XDocumentIndex
> xRef
=
559 SwXDocumentIndex::CreateXDocumentIndex(rPam
.GetDoc(),
560 static_cast<SwTOXBaseSection
*>(pBase
));
565 eNewState
= PropertyState_DEFAULT_VALUE
;
568 case FN_UNO_TEXT_FIELD
:
570 const SwPosition
*pPos
= rPam
.Start();
571 const SwTextNode
*pTextNd
=
572 rPam
.GetDoc().GetNodes()[pPos
->GetNodeIndex()]->GetTextNode();
573 const SwTextAttr
* pTextAttr
= pTextNd
574 ? pTextNd
->GetFieldTextAttrAt(pPos
->GetContentIndex(), ::sw::GetTextAttrMode::Default
)
576 if ( pTextAttr
!= nullptr )
580 uno::Reference
<text::XTextField
> const xField(
581 SwXTextField::CreateXTextField(&rPam
.GetDoc(),
582 &pTextAttr
->GetFormatField()));
587 eNewState
= PropertyState_DEFAULT_VALUE
;
590 case FN_UNO_TEXT_TABLE
:
593 SwStartNode
* pSttNode
= rPam
.GetPointNode().StartOfSectionNode();
594 SwStartNodeType eType
= pSttNode
->GetStartNodeType();
595 if(SwTableBoxStartNode
== eType
)
599 const SwTableNode
* pTableNode
= pSttNode
->FindTableNode();
600 SwFrameFormat
* pTableFormat
= pTableNode
->GetTable().GetFrameFormat();
601 //SwTable& rTable = static_cast<SwTableNode*>(pSttNode)->GetTable();
602 if(FN_UNO_TEXT_TABLE
== rEntry
.nWID
)
604 uno::Reference
< XTextTable
> xTable
= SwXTextTables::GetObject(*pTableFormat
);
609 SwTableBox
* pBox
= pSttNode
->GetTableBox();
610 uno::Reference
< XCell
> xCell
= SwXCell::CreateXCell(pTableFormat
, pBox
);
616 eNewState
= PropertyState_DEFAULT_VALUE
;
619 case FN_UNO_TEXT_FRAME
:
621 SwStartNode
* pSttNode
= rPam
.GetPointNode().StartOfSectionNode();
622 SwStartNodeType eType
= pSttNode
->GetStartNodeType();
624 SwFrameFormat
* pFormat
;
625 if(eType
== SwFlyStartNode
&& nullptr != (pFormat
= pSttNode
->GetFlyFormat()))
627 // Create a wrapper only for text frames, not for graphic or OLE nodes.
628 if (pAny
&& !rPam
.GetPointNode().IsNoTextNode())
630 uno::Reference
<XTextFrame
> const xFrame(
631 SwXTextFrame::CreateXTextFrame(*pFormat
->GetDoc(), pFormat
));
636 eNewState
= PropertyState_DEFAULT_VALUE
;
639 case FN_UNO_TEXT_SECTION
:
641 SwSection
* pSect
= SwDoc::GetCurrSection(*rPam
.GetPoint());
646 uno::Reference
< XTextSection
> xSect
= SwXTextSections::GetObject( *pSect
->GetFormat() );
651 eNewState
= PropertyState_DEFAULT_VALUE
;
654 case FN_UNO_TEXT_PARAGRAPH
:
656 SwTextNode
* pTextNode
= rPam
.GetPoint()->GetNode().GetTextNode();
661 uno::Reference
<text::XTextContent
> xParagraph
= SwXParagraph::CreateXParagraph(pTextNode
->GetDoc(), pTextNode
);
662 *pAny
<<= xParagraph
;
666 eNewState
= PropertyState_DEFAULT_VALUE
;
669 case FN_UNO_SORTED_TEXT_ID
:
673 sal_Int32 nIndex
= -1;
674 SwTextNode
* pTextNode
= rPam
.GetPoint()->GetNode().GetTextNode();
676 nIndex
= pTextNode
->GetIndex().get();
682 case FN_UNO_FOOTNOTE
:
684 SwTextAttr
*const pTextAttr
= rPam
.GetPointNode().IsTextNode() ?
685 rPam
.GetPointNode().GetTextNode()->GetTextAttrForCharAt(
686 rPam
.GetPoint()->GetContentIndex(), RES_TXTATR_FTN
) : nullptr;
689 const SwFormatFootnote
& rFootnote
= pTextAttr
->GetFootnote();
690 if(rFootnote
.IsEndNote() == (FN_UNO_ENDNOTE
== rEntry
.nWID
))
694 const uno::Reference
< text::XFootnote
> xFootnote
=
695 SwXFootnote::CreateXFootnote(rPam
.GetDoc(),
696 &const_cast<SwFormatFootnote
&>(rFootnote
));
701 eNewState
= PropertyState_DEFAULT_VALUE
;
704 eNewState
= PropertyState_DEFAULT_VALUE
;
707 case FN_UNO_REFERENCE_MARK
:
709 std::vector
<SwTextAttr
*> marks
;
710 if (rPam
.GetPointNode().IsTextNode())
712 marks
= rPam
.GetPointNode().GetTextNode()->GetTextAttrsAt(
713 rPam
.GetPoint()->GetContentIndex(), RES_TXTATR_REFMARK
);
718 { // hmm... can only return 1 here
719 const SwFormatRefMark
& rRef
= (*marks
.begin())->GetRefMark();
720 uno::Reference
<XTextContent
> const xRef
=
721 SwXReferenceMark::CreateXReferenceMark(rPam
.GetDoc(),
722 const_cast<SwFormatRefMark
*>(&rRef
));
727 eNewState
= PropertyState_DEFAULT_VALUE
;
730 case FN_UNO_NESTED_TEXT_CONTENT
:
732 uno::Reference
<XTextContent
> const xRet(rPam
.GetPointNode().IsTextNode()
733 ? GetNestedTextContent(*rPam
.GetPointNode().GetTextNode(),
734 rPam
.GetPoint()->GetContentIndex(), false)
745 eNewState
= PropertyState_DEFAULT_VALUE
;
749 case FN_UNO_CHARFMT_SEQUENCE
:
752 SwTextNode
*const pTextNode
= rPam
.GetPointNode().GetTextNode();
753 if (&rPam
.GetPointNode() == &rPam
.GetMarkNode()
754 && pTextNode
&& pTextNode
->GetpSwpHints())
756 sal_Int32 nPaMStart
= rPam
.Start()->GetContentIndex();
757 sal_Int32 nPaMEnd
= rPam
.End()->GetContentIndex();
758 Sequence
< OUString
> aCharStyles
;
759 SwpHints
* pHints
= pTextNode
->GetpSwpHints();
760 for( size_t nAttr
= 0; nAttr
< pHints
->Count(); ++nAttr
)
762 SwTextAttr
* pAttr
= pHints
->Get( nAttr
);
763 if(pAttr
->Which() != RES_TXTATR_CHARFMT
)
765 const sal_Int32 nAttrStart
= pAttr
->GetStart();
766 const sal_Int32 nAttrEnd
= *pAttr
->GetEnd();
767 //check if the attribute touches the selection
768 if( ( nAttrEnd
> nPaMStart
&& nAttrStart
< nPaMEnd
) ||
769 ( !nAttrStart
&& !nAttrEnd
&& !nPaMStart
&& !nPaMEnd
) )
771 //check for overlapping
772 if(nAttrStart
> nPaMStart
||
775 aCharStyles
.realloc(0);
780 //now the attribute should start before or at the selection
781 //and it should end at the end of the selection or behind
782 OSL_ENSURE(nAttrStart
<= nPaMStart
&& nAttrEnd
>=nPaMEnd
,
783 "attribute overlaps or is outside");
784 //now the name of the style has to be added to the sequence
785 aCharStyles
.realloc(aCharStyles
.getLength() + 1);
786 OSL_ENSURE(pAttr
->GetCharFormat().GetCharFormat(), "no character format set");
787 aCharStyles
.getArray()[aCharStyles
.getLength() - 1] =
788 SwStyleNameMapper::GetProgName(
789 pAttr
->GetCharFormat().GetCharFormat()->GetName(), SwGetPoolIdFromName::ChrFmt
);
795 aCharStyles
.hasElements() ?
796 PropertyState_DIRECT_VALUE
: PropertyState_DEFAULT_VALUE
;
798 (*pAny
) <<= aCharStyles
;
801 eNewState
= PropertyState_DEFAULT_VALUE
;
804 case RES_TXTATR_CHARFMT
:
806 default: bDone
= false;
813 sal_Int16
IsNodeNumStart(SwPaM
const & rPam
, PropertyState
& eState
)
815 const SwTextNode
* pTextNd
= rPam
.GetPointNode().GetTextNode();
816 // correction: check, if restart value is set at the text node and use
817 // new method <SwTextNode::GetAttrListRestartValue()> to retrieve the value
818 if ( pTextNd
&& pTextNd
->GetNumRule() && pTextNd
->IsListRestart() &&
819 pTextNd
->HasAttrListRestartValue() )
821 eState
= PropertyState_DIRECT_VALUE
;
822 sal_Int16 nTmp
= sal::static_int_cast
< sal_Int16
>(pTextNd
->GetAttrListRestartValue());
825 eState
= PropertyState_DEFAULT_VALUE
;
829 void setNumberingProperty(const Any
& rValue
, SwPaM
& rPam
)
831 uno::Reference
<XIndexReplace
> xIndexReplace
;
832 if(rValue
>>= xIndexReplace
)
834 auto pSwNum
= dynamic_cast<SwXNumberingRules
*>(xIndexReplace
.get());
837 SwDoc
& rDoc
= rPam
.GetDoc();
838 if(pSwNum
->GetNumRule())
840 SwNumRule
aRule(*pSwNum
->GetNumRule());
841 const OUString
* pNewCharStyles
= pSwNum
->GetNewCharStyleNames();
842 const OUString
* pBulletFontNames
= pSwNum
->GetBulletFontNames();
843 for(sal_uInt16 i
= 0; i
< MAXLEVEL
; i
++)
845 SwNumFormat
aFormat(aRule
.Get( i
));
846 if (!pNewCharStyles
[i
].isEmpty() &&
847 !SwXNumberingRules::isInvalidStyle(pNewCharStyles
[i
]) &&
848 (!aFormat
.GetCharFormat() || pNewCharStyles
[i
] != aFormat
.GetCharFormat()->GetName()))
850 if (pNewCharStyles
[i
].isEmpty())
853 // Is something missing/wrong here?
854 // if condition is always false due to outer check!
855 aFormat
.SetCharFormat(nullptr);
860 // get CharStyle and set the rule
861 const size_t nChCount
= rDoc
.GetCharFormats()->size();
862 SwCharFormat
* pCharFormat
= nullptr;
863 for(size_t nCharFormat
= 0; nCharFormat
< nChCount
; ++nCharFormat
)
865 SwCharFormat
& rChFormat
= *((*(rDoc
.GetCharFormats()))[nCharFormat
]);
866 if(rChFormat
.GetName() == pNewCharStyles
[i
])
868 pCharFormat
= &rChFormat
;
875 SfxStyleSheetBasePool
* pPool
= rDoc
.GetDocShell()->GetStyleSheetPool();
876 SfxStyleSheetBase
* pBase
;
877 pBase
= pPool
->Find(pNewCharStyles
[i
], SfxStyleFamily::Char
);
878 // shall it really be created?
880 pBase
= &pPool
->Make(pNewCharStyles
[i
], SfxStyleFamily::Page
);
881 pCharFormat
= static_cast<SwDocStyleSheet
*>(pBase
)->GetCharFormat();
884 aFormat
.SetCharFormat(pCharFormat
);
887 //Now again for fonts
889 !pBulletFontNames
[i
].isEmpty() &&
890 !SwXNumberingRules::isInvalidStyle(pBulletFontNames
[i
]) &&
891 (!aFormat
.GetBulletFont() || aFormat
.GetBulletFont()->GetFamilyName() != pBulletFontNames
[i
])
894 const SvxFontListItem
* pFontListItem
=
895 static_cast<const SvxFontListItem
* >(rDoc
.GetDocShell()
896 ->GetItem( SID_ATTR_CHAR_FONTLIST
));
897 const FontList
* pList
= pFontListItem
->GetFontList();
899 FontMetric aFontMetric
= pList
->Get(
900 pBulletFontNames
[i
],WEIGHT_NORMAL
, ITALIC_NONE
);
901 vcl::Font
aFont(aFontMetric
);
902 aFormat
.SetBulletFont(&aFont
);
904 aRule
.Set( i
, aFormat
);
906 UnoActionContext
aAction(&rDoc
);
908 if( rPam
.GetNext() != &rPam
) // Multiple selection?
910 rDoc
.GetIDocumentUndoRedo().StartUndo( SwUndoId::START
, nullptr );
911 SwPamRanges
aRangeArr( rPam
);
912 SwPaM
aPam( *rPam
.GetPoint() );
913 for ( size_t n
= 0; n
< aRangeArr
.Count(); ++n
)
915 // no start of a new list
916 rDoc
.SetNumRule( aRangeArr
.SetPam( n
, aPam
), aRule
, false );
918 rDoc
.GetIDocumentUndoRedo().EndUndo( SwUndoId::END
, nullptr );
922 // no start of a new list
923 rDoc
.SetNumRule( rPam
, aRule
, false );
927 else if(!pSwNum
->GetCreatedNumRuleName().isEmpty())
929 UnoActionContext
aAction( &rDoc
);
930 SwNumRule
* pRule
= rDoc
.FindNumRulePtr( pSwNum
->GetCreatedNumRuleName() );
932 throw RuntimeException();
933 // no start of a new list
934 rDoc
.SetNumRule( rPam
, *pRule
, false );
940 UnoActionContext
aAction(&rDoc
);
941 SwNumRule
* pRule
= rDoc
.GetOutlineNumRule();
943 throw RuntimeException();
944 rDoc
.SetNumRule( rPam
, *pRule
, false );
948 else if ( rValue
.getValueType() == cppu::UnoType
<void>::get() )
950 rPam
.GetDoc().DelNumRules(rPam
);
954 void getNumberingProperty(SwPaM
& rPam
, PropertyState
& eState
, Any
* pAny
)
956 const SwNumRule
* pNumRule
= SwDoc::GetNumRuleAtPos( *rPam
.GetPoint() );
959 uno::Reference
< XIndexReplace
> xNum
= new SwXNumberingRules(*pNumRule
);
962 eState
= PropertyState_DIRECT_VALUE
;
965 eState
= PropertyState_DEFAULT_VALUE
;
968 void GetCurPageStyle(SwPaM
const & rPaM
, OUString
&rString
)
970 if (!rPaM
.GetPointContentNode())
971 return; // TODO: is there an easy way to get it for tables/sections?
972 SwRootFrame
* pLayout
= rPaM
.GetDoc().getIDocumentLayoutAccess().GetCurrentLayout();
973 // Consider the position inside the content node, since the node may span over multiple pages
974 // with different page styles.
975 SwContentFrame
* pFrame
= rPaM
.GetPointContentNode()->getLayoutFrame(pLayout
, rPaM
.GetPoint());
978 const SwPageFrame
* pPage
= pFrame
->FindPageFrame();
981 SwStyleNameMapper::FillProgName(pPage
->GetPageDesc()->GetName(),
982 rString
, SwGetPoolIdFromName::PageDesc
);
987 // reset special properties of the cursor
988 void resetCursorPropertyValue(const SfxItemPropertyMapEntry
& rEntry
, SwPaM
& rPam
)
990 SwDoc
& rDoc
= rPam
.GetDoc();
993 case FN_UNO_PARA_STYLE
:
995 case FN_UNO_PAGE_STYLE
:
997 case FN_UNO_NUM_START_VALUE
:
999 UnoActionContext
aAction(&rDoc
);
1001 if( rPam
.GetNext() != &rPam
) // Multiple selection?
1003 rDoc
.GetIDocumentUndoRedo().StartUndo( SwUndoId::START
, nullptr );
1004 SwPamRanges
aRangeArr( rPam
);
1005 SwPaM
aPam( *rPam
.GetPoint() );
1006 for( size_t n
= 0; n
< aRangeArr
.Count(); ++n
)
1007 rDoc
.SetNodeNumStart( *aRangeArr
.SetPam( n
, aPam
).GetPoint(), 1 );
1008 rDoc
.GetIDocumentUndoRedo().EndUndo( SwUndoId::END
, nullptr );
1011 rDoc
.SetNodeNumStart( *rPam
.GetPoint(), 0 );
1015 case FN_UNO_NUM_LEVEL
:
1017 case FN_UNO_NUM_RULES
:
1019 case FN_UNO_CHARFMT_SEQUENCE
:
1021 rDoc
.ResetAttrs(rPam
, true, { RES_TXTATR_CHARFMT
});
1027 void InsertFile(SwUnoCursor
* pUnoCursor
, const OUString
& rURL
,
1028 const uno::Sequence
< beans::PropertyValue
>& rOptions
)
1030 if (SwTextNode
const*const pTextNode
= pUnoCursor
->GetPoint()->GetNode().GetTextNode())
1032 // TODO: check meta field here too in case it ever grows a 2nd char
1033 if (pTextNode
->GetTextAttrAt(pUnoCursor
->GetPoint()->GetContentIndex(),
1034 RES_TXTATR_INPUTFIELD
, ::sw::GetTextAttrMode::Parent
))
1036 throw uno::RuntimeException("cannot insert file inside input field");
1039 if (pTextNode
->GetTextAttrAt(pUnoCursor
->GetPoint()->GetContentIndex(),
1040 RES_TXTATR_CONTENTCONTROL
, ::sw::GetTextAttrMode::Parent
))
1042 throw uno::RuntimeException("cannot insert file inside content controls");
1046 std::unique_ptr
<SfxMedium
> pMed
;
1047 SwDoc
& rDoc
= pUnoCursor
->GetDoc();
1048 SwDocShell
* pDocSh
= rDoc
.GetDocShell();
1049 utl::MediaDescriptor
aMediaDescriptor( rOptions
);
1050 OUString sFileName
= rURL
;
1051 OUString sFilterName
, sFilterOptions
, sPassword
, sBaseURL
;
1052 uno::Reference
< io::XStream
> xStream
;
1053 uno::Reference
< io::XInputStream
> xInputStream
;
1055 if( sFileName
.isEmpty() )
1056 aMediaDescriptor
[utl::MediaDescriptor::PROP_URL
] >>= sFileName
;
1057 if( sFileName
.isEmpty() )
1058 aMediaDescriptor
[utl::MediaDescriptor::PROP_FILENAME
] >>= sFileName
;
1059 aMediaDescriptor
[utl::MediaDescriptor::PROP_INPUTSTREAM
] >>= xInputStream
;
1060 aMediaDescriptor
[utl::MediaDescriptor::PROP_STREAM
] >>= xStream
;
1061 aMediaDescriptor
[utl::MediaDescriptor::PROP_INPUTSTREAM
] >>= xInputStream
;
1062 aMediaDescriptor
[utl::MediaDescriptor::PROP_FILTERNAME
] >>= sFilterName
;
1063 aMediaDescriptor
[utl::MediaDescriptor::PROP_FILTEROPTIONS
] >>= sFilterOptions
;
1064 aMediaDescriptor
[utl::MediaDescriptor::PROP_PASSWORD
] >>= sPassword
;
1065 aMediaDescriptor
[utl::MediaDescriptor::PROP_DOCUMENTBASEURL
] >>= sBaseURL
;
1066 if ( !xInputStream
.is() && xStream
.is() )
1067 xInputStream
= xStream
->getInputStream();
1069 if(!pDocSh
|| (sFileName
.isEmpty() && !xInputStream
.is()))
1072 SfxObjectFactory
& rFact
= pDocSh
->GetFactory();
1073 std::shared_ptr
<const SfxFilter
> pFilter
= rFact
.GetFilterContainer()->GetFilter4FilterName( sFilterName
);
1074 uno::Reference
< embed::XStorage
> xReadStorage
;
1075 if( xInputStream
.is() )
1077 uno::Sequence
< uno::Any
> aArgs
{ uno::Any(xInputStream
),
1078 uno::Any(embed::ElementModes::READ
) };
1081 xReadStorage
.set( ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs
),
1084 catch( const io::IOException
&) {}
1088 if( xInputStream
.is() && !xReadStorage
.is())
1090 pMed
.reset(new SfxMedium
);
1091 pMed
->setStreamToLoadFrom(xInputStream
, true );
1094 pMed
.reset(xReadStorage
.is() ?
1095 new SfxMedium(xReadStorage
, sBaseURL
) :
1096 new SfxMedium(sFileName
, StreamMode::READ
));
1097 if( !sBaseURL
.isEmpty() )
1098 pMed
->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, sBaseURL
) );
1100 SfxFilterMatcher
aMatcher( rFact
.GetFilterContainer()->GetName() );
1101 ErrCode nErr
= aMatcher
.GuessFilter(*pMed
, pFilter
, SfxFilterFlags::NONE
);
1102 if ( nErr
|| !pFilter
)
1104 pMed
->SetFilter( pFilter
);
1108 if( xInputStream
.is() && !xReadStorage
.is())
1110 pMed
.reset(new SfxMedium
);
1111 pMed
->setStreamToLoadFrom(xInputStream
, true );
1112 pMed
->SetFilter( pFilter
);
1116 if( xReadStorage
.is() )
1118 pMed
.reset(new SfxMedium(xReadStorage
, sBaseURL
));
1119 pMed
->SetFilter( pFilter
);
1122 pMed
.reset(new SfxMedium(sFileName
, StreamMode::READ
, pFilter
, nullptr));
1124 if(!sFilterOptions
.isEmpty())
1125 pMed
->GetItemSet()->Put( SfxStringItem( SID_FILE_FILTEROPTIONS
, sFilterOptions
) );
1126 if(!sBaseURL
.isEmpty())
1127 pMed
->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, sBaseURL
) );
1130 // this sourcecode is not responsible for the lifetime of the shell, SfxObjectShellLock should not be used
1131 SfxObjectShellRef
aRef( pDocSh
);
1133 pMed
->Download(); // if necessary: start the download
1134 if( !(aRef
.is() && 1 < aRef
->GetRefCount()) ) // Ref still valid?
1138 SfxItemSet
* pSet
= pMed
->GetItemSet();
1139 pSet
->Put(SfxBoolItem(FN_API_CALL
, true));
1140 if(!sPassword
.isEmpty())
1141 pSet
->Put(SfxStringItem(SID_PASSWORD
, sPassword
));
1142 Reader
*pRead
= pDocSh
->StartConvertFrom( *pMed
, pRdr
, nullptr, pUnoCursor
);
1146 UnoActionContext
aContext(&rDoc
);
1148 if(pUnoCursor
->HasMark())
1149 rDoc
.getIDocumentContentOperations().DeleteAndJoin(*pUnoCursor
);
1151 SwNodeIndex
aSave( pUnoCursor
->GetPoint()->GetNode(), -1 );
1152 sal_Int32 nContent
= pUnoCursor
->GetPoint()->GetContentIndex();
1154 ErrCode nErrno
= pRdr
->Read( *pRead
); // and paste the document
1159 pUnoCursor
->SetMark();
1160 pUnoCursor
->GetMark()->Assign( aSave
);
1162 SwContentNode
* pCntNode
= aSave
.GetNode().GetContentNode();
1165 pUnoCursor
->GetMark()->SetContent( nContent
);
1169 // insert text and scan for CR characters in order to insert
1170 // paragraph breaks at those positions by calling SplitNode
1171 bool DocInsertStringSplitCR(
1173 const SwPaM
&rNewCursor
,
1174 std::u16string_view rText
,
1175 const bool bForceExpandHints
)
1179 for (size_t i
= 0; i
< rText
.size(); ++i
)
1181 sal_Unicode
const ch(rText
[i
]);
1182 if (linguistic::IsControlChar(ch
)
1183 && ch
!= '\r' && ch
!= '\n' && ch
!= '\t')
1185 SAL_WARN("sw.uno", "DocInsertStringSplitCR: refusing to insert control character " << int(ch
));
1190 const SwInsertFlags nInsertFlags
=
1192 ? ( SwInsertFlags::FORCEHINTEXPAND
| SwInsertFlags::EMPTYEXPAND
)
1193 : SwInsertFlags::EMPTYEXPAND
;
1195 // grouping done in InsertString is intended for typing, not API calls
1196 ::sw::GroupUndoGuard
const undoGuard(rDoc
.GetIDocumentUndoRedo());
1197 SwTextNode
* const pTextNd
=
1198 rNewCursor
.GetPoint()->GetNode().GetTextNode();
1201 SAL_INFO("sw.uno", "DocInsertStringSplitCR: need a text node");
1205 sal_Int32 nStartIdx
= 0;
1206 const sal_Int32 nMaxLength
= COMPLETE_STRING
- pTextNd
->GetText().getLength();
1208 size_t nIdx
= rText
.find( '\r', nStartIdx
);
1209 if( ( nIdx
== std::u16string_view::npos
&& nMaxLength
< sal_Int32(rText
.size()) ) ||
1210 ( nIdx
!= std::u16string_view::npos
&& nMaxLength
< sal_Int32(nIdx
) ) )
1214 while (nIdx
!= std::u16string_view::npos
)
1216 OSL_ENSURE( sal_Int32(nIdx
) - nStartIdx
>= 0, "index negative!" );
1217 aText
= rText
.substr( nStartIdx
, nIdx
- nStartIdx
);
1218 if (!aText
.isEmpty() &&
1219 !rDoc
.getIDocumentContentOperations().InsertString( rNewCursor
, aText
, nInsertFlags
))
1221 OSL_FAIL( "Doc->Insert(Str) failed." );
1224 if (!rDoc
.getIDocumentContentOperations().SplitNode( *rNewCursor
.GetPoint(), false ) )
1226 OSL_FAIL( "SplitNode failed" );
1229 nStartIdx
= nIdx
+ 1;
1230 nIdx
= rText
.find( '\r', nStartIdx
);
1232 aText
= rText
.substr( nStartIdx
);
1233 if (!aText
.isEmpty() &&
1234 !rDoc
.getIDocumentContentOperations().InsertString( rNewCursor
, aText
, nInsertFlags
))
1236 OSL_FAIL( "Doc->Insert(Str) failed." );
1243 void makeRedline( SwPaM
const & rPaM
,
1244 std::u16string_view rRedlineType
,
1245 const uno::Sequence
< beans::PropertyValue
>& rRedlineProperties
)
1247 IDocumentRedlineAccess
& rRedlineAccess
= rPaM
.GetDoc().getIDocumentRedlineAccess();
1250 if ( rRedlineType
== u
"Insert" )
1251 eType
= RedlineType::Insert
;
1252 else if ( rRedlineType
== u
"Delete" )
1253 eType
= RedlineType::Delete
;
1254 else if ( rRedlineType
== u
"Format" )
1255 eType
= RedlineType::Format
;
1256 else if ( rRedlineType
== u
"TextTable" )
1257 eType
= RedlineType::Table
;
1258 else if ( rRedlineType
== u
"ParagraphFormat" )
1259 eType
= RedlineType::ParagraphFormat
;
1261 throw lang::IllegalArgumentException();
1263 //todo: what about REDLINE_FMTCOLL?
1264 std::size_t nAuthor
= 0;
1267 ::util::DateTime aStamp
;
1268 uno::Sequence
< beans::PropertyValue
> aRevertProperties
;
1269 bool bIsMoved
= false;
1270 bool bFoundComment
= false;
1271 bool bFoundStamp
= false;
1272 bool bFoundRevertProperties
= false;
1273 for (const css::beans::PropertyValue
& rProp
: rRedlineProperties
)
1275 if (rProp
.Name
== "RedlineAuthor")
1277 if( rProp
.Value
>>= sAuthor
)
1278 nAuthor
= rRedlineAccess
.InsertRedlineAuthor(sAuthor
);
1280 else if (rProp
.Name
== "RedlineComment")
1281 bFoundComment
= rProp
.Value
>>= sComment
;
1282 else if (rProp
.Name
== "RedlineDateTime")
1283 bFoundStamp
= rProp
.Value
>>= aStamp
;
1284 else if (rProp
.Name
== "RedlineRevertProperties")
1285 bFoundRevertProperties
= rProp
.Value
>>= aRevertProperties
;
1286 else if (rProp
.Name
== "RedlineMoved")
1287 rProp
.Value
>>= bIsMoved
;
1290 SwRedlineData
aRedlineData( eType
, nAuthor
);
1292 aRedlineData
.SetComment( sComment
);
1294 aRedlineData
.SetTimeStamp( DateTime( aStamp
));
1296 std::unique_ptr
<SwRedlineExtraData_FormatColl
> xRedlineExtraData
;
1298 // Read the 'Redline Revert Properties' from the parameters
1299 // Check if the value exists
1300 if ( bFoundRevertProperties
)
1303 // Make sure that paragraph format gets its own map, otherwise e.g. fill attributes are not preserved.
1304 if (eType
== RedlineType::ParagraphFormat
)
1306 nMap
= PROPERTY_MAP_PARAGRAPH
;
1307 if (!aRevertProperties
.hasElements())
1309 // to reject the paragraph style change, use standard style
1310 xRedlineExtraData
.reset(new SwRedlineExtraData_FormatColl( "", RES_POOLCOLL_STANDARD
, nullptr ));
1314 nMap
= PROPERTY_MAP_TEXTPORTION_EXTENSIONS
;
1315 SfxItemPropertySet
const& rPropSet
= *aSwMapProvider
.GetPropertySet(nMap
);
1317 // Check if there are any properties
1318 if (aRevertProperties
.hasElements())
1320 SwDoc
& rDoc
= rPaM
.GetDoc();
1322 // Build set of attributes we want to fetch
1323 WhichRangesContainer aWhichPairs
;
1324 std::vector
<SfxItemPropertyMapEntry
const*> aEntries
;
1325 std::vector
<uno::Any
> aValues
;
1326 aEntries
.reserve(aRevertProperties
.getLength());
1327 sal_uInt16 nStyleId
= USHRT_MAX
;
1328 sal_uInt16 nNumId
= USHRT_MAX
;
1329 for (const auto& rRevertProperty
: std::as_const(aRevertProperties
))
1331 const OUString
&rPropertyName
= rRevertProperty
.Name
;
1332 SfxItemPropertyMapEntry
const* pEntry
= rPropSet
.getPropertyMap().getByName(rPropertyName
);
1339 else if (pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
1343 else if (rPropertyName
== "NumberingRules")
1345 aWhichPairs
= aWhichPairs
.MergeRange(RES_PARATR_NUMRULE
, RES_PARATR_NUMRULE
);
1346 nNumId
= aEntries
.size();
1350 aWhichPairs
= aWhichPairs
.MergeRange(pEntry
->nWID
, pEntry
->nWID
);
1351 if (rPropertyName
== "ParaStyleName")
1352 nStyleId
= aEntries
.size();
1354 aEntries
.push_back(pEntry
);
1355 aValues
.push_back(rRevertProperty
.Value
);
1358 if (!aWhichPairs
.empty())
1360 sal_uInt16 nStylePoolId
= USHRT_MAX
;
1361 OUString sParaStyleName
, sUIStyle
;
1362 SfxItemSet
aItemSet(rDoc
.GetAttrPool(), std::move(aWhichPairs
));
1364 for (size_t i
= 0; i
< aEntries
.size(); ++i
)
1366 const uno::Any
&rValue
= aValues
[i
];
1369 uno::Reference
<container::XNamed
> xNumberingRules
;
1370 rValue
>>= xNumberingRules
;
1371 if (xNumberingRules
.is())
1373 aItemSet
.Put( SwNumRuleItem( xNumberingRules
->getName() ));
1374 // keep it during export
1375 SwNumRule
* pRule
= rDoc
.FindNumRulePtr(
1376 xNumberingRules
->getName());
1378 pRule
->SetUsedByRedline(true);
1383 SfxItemPropertyMapEntry
const*const pEntry
= aEntries
[i
];
1384 rPropSet
.setPropertyValue(*pEntry
, rValue
, aItemSet
);
1386 rValue
>>= sParaStyleName
;
1390 if (eType
== RedlineType::ParagraphFormat
&& sParaStyleName
.isEmpty())
1391 nStylePoolId
= RES_POOLCOLL_STANDARD
;
1393 // tdf#149747 Get UI style name from programmatic style name
1394 SwStyleNameMapper::FillUIName(sParaStyleName
, sUIStyle
,
1395 SwGetPoolIdFromName::TxtColl
);
1396 xRedlineExtraData
.reset(new SwRedlineExtraData_FormatColl(
1397 sUIStyle
.isEmpty() ? sParaStyleName
: sUIStyle
, nStylePoolId
, &aItemSet
));
1399 else if (eType
== RedlineType::ParagraphFormat
)
1400 xRedlineExtraData
.reset(new SwRedlineExtraData_FormatColl( "", RES_POOLCOLL_STANDARD
, nullptr ));
1404 SwRangeRedline
* pRedline
= new SwRangeRedline( aRedlineData
, rPaM
);
1406 // set IsMoved bit of the redline to show and handle moved text
1408 pRedline
->SetMoved();
1410 RedlineFlags nPrevMode
= rRedlineAccess
.GetRedlineFlags( );
1411 // xRedlineExtraData is copied here
1412 pRedline
->SetExtraData( xRedlineExtraData
.get() );
1414 rRedlineAccess
.SetRedlineFlags_intern(RedlineFlags::On
);
1415 auto const result(rRedlineAccess
.AppendRedline(pRedline
, false));
1416 rRedlineAccess
.SetRedlineFlags_intern( nPrevMode
);
1417 if (IDocumentRedlineAccess::AppendResult::IGNORED
== result
)
1418 throw lang::IllegalArgumentException();
1421 void makeTableRowRedline( SwTableLine
& rTableLine
,
1422 std::u16string_view rRedlineType
,
1423 const uno::Sequence
< beans::PropertyValue
>& rRedlineProperties
)
1425 SwDoc
* pDoc
= rTableLine
.GetFrameFormat()->GetDoc();
1426 IDocumentRedlineAccess
* pRedlineAccess
= &pDoc
->getIDocumentRedlineAccess();
1429 if ( rRedlineType
== u
"TableRowInsert" )
1431 eType
= RedlineType::TableRowInsert
;
1433 else if ( rRedlineType
== u
"TableRowDelete" )
1435 eType
= RedlineType::TableRowDelete
;
1439 throw lang::IllegalArgumentException();
1442 // set table row property "HasTextChangesOnly" to false
1443 // to handle tracked deletion or insertion of the table row on the UI
1444 const SvxPrintItem
*pHasTextChangesOnlyProp
=
1445 rTableLine
.GetFrameFormat()->GetAttrSet().GetItem
<SvxPrintItem
>(RES_PRINT
);
1446 if ( !pHasTextChangesOnlyProp
|| pHasTextChangesOnlyProp
->GetValue() )
1448 SvxPrintItem
aSetTracking(RES_PRINT
, false);
1449 SwNodeIndex
aInsPos( *(rTableLine
.GetTabBoxes()[0]->GetSttNd()), 1 );
1450 // as a workaround for the rows without text content,
1451 // add a redline with invisible text CH_TXT_TRACKED_DUMMY_CHAR
1452 if ( rTableLine
.IsEmpty() )
1454 SwPaM
aPaM(aInsPos
);
1455 pDoc
->getIDocumentContentOperations().InsertString( aPaM
,
1456 OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR
) );
1458 aPaM
.GetMark()->SetContent(0);
1459 makeRedline(aPaM
, RedlineType::TableRowInsert
== eType
1461 : u
"Delete", rRedlineProperties
);
1463 SwCursor
aCursor( SwPosition(aInsPos
), nullptr );
1464 pDoc
->SetRowNotTracked( aCursor
, aSetTracking
);
1467 comphelper::SequenceAsHashMap
aPropMap( rRedlineProperties
);
1468 std::size_t nAuthor
= 0;
1470 if( aPropMap
.getValue("RedlineAuthor") >>= sAuthor
)
1471 nAuthor
= pRedlineAccess
->InsertRedlineAuthor(sAuthor
);
1474 SwRedlineData
aRedlineData( eType
, nAuthor
);
1475 if( aPropMap
.getValue("RedlineComment") >>= sComment
)
1476 aRedlineData
.SetComment( sComment
);
1478 ::util::DateTime aStamp
;
1479 if( aPropMap
.getValue("RedlineDateTime") >>= aStamp
)
1481 aRedlineData
.SetTimeStamp(
1482 DateTime( Date( aStamp
.Day
, aStamp
.Month
, aStamp
.Year
), tools::Time( aStamp
.Hours
, aStamp
.Minutes
, aStamp
.Seconds
) ) );
1485 SwTableRowRedline
* pRedline
= new SwTableRowRedline( aRedlineData
, rTableLine
);
1486 RedlineFlags nPrevMode
= pRedlineAccess
->GetRedlineFlags( );
1487 pRedline
->SetExtraData( nullptr );
1489 pRedlineAccess
->SetRedlineFlags_intern(RedlineFlags::On
);
1490 bool bRet
= pRedlineAccess
->AppendTableRowRedline( pRedline
);
1491 pRedlineAccess
->SetRedlineFlags_intern( nPrevMode
);
1493 throw lang::IllegalArgumentException();
1496 void makeTableCellRedline( SwTableBox
& rTableBox
,
1497 std::u16string_view rRedlineType
,
1498 const uno::Sequence
< beans::PropertyValue
>& rRedlineProperties
)
1500 SwDoc
* pDoc
= rTableBox
.GetFrameFormat()->GetDoc();
1501 IDocumentRedlineAccess
* pRedlineAccess
= &pDoc
->getIDocumentRedlineAccess();
1504 if ( rRedlineType
== u
"TableCellInsert" )
1506 eType
= RedlineType::TableCellInsert
;
1508 else if ( rRedlineType
== u
"TableCellDelete" )
1510 eType
= RedlineType::TableCellDelete
;
1514 throw lang::IllegalArgumentException();
1517 // set table row property "HasTextChangesOnly" to false
1518 // to handle tracked deletion or insertion of the table row on the UI
1519 const SvxPrintItem
*pHasTextChangesOnlyProp
=
1520 rTableBox
.GetFrameFormat()->GetAttrSet().GetItem
<SvxPrintItem
>(RES_PRINT
);
1521 if ( !pHasTextChangesOnlyProp
|| pHasTextChangesOnlyProp
->GetValue() )
1523 SvxPrintItem
aSetTracking(RES_PRINT
, false);
1524 SwNodeIndex
aInsPos( *rTableBox
.GetSttNd(), 1 );
1525 // as a workaround for the cells without text content,
1526 // add a redline with invisible text CH_TXT_TRACKED_DUMMY_CHAR
1527 if ( rTableBox
.IsEmpty() )
1529 SwPaM
aPaM(aInsPos
);
1530 pDoc
->getIDocumentContentOperations().InsertString( aPaM
,
1531 OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR
) );
1533 aPaM
.GetMark()->SetContent(0);
1534 makeRedline(aPaM
, RedlineType::TableCellInsert
== eType
1536 : u
"Delete", rRedlineProperties
);
1538 SwCursor
aCursor( SwPosition(aInsPos
), nullptr );
1539 pDoc
->SetBoxAttr( aCursor
, aSetTracking
);
1542 comphelper::SequenceAsHashMap
aPropMap( rRedlineProperties
);
1543 std::size_t nAuthor
= 0;
1545 if( aPropMap
.getValue("RedlineAuthor") >>= sAuthor
)
1546 nAuthor
= pRedlineAccess
->InsertRedlineAuthor(sAuthor
);
1549 SwRedlineData
aRedlineData( eType
, nAuthor
);
1550 if( aPropMap
.getValue("RedlineComment") >>= sComment
)
1551 aRedlineData
.SetComment( sComment
);
1553 ::util::DateTime aStamp
;
1554 if( aPropMap
.getValue("RedlineDateTime") >>= aStamp
)
1556 aRedlineData
.SetTimeStamp(
1557 DateTime( Date( aStamp
.Day
, aStamp
.Month
, aStamp
.Year
), tools::Time( aStamp
.Hours
, aStamp
.Minutes
, aStamp
.Seconds
) ) );
1560 SwTableCellRedline
* pRedline
= new SwTableCellRedline( aRedlineData
, rTableBox
);
1561 RedlineFlags nPrevMode
= pRedlineAccess
->GetRedlineFlags( );
1562 pRedline
->SetExtraData( nullptr );
1564 pRedlineAccess
->SetRedlineFlags_intern(RedlineFlags::On
);
1565 bool bRet
= pRedlineAccess
->AppendTableCellRedline( pRedline
);
1566 pRedlineAccess
->SetRedlineFlags_intern( nPrevMode
);
1568 throw lang::IllegalArgumentException();
1571 void SwAnyMapHelper::SetValue( sal_uInt16 nWhichId
, sal_uInt16 nMemberId
, const uno::Any
& rAny
)
1573 sal_uInt32 nKey
= (nWhichId
<< 16) + nMemberId
;
1577 bool SwAnyMapHelper::FillValue( sal_uInt16 nWhichId
, sal_uInt16 nMemberId
, const uno::Any
*& pAny
)
1580 sal_uInt32 nKey
= (nWhichId
<< 16) + nMemberId
;
1581 auto aIt
= m_Map
.find( nKey
);
1582 if (aIt
!= m_Map
.end())
1584 pAny
= & aIt
->second
;
1590 }//namespace SwUnoCursorHelper
1592 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */