xref: /core/sw/source/uibase/shells/textsh1.cxx (revision 0881a030e11e28f289eda41dbdebb7f7fcf807d4)
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 <sal/config.h>
21 
22 #include <config_features.h>
23 
24 #include <com/sun/star/i18n/WordType.hpp>
25 #include <com/sun/star/frame/XStorable.hpp>
26 #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
27 #include <com/sun/star/linguistic2/XThesaurus.hpp>
28 #include <com/sun/star/text/XContentControlsSupplier.hpp>
29 
30 #include <hintids.hxx>
31 #include <cmdid.h>
32 #include <comphelper/lok.hxx>
33 #include <comphelper/propertysequence.hxx>
34 
35 #include <i18nutil/unicode.hxx>
36 #include <i18nlangtag/languagetag.hxx>
37 #include <svtools/langtab.hxx>
38 #include <svl/numformat.hxx>
39 #include <svl/slstitm.hxx>
40 #include <svl/stritem.hxx>
41 #include <sfx2/htmlmode.hxx>
42 #include <svl/whiter.hxx>
43 #include <sfx2/bindings.hxx>
44 #include <sfx2/namedcolor.hxx>
45 #include <sfx2/viewfrm.hxx>
46 #include <vcl/unohelp2.hxx>
47 #include <vcl/weld.hxx>
48 #include <sfx2/lokhelper.hxx>
49 #include <sfx2/request.hxx>
50 #include <svl/eitem.hxx>
51 #include <editeng/lrspitem.hxx>
52 #include <editeng/colritem.hxx>
53 #include <editeng/tstpitem.hxx>
54 #include <editeng/brushitem.hxx>
55 #include <editeng/svxacorr.hxx>
56 #include <svl/cjkoptions.hxx>
57 #include <svl/ctloptions.hxx>
58 #include <IDocumentDrawModelAccess.hxx>
59 #include <IDocumentSettingAccess.hxx>
60 #include <charfmt.hxx>
61 #include <svx/SmartTagItem.hxx>
62 #include <svx/xflgrit.hxx>
63 #include <svx/xflhtit.hxx>
64 #include <svx/xfillit0.hxx>
65 #include <fmtinfmt.hxx>
66 #include <wrtsh.hxx>
67 #include <wview.hxx>
68 #include <swmodule.hxx>
69 #include <viewopt.hxx>
70 #include <uitool.hxx>
71 #include <textsh.hxx>
72 #include <IMark.hxx>
73 #include <swdtflvr.hxx>
74 #include <swundo.hxx>
75 #include <reffld.hxx>
76 #include <textcontentcontrol.hxx>
77 #include <txatbase.hxx>
78 #include <docsh.hxx>
79 #include <inputwin.hxx>
80 #include <chrdlgmodes.hxx>
81 #include <fmtcol.hxx>
82 #include <cellatr.hxx>
83 #include <edtwin.hxx>
84 #include <fldmgr.hxx>
85 #include <ndtxt.hxx>
86 #include <strings.hrc>
87 #include <paratr.hxx>
88 #include <vcl/svapp.hxx>
89 #include <sfx2/app.hxx>
90 #include <breakit.hxx>
91 #include <SwSmartTagMgr.hxx>
92 #include <editeng/acorrcfg.hxx>
93 #include <swabstdlg.hxx>
94 #include <sfx2/sfxdlg.hxx>
95 #include <com/sun/star/container/XNameContainer.hpp>
96 #include <com/sun/star/beans/XPropertySet.hpp>
97 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
98 #include <com/sun/star/uno/Any.hxx>
99 #include <com/sun/star/linguistic2/ProofreadingResult.hpp>
100 #include <com/sun/star/linguistic2/XDictionary.hpp>
101 #include <com/sun/star/linguistic2/XSpellAlternatives.hpp>
102 #include <editeng/unolingu.hxx>
103 #include <doc.hxx>
104 #include <drawdoc.hxx>
105 #include <view.hxx>
106 #include <pam.hxx>
107 #include <sfx2/objface.hxx>
108 #include <langhelper.hxx>
109 #include <uiitems.hxx>
110 #include <svx/nbdtmgfact.hxx>
111 #include <svx/nbdtmg.hxx>
112 #include <SwRewriter.hxx>
113 #include <svx/drawitem.hxx>
114 #include <numrule.hxx>
115 #include <memory>
116 #include <xmloff/odffields.hxx>
117 #include <bookmark.hxx>
118 #include <linguistic/misc.hxx>
119 #include <comphelper/sequenceashashmap.hxx>
120 #include <comphelper/scopeguard.hxx>
121 #include <authfld.hxx>
122 #include <config_wasm_strip.h>
123 #if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
124 #include <officecfg/Office/Common.hxx>
125 #include <officecfg/Office/Linguistic.hxx>
126 #include <svl/visitem.hxx>
127 #include <translatelangselect.hxx>
128 #endif // HAVE_FEATURE_CURL && ENABLE_WASM_STRIP_EXTRA
129 #include <translatehelper.hxx>
130 #include <IDocumentContentOperations.hxx>
131 #include <IDocumentUndoRedo.hxx>
132 #include <fmtcntnt.hxx>
133 #include <fmtrfmrk.hxx>
134 #include <cntfrm.hxx>
135 #include <flyfrm.hxx>
136 #include <unoprnms.hxx>
137 #include <boost/property_tree/json_parser.hpp>
138 #include <formatcontentcontrol.hxx>
139 #include <rtl/uri.hxx>
140 #include <unotxdoc.hxx>
141 #include <expfld.hxx>
142 #include <sax/tools/converter.hxx>
143 
144 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
145 #include <com/sun/star/chart2/XInternalDataProvider.hpp>
146 #include <com/sun/star/chart2/XChartDocument.hpp>
147 #include <com/sun/star/chart/XChartDocument.hpp>
148 #include <com/sun/star/chart/XChartDataArray.hpp>
149 #include <com/sun/star/chart2/XTitle.hpp>
150 #include <com/sun/star/chart2/XTitled.hpp>
151 #include <com/sun/star/chart/ChartDataRowSource.hpp>
152 #include <com/sun/star/util/XModifiable.hpp>
153 
154 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
155 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
156 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
157 #include <com/sun/star/util/XCloneable.hpp>
158 
159 #include <com/sun/star/util/SearchAlgorithms2.hpp>
160 #include <com/sun/star/document/XDocumentProperties2.hpp>
161 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
162 
163 #include <com/sun/star/beans/XPropertyAccess.hpp>
164 #include <com/sun/star/beans/PropertyAttribute.hpp>
165 
166 using namespace ::com::sun::star;
167 using namespace com::sun::star::beans;
168 using namespace ::com::sun::star::container;
169 using namespace com::sun::star::style;
170 using namespace svx::sidebar;
171 
172 static void sw_CharDialogResult(const SfxItemSet* pSet, SwWrtShell &rWrtSh, std::shared_ptr<SfxItemSet> const & pCoreSet, bool bSel,
173                                 bool bSelectionPut, bool bApplyToParagraph, SfxRequest *pReq);
174 
sw_CharDialog(SwWrtShell & rWrtSh,bool bUseDialog,bool bApplyToParagraph,sal_uInt16 nSlot,const SfxItemSet * pArgs,SfxRequest * pReq)175 static void sw_CharDialog(SwWrtShell& rWrtSh, bool bUseDialog, bool bApplyToParagraph,
176                           sal_uInt16 nSlot, const SfxItemSet* pArgs, SfxRequest* pReq)
177 {
178     FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &rWrtSh.GetView()) != nullptr );
179     SwModule::get()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast<sal_uInt16>(eMetric)));
180     auto pCoreSet = std::make_shared<SfxItemSetFixed<
181             RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
182             RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
183             RES_BACKGROUND, RES_SHADOW,
184             SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
185             SID_HTML_MODE, SID_HTML_MODE,
186             SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, SID_ATTR_CHAR_WIDTH_FIT_TO_LINE,
187             FN_PARAM_SELECTION, FN_PARAM_SELECTION>> ( rWrtSh.GetView().GetPool() );
188     rWrtSh.GetCurAttr(*pCoreSet);
189 
190     bool bSel = rWrtSh.HasSelection();
191     bool bSelectionPut = false;
192     if(bSel || rWrtSh.IsInWord())
193     {
194         if(!bSel)
195         {
196             rWrtSh.StartAction();
197             rWrtSh.Push();
198             if(!rWrtSh.SelectTextAttr( RES_TXTATR_INETFMT ))
199                 rWrtSh.SelWrd();
200         }
201         pCoreSet->Put(SfxStringItem(FN_PARAM_SELECTION, rWrtSh.GetSelText()));
202         bSelectionPut = true;
203         if(!bSel)
204         {
205             rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
206             rWrtSh.EndAction();
207         }
208     }
209     pCoreSet->Put(SfxUInt16Item(SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, rWrtSh.GetScalingOfSelectedText()));
210 
211     ::ConvertAttrCharToGen(*pCoreSet);
212 
213     // Setting the BoxInfo
214     ::PrepareBoxInfo(*pCoreSet, rWrtSh);
215 
216     pCoreSet->Put(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(rWrtSh.GetView().GetDocShell())));
217     VclPtr<SfxAbstractTabDialog> pDlg;
218     if ( bUseDialog && GetActiveView() )
219     {
220         SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
221         pDlg.reset(pFact->CreateSwCharDlg(rWrtSh.GetView().GetFrameWeld(), rWrtSh.GetView(), *pCoreSet, SwCharDlgMode::Std));
222 
223         if (nSlot == SID_CHAR_DLG_EFFECT)
224             pDlg->SetCurPageId(u"fonteffects"_ustr);
225         else if (nSlot == SID_CHAR_DLG_POSITION)
226             pDlg->SetCurPageId(u"position"_ustr);
227         else if (nSlot == SID_CHAR_DLG_FOR_PARAGRAPH)
228             pDlg->SetCurPageId(u"font"_ustr);
229         else if (pReq)
230         {
231             const SfxStringItem* pItem = (*pReq).GetArg<SfxStringItem>(FN_PARAM_1);
232             if (pItem)
233                 pDlg->SetCurPageId(pItem->GetValue());
234         }
235     }
236 
237     if (bUseDialog)
238     {
239         std::shared_ptr<SfxRequest> pRequest;
240         if (pReq)
241         {
242             pRequest = std::make_shared<SfxRequest>(*pReq);
243             pReq->Ignore(); // the 'old' request is not relevant any more
244         }
245         pDlg->StartExecuteAsync([pDlg, &rWrtSh, pCoreSet=std::move(pCoreSet), bSel,
246                                  bSelectionPut, bApplyToParagraph,
247                                  pRequest=std::move(pRequest)](sal_Int32 nResult){
248             if (nResult == RET_OK)
249             {
250                 sw_CharDialogResult(pDlg->GetOutputItemSet(), rWrtSh, pCoreSet, bSel, bSelectionPut,
251                                     bApplyToParagraph, pRequest.get());
252             }
253             pDlg->disposeOnce();
254         });
255     }
256     else if (pArgs)
257     {
258         sw_CharDialogResult(pArgs, rWrtSh, pCoreSet, bSel, bSelectionPut, bApplyToParagraph, pReq);
259     }
260 }
261 
sw_CharDialogResult(const SfxItemSet * pSet,SwWrtShell & rWrtSh,std::shared_ptr<SfxItemSet> const & pCoreSet,bool bSel,bool bSelectionPut,bool bApplyToParagraph,SfxRequest * pReq)262 static void sw_CharDialogResult(const SfxItemSet* pSet, SwWrtShell& rWrtSh, std::shared_ptr<SfxItemSet> const & pCoreSet, bool bSel,
263                                 bool bSelectionPut, bool bApplyToParagraph, SfxRequest* pReq)
264 {
265     SfxItemSet aTmpSet( *pSet );
266     ::ConvertAttrGenToChar(aTmpSet, *pCoreSet);
267 
268     const bool bWasLocked = rWrtSh.IsViewLocked();
269     if (bApplyToParagraph)
270     {
271         rWrtSh.StartAction();
272         rWrtSh.LockView(true);
273         rWrtSh.Push();
274         SwLangHelper::SelectCurrentPara(rWrtSh);
275     }
276 
277     const SfxStringItem* pSelectionItem;
278     bool bInsert = false;
279     sal_Int32 nInsert = 0;
280 
281     // The old item is for unknown reasons back in the set again.
282     if( !bSelectionPut && (pSelectionItem = aTmpSet.GetItemIfSet(FN_PARAM_SELECTION, false)) )
283     {
284         const OUString& sInsert = pSelectionItem->GetValue();
285         bInsert = !sInsert.isEmpty();
286         if(bInsert)
287         {
288             nInsert = sInsert.getLength();
289             rWrtSh.StartAction();
290             rWrtSh.Insert( sInsert );
291             rWrtSh.SetMark();
292             rWrtSh.ExtendSelection(false, sInsert.getLength());
293             SfxRequest aReq(rWrtSh.GetView().GetViewFrame(), FN_INSERT_STRING);
294             aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, sInsert ) );
295             aReq.Done();
296             SfxRequest aReq1(rWrtSh.GetView().GetViewFrame(), FN_CHAR_LEFT);
297             aReq1.AppendItem( SfxInt32Item(FN_PARAM_MOVE_COUNT, nInsert) );
298             aReq1.AppendItem( SfxBoolItem(FN_PARAM_MOVE_SELECTION, true) );
299             aReq1.Done();
300         }
301     }
302     aTmpSet.ClearItem(FN_PARAM_SELECTION);
303 
304     SwTextFormatColl* pColl = rWrtSh.GetCurTextFormatColl();
305     if(bSel && rWrtSh.IsSelFullPara() && pColl && pColl->IsAutoUpdateOnDirectFormat())
306     {
307         rWrtSh.AutoUpdatePara(pColl, aTmpSet);
308     }
309     else
310         rWrtSh.SetAttrSet( aTmpSet );
311     if (pReq)
312         pReq->Done(aTmpSet);
313     if(bInsert)
314     {
315         SfxRequest aReq1(rWrtSh.GetView().GetViewFrame(), FN_CHAR_RIGHT);
316         aReq1.AppendItem( SfxInt32Item(FN_PARAM_MOVE_COUNT, nInsert) );
317         aReq1.AppendItem( SfxBoolItem(FN_PARAM_MOVE_SELECTION, false) );
318         aReq1.Done();
319         rWrtSh.SwapPam();
320         rWrtSh.ClearMark();
321         rWrtSh.DontExpandFormat();
322         rWrtSh.EndAction();
323     }
324 
325     if (bApplyToParagraph)
326     {
327         rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
328         rWrtSh.LockView(bWasLocked);
329         rWrtSh.EndAction();
330     }
331 }
332 
333 
sw_ParagraphDialogResult(SfxItemSet * pSet,SwWrtShell & rWrtSh,SfxRequest & rReq,SwPaM * pPaM)334 static void sw_ParagraphDialogResult(SfxItemSet* pSet, SwWrtShell &rWrtSh, SfxRequest& rReq, SwPaM* pPaM)
335 {
336     if (!pSet)
337         return;
338 
339     rReq.Done( *pSet );
340     ::SfxToSwPageDescAttr( rWrtSh, *pSet );
341     // #i56253#
342     // enclose all undos.
343     // Thus, check conditions, if actions will be performed.
344     const bool bUndoNeeded( pSet->Count() ||
345             SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART) ||
346             SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART_AT) );
347     if ( bUndoNeeded )
348     {
349         rWrtSh.StartUndo( SwUndoId::INSATTR );
350     }
351     if( pSet->Count() )
352     {
353         rWrtSh.StartAction();
354         if ( const SfxStringItem* pDropTextItem = pSet->GetItemIfSet(FN_DROP_TEXT, false) )
355         {
356             if ( !pDropTextItem->GetValue().isEmpty() )
357                 rWrtSh.ReplaceDropText(pDropTextItem->GetValue(), pPaM);
358         }
359         rWrtSh.SetAttrSet(*pSet, SetAttrMode::DEFAULT, pPaM);
360         rWrtSh.EndAction();
361         SwTextFormatColl* pColl = rWrtSh.GetPaMTextFormatColl(pPaM);
362         if(pColl && pColl->IsAutoUpdateOnDirectFormat())
363         {
364             rWrtSh.AutoUpdatePara(pColl, *pSet, pPaM);
365         }
366     }
367 
368     if( SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART) )
369     {
370         //SetNumRuleStart(true) restarts the numbering at the value
371         //that is defined at the starting point of the numbering level
372         //otherwise the SetNodeNumStart() value determines the start
373         //if it's set to something different than USHRT_MAX
374 
375         bool bStart = static_cast<const SfxBoolItem&>(pSet->Get(FN_NUMBER_NEWSTART)).GetValue();
376 
377         // Default value for restart value has to be USHRT_MAX
378         // in order to indicate that the restart value of the list
379         // style has to be used on restart.
380         sal_uInt16 nNumStart = USHRT_MAX;
381         if( SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART_AT) )
382         {
383             nNumStart = pSet->Get(FN_NUMBER_NEWSTART_AT).GetValue();
384         }
385         rWrtSh.SetNumRuleStart(bStart, pPaM);
386         rWrtSh.SetNodeNumStart(nNumStart);
387     }
388     else if( SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART_AT) )
389     {
390         rWrtSh.SetNodeNumStart(pSet->Get(FN_NUMBER_NEWSTART_AT).GetValue());
391         rWrtSh.SetNumRuleStart(false, pPaM);
392     }
393     // #i56253#
394     if ( bUndoNeeded )
395     {
396         rWrtSh.EndUndo( SwUndoId::INSATTR );
397     }
398 }
399 
400 namespace {
401 
InsertBreak(SwWrtShell & rWrtSh,sal_uInt16 nKind,::std::optional<sal_uInt16> oPageNumber,const UIName & rTemplateName,std::optional<SwLineBreakClear> oClear)402 void InsertBreak(SwWrtShell& rWrtSh,
403                  sal_uInt16 nKind,
404                  ::std::optional<sal_uInt16> oPageNumber,
405                  const UIName& rTemplateName, std::optional<SwLineBreakClear> oClear)
406 {
407     switch ( nKind )
408     {
409         case 1 :
410             rWrtSh.InsertLineBreak(oClear);
411             break;
412         case 2 :
413             rWrtSh.InsertColumnBreak(); break;
414         case 3 :
415         {
416             rWrtSh.StartAllAction();
417             if( !rTemplateName.isEmpty() )
418                 rWrtSh.InsertPageBreak( &rTemplateName, oPageNumber );
419             else
420                 rWrtSh.InsertPageBreak();
421             rWrtSh.EndAllAction();
422         }
423     }
424 }
425 
GetLocalURL(const SwWrtShell & rSh)426 OUString GetLocalURL(const SwWrtShell& rSh)
427 {
428     SwField* pField = rSh.GetCurField();
429     if (!pField)
430     {
431         return OUString();
432     }
433 
434     if (pField->GetTyp()->Which() != SwFieldIds::TableOfAuthorities)
435     {
436         return OUString();
437     }
438 
439     const auto& rAuthorityField = *static_cast<const SwAuthorityField*>(pField);
440     SwAuthEntry* pAuthEntry = rAuthorityField.GetAuthEntry();
441     if (!pAuthEntry)
442     {
443         return OUString();
444     }
445 
446     const OUString& rLocalURL = pAuthEntry->GetAuthorField(AUTH_FIELD_LOCAL_URL);
447     return rLocalURL;
448 }
449 
UpdateSections(const SfxRequest & rReq,SwWrtShell & rWrtSh)450 void UpdateSections(const SfxRequest& rReq, SwWrtShell& rWrtSh)
451 {
452     OUString aSectionNamePrefix;
453     const SfxStringItem* pSectionNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
454     if (pSectionNamePrefix)
455     {
456         aSectionNamePrefix = pSectionNamePrefix->GetValue();
457     }
458 
459     uno::Sequence<beans::PropertyValues> aSections;
460     const SfxUnoAnyItem* pSections = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_2);
461     if (pSections)
462     {
463         pSections->GetValue() >>= aSections;
464     }
465 
466     rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_SECTIONS, nullptr);
467     rWrtSh.StartAction();
468 
469     SwDoc* pDoc = rWrtSh.GetDoc();
470     sal_Int32 nSectionIndex = 0;
471     const SwSectionFormats& rFormats = pDoc->GetSections();
472     IDocumentContentOperations& rIDCO = pDoc->getIDocumentContentOperations();
473     for (size_t i = 0; i < rFormats.size(); ++i)
474     {
475         const SwSectionFormat* pFormat = rFormats[i];
476         if (!pFormat->GetName().toString().startsWith(aSectionNamePrefix))
477         {
478             continue;
479         }
480 
481         if (nSectionIndex >= aSections.getLength())
482         {
483             break;
484         }
485 
486         comphelper::SequenceAsHashMap aMap(aSections[nSectionIndex++]);
487         UIName aSectionName( aMap[u"RegionName"_ustr].get<OUString>() );
488         if (aSectionName != pFormat->GetName())
489         {
490             const_cast<SwSectionFormat*>(pFormat)->SetFormatName(aSectionName, /*bBroadcast=*/true);
491             SwSectionData aSectionData(*pFormat->GetSection());
492             aSectionData.SetSectionName(aSectionName);
493             pDoc->UpdateSection(i, aSectionData);
494         }
495 
496         const SwFormatContent& rContent = pFormat->GetContent();
497         const SwNodeIndex* pContentNodeIndex = rContent.GetContentIdx();
498         if (pContentNodeIndex)
499         {
500             SwPaM aSectionStart(SwPosition{*pContentNodeIndex});
501             aSectionStart.Move(fnMoveForward, GoInContent);
502             SwPaM* pCursorPos = rWrtSh.GetCursor();
503             *pCursorPos = aSectionStart;
504             rWrtSh.EndOfSection(/*bSelect=*/true);
505             rIDCO.DeleteAndJoin(*pCursorPos);
506             rWrtSh.EndSelect();
507 
508             OUString aSectionText = aMap[u"Content"_ustr].get<OUString>();
509             SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aSectionText.toUtf8());
510         }
511     }
512 
513     rWrtSh.EndAction();
514     rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_SECTIONS, nullptr);
515 }
516 
DeleteSections(const SfxRequest & rReq,SwWrtShell & rWrtSh)517 void DeleteSections(const SfxRequest& rReq, SwWrtShell& rWrtSh)
518 {
519     OUString aSectionNamePrefix;
520     const SfxStringItem* pSectionNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
521     if (pSectionNamePrefix)
522     {
523         aSectionNamePrefix = pSectionNamePrefix->GetValue();
524     }
525 
526     rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_SECTIONS, nullptr);
527     rWrtSh.StartAction();
528     comphelper::ScopeGuard g(
529         [&rWrtSh]
530         {
531             rWrtSh.EndAction();
532             rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_SECTIONS, nullptr);
533         });
534 
535     SwDoc* pDoc = rWrtSh.GetDoc();
536     std::vector<SwSectionFormat*> aRemovals;
537     for (SwSectionFormat* pFormat : pDoc->GetSections())
538         if (aSectionNamePrefix.isEmpty() || pFormat->GetName().toString().startsWith(aSectionNamePrefix))
539             aRemovals.push_back(pFormat);
540 
541     for (const auto& pFormat : aRemovals)
542     {
543         // Just delete the format, not the content of the section.
544         pDoc->DelSectionFormat(pFormat);
545     }
546 }
547 
DeleteContentControl(const SwWrtShell & rWrtSh)548 void DeleteContentControl( const SwWrtShell& rWrtSh )
549 {
550     SwTextContentControl* pTextContentControl = rWrtSh.CursorInsideContentControl();
551     if (pTextContentControl) {
552         const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl();
553         const std::shared_ptr<SwContentControl>& pContentControl = rFormatContentControl.GetContentControl();
554         pContentControl->SetReadWrite(true);
555         pTextContentControl->Delete(true);
556     }
557 }
558 
559 
UpdateBookmarks(const SfxRequest & rReq,SwWrtShell & rWrtSh)560 void UpdateBookmarks(const SfxRequest& rReq, SwWrtShell& rWrtSh)
561 {
562     if (rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
563     {
564         return;
565     }
566 
567     OUString aBookmarkNamePrefix;
568     const SfxStringItem* pBookmarkNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
569     if (pBookmarkNamePrefix)
570     {
571         aBookmarkNamePrefix = pBookmarkNamePrefix->GetValue();
572     }
573 
574     uno::Sequence<beans::PropertyValues> aBookmarks;
575     const SfxUnoAnyItem* pBookmarks = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_2);
576     if (pBookmarks)
577     {
578         pBookmarks->GetValue() >>= aBookmarks;
579     }
580 
581     rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_BOOKMARKS, nullptr);
582     rWrtSh.StartAction();
583 
584     IDocumentMarkAccess& rIDMA = *rWrtSh.GetDoc()->getIDocumentMarkAccess();
585     sal_Int32 nBookmarkIndex = 0;
586     bool bSortMarks = false;
587     for (auto it = rIDMA.getBookmarksBegin(); it != rIDMA.getBookmarksEnd(); ++it)
588     {
589         sw::mark::Bookmark* pMark = *it;
590         assert(pMark);
591         if (!pMark->GetName().toString().startsWith(aBookmarkNamePrefix))
592         {
593             continue;
594         }
595 
596         if (aBookmarks.getLength() <= nBookmarkIndex)
597         {
598             continue;
599         }
600 
601         comphelper::SequenceAsHashMap aMap(aBookmarks[nBookmarkIndex++]);
602         if (aMap[u"Bookmark"_ustr].get<OUString>() != pMark->GetName())
603         {
604             rIDMA.renameMark(pMark, SwMarkName(aMap[u"Bookmark"_ustr].get<OUString>()));
605         }
606 
607         OUString aBookmarkText = aMap[u"BookmarkText"_ustr].get<OUString>();
608 
609         // Insert markers to remember where the paste positions are.
610         SwPaM aMarkers(pMark->GetMarkEnd());
611         IDocumentContentOperations& rIDCO = rWrtSh.GetDoc()->getIDocumentContentOperations();
612         bool bSuccess = rIDCO.InsertString(aMarkers, u"XY"_ustr);
613         if (bSuccess)
614         {
615             SwPaM aPasteEnd(pMark->GetMarkEnd());
616             aPasteEnd.Move(fnMoveForward, GoInContent);
617 
618             // Paste HTML content.
619             SwPaM* pCursorPos = rWrtSh.GetCursor();
620             *pCursorPos = aPasteEnd;
621             SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aBookmarkText.toUtf8());
622 
623             // Update the bookmark to point to the new content.
624             SwPaM aPasteStart(pMark->GetMarkEnd());
625             aPasteStart.Move(fnMoveForward, GoInContent);
626             SwPaM aStartMarker(pMark->GetMarkStart(), *aPasteStart.GetPoint());
627             SwPaM aEndMarker(*aPasteEnd.GetPoint(), *aPasteEnd.GetPoint());
628             aEndMarker.GetMark()->AdjustContent(1);
629             pMark->SetMarkPos(*aPasteStart.GetPoint());
630             pMark->SetOtherMarkPos(*aPasteEnd.GetPoint());
631             bSortMarks = true;
632 
633             // Remove markers. the start marker includes the old content as well.
634             rIDCO.DeleteAndJoin(aStartMarker);
635             rIDCO.DeleteAndJoin(aEndMarker);
636         }
637     }
638     if (bSortMarks)
639     {
640         rIDMA.assureSortedMarkContainers();
641     }
642 
643     rWrtSh.EndAction();
644     rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_BOOKMARKS, nullptr);
645 }
646 
UpdateBookmark(const SfxRequest & rReq,SwWrtShell & rWrtSh)647 void UpdateBookmark(const SfxRequest& rReq, SwWrtShell& rWrtSh)
648 {
649     if (rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
650     {
651         return;
652     }
653 
654     OUString aBookmarkNamePrefix;
655     const SfxStringItem* pBookmarkNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
656     if (pBookmarkNamePrefix)
657     {
658         aBookmarkNamePrefix = pBookmarkNamePrefix->GetValue();
659     }
660 
661     uno::Sequence<beans::PropertyValue> aBookmark;
662     const SfxUnoAnyItem* pBookmarks = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_2);
663     if (pBookmarks)
664     {
665         pBookmarks->GetValue() >>= aBookmark;
666     }
667 
668     IDocumentMarkAccess& rIDMA = *rWrtSh.GetDoc()->getIDocumentMarkAccess();
669     SwPosition& rCursor = *rWrtSh.GetCursor()->GetPoint();
670     sw::mark::Bookmark* pBookmark = rIDMA.getOneInnermostBookmarkFor(rCursor);
671     if (!pBookmark || !pBookmark->GetName().toString().startsWith(aBookmarkNamePrefix))
672     {
673         return;
674     }
675 
676     SwRewriter aRewriter;
677     aRewriter.AddRule(UndoArg1, pBookmark->GetName());
678     rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_BOOKMARK, &aRewriter);
679     rWrtSh.StartAction();
680     comphelper::ScopeGuard g(
681         [&rWrtSh, &aRewriter]
682         {
683             rWrtSh.EndAction();
684             rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_BOOKMARK, &aRewriter);
685         });
686 
687 
688     comphelper::SequenceAsHashMap aMap(aBookmark);
689     if (aMap[u"Bookmark"_ustr].get<OUString>() != pBookmark->GetName())
690     {
691         rIDMA.renameMark(pBookmark, SwMarkName(aMap[u"Bookmark"_ustr].get<OUString>()));
692     }
693 
694     // Insert markers to remember where the paste positions are.
695     SwPaM aMarkers(pBookmark->GetMarkEnd());
696     IDocumentContentOperations& rIDCO = rWrtSh.GetDoc()->getIDocumentContentOperations();
697     if (!rIDCO.InsertString(aMarkers, u"XY"_ustr))
698     {
699         return;
700     }
701 
702     SwPaM aPasteEnd(pBookmark->GetMarkEnd());
703     aPasteEnd.Move(fnMoveForward, GoInContent);
704 
705     OUString aBookmarkText = aMap[u"BookmarkText"_ustr].get<OUString>();
706 
707     // Paste HTML content.
708     SwPaM* pCursorPos = rWrtSh.GetCursor();
709     *pCursorPos = aPasteEnd;
710     SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aBookmarkText.toUtf8());
711 
712     // Update the bookmark to point to the new content.
713     SwPaM aPasteStart(pBookmark->GetMarkEnd());
714     aPasteStart.Move(fnMoveForward, GoInContent);
715     SwPaM aStartMarker(pBookmark->GetMarkStart(), *aPasteStart.GetPoint());
716     SwPaM aEndMarker(*aPasteEnd.GetPoint(), *aPasteEnd.GetPoint());
717     aEndMarker.GetMark()->AdjustContent(1);
718     pBookmark->SetMarkPos(*aPasteStart.GetPoint());
719     pBookmark->SetOtherMarkPos(*aPasteEnd.GetPoint());
720 
721     // Remove markers. the start marker includes the old content as well.
722     rIDCO.DeleteAndJoin(aStartMarker);
723     rIDCO.DeleteAndJoin(aEndMarker);
724     rIDMA.assureSortedMarkContainers();
725 }
726 
DeleteBookmarks(const SfxRequest & rReq,SwWrtShell & rWrtSh)727 void DeleteBookmarks(const SfxRequest& rReq, SwWrtShell& rWrtSh)
728 {
729     if (rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
730     {
731         return;
732     }
733 
734     OUString aBookmarkNamePrefix;
735     const SfxStringItem* pBookmarkNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
736     if (pBookmarkNamePrefix)
737     {
738         aBookmarkNamePrefix = pBookmarkNamePrefix->GetValue();
739     }
740 
741     rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_BOOKMARKS, nullptr);
742     rWrtSh.StartAction();
743     comphelper::ScopeGuard g(
744         [&rWrtSh]
745         {
746             rWrtSh.EndAction();
747             rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_BOOKMARKS, nullptr);
748         });
749 
750     IDocumentMarkAccess* pMarkAccess = rWrtSh.GetDoc()->getIDocumentMarkAccess();
751     std::vector<sw::mark::MarkBase*> aRemovals;
752     for (auto it = pMarkAccess->getBookmarksBegin(); it != pMarkAccess->getBookmarksEnd(); ++it)
753     {
754         sw::mark::Bookmark* pBookmark = *it;
755         assert(pBookmark);
756 
757         if (!aBookmarkNamePrefix.isEmpty())
758         {
759             if (!pBookmark->GetName().toString().startsWith(aBookmarkNamePrefix))
760             {
761                 continue;
762             }
763         }
764 
765         aRemovals.push_back(pBookmark);
766     }
767 
768     for (const auto& pMark : aRemovals)
769     {
770         pMarkAccess->deleteMark(pMark);
771     }
772 }
773 
DeleteFields(const SfxRequest & rReq,SwWrtShell & rWrtSh)774 void DeleteFields(const SfxRequest& rReq, SwWrtShell& rWrtSh)
775 {
776     const SfxStringItem* pTypeName = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
777     if (!pTypeName || pTypeName->GetValue() != "SetRef")
778     {
779         // This is implemented so far only for reference marks.
780         return;
781     }
782 
783     OUString aNamePrefix;
784     const SfxStringItem* pNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
785     if (pNamePrefix)
786     {
787         aNamePrefix = pNamePrefix->GetValue();
788     }
789 
790     SwDoc* pDoc = rWrtSh.GetDoc();
791     pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_FIELDS, nullptr);
792     rWrtSh.StartAction();
793     comphelper::ScopeGuard g(
794         [&rWrtSh]
795         {
796             rWrtSh.EndAction();
797             rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_FIELDS, nullptr);
798         });
799 
800     std::vector<const SwFormatRefMark*> aRemovals;
801     for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i)
802     {
803         const SwFormatRefMark* pRefMark = pDoc->GetRefMark(i);
804         if (!aNamePrefix.isEmpty())
805         {
806             if (!pRefMark->GetRefName().toString().startsWith(aNamePrefix))
807             {
808                 continue;
809             }
810         }
811 
812         aRemovals.push_back(pRefMark);
813     }
814 
815     for (const auto& pMark : aRemovals)
816     {
817         pDoc->DeleteFormatRefMark(pMark);
818     }
819 }
820 
lcl_LogWarning(std::string sWarning)821 void lcl_LogWarning(std::string sWarning)
822 {
823     LOK_WARN("sw.transform",  sWarning);
824 }
825 
lcl_ChangeChartColumnCount(const uno::Reference<chart2::XChartDocument> & xChartDoc,sal_Int32 nId,bool bInsert,bool bResize=false)826 bool lcl_ChangeChartColumnCount(const uno::Reference<chart2::XChartDocument>& xChartDoc, sal_Int32 nId,
827                                 bool bInsert, bool bResize = false)
828 {
829     uno::Reference<chart2::XDiagram> xDiagram = xChartDoc->getFirstDiagram();
830     if (!xDiagram.is())
831         return false;
832     uno::Reference<chart2::XCoordinateSystemContainer> xCooSysContainer(xDiagram, uno::UNO_QUERY);
833     if (!xCooSysContainer.is())
834         return false;
835     uno::Sequence<uno::Reference<chart2::XCoordinateSystem>> xCooSysSequence(
836         xCooSysContainer->getCoordinateSystems());
837     if (xCooSysSequence.getLength() <= 0)
838         return false;
839     uno::Reference<chart2::XChartTypeContainer> xChartTypeContainer(xCooSysSequence[0],
840                                                                     uno::UNO_QUERY);
841     if (!xChartTypeContainer.is())
842         return false;
843     uno::Sequence<uno::Reference<chart2::XChartType>> xChartTypeSequence(
844         xChartTypeContainer->getChartTypes());
845     if (xChartTypeSequence.getLength() <= 0)
846         return false;
847     uno::Reference<chart2::XDataSeriesContainer> xDSContainer(xChartTypeSequence[0],
848                                                               uno::UNO_QUERY);
849     if (!xDSContainer.is())
850         return false;
851 
852     uno::Reference<chart2::XInternalDataProvider> xIDataProvider(xChartDoc->getDataProvider(),
853                                                                  uno::UNO_QUERY);
854     if (!xIDataProvider.is())
855         return false;
856 
857     uno::Sequence<uno::Reference<chart2::XDataSeries>> aSeriesSeq(xDSContainer->getDataSeries());
858 
859     int nSeriesCount = aSeriesSeq.getLength();
860 
861     if (bResize)
862     {
863         // Resize is actually some inserts, or deletes
864         if (nId > nSeriesCount)
865         {
866             bInsert = true;
867         }
868         else if (nId < nSeriesCount)
869         {
870             bInsert = false;
871         }
872         else
873         {
874             // Resize to the same size. No change needed
875             return true;
876         }
877     }
878 
879     // insert or delete
880     if (bInsert)
881     {
882         // insert
883         if (nId > nSeriesCount && !bResize)
884             return false;
885 
886         int nInsertCount = bResize ? nId - nSeriesCount : 1;
887 
888         // call dialog code
889         if (bResize)
890         {
891             for (int i = 0; i < nInsertCount; i++)
892             {
893                 xIDataProvider->insertDataSeries(nSeriesCount);
894             }
895             return true;
896         }
897 
898         xIDataProvider->insertDataSeries(nId);
899     }
900     else
901     {
902         // delete 1 or more columns
903         if (nId >= nSeriesCount)
904             return false;
905         int nDeleteCount = bResize ? nSeriesCount - nId : 1;
906         for (int i = 0; i < nDeleteCount; i++)
907         {
908             xDSContainer->removeDataSeries(aSeriesSeq[nId]);
909         }
910     }
911     return true;
912 }
913 
lcl_ResizeChartColumns(const uno::Reference<chart2::XChartDocument> & xChartDoc,sal_Int32 nSize)914 bool lcl_ResizeChartColumns(const uno::Reference<chart2::XChartDocument>& xChartDoc, sal_Int32 nSize)
915 {
916     return lcl_ChangeChartColumnCount(xChartDoc, nSize, false, true);
917 }
918 
lcl_InsertChartColumns(const uno::Reference<chart2::XChartDocument> & xChartDoc,sal_Int32 nId)919 bool lcl_InsertChartColumns(const uno::Reference<chart2::XChartDocument>& xChartDoc, sal_Int32 nId)
920 {
921     return lcl_ChangeChartColumnCount(xChartDoc, nId, true);
922 }
923 
lcl_DeleteChartColumns(const uno::Reference<chart2::XChartDocument> & xChartDoc,sal_Int32 nId)924 bool lcl_DeleteChartColumns(const uno::Reference<chart2::XChartDocument>& xChartDoc, sal_Int32 nId)
925 {
926     return lcl_ChangeChartColumnCount(xChartDoc, nId, false);
927 }
928 }
929 
AddWordToWordbook(const uno::Reference<linguistic2::XDictionary> & xDictionary,SwWrtShell & rWrtSh)930 static bool AddWordToWordbook(const uno::Reference<linguistic2::XDictionary>& xDictionary, SwWrtShell &rWrtSh)
931 {
932     if (!xDictionary)
933         return false;
934 
935     SwRect aToFill;
936     uno::Reference<linguistic2::XSpellAlternatives>  xSpellAlt(rWrtSh.GetCorrection(nullptr, aToFill));
937     if (!xSpellAlt.is())
938         return false;
939 
940     OUString sWord = xSpellAlt->getWord();
941     linguistic::DictionaryError nAddRes = linguistic::AddEntryToDic(xDictionary, sWord, false, OUString());
942     if (linguistic::DictionaryError::NONE != nAddRes && xDictionary.is() && !xDictionary->getEntry(sWord).is())
943     {
944         SvxDicError(rWrtSh.GetView().GetFrameWeld(), nAddRes);
945         return false;
946     }
947     return true;
948 }
949 
Execute(SfxRequest & rReq)950 void SwTextShell::Execute(SfxRequest &rReq)
951 {
952     bool bUseDialog = true;
953     const SfxItemSet *pArgs = rReq.GetArgs();
954     SwWrtShell& rWrtSh = GetShell();
955     const SfxPoolItem* pItem = nullptr;
956     const sal_uInt16 nSlot = rReq.GetSlot();
957     if(pArgs)
958         pArgs->GetItemState(GetPool().GetWhichIDFromSlotID(nSlot), false, &pItem);
959     switch( nSlot )
960     {
961         case SID_UNICODE_NOTATION_TOGGLE:
962         {
963             tools::Long nMaxUnits = 256;
964             sal_Int32 nSelLength = rWrtSh.GetSelText().getLength();
965             if( rWrtSh.IsSelection() && !rWrtSh.IsMultiSelection() && (nSelLength < nMaxUnits) )
966                 nMaxUnits = nSelLength;
967 
968             tools::Long index = 0;
969             ToggleUnicodeCodepoint aToggle;
970             while( nMaxUnits-- && aToggle.AllowMoreInput(rWrtSh.GetChar(true, index-1)) )
971                 --index;
972 
973             OUString sReplacement = aToggle.ReplacementString();
974             if( !sReplacement.isEmpty() )
975             {
976                 if (rWrtSh.HasReadonlySel() && !rWrtSh.CursorInsideInputField())
977                 {
978                     // Only break if there's something to do; don't nag with the dialog otherwise
979                     rWrtSh.InfoReadOnlyDialog(false);
980                     break;
981                 }
982                 OUString stringToReplace = aToggle.StringToReplace();
983                 SwRewriter aRewriter;
984                 aRewriter.AddRule( UndoArg1, stringToReplace );
985                 aRewriter.AddRule( UndoArg2, SwResId(STR_YIELDS) );
986                 aRewriter.AddRule( UndoArg3, sReplacement );
987                 rWrtSh.StartUndo(SwUndoId::REPLACE, &aRewriter);
988                 rWrtSh.GetCursor()->Normalize(false);
989 
990                 rWrtSh.ClearMark();
991                 if( rWrtSh.IsInSelect() )  // cancel any in-progress keyboard selection as well
992                     rWrtSh.EndSelect();
993                 // Select exactly what was chosen for replacement
994                 rWrtSh.GetCursor()->SetMark();
995                 rWrtSh.GetCursor()->GetPoint()->AdjustContent(-stringToReplace.getLength());
996                 rWrtSh.DelLeft();
997                 rWrtSh.Insert2( sReplacement );
998                 rWrtSh.EndUndo(SwUndoId::REPLACE, &aRewriter);
999             }
1000         }
1001         break;
1002 
1003         case SID_LANGUAGE_STATUS:
1004         {
1005             // get the language
1006             OUString aNewLangText;
1007             const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(SID_LANGUAGE_STATUS);
1008             if (pItem2)
1009                 aNewLangText = pItem2->GetValue();
1010 
1011             //!! Remember the view frame right now...
1012             //!! (call to GetView().GetViewFrame() will break if the
1013             //!! SwTextShell got destroyed meanwhile.)
1014             SfxViewFrame& rViewFrame = GetView().GetViewFrame();
1015 
1016             if (aNewLangText == "*")
1017             {
1018                 // open the dialog "Tools/Options/Languages and Locales - General"
1019                 // to set the documents default language
1020                 SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1021                 ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog(GetView().GetFrameWeld(), SID_LANGUAGE_OPTIONS));
1022                 pDlg->Execute();
1023             }
1024             else
1025             {
1026                 //!! We have to use StartAction / EndAction bracketing in
1027                 //!! order to prevent possible destruction of the SwTextShell
1028                 //!! due to the selection changes coming below.
1029                 rWrtSh.StartAction();
1030                 // prevent view from jumping because of (temporary) selection changes
1031                 rWrtSh.LockView( true );
1032 
1033                 // setting the new language...
1034                 if (!aNewLangText.isEmpty())
1035                 {
1036                     static constexpr OUString aSelectionLangPrefix(u"Current_"_ustr);
1037                     static constexpr OUString aParagraphLangPrefix(u"Paragraph_"_ustr);
1038                     static constexpr OUString aDocumentLangPrefix(u"Default_"_ustr);
1039 
1040                     SfxItemSetFixed<RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
1041                                     RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
1042                                     RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
1043                                     RES_CHRATR_SCRIPT_HINT, RES_CHRATR_SCRIPT_HINT>
1044                         aCoreSet(GetPool());
1045 
1046                     sal_Int32 nPos = 0;
1047                     bool bForSelection = true;
1048                     bool bForParagraph = false;
1049                     if (-1 != (nPos = aNewLangText.indexOf( aSelectionLangPrefix )))
1050                     {
1051                         // ... for the current selection
1052                         aNewLangText = aNewLangText.replaceAt(nPos, aSelectionLangPrefix.getLength(), u"");
1053                         bForSelection = true;
1054                     }
1055                     else if (-1 != (nPos = aNewLangText.indexOf(aParagraphLangPrefix)))
1056                     {
1057                         // ... for the current paragraph language
1058                         aNewLangText = aNewLangText.replaceAt(nPos, aParagraphLangPrefix.getLength(), u"");
1059                         bForSelection = true;
1060                         bForParagraph = true;
1061                     }
1062                     else if (-1 != (nPos = aNewLangText.indexOf(aDocumentLangPrefix)))
1063                     {
1064                         // ... as default document language
1065                         aNewLangText = aNewLangText.replaceAt(nPos, aDocumentLangPrefix.getLength(), u"");
1066                         bForSelection = false;
1067                     }
1068 
1069                     if (bForParagraph || !bForSelection)
1070                     {
1071                         rWrtSh.Push(); // save selection for later restoration
1072                         rWrtSh.ClearMark(); // fdo#67796: invalidate table crsr
1073                     }
1074 
1075                     if (bForParagraph)
1076                         SwLangHelper::SelectCurrentPara( rWrtSh );
1077 
1078                     if (!bForSelection) // document language to be changed...
1079                     {
1080                         rWrtSh.SelAll();
1081                         rWrtSh.ExtendedSelectAll();
1082                     }
1083 
1084                     rWrtSh.StartUndo( ( !bForParagraph && !bForSelection ) ? SwUndoId::SETDEFTATTR : SwUndoId::EMPTY );
1085                     if (aNewLangText == "LANGUAGE_NONE")
1086                         SwLangHelper::SetLanguage_None( rWrtSh, bForSelection, aCoreSet );
1087                     else if (aNewLangText == "RESET_LANGUAGES")
1088                         SwLangHelper::ResetLanguages( rWrtSh );
1089                     else
1090                         SwLangHelper::SetLanguage( rWrtSh, aNewLangText, bForSelection, aCoreSet );
1091                     rWrtSh.EndUndo();
1092 
1093                     if (bForParagraph || !bForSelection)
1094                     {
1095                         rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // restore selection...
1096                     }
1097                 }
1098 
1099                 rWrtSh.LockView( false );
1100                 rWrtSh.EndAction();
1101             }
1102 
1103             // invalidate slot to get the new language displayed
1104             rViewFrame.GetBindings().Invalidate( nSlot );
1105 
1106             rReq.Done();
1107             break;
1108         }
1109 
1110         case SID_THES:
1111         {
1112             // replace word/selection with text from selected sub menu entry
1113             OUString aReplaceText;
1114             const SfxStringItem* pItem2 = rReq.GetArg(FN_PARAM_THES_WORD_REPLACE);
1115             if (pItem2)
1116                 aReplaceText = pItem2->GetValue();
1117             if (!aReplaceText.isEmpty())
1118             {
1119                 SwView &rView2 = rWrtSh.GetView();
1120                 const bool bSelection = rWrtSh.HasSelection();
1121                 const OUString aLookUpText = rView2.GetThesaurusLookUpText( bSelection );
1122                 rView2.InsertThesaurusSynonym( aReplaceText, aLookUpText, bSelection );
1123             }
1124         }
1125         break;
1126 
1127         case SID_CHARMAP:
1128         {
1129             InsertSymbol( rReq );
1130         }
1131         break;
1132         case FN_INSERT_FOOTNOTE:
1133         case FN_INSERT_ENDNOTE:
1134         {
1135             OUString aStr;
1136             const SfxStringItem* pFont = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
1137             const SfxStringItem* pNameItem = rReq.GetArg<SfxStringItem>(nSlot);
1138             if ( pNameItem )
1139                 aStr = pNameItem->GetValue();
1140             bool bFont = pFont && !pFont->GetValue().isEmpty();
1141             rWrtSh.StartUndo( SwUndoId::UI_INSERT_FOOTNOTE );
1142             rWrtSh.InsertFootnote( aStr, nSlot == FN_INSERT_ENDNOTE, !bFont );
1143             if ( bFont )
1144             {
1145                 rWrtSh.Left( SwCursorSkipMode::Chars, true, 1, false );
1146                 SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONT> aSet( rWrtSh.GetAttrPool() );
1147                 rWrtSh.GetCurAttr( aSet );
1148                 rWrtSh.SetAttrSet( aSet, SetAttrMode::DONTEXPAND );
1149                 rWrtSh.ResetSelect(nullptr, false, ScrollSizeMode::ScrollSizeDefault);
1150                 rWrtSh.EndSelect();
1151                 rWrtSh.GotoFootnoteText();
1152             }
1153             rWrtSh.EndUndo( SwUndoId::UI_INSERT_FOOTNOTE );
1154             rReq.Done();
1155         }
1156         break;
1157         case FN_INSERT_FOOTNOTE_DLG:
1158         {
1159             SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1160             VclPtr<AbstractInsFootNoteDlg> pDlg(pFact->CreateInsFootNoteDlg(
1161                 GetView().GetFrameWeld(), rWrtSh));
1162             pDlg->SetHelpId(GetStaticInterface()->GetSlot(nSlot)->GetCommand());
1163             pDlg->StartExecuteAsync(
1164                 [this, pDlg] (sal_Int32 nResult)->void
1165                 {
1166                     if ( nResult == RET_OK )
1167                     {
1168                         pDlg->Apply();
1169                         const sal_uInt16 nId = pDlg->IsEndNote() ? FN_INSERT_ENDNOTE : FN_INSERT_FOOTNOTE;
1170                         SfxRequest aReq(GetView().GetViewFrame(), nId);
1171                         if ( !pDlg->GetStr().isEmpty() )
1172                             aReq.AppendItem( SfxStringItem( nId, pDlg->GetStr() ) );
1173                         if ( !pDlg->GetFontName().isEmpty() )
1174                             aReq.AppendItem( SfxStringItem( FN_PARAM_1, pDlg->GetFontName() ) );
1175                         ExecuteSlot( aReq );
1176                     }
1177                     pDlg->disposeOnce();
1178                 }
1179             );
1180             rReq.Ignore();
1181         }
1182         break;
1183         case FN_FORMAT_FOOTNOTE_DLG:
1184         case FN_FORMAT_CURRENT_FOOTNOTE_DLG:
1185         {
1186             GetView().ExecFormatFootnote();
1187             break;
1188         }
1189         case SID_INSERTDOC:
1190         {
1191             GetView().ExecuteInsertDoc( rReq, pItem );
1192             break;
1193         }
1194         case FN_FORMAT_RESET:
1195         {
1196             // #i78856, reset all attributes but not the language attributes
1197             // (for this build an array of all relevant attributes and
1198             // remove the languages from that)
1199             o3tl::sorted_vector<sal_uInt16> aAttribs;
1200 
1201             static constexpr std::pair<sal_uInt16, sal_uInt16> aResetableSetRange[] = {
1202                 // tdf#40496: we don't want to change writing direction, so exclude RES_FRAMEDIR:
1203                 { RES_FRMATR_BEGIN, RES_FRAMEDIR - 1 },
1204                 { RES_FRAMEDIR + 1, RES_FRMATR_END - 1 },
1205                 { RES_CHRATR_BEGIN, RES_CHRATR_LANGUAGE - 1 },
1206                 { RES_CHRATR_LANGUAGE + 1, RES_CHRATR_CJK_LANGUAGE - 1 },
1207                 { RES_CHRATR_CJK_LANGUAGE + 1, RES_CHRATR_CTL_LANGUAGE - 1 },
1208                 { RES_CHRATR_CTL_LANGUAGE + 1, RES_CHRATR_END - 1 },
1209                 { RES_PARATR_BEGIN, RES_PARATR_END - 1 },
1210                 { RES_PARATR_LIST_AUTOFMT, RES_PARATR_LIST_AUTOFMT },
1211                 { RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER },
1212                 { RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END - 1 },
1213             };
1214             for (const auto& [nBegin, nEnd] : aResetableSetRange)
1215             {
1216                 for (sal_uInt16 i = nBegin; i <= nEnd; ++i)
1217                     aAttribs.insert( i );
1218             }
1219 
1220             // also clear the direct formatting flag inside SwTableBox(es)
1221             if (SwFEShell* pFEShell = GetView().GetDocShell()->GetFEShell())
1222                 pFEShell->UpdateTableStyleFormatting(nullptr, true);
1223 
1224             // tdf#160801 fix crash by delaying resetting of attributes
1225             // Calling SwWrtShell::ResetAttr() will sometimes delete the
1226             // current SwTextShell instance so call it after clearing the
1227             // direct formatting flag.
1228             rWrtSh.ResetAttr( aAttribs );
1229 
1230             rReq.Done();
1231             break;
1232         }
1233         case FN_INSERT_BREAK_DLG:
1234         {
1235             if ( pItem )
1236             {
1237                 ::std::optional<sal_uInt16> oPageNumber;
1238                 std::optional<SwLineBreakClear> oClear;
1239                 UIName aTemplateName;
1240                 sal_uInt16 nKind = static_cast<const SfxInt16Item*>(pItem)->GetValue();
1241                 const SfxStringItem* pTemplate = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
1242                 const SfxUInt16Item* pNumber = rReq.GetArg<SfxUInt16Item>(FN_PARAM_2);
1243                 const SfxBoolItem* pIsNumberFilled = rReq.GetArg<SfxBoolItem>(FN_PARAM_3);
1244                 if ( pTemplate )
1245                     aTemplateName = UIName(pTemplate->GetValue());
1246                 if ( pNumber && pIsNumberFilled && pIsNumberFilled->GetValue() )
1247                     oPageNumber = pNumber->GetValue();
1248 
1249                 InsertBreak(rWrtSh, nKind, oPageNumber, aTemplateName, oClear);
1250             }
1251             else
1252             {
1253                 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1254 
1255                 std::shared_ptr<AbstractSwBreakDlg> pAbstractDialog(pFact->CreateSwBreakDlg(GetView().GetFrameWeld(), rWrtSh));
1256                 std::shared_ptr<weld::DialogController> pDialogController(pAbstractDialog->getDialogController());
1257 
1258                 weld::DialogController::runAsync(pDialogController,
1259                     [pAbstractDialog=std::move(pAbstractDialog), &rWrtSh] (sal_Int32 nResult) {
1260                         if( RET_OK == nResult )
1261                         {
1262                             sal_uInt16 nKind = pAbstractDialog->GetKind();
1263                             OUString aTemplateName = pAbstractDialog->GetTemplateName();
1264                             ::std::optional<sal_uInt16> oPageNumber = pAbstractDialog->GetPageNumber();
1265                             std::optional<SwLineBreakClear> oClear = pAbstractDialog->GetClear();
1266 
1267                             InsertBreak(rWrtSh, nKind, oPageNumber, UIName(aTemplateName), oClear);
1268                         }
1269                     });
1270             }
1271 
1272             break;
1273         }
1274         case FN_INSERT_BOOKMARK:
1275         {
1276             const SfxStringItem* pBookmarkText = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
1277             SwPaM* pCursorPos = rWrtSh.GetCursor();
1278             if ( pItem )
1279             {
1280                 rWrtSh.StartAction();
1281                 OUString sName = static_cast<const SfxStringItem*>(pItem)->GetValue();
1282 
1283                 if (pBookmarkText)
1284                 {
1285                     OUString aBookmarkText = pBookmarkText->GetValue();
1286                     // Split node to remember where the start position is.
1287                     bool bSuccess = rWrtSh.GetDoc()->getIDocumentContentOperations().SplitNode(
1288                         *pCursorPos->GetPoint(), /*bChkTableStart=*/false);
1289                     if (bSuccess)
1290                     {
1291                         SwPaM aBookmarkPam(*pCursorPos->GetPoint());
1292                         aBookmarkPam.Move(fnMoveBackward, GoInContent);
1293 
1294                         // Paste HTML content.
1295                         SwTranslateHelper::PasteHTMLToPaM(
1296                             rWrtSh, pCursorPos, aBookmarkText.toUtf8());
1297                         if (pCursorPos->GetPoint()->GetContentIndex() == 0)
1298                         {
1299                             // The paste created a last empty text node, remove it.
1300                             SwPaM aPam(*pCursorPos->GetPoint());
1301                             aPam.SetMark();
1302                             aPam.Move(fnMoveBackward, GoInContent);
1303                             rWrtSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPam);
1304                         }
1305 
1306                         // Undo the above SplitNode().
1307                         aBookmarkPam.SetMark();
1308                         aBookmarkPam.Move(fnMoveForward, GoInContent);
1309                         rWrtSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(
1310                             aBookmarkPam);
1311                         *aBookmarkPam.GetMark() = *pCursorPos->GetPoint();
1312                         *pCursorPos = aBookmarkPam;
1313                     }
1314                 }
1315 
1316                 rWrtSh.SetBookmark( vcl::KeyCode(), SwMarkName(sName) );
1317                 if (pBookmarkText)
1318                 {
1319                     pCursorPos->DeleteMark();
1320                 }
1321                 rWrtSh.EndAction();
1322                 break;
1323             }
1324             [[fallthrough]];
1325         }
1326         case FN_EDIT_BOOKMARK:
1327         {
1328             ::std::optional<OUString> oName;
1329             if (pItem)
1330                 oName.emplace(static_cast<const SfxStringItem*>(pItem)->GetValue());
1331 
1332             {
1333                 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1334                 ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSwInsertBookmarkDlg(GetView().GetFrameWeld(), rWrtSh, oName ? &*oName : nullptr));
1335                 VclAbstractDialog::AsyncContext aContext;
1336                 aContext.maEndDialogFn = [](sal_Int32){};
1337                 pDlg->StartExecuteAsync(aContext);
1338             }
1339 
1340             break;
1341         }
1342         case FN_UPDATE_BOOKMARKS:
1343         {
1344             // This updates all bookmarks in the document that match the conditions specified in
1345             // rReq.
1346             UpdateBookmarks(rReq, rWrtSh);
1347             break;
1348         }
1349         case FN_UPDATE_BOOKMARK:
1350         {
1351             // This updates the bookmark under the cursor.
1352             UpdateBookmark(rReq, rWrtSh);
1353             break;
1354         }
1355         case FN_DELETE_BOOKMARK:
1356         {
1357             // This deletes a bookmark with the specified name.
1358             if (pItem && !rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
1359             {
1360                 IDocumentMarkAccess* const pMarkAccess = rWrtSh.getIDocumentMarkAccess();
1361                 pMarkAccess->deleteMark(pMarkAccess->findMark(SwMarkName(static_cast<const SfxStringItem*>(pItem)->GetValue())), false);
1362             }
1363             break;
1364         }
1365         case FN_DELETE_BOOKMARKS:
1366         {
1367             // This deletes all bookmarks in the document matching a specified prefix.
1368             DeleteBookmarks(rReq, rWrtSh);
1369             break;
1370         }
1371         case FN_DELETE_FIELDS:
1372         {
1373             // This deletes all fields in the document matching a specified type & prefix.
1374             DeleteFields(rReq, rWrtSh);
1375             break;
1376         }
1377         case FN_UPDATE_SECTIONS:
1378         {
1379             UpdateSections(rReq, rWrtSh);
1380             break;
1381         }
1382         case FN_DELETE_SECTIONS:
1383         {
1384             // This deletes all sections in the document matching a specified prefix. Note that the
1385             // section is deleted, but not its contents.
1386             DeleteSections(rReq, rWrtSh);
1387             break;
1388         }
1389         case FN_DELETE_CONTENT_CONTROL:
1390         {
1391             DeleteContentControl( rWrtSh );
1392             break;
1393         }
1394         case FN_SET_REMINDER:
1395         {
1396             // collect and sort navigator reminder names
1397             IDocumentMarkAccess* const pMarkAccess = rWrtSh.getIDocumentMarkAccess();
1398             std::vector< SwMarkName > vNavMarkNames;
1399             for(auto ppMark = pMarkAccess->getAllMarksBegin();
1400                 ppMark != pMarkAccess->getAllMarksEnd();
1401                 ++ppMark)
1402             {
1403                 if( IDocumentMarkAccess::GetType(**ppMark) == IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER )
1404                     vNavMarkNames.push_back((*ppMark)->GetName());
1405             }
1406             std::sort(vNavMarkNames.begin(), vNavMarkNames.end());
1407 
1408             // we are maxed out so delete the first one
1409             // this assumes that IDocumentMarkAccess generates Names in ascending order
1410             if(vNavMarkNames.size() == MAX_MARKS)
1411                 pMarkAccess->deleteMark(pMarkAccess->findMark(vNavMarkNames[0]), false);
1412 
1413             rWrtSh.SetBookmark(vcl::KeyCode(), SwMarkName(), IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER);
1414             SwView::SetActMark(vNavMarkNames.size() < MAX_MARKS ? vNavMarkNames.size() : MAX_MARKS-1);
1415 
1416             break;
1417         }
1418         case FN_AUTOFORMAT_REDLINE_APPLY:
1419         {
1420             SvxSwAutoFormatFlags aFlags(SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags());
1421             // This must always be false for the postprocessing.
1422             aFlags.bAFormatByInput = false;
1423             aFlags.bWithRedlining = true;
1424             rWrtSh.AutoFormat( &aFlags, false );
1425             aFlags.bWithRedlining = false;
1426 
1427             SfxViewFrame& rVFrame = GetView().GetViewFrame();
1428             if (rVFrame.HasChildWindow(FN_REDLINE_ACCEPT))
1429                 rVFrame.ToggleChildWindow(FN_REDLINE_ACCEPT);
1430 
1431             SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1432             auto xRequest = std::make_shared<SfxRequest>(rReq);
1433             rReq.Ignore(); // the 'old' request is not relevant any more
1434             VclPtr<AbstractSwModalRedlineAcceptDlg> pDlg(pFact->CreateSwModalRedlineAcceptDlg(GetView().GetEditWin().GetFrameWeld()));
1435             pDlg->StartExecuteAsync(
1436                 [pDlg, xRequest=std::move(xRequest)] (sal_Int32 /*nResult*/)->void
1437                 {
1438                     pDlg->disposeOnce();
1439                     xRequest->Done();
1440                 }
1441             );
1442         }
1443         break;
1444 
1445         case FN_AUTOFORMAT_APPLY:
1446         {
1447             SvxSwAutoFormatFlags aFlags(SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags());
1448             // This must always be false for the postprocessing.
1449             aFlags.bAFormatByInput = false;
1450             rWrtSh.AutoFormat( &aFlags, false );
1451             rReq.Done();
1452         }
1453         break;
1454         case FN_AUTOFORMAT_AUTO:
1455         {
1456             SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
1457             bool bSet = pItem ? static_cast<const SfxBoolItem*>(pItem)->GetValue() : !rACfg.IsAutoFormatByInput();
1458             if( bSet != rACfg.IsAutoFormatByInput() )
1459             {
1460                 rACfg.SetAutoFormatByInput( bSet );
1461                 rACfg.Commit();
1462                 GetView().GetViewFrame().GetBindings().Invalidate( nSlot );
1463                 if ( !pItem )
1464                     rReq.AppendItem( SfxBoolItem( GetPool().GetWhichIDFromSlotID(nSlot), bSet ) );
1465                 rReq.Done();
1466             }
1467         }
1468         break;
1469         case FN_AUTO_CORRECT:
1470         {
1471             // At first set to blank as default.
1472             rWrtSh.AutoCorrect( *SvxAutoCorrCfg::Get().GetAutoCorrect(), ' ' );
1473             rReq.Done();
1474         }
1475         break;
1476         case FN_TABLE_SORT_DIALOG:
1477         case FN_SORTING_DLG:
1478         {
1479             SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1480             VclPtr<AbstractSwSortDlg> pDlg(pFact->CreateSwSortingDialog(GetView().GetFrameWeld(), rWrtSh));
1481             auto xRequest = std::make_shared<SfxRequest>(rReq);
1482             rReq.Ignore(); // the 'old' request is not relevant any more
1483             pDlg->StartExecuteAsync(
1484                 [pDlg, xRequest=std::move(xRequest)] (sal_Int32 nResult)->void
1485                 {
1486                     if (nResult == RET_OK)
1487                         pDlg->Apply();
1488                     pDlg->disposeOnce();
1489                     xRequest->Done();
1490                 }
1491             );
1492         }
1493         break;
1494         case FN_NUMBERING_OUTLINE_DLG:
1495         {
1496             GetView().ExecNumberingOutline(GetPool());
1497             rReq.Done();
1498         }
1499             break;
1500         case FN_CALCULATE:
1501             {
1502                 rtl::Reference<SwTransferable> pTransfer = new SwTransferable( rWrtSh );
1503                 pTransfer->CalculateAndCopy();
1504                 rReq.Done();
1505             }
1506             break;
1507         case FN_GOTO_REFERENCE:
1508         {
1509             SwField *pField = rWrtSh.GetCurField();
1510             if(pField && pField->GetTypeId() == SwFieldTypesEnum::GetRef)
1511             {
1512                 rWrtSh.StartAllAction();
1513                 rWrtSh.SwCursorShell::GotoRefMark( static_cast<SwGetRefField*>(pField)->GetSetRefName(),
1514                                     static_cast<SwGetRefField*>(pField)->GetSubType(),
1515                                     static_cast<SwGetRefField*>(pField)->GetSeqNo(),
1516                                     static_cast<SwGetRefField*>(pField)->GetFlags() );
1517                 rWrtSh.EndAllAction();
1518                 rReq.Done();
1519             }
1520         }
1521             break;
1522         case FN_EDIT_FORMULA:
1523         {
1524             const sal_uInt16 nId = SwInputChild::GetChildWindowId();
1525             SfxViewFrame& rVFrame = GetView().GetViewFrame();
1526             if(pItem)
1527             {
1528                 //if the ChildWindow is active it has to be removed
1529                 if( rVFrame.HasChildWindow( nId ) )
1530                 {
1531                     rVFrame.ToggleChildWindow( nId );
1532                     rVFrame.GetBindings().InvalidateAll( true );
1533                 }
1534 
1535                 OUString sFormula(static_cast<const SfxStringItem*>(pItem)->GetValue());
1536                 SwFieldMgr aFieldMgr;
1537                 rWrtSh.StartAllAction();
1538                 bool bDelSel = rWrtSh.HasSelection();
1539                 if( bDelSel )
1540                 {
1541                     rWrtSh.StartUndo( SwUndoId::START );
1542                     rWrtSh.DelRight();
1543                 }
1544                 else
1545                 {
1546                     rWrtSh.EnterStdMode();
1547                 }
1548 
1549                 if( !bDelSel && aFieldMgr.GetCurField() && SwFieldTypesEnum::Formel == aFieldMgr.GetCurTypeId() )
1550                     aFieldMgr.UpdateCurField( static_cast<SwGetExpField*>(aFieldMgr.GetCurField())->GetFormat(), OUString(), sFormula );
1551                 else if( !sFormula.isEmpty() )
1552                 {
1553                     if( rWrtSh.IsCursorInTable() )
1554                     {
1555                         SfxItemSetFixed<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA> aSet( rWrtSh.GetAttrPool() );
1556                         aSet.Put( SwTableBoxFormula( sFormula ));
1557                         rWrtSh.SetTableBoxFormulaAttrs( aSet );
1558                         rWrtSh.UpdateTable();
1559                     }
1560                     else
1561                     {
1562                         SvNumberFormatter* pFormatter = rWrtSh.GetNumberFormatter();
1563                         const sal_uInt32 nSysNumFormat = pFormatter->GetFormatIndex( NF_NUMBER_STANDARD, LANGUAGE_SYSTEM);
1564                         SwInsertField_Data aData(SwFieldTypesEnum::Formel, static_cast<sal_uInt16>(SwGetSetExpType::Formula), OUString(), sFormula, nSysNumFormat);
1565                         aFieldMgr.InsertField(aData);
1566                     }
1567                 }
1568 
1569                 if( bDelSel )
1570                     rWrtSh.EndUndo( SwUndoId::END );
1571                 rWrtSh.EndAllAction();
1572                 rReq.Done();
1573             }
1574             else
1575             {
1576                 rWrtSh.EndAllTableBoxEdit();
1577                 rVFrame.ToggleChildWindow( nId );
1578                 if( !rVFrame.HasChildWindow( nId ) )
1579                     rVFrame.GetBindings().InvalidateAll( true );
1580                 rReq.Ignore();
1581             }
1582         }
1583 
1584         break;
1585         case FN_TABLE_UNSET_READ_ONLY:
1586         {
1587             rWrtSh.UnProtectTables();
1588         }
1589         break;
1590         case SID_EDIT_HYPERLINK:
1591         {
1592             if (!rWrtSh.HasSelection())
1593             {
1594                 SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
1595                 rWrtSh.GetCurAttr(aSet);
1596                 if (SfxItemState::SET > aSet.GetItemState(RES_TXTATR_INETFMT))
1597                 {
1598                     // Didn't find a hyperlink to edit yet.
1599 
1600                     // If the cursor is just before an unselected hyperlink,
1601                     // the dialog will not know that it should edit that hyperlink,
1602                     // so in this case, first select it so the dialog will find the hyperlink.
1603                     // The dialog would leave the hyperlink selected anyway after a successful edit
1604                     // (although it isn't normally selected after a cancel, but oh well).
1605                     if (!rWrtSh.SelectTextAttr(RES_TXTATR_INETFMT))
1606                         break;
1607                 }
1608             }
1609 
1610             GetView().GetViewFrame().SetChildWindow(SID_HYPERLINK_DIALOG, true);
1611         }
1612         break;
1613         case SID_REMOVE_HYPERLINK:
1614         {
1615             bool bSel = rWrtSh.HasSelection();
1616             if(!bSel)
1617             {
1618                 rWrtSh.StartAction();
1619                 rWrtSh.Push();
1620                 if(!rWrtSh.SelectTextAttr( RES_TXTATR_INETFMT ))
1621                     rWrtSh.SelWrd();
1622             }
1623             //now remove the attribute
1624             rWrtSh.ResetAttr({ RES_TXTATR_INETFMT });
1625             if(!bSel)
1626             {
1627                 rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
1628                 rWrtSh.EndAction();
1629             }
1630         }
1631         break;
1632         case SID_ATTR_BRUSH_CHAR :
1633         case SID_ATTR_CHAR_SCALEWIDTH :
1634         case SID_ATTR_CHAR_ROTATED :
1635         case FN_TXTATR_INET :
1636         {
1637             const sal_uInt16 nWhich = GetPool().GetWhichIDFromSlotID( nSlot );
1638             if ( pArgs && pArgs->GetItemState( nWhich ) == SfxItemState::SET )
1639                 bUseDialog = false;
1640             [[fallthrough]];
1641         }
1642         case SID_CHAR_DLG:
1643         case SID_CHAR_DLG_EFFECT:
1644         case SID_CHAR_DLG_POSITION:
1645         {
1646             sw_CharDialog(rWrtSh, bUseDialog, /*ApplyToParagraph*/false, nSlot, pArgs, &rReq);
1647         }
1648         break;
1649         case SID_CHAR_DLG_FOR_PARAGRAPH:
1650         {
1651             sw_CharDialog(rWrtSh, /*UseDialog*/true, /*ApplyToParagraph*/true, nSlot, pArgs, &rReq);
1652         }
1653         break;
1654         case SID_ATTR_LRSPACE :
1655         case SID_ATTR_ULSPACE :
1656         case SID_ATTR_BRUSH :
1657         case SID_PARA_VERTALIGN :
1658         case SID_ATTR_PARA_NUMRULE :
1659         case SID_ATTR_PARA_REGISTER :
1660         case SID_ATTR_PARA_PAGENUM :
1661         case FN_FORMAT_LINENUMBER :
1662         case FN_NUMBER_NEWSTART :
1663         case FN_NUMBER_NEWSTART_AT :
1664         case FN_FORMAT_DROPCAPS :
1665         case FN_DROP_TEXT:
1666         case SID_ATTR_PARA_LRSPACE:
1667         {
1668             const sal_uInt16 nWhich = GetPool().GetWhichIDFromSlotID( nSlot );
1669             if ( pArgs && pArgs->GetItemState( nWhich ) == SfxItemState::SET )
1670                 bUseDialog = false;
1671             [[fallthrough]];
1672         }
1673         case SID_PARA_DLG:
1674         {
1675             SwPaM* pPaM = nullptr;
1676 
1677             if ( pArgs )
1678             {
1679                 const SwPaMItem* pPaMItem = pArgs->GetItemIfSet( GetPool().GetWhichIDFromSlotID( FN_PARAM_PAM ), false );
1680                 if ( pPaMItem )
1681                     pPaM = pPaMItem->GetValue( );
1682             }
1683 
1684             if ( !pPaM )
1685                 pPaM = rWrtSh.GetCursor();
1686 
1687             FieldUnit eMetric = ::GetDfltMetric( dynamic_cast<SwWebView*>( &GetView()) != nullptr );
1688             SwModule* mod = SwModule::get();
1689             mod->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast<sal_uInt16>(eMetric)));
1690 
1691             bool bApplyCharUnit = ::HasCharUnit( dynamic_cast<SwWebView*>( &GetView()) != nullptr  );
1692             mod->PutItem(SfxBoolItem(SID_ATTR_APPLYCHARUNIT, bApplyCharUnit));
1693 
1694             SfxItemSetFixed<
1695                     RES_PARATR_BEGIN, RES_FRMATR_END - 1,
1696                     // FillAttribute support:
1697                     XATTR_FILL_FIRST, XATTR_FILL_LAST,
1698                     // Includes SID_ATTR_TABSTOP_POS:
1699                     SID_ATTR_TABSTOP_DEFAULTS, SID_ATTR_TABSTOP_OFFSET,
1700                     SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
1701                     SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP,
1702                     // Items to hand over XPropertyList things like XColorList,
1703                     // XHatchList, XGradientList, and XBitmapList to the Area
1704                     // TabPage:
1705                     SID_COLOR_TABLE, SID_PATTERN_LIST,
1706                     SID_HTML_MODE, SID_HTML_MODE,
1707                     SID_ATTR_PARA_PAGENUM, SID_ATTR_PARA_PAGENUM,
1708                     FN_PARAM_1, FN_PARAM_1,
1709                     FN_NUMBER_NEWSTART, FN_NUMBER_NEWSTART_AT,
1710                     FN_DROP_TEXT, FN_DROP_CHAR_STYLE_NAME>  aCoreSet( GetPool() );
1711 
1712             // get also the list level indent values merged as LR-SPACE item, if needed.
1713             rWrtSh.GetPaMAttr( pPaM, aCoreSet, true );
1714 
1715             // create needed items for XPropertyList entries from the DrawModel so that
1716             // the Area TabPage can access them
1717             // Do this after GetCurAttr, this resets the ItemSet content again
1718             SwDrawModel* pDrawModel = GetView().GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
1719 
1720             aCoreSet.Put(SvxColorListItem(pDrawModel->GetColorList(), SID_COLOR_TABLE));
1721             aCoreSet.Put(SvxGradientListItem(pDrawModel->GetGradientList(), SID_GRADIENT_LIST));
1722             aCoreSet.Put(SvxHatchListItem(pDrawModel->GetHatchList(), SID_HATCH_LIST));
1723             aCoreSet.Put(SvxBitmapListItem(pDrawModel->GetBitmapList(), SID_BITMAP_LIST));
1724             aCoreSet.Put(SvxPatternListItem(pDrawModel->GetPatternList(), SID_PATTERN_LIST));
1725             aCoreSet.Put(SfxUInt16Item(SID_HTML_MODE,
1726                             ::GetHtmlMode(GetView().GetDocShell())));
1727 
1728             // Tabulators: Put DefaultTabs into ItemSet
1729             const SvxTabStopItem& rDefTabs =
1730                             GetPool().GetUserOrPoolDefaultItem(RES_PARATR_TABSTOP);
1731 
1732             const sal_uInt16 nDefDist = o3tl::narrowing<sal_uInt16>(::GetTabDist( rDefTabs ));
1733             SfxUInt16Item aDefDistItem( SID_ATTR_TABSTOP_DEFAULTS, nDefDist );
1734             aCoreSet.Put( aDefDistItem );
1735 
1736             // Current tabulator
1737             SfxUInt16Item aTabPos( SID_ATTR_TABSTOP_POS, 0 );
1738             aCoreSet.Put( aTabPos );
1739 
1740             // Left border as offset
1741             //#i24363# tab stops relative to indent
1742             const tools::Long nOff
1743                 = rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT)
1744                       ? aCoreSet.Get(RES_MARGIN_TEXTLEFT).ResolveTextLeft({})
1745                       : 0;
1746             SfxInt32Item aOff( SID_ATTR_TABSTOP_OFFSET, nOff );
1747             aCoreSet.Put( aOff );
1748 
1749             // Setting the BoxInfo
1750             ::PrepareBoxInfo( aCoreSet, rWrtSh );
1751 
1752             // Current page format
1753             ::SwToSfxPageDescAttr( aCoreSet );
1754 
1755             // Properties of numbering
1756             if (rWrtSh.GetNumRuleAtCurrCursorPos())
1757             {
1758                 SfxBoolItem aStart( FN_NUMBER_NEWSTART, rWrtSh.IsNumRuleStart( pPaM ) );
1759                 aCoreSet.Put(aStart);
1760                 SfxUInt16Item aStartAt( FN_NUMBER_NEWSTART_AT,
1761                                         rWrtSh.GetNodeNumStart( pPaM ) );
1762                 aCoreSet.Put(aStartAt);
1763             }
1764             VclPtr<SfxAbstractTabDialog> pDlg;
1765 
1766             if ( bUseDialog && GetActiveView() )
1767             {
1768                 OUString sDefPage;
1769                 if (pItem)
1770                     sDefPage = static_cast<const SfxStringItem*>(pItem)->GetValue();
1771 
1772                 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1773                 pDlg.reset(pFact->CreateSwParaDlg(GetView().GetFrameWeld(), GetView(), aCoreSet, false, sDefPage));
1774             }
1775 
1776             if ( !bUseDialog )
1777             {
1778                 if ( nSlot == SID_ATTR_PARA_LRSPACE)
1779                 {
1780                     SvxLRSpaceItem aParaMargin(static_cast<const SvxLRSpaceItem&>(pArgs->Get(nSlot)));
1781                     SvxFirstLineIndentItem firstLine(RES_MARGIN_FIRSTLINE);
1782                     SvxTextLeftMarginItem leftMargin(RES_MARGIN_TEXTLEFT);
1783                     SvxRightMarginItem rightMargin(RES_MARGIN_RIGHT);
1784                     firstLine.SetTextFirstLineOffset(aParaMargin.GetTextFirstLineOffset(),
1785                                                      aParaMargin.GetPropTextFirstLineOffset());
1786                     firstLine.SetAutoFirst(aParaMargin.IsAutoFirst());
1787                     leftMargin.SetTextLeft(aParaMargin.GetTextLeft(), aParaMargin.GetPropLeft());
1788                     rightMargin.SetRight(aParaMargin.GetRight(), aParaMargin.GetPropRight());
1789                     aCoreSet.Put(firstLine);
1790                     aCoreSet.Put(leftMargin);
1791                     aCoreSet.Put(rightMargin);
1792 
1793                     sw_ParagraphDialogResult(&aCoreSet, rWrtSh, rReq, pPaM);
1794                 }
1795                 else
1796                     sw_ParagraphDialogResult(const_cast<SfxItemSet*>(pArgs), rWrtSh, rReq, pPaM);
1797             }
1798             else if (pDlg)
1799             {
1800                 auto pRequest = std::make_shared<SfxRequest>(rReq);
1801                 rReq.Ignore(); // the 'old' request is not relevant any more
1802 
1803                 auto vCursors = CopyPaMRing(*pPaM); // tdf#134439 make a copy to use at later apply
1804                 pDlg->StartExecuteAsync([pDlg, &rWrtSh, pDrawModel, pRequest=std::move(pRequest), nDefDist, vCursors=std::move(vCursors)](sal_Int32 nResult){
1805                     if (nResult == RET_OK)
1806                     {
1807                         // Apply defaults if necessary.
1808                         SfxItemSet* pSet = const_cast<SfxItemSet*>(pDlg->GetOutputItemSet());
1809                         sal_uInt16 nNewDist;
1810                         const SfxUInt16Item* pDefaultsItem = pSet->GetItemIfSet(SID_ATTR_TABSTOP_DEFAULTS, false);
1811                         if (pDefaultsItem && nDefDist != (nNewDist = pDefaultsItem->GetValue()) )
1812                         {
1813                             SvxTabStopItem aDefTabs( 0, 0, SvxTabAdjust::Default, RES_PARATR_TABSTOP );
1814                             MakeDefTabs( nNewDist, aDefTabs );
1815                             rWrtSh.SetDefault( aDefTabs );
1816                             pSet->ClearItem( SID_ATTR_TABSTOP_DEFAULTS );
1817                         }
1818 
1819                         const SfxPoolItem* pItem2 = nullptr;
1820                         if (SfxItemState::SET == pSet->GetItemState(FN_PARAM_1, false, &pItem2))
1821                         {
1822                             pSet->Put(SfxStringItem(FN_DROP_TEXT, static_cast<const SfxStringItem*>(pItem2)->GetValue()));
1823                             pSet->ClearItem(FN_PARAM_1);
1824                         }
1825 
1826                         if (const SwFormatDrop* pDropItem = pSet->GetItemIfSet(RES_PARATR_DROP, false))
1827                         {
1828                             UIName sCharStyleName;
1829                             if (pDropItem->GetCharFormat())
1830                                 sCharStyleName = pDropItem->GetCharFormat()->GetName();
1831                             pSet->Put(SfxStringItem(FN_DROP_CHAR_STYLE_NAME, sCharStyleName.toString()));
1832                         }
1833 
1834                         const XFillStyleItem* pFS = pSet->GetItem<XFillStyleItem>(XATTR_FILLSTYLE);
1835                         bool bSet = pFS && pFS->GetValue() == drawing::FillStyle_GRADIENT;
1836                         const XFillGradientItem* pTempGradItem
1837                             = bSet ? pSet->GetItem<XFillGradientItem>(XATTR_FILLGRADIENT) : nullptr;
1838                         if (pTempGradItem && pTempGradItem->GetName().isEmpty())
1839                         {
1840                             // MigrateItemSet guarantees unique gradient names
1841                             SfxItemSetFixed<XATTR_FILLGRADIENT, XATTR_FILLGRADIENT> aMigrateSet(rWrtSh.GetView().GetPool());
1842                             aMigrateSet.Put(XFillGradientItem(u"gradient"_ustr, pTempGradItem->GetGradientValue()));
1843                             SdrModel::MigrateItemSet(&aMigrateSet, pSet, *pDrawModel);
1844                         }
1845 
1846                         bSet = pFS && pFS->GetValue() == drawing::FillStyle_HATCH;
1847                         const XFillHatchItem* pTempHatchItem
1848                             = bSet ? pSet->GetItem<XFillHatchItem>(XATTR_FILLHATCH) : nullptr;
1849                         if (pTempHatchItem && pTempHatchItem->GetName().isEmpty())
1850                         {
1851                             SfxItemSetFixed<XATTR_FILLHATCH, XATTR_FILLHATCH> aMigrateSet(rWrtSh.GetView().GetPool());
1852                             aMigrateSet.Put(XFillHatchItem(u"hatch"_ustr, pTempHatchItem->GetHatchValue()));
1853                             SdrModel::MigrateItemSet(&aMigrateSet, pSet, *pDrawModel);
1854                         }
1855 
1856                         sw_ParagraphDialogResult(pSet, rWrtSh, *pRequest, vCursors->front().get());
1857                     }
1858                     pDlg->disposeOnce();
1859                 });
1860             }
1861         }
1862         break;
1863         case FN_NUM_CONTINUE:
1864         {
1865             OUString sContinuedListId;
1866             const SwNumRule* pRule =
1867                 rWrtSh.SearchNumRule( true, sContinuedListId );
1868             // #i86492#
1869             // Search also for bullet list
1870             if ( !pRule )
1871             {
1872                 pRule = rWrtSh.SearchNumRule( false, sContinuedListId );
1873             }
1874             if ( pRule )
1875             {
1876                 rWrtSh.SetCurNumRule( *pRule, false, sContinuedListId );
1877             }
1878         }
1879         break;
1880 
1881         case FN_SELECT_PARA:
1882         {
1883             if ( !rWrtSh.IsSttOfPara() )
1884                 rWrtSh.SttPara();
1885             else
1886                 rWrtSh.EnterStdMode();
1887             rWrtSh.EndPara( true );
1888         }
1889         break;
1890 
1891         case SID_DEC_INDENT:
1892         case SID_INC_INDENT:
1893         //According to the requirement, modified the behavior when user
1894         //using the indent button on the toolbar. Now if we increase/decrease indent for a
1895         //paragraph which has bullet style it will increase/decrease the bullet level.
1896         {
1897             //If the current paragraph has bullet call the function to
1898             //increase or decrease the bullet level.
1899             //Why could I know whether a paragraph has bullet or not by checking the below conditions?
1900             //Please refer to the "case KEY_TAB:" section in SwEditWin::KeyInput(..) :
1901             //      if( rSh.GetCurNumRule() && rSh.IsSttOfPara() &&
1902             //                  !rSh.HasReadonlySel() )
1903             //              eKeyState = KS_NumDown;
1904             //Above code demonstrates that when the cursor is at the start of a paragraph which has bullet,
1905             //press TAB will increase the bullet level.
1906             //So I copied from that ^^
1907             if ( rWrtSh.GetNumRuleAtCurrCursorPos() && !rWrtSh.HasReadonlySel() )
1908             {
1909                 rWrtSh.NumUpDown( SID_INC_INDENT == nSlot );
1910             }
1911             else                //execute the original processing functions
1912             {
1913                 //below is copied of the old codes
1914                 rWrtSh.MoveLeftMargin( SID_INC_INDENT == nSlot, rReq.GetModifier() != KEY_MOD1 );
1915             }
1916         }
1917         rReq.Done();
1918         break;
1919 
1920         case FN_DEC_INDENT_OFFSET:
1921         case FN_INC_INDENT_OFFSET:
1922             rWrtSh.MoveLeftMargin( FN_INC_INDENT_OFFSET == nSlot, rReq.GetModifier() == KEY_MOD1 );
1923             rReq.Done();
1924             break;
1925 
1926         case SID_ATTR_CHAR_COLOR2:
1927         {
1928             std::unique_ptr<const SvxColorItem> pRecentColor; // manage lifecycle scope
1929             if (!pItem)
1930             {
1931                 // no color provided: use the pre-selected color shown in the toolbar/sidebar
1932                 const std::optional<NamedColor> oColor
1933                     = GetView().GetDocShell()->GetRecentColor(SID_ATTR_CHAR_COLOR);
1934                 if (oColor.has_value())
1935                 {
1936                     const model::ComplexColor aCol = (*oColor).getComplexColor();
1937                     pRecentColor = std::make_unique<const SvxColorItem>(
1938                         aCol.getFinalColor(), aCol, RES_CHRATR_COLOR);
1939                     pItem = pRecentColor.get();
1940                 }
1941             }
1942 
1943             if (pItem)
1944             {
1945                 auto* pColorItem = static_cast<const SvxColorItem*>(pItem);
1946                 SwEditWin& rEditWin = GetView().GetEditWin();
1947                 rEditWin.SetWaterCanTextColor(pColorItem->GetValue());
1948                 SwApplyTemplate* pApply = rEditWin.GetApplyTemplate();
1949 
1950                 // If there is a selection, then set the color on it
1951                 // otherwise, it'll be the color for the next text to be typed
1952                 if (!pApply || pApply->nColor != SID_ATTR_CHAR_COLOR_EXT)
1953                 {
1954                     rWrtSh.SetAttrItem(SvxColorItem(pColorItem->GetValue(), pColorItem->getComplexColor(), RES_CHRATR_COLOR));
1955                 }
1956 
1957                 rReq.Done();
1958             }
1959         }
1960         break;
1961         case SID_ATTR_CHAR_BACK_COLOR:
1962         case SID_ATTR_CHAR_COLOR_BACKGROUND: // deprecated
1963         case SID_ATTR_CHAR_COLOR_EXT:
1964         {
1965             Color aColor = COL_TRANSPARENT;
1966             model::ComplexColor aComplexColor;
1967 
1968             if (pItem)
1969             {
1970                 auto* pColorItem = static_cast<const SvxColorItem*>(pItem);
1971                 aColor = pColorItem->GetValue();
1972                 aComplexColor = pColorItem->getComplexColor();
1973             }
1974             else if (nSlot == SID_ATTR_CHAR_BACK_COLOR)
1975             {
1976                 // no color provided: use the pre-selected color shown in the toolbar/sidebar
1977                 const std::optional<NamedColor> oColor
1978                     = GetView().GetDocShell()->GetRecentColor(nSlot);
1979                 if (oColor.has_value())
1980                 {
1981                     aComplexColor = (*oColor).getComplexColor();
1982                     aColor = aComplexColor.getFinalColor();
1983                 }
1984             }
1985 
1986             SwEditWin& rEdtWin = GetView().GetEditWin();
1987             if (nSlot != SID_ATTR_CHAR_COLOR_EXT)
1988                 rEdtWin.SetWaterCanTextBackColor(aColor);
1989             else if (pItem)
1990                 rEdtWin.SetWaterCanTextColor(aColor);
1991 
1992             SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
1993             SwApplyTemplate aTempl;
1994             if (!pApply && (rWrtSh.HasSelection() || rReq.IsAPI()))
1995             {
1996                 if (nSlot != SID_ATTR_CHAR_COLOR_EXT)
1997                 {
1998                     SfxItemSetFixed<RES_CHRATR_BACKGROUND, RES_CHRATR_BACKGROUND> aCoreSet( rWrtSh.GetView().GetPool() );
1999 
2000                     rWrtSh.GetCurAttr(aCoreSet);
2001 
2002                     // Remove highlight if already set of the same color
2003                     const SvxBrushItem& rBrushItem = aCoreSet.Get(RES_CHRATR_BACKGROUND);
2004                     if (aColor == rBrushItem.GetColor())
2005                     {
2006                         aComplexColor = model::ComplexColor();
2007                         aColor = COL_TRANSPARENT;
2008                     }
2009                     ApplyCharBackground(aColor, aComplexColor, rWrtSh);
2010                 }
2011                 else
2012                     rWrtSh.SetAttrItem(SvxColorItem(aColor, aComplexColor, RES_CHRATR_COLOR));
2013             }
2014             else
2015             {
2016                 if(!pApply || pApply->nColor != nSlot)
2017                     aTempl.nColor = nSlot;
2018                 rEdtWin.SetApplyTemplate(aTempl);
2019             }
2020 
2021             rReq.Done();
2022         }
2023         break;
2024 
2025         case FN_NUM_BULLET_MOVEDOWN:
2026             if (!rWrtSh.IsAddMode())
2027                 rWrtSh.MoveParagraph();
2028             rReq.Done();
2029             break;
2030 
2031         case FN_NUM_BULLET_MOVEUP:
2032             if (!rWrtSh.IsAddMode())
2033                 rWrtSh.MoveParagraph(SwNodeOffset(-1));
2034             rReq.Done();
2035             break;
2036         case SID_INSERT_HYPERLINK:
2037         {
2038             SfxRequest aReq(SID_HYPERLINK_DIALOG, SfxCallMode::SLOT, SfxGetpApp()->GetPool());
2039             GetView().GetViewFrame().ExecuteSlot( aReq);
2040             rReq.Ignore();
2041         }
2042         break;
2043         case SID_RUBY_DIALOG:
2044         case SID_HYPERLINK_DIALOG:
2045         {
2046             SfxRequest aReq(nSlot, SfxCallMode::SLOT, SfxGetpApp()->GetPool());
2047             GetView().GetViewFrame().ExecuteSlot( aReq);
2048             rReq.Ignore();
2049         }
2050         break;
2051     case FN_INSERT_PAGEHEADER:
2052     case FN_INSERT_PAGEFOOTER:
2053     if(pArgs && pArgs->Count())
2054     {
2055         OUString sStyleName;
2056         if(pItem)
2057             sStyleName = static_cast<const SfxStringItem*>(pItem)->GetValue();
2058         bool bOn = true;
2059         if( SfxItemState::SET == pArgs->GetItemState(FN_PARAM_1, false, &pItem))
2060             bOn = static_cast<const SfxBoolItem*>(pItem)->GetValue();
2061         rWrtSh.ChangeHeaderOrFooter(UIName(sStyleName), FN_INSERT_PAGEHEADER == nSlot, bOn, !rReq.IsAPI());
2062         rReq.Done();
2063     }
2064     break;
2065     case FN_READONLY_SELECTION_MODE :
2066         if(GetView().GetDocShell()->IsReadOnly())
2067         {
2068             rWrtSh.SetReadonlySelectionOption(
2069                 !rWrtSh.GetViewOptions()->IsSelectionInReadonly());
2070             rWrtSh.ShowCursor();
2071         }
2072     break;
2073     case FN_SELECTION_MODE_DEFAULT:
2074     case FN_SELECTION_MODE_BLOCK :
2075     {
2076         bool bSetBlockMode = !rWrtSh.IsBlockMode();
2077         if( pArgs && SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem))
2078             bSetBlockMode = static_cast<const SfxBoolItem*>(pItem)->GetValue();
2079         if( ( nSlot == FN_SELECTION_MODE_DEFAULT ) != bSetBlockMode )
2080             rWrtSh.EnterBlockMode();
2081         else
2082             rWrtSh.EnterStdMode();
2083         SfxBindings &rBnd = GetView().GetViewFrame().GetBindings();
2084         rBnd.Invalidate(FN_STAT_SELMODE);
2085         rBnd.Update(FN_STAT_SELMODE);
2086     }
2087     break;
2088     case SID_OPEN_HYPERLINK:
2089     case SID_COPY_HYPERLINK_LOCATION:
2090     {
2091         SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
2092         rWrtSh.GetCurAttr(aSet);
2093 
2094         const SwFormatINetFormat* pINetFormat = nullptr;
2095         if(SfxItemState::SET <= aSet.GetItemState( RES_TXTATR_INETFMT ))
2096             pINetFormat = &aSet.Get(RES_TXTATR_INETFMT);
2097         else if (!rWrtSh.HasSelection())
2098         {
2099             // is the cursor at the beginning of a hyperlink?
2100             const SwTextNode* pTextNd = rWrtSh.GetCursor()->GetPointNode().GetTextNode();
2101             if (pTextNd)
2102             {
2103                 const sal_Int32 nIndex = rWrtSh.GetCursor()->Start()->GetContentIndex();
2104                 const SwTextAttr* pINetFmt = pTextNd->GetTextAttrAt(nIndex, RES_TXTATR_INETFMT);
2105                 if (pINetFmt && !pINetFmt->GetINetFormat().GetValue().isEmpty())
2106                     pINetFormat = &pINetFmt->GetINetFormat();
2107             }
2108         }
2109 
2110         if (pINetFormat)
2111         {
2112             if (nSlot == SID_OPEN_HYPERLINK)
2113             {
2114                 rWrtSh.ClickToINetAttr(*pINetFormat);
2115             }
2116             else if (nSlot == SID_COPY_HYPERLINK_LOCATION)
2117             {
2118                 OUString hyperlinkLocation = pINetFormat->GetValue();
2119                 ::uno::Reference< datatransfer::clipboard::XClipboard > xClipboard = GetView().GetEditWin().GetClipboard();
2120                 vcl::unohelper::TextDataObject::CopyStringTo(hyperlinkLocation, xClipboard, SfxViewShell::Current());
2121             }
2122         }
2123         else
2124         {
2125             SwField* pField = rWrtSh.GetCurField();
2126             if (pField && pField->GetTyp()->Which() == SwFieldIds::TableOfAuthorities)
2127             {
2128                 const auto& rAuthorityField = *static_cast<const SwAuthorityField*>(pField);
2129                 OUString targetURL = u""_ustr;
2130 
2131                 if (auto targetType = rAuthorityField.GetTargetType();
2132                     targetType == SwAuthorityField::TargetType::UseDisplayURL
2133                     || targetType == SwAuthorityField::TargetType::UseTargetURL)
2134                 {
2135                     // Bibliography entry with URL also provides a hyperlink.
2136                     targetURL = rAuthorityField.GetAbsoluteURL();
2137                 }
2138 
2139                 if (targetURL.getLength() > 0)
2140                 {
2141                     if (nSlot == SID_OPEN_HYPERLINK)
2142                     {
2143                         ::LoadURL(rWrtSh, targetURL, LoadUrlFlags::NewView, /*rTargetFrameName=*/OUString());
2144                     }
2145                     else if (nSlot == SID_COPY_HYPERLINK_LOCATION)
2146                     {
2147                         ::uno::Reference< datatransfer::clipboard::XClipboard > xClipboard = GetView().GetEditWin().GetClipboard();
2148                         vcl::unohelper::TextDataObject::CopyStringTo(targetURL, xClipboard, SfxViewShell::Current());
2149                     }
2150                 }
2151             }
2152         }
2153     }
2154     break;
2155     case FN_OPEN_LOCAL_URL:
2156     {
2157         OUString aLocalURL = GetLocalURL(rWrtSh);
2158         if (!aLocalURL.isEmpty())
2159         {
2160             ::LoadURL(rWrtSh, aLocalURL, LoadUrlFlags::NewView, /*rTargetFrameName=*/OUString());
2161         }
2162     }
2163     break;
2164     case SID_OPEN_XML_FILTERSETTINGS:
2165     {
2166         HandleOpenXmlFilterSettings(rReq);
2167     }
2168     break;
2169     case FN_FORMAT_APPLY_HEAD1:
2170     {
2171     }
2172     break;
2173     case FN_FORMAT_APPLY_HEAD2:
2174     {
2175     }
2176     break;
2177     case FN_FORMAT_APPLY_HEAD3:
2178     {
2179     }
2180     break;
2181     case FN_FORMAT_APPLY_DEFAULT:
2182     {
2183     }
2184     break;
2185     case FN_FORMAT_APPLY_TEXTBODY:
2186     {
2187     }
2188     break;
2189     case FN_WORDCOUNT_DIALOG:
2190     {
2191         GetView().UpdateWordCount(this, nSlot);
2192     }
2193     break;
2194     case FN_PROTECT_FIELDS:
2195     case FN_PROTECT_BOOKMARKS:
2196     {
2197         IDocumentSettingAccess& rIDSA = rWrtSh.getIDocumentSettingAccess();
2198         DocumentSettingId aSettingId = nSlot == FN_PROTECT_FIELDS
2199                                            ? DocumentSettingId::PROTECT_FIELDS
2200                                            : DocumentSettingId::PROTECT_BOOKMARKS;
2201         rIDSA.set(aSettingId, !rIDSA.get(aSettingId));
2202         // Invalidate so that toggle state gets updated
2203         SfxViewFrame& rViewFrame = GetView().GetViewFrame();
2204         rViewFrame.GetBindings().Invalidate(nSlot);
2205         rViewFrame.GetBindings().Update(nSlot);
2206     }
2207     break;
2208     case SID_FM_CTL_PROPERTIES:
2209     {
2210         SwPosition aPos(*GetShell().GetCursor()->GetPoint());
2211         sw::mark::Fieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
2212         if ( !pFieldBM )
2213         {
2214             aPos.AdjustContent(-1);
2215             pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
2216         }
2217 
2218         if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN
2219              && !(rWrtSh.GetCurrSection() && rWrtSh.GetCurrSection()->IsProtect()) )
2220         {
2221             SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2222             VclPtr<AbstractDropDownFormFieldDialog> pDlg(pFact->CreateDropDownFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pFieldBM));
2223             auto xRequest = std::make_shared<SfxRequest>(rReq);
2224             rReq.Ignore(); // the 'old' request is not relevant any more
2225             auto pWrtSh = &rWrtSh;
2226             pDlg->StartExecuteAsync(
2227                 [pDlg, pFieldBM, pWrtSh, xRequest=std::move(xRequest)] (sal_Int32 nResult)->void
2228                 {
2229                     if (nResult == RET_OK)
2230                     {
2231                         pDlg->Apply();
2232                         pFieldBM->Invalidate();
2233                         pWrtSh->InvalidateWindows( SwRect(pWrtSh->GetView().GetVisArea()) );
2234                         pWrtSh->UpdateCursor(); // cursor position might be invalid
2235                     }
2236                     pDlg->disposeOnce();
2237                     xRequest->Done();
2238                 }
2239             );
2240         }
2241         else if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDATE )
2242         {
2243             SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2244             sw::mark::DateFieldmark* pDateField = &dynamic_cast<sw::mark::DateFieldmark&>(*pFieldBM);
2245             VclPtr<AbstractDateFormFieldDialog> pDlg(pFact->CreateDateFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pDateField, *GetView().GetDocShell()->GetDoc()));
2246             auto pWrtSh = &rWrtSh;
2247             auto xRequest = std::make_shared<SfxRequest>(rReq);
2248             rReq.Ignore(); // the 'old' request is not relevant any more
2249             pDlg->StartExecuteAsync(
2250                 [pDlg, pWrtSh, pDateField, xRequest=std::move(xRequest)] (sal_Int32 nResult)->void
2251                 {
2252                     if (nResult == RET_OK)
2253                     {
2254                         pDlg->Apply();
2255                         pDateField->Invalidate();
2256                         pWrtSh->InvalidateWindows( SwRect(pWrtSh->GetView().GetVisArea()) );
2257                         pWrtSh->UpdateCursor(); // cursor position might be invalid
2258                     }
2259                     pDlg->disposeOnce();
2260                     xRequest->Done();
2261                 }
2262             );
2263         }
2264         else
2265         {
2266             SfxRequest aReq(GetView().GetViewFrame(), SID_FM_CTL_PROPERTIES);
2267             aReq.AppendItem( SfxBoolItem( SID_FM_CTL_PROPERTIES, true ) );
2268             rWrtSh.GetView().GetFormShell()->Execute( aReq );
2269         }
2270     }
2271     break;
2272     case SID_FM_TRANSLATE:
2273     {
2274 #if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
2275         const SfxPoolItem* pTargetLangStringItem = nullptr;
2276         if (pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_TARGETLANG_STR, false, &pTargetLangStringItem))
2277         {
2278             std::optional<OUString> oDeeplAPIUrl = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get();
2279             std::optional<OUString> oDeeplKey = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get();
2280             if (!oDeeplAPIUrl || oDeeplAPIUrl->isEmpty() || !oDeeplKey || oDeeplKey->isEmpty())
2281             {
2282                 SAL_WARN("sw.ui", "SID_FM_TRANSLATE: API options are not set");
2283                 break;
2284             }
2285             const OString aAPIUrl = OUStringToOString(rtl::Concat2View(*oDeeplAPIUrl + "?tag_handling=html"), RTL_TEXTENCODING_UTF8).trim();
2286             const OString aAuthKey = OUStringToOString(*oDeeplKey, RTL_TEXTENCODING_UTF8).trim();
2287             OString aTargetLang = OUStringToOString(static_cast<const SfxStringItem*>(pTargetLangStringItem)->GetValue(), RTL_TEXTENCODING_UTF8);
2288             SwTranslateHelper::TranslateAPIConfig aConfig({aAPIUrl, aAuthKey, aTargetLang});
2289             SwTranslateHelper::TranslateDocument(rWrtSh, aConfig);
2290         }
2291         else
2292         {
2293             SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2294             std::shared_ptr<AbstractSwTranslateLangSelectDlg> pAbstractDialog(pFact->CreateSwTranslateLangSelectDlg(GetView().GetFrameWeld(), rWrtSh));
2295             std::shared_ptr<weld::DialogController> pDialogController(pAbstractDialog->getDialogController());
2296             weld::DialogController::runAsync(pDialogController, [] (sal_Int32 /*nResult*/) { });
2297         }
2298 #endif // HAVE_FEATURE_CURL && ENABLE_WASM_STRIP_EXTRA
2299     }
2300     break;
2301     case SID_SPELLCHECK_IGNORE:
2302     {
2303         SwPaM *pPaM = rWrtSh.GetCursor();
2304         if (pPaM)
2305             SwEditShell::IgnoreGrammarErrorAt( *pPaM );
2306     }
2307     break;
2308     case SID_SPELLCHECK_IGNORE_ALL:
2309     {
2310         OUString sApplyText;
2311         const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
2312         if (pItem2)
2313             sApplyText = pItem2->GetValue();
2314 
2315         if(sApplyText == "Grammar")
2316         {
2317             linguistic2::ProofreadingResult aGrammarCheckRes;
2318             sal_Int32 nErrorInResult = -1;
2319             uno::Sequence< OUString > aSuggestions;
2320             sal_Int32 nErrorPosInText = -1;
2321             SwRect aToFill;
2322             bool bCorrectionRes = rWrtSh.GetGrammarCorrection( aGrammarCheckRes, nErrorPosInText, nErrorInResult, aSuggestions, nullptr, aToFill );
2323             if(bCorrectionRes)
2324             {
2325                 try {
2326                     uno::Reference< linguistic2::XDictionary > xDictionary = LinguMgr::GetIgnoreAllList();
2327                     aGrammarCheckRes.xProofreader->ignoreRule(
2328                         aGrammarCheckRes.aErrors[ nErrorInResult ].aRuleIdentifier,
2329                             aGrammarCheckRes.aLocale );
2330                     // refresh the layout of the actual paragraph (faster)
2331                     SwPaM *pPaM = rWrtSh.GetCursor();
2332                     if (pPaM)
2333                         SwEditShell::IgnoreGrammarErrorAt( *pPaM );
2334                     if (xDictionary.is() && pPaM)
2335                     {
2336                         linguistic::AddEntryToDic( xDictionary, pPaM->GetText(), false, OUString() );
2337                         // refresh the layout of all paragraphs (workaround to launch a dictionary event)
2338                         xDictionary->setActive(false);
2339                         xDictionary->setActive(true);
2340                     }
2341                 }
2342                 catch( const uno::Exception& )
2343                 {
2344                 }
2345             }
2346         }
2347         else if (sApplyText == "Spelling")
2348         {
2349             AddWordToWordbook(LinguMgr::GetIgnoreAllList(), rWrtSh);
2350         }
2351     }
2352     break;
2353     case SID_ADD_TO_WORDBOOK:
2354     {
2355         OUString aDicName;
2356         if (const SfxStringItem* pItem1 = rReq.GetArg<SfxStringItem>(FN_PARAM_1))
2357             aDicName = pItem1->GetValue();
2358 
2359         uno::Reference<linguistic2::XSearchableDictionaryList> xDicList(LinguMgr::GetDictionaryList());
2360         uno::Reference<linguistic2::XDictionary> xDic = xDicList.is() ? xDicList->getDictionaryByName(aDicName) : nullptr;
2361         if (AddWordToWordbook(xDic, rWrtSh))
2362         {
2363             // save modified user-dictionary if it is persistent
2364             uno::Reference<frame::XStorable> xSavDic(xDic, uno::UNO_QUERY);
2365             if (xSavDic.is())
2366                 xSavDic->store();
2367         }
2368         break;
2369     }
2370     break;
2371     case SID_SPELLCHECK_APPLY_SUGGESTION:
2372     {
2373         OUString sApplyText;
2374         const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
2375         if (pItem2)
2376             sApplyText = pItem2->GetValue();
2377 
2378         static constexpr OUString sSpellingRule(u"Spelling_"_ustr);
2379         static constexpr OUString sGrammarRule(u"Grammar_"_ustr);
2380 
2381         bool bGrammar = false;
2382         sal_Int32 nPos = 0;
2383         uno::Reference< linguistic2::XSpellAlternatives >  xSpellAlt;
2384         if(-1 != (nPos = sApplyText.indexOf( sGrammarRule )))
2385         {
2386             sApplyText = sApplyText.replaceAt(nPos, sGrammarRule.getLength(), u"");
2387             bGrammar = true;
2388         }
2389         else if (-1 != (nPos = sApplyText.indexOf( sSpellingRule )))
2390         {
2391             sApplyText = sApplyText.replaceAt(nPos, sSpellingRule.getLength(), u"");
2392             SwRect aToFill;
2393             xSpellAlt.set(rWrtSh.GetCorrection(nullptr, aToFill));
2394             bGrammar = false;
2395         }
2396 
2397         if (!bGrammar && !xSpellAlt.is())
2398             return;
2399 
2400         bool bOldIns = rWrtSh.IsInsMode();
2401         rWrtSh.SetInsMode();
2402 
2403         OUString aTmp( sApplyText );
2404         OUString aOrig( bGrammar ? OUString() : xSpellAlt->getWord() );
2405 
2406         // if original word has a trailing . (likely the end of a sentence)
2407         // and the replacement text hasn't, then add it to the replacement
2408         if (!aTmp.isEmpty() && !aOrig.isEmpty() &&
2409             aOrig.endsWith(".") && /* !IsAlphaNumeric ??*/
2410             !aTmp.endsWith("."))
2411         {
2412             aTmp += ".";
2413         }
2414 
2415         SwRewriter aRewriter;
2416 
2417         aRewriter.AddRule(UndoArg1, rWrtSh.GetCursorDescr()
2418             // don't show the hidden control character of the comment
2419             .replaceAll(OUStringChar(CH_TXTATR_INWORD), "") );
2420         aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
2421 
2422         OUString aTmpStr = SwResId(STR_START_QUOTE) +
2423             aTmp + SwResId(STR_END_QUOTE);
2424         aRewriter.AddRule(UndoArg3, aTmpStr);
2425 
2426         rWrtSh.StartUndo(SwUndoId::UI_REPLACE, &aRewriter);
2427         rWrtSh.StartAction();
2428 
2429         // keep comments at the end of the replacement in case spelling correction is
2430         // invoked via the context menu. The spell check dialog does the correction in edlingu.cxx.
2431         rWrtSh.ReplaceKeepComments(aTmp);
2432 
2433         rWrtSh.EndAction();
2434         rWrtSh.EndUndo();
2435 
2436         rWrtSh.SetInsMode( bOldIns );
2437     }
2438     break;
2439         case FN_TRANSFORM_DOCUMENT_STRUCTURE:
2440         {
2441             // get the parameter, what to transform
2442             OUString aDataJson;
2443             const SfxStringItem* pDataJson = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
2444             if (pDataJson)
2445             {
2446                 aDataJson = pDataJson->GetValue();
2447                 aDataJson = rtl::Uri::decode(aDataJson, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
2448             }
2449 
2450             // parse the JSON got prom parameter
2451             boost::property_tree::ptree aTree;
2452             std::stringstream aStream(
2453                 (std::string(OUStringToOString(aDataJson, RTL_TEXTENCODING_UTF8))));
2454             try
2455             {
2456                 boost::property_tree::read_json(aStream, aTree);
2457             }
2458             catch (...)
2459             {
2460                 lcl_LogWarning("FillApi Transform parameter, Wrong JSON format. ");
2461                 throw;
2462             }
2463 
2464             // get the loaded content controls
2465             uno::Reference<text::XContentControlsSupplier> xCCSupplier(
2466                 GetView().GetDocShell()->GetModel(), uno::UNO_QUERY);
2467             if (!xCCSupplier.is())
2468                 break;
2469 
2470             uno::Reference<container::XIndexAccess> xContentControls
2471                 = xCCSupplier->getContentControls();
2472             int iCCcount = xContentControls->getCount();
2473 
2474             enum class ContentFilterType
2475             {
2476                 ERROR = -1,
2477                 INDEX,
2478                 TAG,
2479                 ALIAS,
2480                 ID
2481             };
2482             std::vector<std::string> aIdTexts = { ".ByIndex.", ".ByTag.", ".ByAlias.", ".ById." };
2483 
2484             // get charts
2485             uno::Reference<text::XTextEmbeddedObjectsSupplier> xEOS(
2486                 GetView().GetDocShell()->GetModel(), uno::UNO_QUERY);
2487             if (!xEOS.is())
2488                 break;
2489             uno::Reference<container::XIndexAccess> xEmbeddeds(xEOS->getEmbeddedObjects(),
2490                                                                uno::UNO_QUERY);
2491             if (!xEmbeddeds.is())
2492                 break;
2493 
2494             sal_Int32 nEOcount = xEmbeddeds->getCount();
2495 
2496             enum class ChartFilterType
2497             {
2498                 ERROR = -1,
2499                 INDEX,
2500                 NAME,
2501                 TITLE,
2502                 SUBTITLE
2503             };
2504             std::vector<std::string> aIdChartTexts
2505                 = { ".ByEmbedIndex.", ".ByEmbedName.", ".ByTitle.", ".BySubTitle." };
2506 
2507             // Iterate through the JSON data loaded into a tree structure
2508             for (const auto& aItem : aTree)
2509             {
2510                 if (aItem.first == "Transforms")
2511                 {
2512                     // Handle all transformations
2513                     for (const auto& aItem2Obj : aItem.second)
2514                     {
2515                         // handle `"Transforms": { `  and `"Transforms": [` cases as well
2516                         // if an element is an object `{...}`, then get the first element of the object
2517                         const auto& aItem2
2518                             = aItem2Obj.first == "" ? *aItem2Obj.second.ordered_begin() : aItem2Obj;
2519 
2520                         if (aItem2.first == "DocumentProperties")
2521                         {
2522                             uno::Reference<document::XDocumentPropertiesSupplier>
2523                                 xDocumentPropsSupplier(GetView().GetDocShell()->GetModel(),
2524                                                        uno::UNO_QUERY);
2525                             if (!xDocumentPropsSupplier.is())
2526                                 continue;
2527                             uno::Reference<document::XDocumentProperties2> xDocProps(
2528                                 xDocumentPropsSupplier->getDocumentProperties(), uno::UNO_QUERY);
2529                             if (!xDocProps.is())
2530                                 continue;
2531 
2532                             for (const auto& aItem3 : aItem2.second)
2533                             {
2534                                 if (aItem3.first == "Author")
2535                                 {
2536                                     xDocProps->setAuthor(
2537                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2538                                                           RTL_TEXTENCODING_UTF8));
2539                                 }
2540                                 else if (aItem3.first == "Generator")
2541                                 {
2542                                     xDocProps->setGenerator(
2543                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2544                                                           RTL_TEXTENCODING_UTF8));
2545                                 }
2546                                 else if (aItem3.first == "CreationDate")
2547                                 {
2548                                     util::DateTime aDateTime;
2549                                     sax::Converter::parseDateTime(
2550                                         aDateTime,
2551                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2552                                                           RTL_TEXTENCODING_UTF8));
2553                                     xDocProps->setCreationDate(aDateTime);
2554                                 }
2555                                 else if (aItem3.first == "Title")
2556                                 {
2557                                     xDocProps->setTitle(
2558                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2559                                                           RTL_TEXTENCODING_UTF8));
2560                                 }
2561                                 else if (aItem3.first == "Subject")
2562                                 {
2563                                     xDocProps->setSubject(
2564                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2565                                                           RTL_TEXTENCODING_UTF8));
2566                                 }
2567                                 else if (aItem3.first == "Description")
2568                                 {
2569                                     xDocProps->setDescription(
2570                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2571                                                           RTL_TEXTENCODING_UTF8));
2572                                 }
2573                                 else if (aItem3.first == "Keywords")
2574                                 {
2575                                     uno::Sequence<OUString> aStringSeq(aItem3.second.size());
2576                                     auto aStringArray = aStringSeq.getArray();
2577                                     int nId = 0;
2578                                     for (const auto& aItem4 : aItem3.second)
2579                                     {
2580                                         aStringArray[nId++] = OStringToOUString(aItem4.second.get_value<std::string>(),
2581                                                           RTL_TEXTENCODING_UTF8);
2582                                     }
2583                                     xDocProps->setKeywords(aStringSeq);
2584                                 }
2585                                 else if (aItem3.first == "Language")
2586                                 {
2587                                     OUString aLanguageStr
2588                                         = OStringToOUString(aItem3.second.get_value<std::string>(),
2589                                                             RTL_TEXTENCODING_UTF8);
2590                                     lang::Locale aLanguageLang
2591                                         = LanguageTag::convertToLocale(aLanguageStr);
2592                                     xDocProps->setLanguage(aLanguageLang);
2593                                 }
2594                                 else if (aItem3.first == "ModifiedBy")
2595                                 {
2596                                     xDocProps->setModifiedBy(
2597                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2598                                                           RTL_TEXTENCODING_UTF8));
2599                                 }
2600                                 else if (aItem3.first == "ModificationDate")
2601                                 {
2602                                     util::DateTime aDateTime;
2603                                     sax::Converter::parseDateTime(
2604                                         aDateTime,
2605                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2606                                                           RTL_TEXTENCODING_UTF8));
2607                                     xDocProps->setModificationDate(aDateTime);
2608                                 }
2609                                 else if (aItem3.first == "PrintedBy")
2610                                 {
2611                                     xDocProps->setPrintedBy(
2612                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2613                                                           RTL_TEXTENCODING_UTF8));
2614                                 }
2615                                 else if (aItem3.first == "PrintDate")
2616                                 {
2617                                     util::DateTime aDateTime;
2618                                     sax::Converter::parseDateTime(
2619                                         aDateTime,
2620                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2621                                                           RTL_TEXTENCODING_UTF8));
2622                                     xDocProps->setPrintDate(aDateTime);
2623                                 }
2624                                 else if (aItem3.first == "TemplateName")
2625                                 {
2626                                     xDocProps->setTemplateName(
2627                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2628                                                           RTL_TEXTENCODING_UTF8));
2629                                 }
2630                                 else if (aItem3.first == "TemplateURL")
2631                                 {
2632                                     xDocProps->setTemplateURL(
2633                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2634                                                           RTL_TEXTENCODING_UTF8));
2635                                 }
2636                                 else if (aItem3.first == "TemplateDate")
2637                                 {
2638                                     util::DateTime aDateTime;
2639                                     sax::Converter::parseDateTime(
2640                                         aDateTime,
2641                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2642                                                           RTL_TEXTENCODING_UTF8));
2643                                     xDocProps->setTemplateDate(aDateTime);
2644                                 }
2645                                 else if (aItem3.first == "AutoloadURL")
2646                                 {
2647                                     // Warning: wrong data here, can freeze LO.
2648                                     xDocProps->setAutoloadURL(
2649                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2650                                                           RTL_TEXTENCODING_UTF8));
2651                                 }
2652                                 else if (aItem3.first == "AutoloadSecs")
2653                                 {
2654                                     //sal_Int32
2655                                     xDocProps->setAutoloadSecs(aItem3.second.get_value<int>());
2656                                 }
2657                                 else if (aItem3.first == "DefaultTarget")
2658                                 {
2659                                     xDocProps->setDefaultTarget(
2660                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2661                                                           RTL_TEXTENCODING_UTF8));
2662                                 }
2663                                 else if (aItem3.first == "DocumentStatistics")
2664                                 {
2665                                     uno::Sequence<beans::NamedValue> aNamedValueSeq(
2666                                         aItem3.second.size());
2667                                     auto aNamedValueArray = aNamedValueSeq.getArray();
2668                                     int nId = 0;
2669                                     for (const auto& aItem4 : aItem3.second)
2670                                     {
2671                                         OUString aName = OStringToOUString(aItem4.first,
2672                                                                            RTL_TEXTENCODING_UTF8);
2673                                         sal_Int32 nValue = aItem4.second.get_value<int>();
2674                                         aNamedValueArray[nId].Name = aName;
2675                                         aNamedValueArray[nId].Value <<= nValue;
2676                                         nId++;
2677                                     }
2678                                     xDocProps->setDocumentStatistics(aNamedValueSeq);
2679                                 }
2680                                 else if (aItem3.first == "EditingCycles")
2681                                 {
2682                                     //sal_Int16
2683                                     xDocProps->setEditingCycles(aItem3.second.get_value<int>());
2684                                 }
2685                                 else if (aItem3.first == "EditingDuration")
2686                                 {
2687                                     //sal_Int32
2688                                     xDocProps->setEditingDuration(aItem3.second.get_value<int>());
2689                                 }
2690                                 else if (aItem3.first == "Contributor")
2691                                 {
2692                                     uno::Sequence<OUString> aStringSeq(aItem3.second.size());
2693                                     auto aStringArray = aStringSeq.getArray();
2694                                     int nId = 0;
2695                                     for (const auto& aItem4 : aItem3.second)
2696                                     {
2697                                         aStringArray[nId++] = OStringToOUString(
2698                                             aItem4.second.get_value<std::string>(),
2699                                             RTL_TEXTENCODING_UTF8);
2700                                     }
2701                                     xDocProps->setContributor(aStringSeq);
2702                                 }
2703                                 else if (aItem3.first == "Coverage")
2704                                 {
2705                                     xDocProps->setCoverage(
2706                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2707                                                           RTL_TEXTENCODING_UTF8));
2708                                 }
2709                                 else if (aItem3.first == "Identifier")
2710                                 {
2711                                     xDocProps->setIdentifier(
2712                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2713                                                           RTL_TEXTENCODING_UTF8));
2714                                 }
2715                                 else if (aItem3.first == "Publisher")
2716                                 {
2717                                     uno::Sequence<OUString> aStringSeq(aItem3.second.size());
2718                                     auto aStringArray = aStringSeq.getArray();
2719                                     int nId = 0;
2720                                     for (const auto& aItem4 : aItem3.second)
2721                                     {
2722                                         aStringArray[nId++] = OStringToOUString(
2723                                             aItem4.second.get_value<std::string>(),
2724                                             RTL_TEXTENCODING_UTF8);
2725                                     }
2726                                     xDocProps->setPublisher(aStringSeq);
2727                                 }
2728                                 else if (aItem3.first == "Relation")
2729                                 {
2730                                     uno::Sequence<OUString> aStringSeq(aItem3.second.size());
2731                                     auto aStringArray = aStringSeq.getArray();
2732                                     int nId = 0;
2733                                     for (const auto& aItem4 : aItem3.second)
2734                                     {
2735                                         aStringArray[nId++] = OStringToOUString(
2736                                             aItem4.second.get_value<std::string>(),
2737                                             RTL_TEXTENCODING_UTF8);
2738                                     }
2739                                     xDocProps->setRelation(aStringSeq);
2740                                 }
2741                                 else if (aItem3.first == "Rights")
2742                                 {
2743                                     xDocProps->setRights(
2744                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2745                                                           RTL_TEXTENCODING_UTF8));
2746                                 }
2747                                 else if (aItem3.first == "Source")
2748                                 {
2749                                     xDocProps->setSource(
2750                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2751                                                           RTL_TEXTENCODING_UTF8));
2752                                 }
2753                                 else if (aItem3.first == "Type")
2754                                 {
2755                                     xDocProps->setType(
2756                                         OStringToOUString(aItem3.second.get_value<std::string>(),
2757                                                           RTL_TEXTENCODING_UTF8));
2758                                 }
2759                                 else if (aItem3.first == "UserDefinedProperties")
2760                                 {
2761                                     const uno::Reference<beans::XPropertyContainer> xUserProps
2762                                         = xDocProps->getUserDefinedProperties();
2763                                     if (!xUserProps.is())
2764                                         continue;
2765                                     uno::Reference<beans::XPropertyAccess> xUserPropsAccess(
2766                                         xDocProps->getUserDefinedProperties(), uno::UNO_QUERY);
2767                                     if (!xUserPropsAccess.is())
2768                                         continue;
2769 
2770                                     for (const auto& aItem4Obj : aItem3.second)
2771                                     {
2772                                         // handle [{},{}...] case as well as {}...}
2773                                         const auto& aItem4 = aItem4Obj.first == ""
2774                                                                  ? *aItem4Obj.second.ordered_begin()
2775                                                                  : aItem4Obj;
2776 
2777                                         if (aItem4.first == "Delete")
2778                                         {
2779                                             std::string aPropName
2780                                                 = aItem4.second.get_value<std::string>();
2781                                             try
2782                                             {
2783                                                 xUserProps->removeProperty(OStringToOUString(
2784                                                     aPropName, RTL_TEXTENCODING_UTF8));
2785                                             }
2786                                             catch (...)
2787                                             {
2788                                                 lcl_LogWarning("FillApi DocumentProperties "
2789                                                                "UserDefinedPropertieschart, failed "
2790                                                                "to delete property: '"
2791                                                                + aPropName + "'");
2792                                             }
2793                                         }
2794                                         else if (aItem4.first.starts_with("Add."))
2795                                         {
2796                                             std::string aPropName = aItem4.first.substr(4);
2797 
2798                                             comphelper::SequenceAsHashMap aUserDefinedProperties(
2799                                                 xUserPropsAccess->getPropertyValues());
2800                                             comphelper::SequenceAsHashMap::iterator it
2801                                                 = aUserDefinedProperties.find(OStringToOUString(
2802                                                     aPropName, RTL_TEXTENCODING_UTF8));
2803                                             bool bToDelete = (it != aUserDefinedProperties.end());
2804 
2805                                             try
2806                                             {
2807                                                 std::stringstream aStreamPart;
2808                                                 aStreamPart << "{\n\"" << aPropName << "\" : ";
2809                                                 boost::property_tree::json_parser::write_json(
2810                                                     aStreamPart, aItem4.second);
2811                                                 aStreamPart << "}";
2812 
2813                                                 OString aJSONPart(aStreamPart.str());
2814                                                 std::vector<beans::PropertyValue> aPropVec
2815                                                     = comphelper::JsonToPropertyValues(aJSONPart);
2816 
2817                                                 if (bToDelete)
2818                                                     xUserProps->removeProperty(aPropVec[0].Name);
2819 
2820                                                 xUserProps->addProperty(
2821                                                     aPropVec[0].Name,
2822                                                     beans::PropertyAttribute::REMOVABLE,
2823                                                     aPropVec[0].Value);
2824                                             }
2825                                             catch(...)
2826                                             {
2827                                                 lcl_LogWarning("FillApi DocumentProperties "
2828                                                                "UserDefinedPropertieschart, failed "
2829                                                                "to add property: '"
2830                                                                + aPropName + "'");
2831                                             }
2832                                         }
2833                                     }
2834                                 }
2835                             }
2836                         }
2837                         if (aItem2.first.starts_with("Charts"))
2838                         {
2839                             std::string aTextEnd = aItem2.first.substr(6);
2840                             std::string aValue = "";
2841                             ChartFilterType iKeyId = ChartFilterType::ERROR;
2842                             // Find how the chart is identified: ByIndex, ByTitle...
2843                             for (size_t i = 0; i < aIdChartTexts.size(); i++)
2844                             {
2845                                 if (aTextEnd.starts_with(aIdChartTexts[i]))
2846                                 {
2847                                     iKeyId = static_cast<ChartFilterType>(i);
2848                                     aValue = aTextEnd.substr(aIdChartTexts[i].length());
2849                                     break;
2850                                 }
2851                             }
2852                             if (iKeyId != ChartFilterType::ERROR)
2853                             {
2854                                 // A chart transformation filter can match multiple charts
2855                                 // In that case every matching charts will be transformed
2856                                 // If no chart match to the filter, then we show warning
2857                                 bool bChartFound = false;
2858                                 for (int i = 0; i < nEOcount; ++i)
2859                                 {
2860                                     uno::Reference<beans::XPropertySet> xShapeProps(
2861                                         xEmbeddeds->getByIndex(i), uno::UNO_QUERY);
2862                                     if (!xShapeProps.is())
2863                                         continue;
2864 
2865                                     uno::Reference<frame::XModel> xDocModel;
2866                                     xShapeProps->getPropertyValue(u"Model"_ustr) >>= xDocModel;
2867                                     if (!xDocModel.is())
2868                                         continue;
2869 
2870                                     uno::Reference<chart2::XChartDocument> xChartDoc(
2871                                         xDocModel, uno::UNO_QUERY);
2872                                     if (!xChartDoc.is())
2873                                         continue;
2874 
2875                                     uno::Reference<chart2::data::XDataProvider> xDataProvider(
2876                                         xChartDoc->getDataProvider());
2877                                     if (!xDataProvider.is())
2878                                         continue;
2879 
2880                                     uno::Reference<chart::XChartDataArray> xDataArray(
2881                                         xChartDoc->getDataProvider(), uno::UNO_QUERY);
2882                                     if (!xDataArray.is())
2883                                         continue;
2884 
2885                                     uno::Reference<chart2::XInternalDataProvider> xIDataProvider(
2886                                         xChartDoc->getDataProvider(), uno::UNO_QUERY);
2887                                     if (!xIDataProvider.is())
2888                                         continue;
2889 
2890                                     uno::Reference<util::XModifiable> xModi(xDocModel,
2891                                                                             uno::UNO_QUERY);
2892                                     if (!xModi.is())
2893                                         continue;
2894 
2895                                     switch (iKeyId)
2896                                     {
2897                                         case ChartFilterType::INDEX:
2898                                         {
2899                                             if (stoi(aValue) != i)
2900                                                 continue;
2901                                         }
2902                                         break;
2903                                         case ChartFilterType::NAME:
2904                                         {
2905                                             uno::Reference<container::XNamed> xNamedShape(
2906                                                 xEmbeddeds->getByIndex(i), uno::UNO_QUERY);
2907                                             if (xNamedShape.is())
2908                                             {
2909                                                 OUString aName;
2910                                                 aName = xNamedShape->getName();
2911                                                 if (OStringToOUString(aValue, RTL_TEXTENCODING_UTF8)
2912                                                     != aName)
2913                                                     continue;
2914                                             }
2915                                         }
2916                                         break;
2917                                         case ChartFilterType::TITLE:
2918                                         {
2919                                             uno::Reference<chart2::XTitled> xTitled(
2920                                                 xChartDoc, uno::UNO_QUERY_THROW);
2921                                             if (!xTitled.is())
2922                                                 continue;
2923                                             uno::Reference<chart2::XTitle> xTitle
2924                                                 = xTitled->getTitleObject();
2925                                             if (!xTitle.is())
2926                                                 continue;
2927 
2928                                             OUString aTitle;
2929                                             const uno::Sequence<
2930                                                 uno::Reference<chart2::XFormattedString>>
2931                                                 aFSSeq = xTitle->getText();
2932                                             for (auto const& fs : aFSSeq)
2933                                                 aTitle += fs->getString();
2934                                             if (OStringToOUString(aValue, RTL_TEXTENCODING_UTF8)
2935                                                 != aTitle)
2936                                                 continue;
2937                                         }
2938                                         break;
2939                                         case ChartFilterType::SUBTITLE:
2940                                         {
2941                                             uno::Reference<chart2::XDiagram> xDiagram
2942                                                 = xChartDoc->getFirstDiagram();
2943                                             if (!xDiagram.is())
2944                                                 continue;
2945 
2946                                             uno::Reference<chart2::XTitled> xTitled(
2947                                                 xDiagram, uno::UNO_QUERY_THROW);
2948                                             if (!xTitled.is())
2949                                                 continue;
2950 
2951                                             uno::Reference<chart2::XTitle> xSubTitle(
2952                                                 xTitled->getTitleObject());
2953                                             if (!xSubTitle.is())
2954                                                 continue;
2955 
2956                                             OUString aSubTitle;
2957                                             const uno::Sequence<
2958                                                 uno::Reference<chart2::XFormattedString>>
2959                                                 aFSSeq = xSubTitle->getText();
2960                                             for (auto const& fs : aFSSeq)
2961                                                 aSubTitle += fs->getString();
2962                                             if (OStringToOUString(aValue, RTL_TEXTENCODING_UTF8)
2963                                                 != aSubTitle)
2964                                                 continue;
2965                                         }
2966                                         break;
2967                                         default:
2968                                             continue;
2969                                     }
2970 
2971                                     // We have a match, this chart need to be transformed
2972                                     // Set all the values (of the chart) what is needed
2973                                     bChartFound = true;
2974 
2975                                     // Check if the InternalDataProvider is row or column based.
2976                                     bool bChartUseColumns = false;
2977                                     uno::Sequence<beans::PropertyValue> aArguments(
2978                                         xDataProvider->detectArguments(nullptr));
2979                                     for (sal_Int32 j = 0; j < aArguments.getLength(); ++j)
2980                                     {
2981                                         if (aArguments[j].Name == "DataRowSource")
2982                                         {
2983                                             css::chart::ChartDataRowSource eRowSource;
2984                                             if (aArguments[j].Value >>= eRowSource)
2985                                                 bChartUseColumns
2986                                                     = (eRowSource
2987                                                        == css::chart::ChartDataRowSource_COLUMNS);
2988                                             break;
2989                                         }
2990                                     }
2991 
2992                                     for (const auto& aItem3Obj : aItem2.second)
2993                                     {
2994                                         //handle [] and {} cases
2995                                         const auto& aItem3 = aItem3Obj.first == ""
2996                                                                  ? *aItem3Obj.second.ordered_begin()
2997                                                                  : aItem3Obj;
2998 
2999                                         if (aItem3.first.starts_with("deletecolumn.")
3000                                             || aItem3.first.starts_with("deleterow.")
3001                                             || aItem3.first.starts_with("insertcolumn.")
3002                                             || aItem3.first.starts_with("insertrow.")
3003                                             || aItem3.first.starts_with("modifycolumn.")
3004                                             || aItem3.first.starts_with("modifyrow."))
3005                                         {
3006                                             // delete insert, or modify a row, or column
3007                                             // column, or row?
3008                                             bool bSetColumn = (aItem3.first[6] == 'c');
3009                                             int nId = stoi(aItem3.first.substr(bSetColumn ? 13 : 10));
3010                                             bool bDelete = aItem3.first.starts_with("delete");
3011                                             // delete/insert a row/column if needed
3012                                             if (!aItem3.first.starts_with("modify"))
3013                                             {
3014                                                 if (bChartUseColumns == bSetColumn)
3015                                                 {
3016                                                     if (bDelete)
3017                                                     {
3018                                                         if (!lcl_DeleteChartColumns(xChartDoc, nId))
3019                                                             continue;
3020                                                         xIDataProvider->deleteSequence(nId);
3021                                                     }
3022                                                     else
3023                                                     {
3024                                                         if (!lcl_InsertChartColumns(xChartDoc, nId))
3025                                                             continue;
3026                                                     }
3027                                                 }
3028                                                 else
3029                                                 {
3030                                                     if (bDelete)
3031                                                     {
3032                                                         xIDataProvider
3033                                                             ->deleteDataPointForAllSequences(nId);
3034                                                     }
3035                                                     else
3036                                                     {
3037                                                         xIDataProvider
3038                                                             ->insertDataPointForAllSequences(nId
3039                                                                                              - 1);
3040                                                     }
3041                                                 }
3042                                             }
3043                                             // set values also, if needed
3044                                             if (!bDelete && aItem3.second.size() > 0)
3045                                             {
3046                                                 uno::Sequence<uno::Sequence<double>> aData
3047                                                     = xDataArray->getData();
3048                                                 uno::Sequence<double>* pRows = aData.getArray();
3049 
3050                                                 int nIndex = 0;
3051                                                 int nX = nId;
3052                                                 int nY = nId;
3053                                                 bool bIndexWarning = false;
3054                                                 for (const auto& aItem4 : aItem3.second)
3055                                                 {
3056                                                     if (bSetColumn)
3057                                                     {
3058                                                         nY = nIndex;
3059                                                     }
3060                                                     else
3061                                                     {
3062                                                         nX = nIndex;
3063                                                     }
3064                                                     if (nY < aData.getLength() && nY >= 0
3065                                                         && nX < pRows[nY].getLength() && nX >= 0)
3066                                                     {
3067                                                         double* pCols = pRows[nY].getArray();
3068                                                         pCols[nX]
3069                                                             = aItem4.second.get_value<double>();
3070                                                     }
3071                                                     else
3072                                                     {
3073                                                         bIndexWarning = true;
3074                                                     }
3075 
3076                                                     nIndex++;
3077                                                 }
3078                                                 if (bIndexWarning)
3079                                                 {
3080                                                     std::string sValues = "";
3081                                                     for (const auto& atemp : aItem3.second)
3082                                                     {
3083                                                         if (sValues != "")
3084                                                         {
3085                                                             sValues += ", ";
3086                                                         }
3087                                                         sValues += atemp.second
3088                                                                        .get_value<std::string>();
3089                                                     }
3090                                                     lcl_LogWarning(
3091                                                         "FillApi chart: Invalid Cell Index at: '"
3092                                                         + aItem3.first + ": " + sValues
3093                                                         + "' (probably too many parameters)");
3094                                                 }
3095 
3096                                                 xDataArray->setData(aData);
3097                                             }
3098                                         }
3099                                         else if (aItem3.first.starts_with("setrowdesc"))
3100                                         {
3101                                             // set row descriptions
3102                                             uno::Sequence<OUString> aRowDesc
3103                                                 = xDataArray->getRowDescriptions();
3104                                             OUString* aRowdata = aRowDesc.getArray();
3105 
3106                                             if (aItem3.first.starts_with("setrowdesc."))
3107                                             {
3108                                                 // set only 1 description
3109                                                 int nValue = stoi(aItem3.first.substr(11));
3110                                                 if (nValue >= 0 && nValue < aRowDesc.getLength())
3111                                                 {
3112                                                     aRowdata[nValue] = OStringToOUString(
3113                                                         aItem3.second.get_value<std::string>(),
3114                                                         RTL_TEXTENCODING_UTF8);
3115                                                 }
3116                                                 else
3117                                                 {
3118                                                     lcl_LogWarning("FillApi chart setrowdesc: "
3119                                                                    "invalid Index at: '"
3120                                                                    + aItem3.first + "'");
3121                                                 }
3122                                             }
3123                                             else
3124                                             {
3125                                                 // set an array of description at once
3126                                                 int nIndex = 0;
3127                                                 for (const auto& aItem4 : aItem3.second)
3128                                                 {
3129                                                     if (nIndex >= aRowDesc.getLength())
3130                                                     {
3131                                                         lcl_LogWarning("FillApi chart setrowdesc: "
3132                                                                        "too many params");
3133                                                         break;
3134                                                     }
3135                                                     aRowdata[nIndex] = OStringToOUString(
3136                                                         aItem4.second.get_value<std::string>(),
3137                                                         RTL_TEXTENCODING_UTF8);
3138                                                     nIndex++;
3139                                                 }
3140                                             }
3141                                             xDataArray->setRowDescriptions(aRowDesc);
3142                                         }
3143                                         else if (aItem3.first.starts_with("setcolumndesc"))
3144                                         {
3145                                             // set column descriptions
3146                                             uno::Sequence<OUString> aColDesc
3147                                                 = xDataArray->getColumnDescriptions();
3148                                             OUString* aColdata = aColDesc.getArray();
3149 
3150                                             if (aItem3.first.starts_with("setcolumndesc."))
3151                                             {
3152                                                 int nValue = stoi(aItem3.first.substr(14));
3153                                                 if (nValue >= 0 && nValue < aColDesc.getLength())
3154                                                 {
3155                                                     aColdata[nValue] = OStringToOUString(
3156                                                         aItem3.second.get_value<std::string>(),
3157                                                         RTL_TEXTENCODING_UTF8);
3158                                                 }
3159                                                 else
3160                                                 {
3161                                                     lcl_LogWarning("FillApi chart setcolumndesc: "
3162                                                                    "invalid Index at: '"
3163                                                                    + aItem3.first + "'");
3164                                                 }
3165                                             }
3166                                             else
3167                                             {
3168                                                 int nIndex = 0;
3169                                                 for (const auto& aItem4 : aItem3.second)
3170                                                 {
3171                                                     if (nIndex >= aColDesc.getLength())
3172                                                     {
3173                                                         lcl_LogWarning(
3174                                                             "FillApi chart setcolumndesc:"
3175                                                             " too many parameters");
3176                                                         break;
3177                                                     }
3178                                                     aColdata[nIndex] = OStringToOUString(
3179                                                         aItem4.second.get_value<std::string>(),
3180                                                         RTL_TEXTENCODING_UTF8);
3181                                                     nIndex++;
3182                                                 }
3183                                             }
3184                                             xDataArray->setColumnDescriptions(aColDesc);
3185                                         }
3186                                         else if (aItem3.first.starts_with("resize"))
3187                                         {
3188                                             if (aItem3.second.size() >= 2)
3189                                             {
3190                                                 auto aItem4 = aItem3.second.begin();
3191                                                 int nY = aItem4->second.get_value<int>();
3192                                                 int nX = (++aItem4)->second.get_value<int>();
3193 
3194                                                 if (nX < 1 || nY < 1)
3195                                                 {
3196                                                     lcl_LogWarning(
3197                                                         "FillApi chart resize: wrong param"
3198                                                         " (Needed: x,y >= 1)");
3199                                                     continue;
3200                                                 }
3201                                                 // here we need to use the new insert column thing
3202                                                 if (!lcl_ResizeChartColumns(xChartDoc, nX))
3203                                                     continue;
3204 
3205                                                 uno::Sequence<uno::Sequence<double>> aData
3206                                                     = xDataArray->getData();
3207                                                 if (aData.getLength() != nY)
3208                                                     aData.realloc(nY);
3209 
3210                                                 for (sal_Int32 j = 0; j < nY; ++j)
3211                                                 {
3212                                                     uno::Sequence<double>* pRows = aData.getArray();
3213                                                     // resize row if needed
3214                                                     if (pRows[j].getLength() != nX)
3215                                                     {
3216                                                         pRows[j].realloc(nX);
3217                                                     }
3218                                                 }
3219                                                 xDataArray->setData(aData);
3220                                             }
3221                                             else
3222                                             {
3223                                                 lcl_LogWarning(
3224                                                     "FillApi chart resize: not enough parameters"
3225                                                     " (x,y is needed)");
3226                                             }
3227                                         }
3228                                         else if (aItem3.first.starts_with("data"))
3229                                         {
3230                                             // set table data values
3231                                             uno::Sequence<uno::Sequence<double>> aData
3232                                                 = xDataArray->getData();
3233 
3234                                             // set only 1 cell data
3235                                             if (aItem3.first.starts_with("datayx."))
3236                                             {
3237                                                 int nPoint = aItem3.first.find('.', 7);
3238                                                 int nY = stoi(aItem3.first.substr(7, nPoint - 7));
3239                                                 int nX = stoi(aItem3.first.substr(nPoint + 1));
3240                                                 bool bValidIndex = false;
3241                                                 if (nY < aData.getLength() && nY >= 0)
3242                                                 {
3243                                                     uno::Sequence<double>* pRows = aData.getArray();
3244                                                     if (nX < pRows[nY].getLength() && nX >= 0)
3245                                                     {
3246                                                         double* pCols = pRows[nY].getArray();
3247                                                         pCols[nX]
3248                                                             = aItem3.second.get_value<double>();
3249                                                         bValidIndex = true;
3250                                                     }
3251                                                 }
3252                                                 if (!bValidIndex)
3253                                                 {
3254                                                     lcl_LogWarning(
3255                                                         "FillApi chart datayx: invalid Index at: '"
3256                                                         + aItem3.first + "'");
3257                                                 }
3258                                             }
3259                                             else
3260                                             {
3261                                                 // set the whole data table
3262                                                 // resize if needed
3263                                                 int nRowsCount = aItem3.second.size();
3264                                                 int nColsCount = 0;
3265 
3266                                                 for (const auto& aItem4 : aItem3.second)
3267                                                 {
3268                                                     if (nColsCount
3269                                                         < static_cast<int>(aItem4.second.size()))
3270                                                     {
3271                                                         nColsCount = aItem4.second.size();
3272                                                     }
3273                                                 }
3274 
3275                                                 if (nColsCount > 0)
3276                                                 {
3277                                                     // here we need to use the new insert column thing
3278                                                     if(!lcl_ResizeChartColumns(xChartDoc, nColsCount))
3279                                                         continue;
3280 
3281                                                     if (aData.getLength() != nRowsCount)
3282                                                         aData.realloc(nRowsCount);
3283 
3284                                                     // set all the rows
3285                                                     sal_Int32 nY = 0;
3286                                                     for (const auto& aItem4 : aItem3.second)
3287                                                     {
3288                                                         uno::Sequence<double>* pRows
3289                                                             = aData.getArray();
3290                                                         // resize row if needed
3291                                                         if (pRows[nY].getLength() != nColsCount)
3292                                                         {
3293                                                             pRows[nY].realloc(nColsCount);
3294                                                         }
3295                                                         double* pCols = pRows[nY].getArray();
3296                                                         // set all values in the row
3297                                                         sal_Int32 nX = 0;
3298                                                         for (const auto& aItem5 : aItem4.second)
3299                                                         {
3300                                                             if (nX >= nColsCount)
3301                                                             {
3302                                                                 // This should never happen
3303                                                                 break;
3304                                                             }
3305                                                             pCols[nX]
3306                                                                 = aItem5.second.get_value<double>();
3307                                                             nX++;
3308                                                         }
3309                                                         nY++;
3310                                                     }
3311                                                 }
3312                                             }
3313                                             xDataArray->setData(aData);
3314                                         }
3315                                         else
3316                                         {
3317                                             lcl_LogWarning("FillApi chart command not recognised: '"
3318                                                            + aItem3.first + "'");
3319                                         }
3320                                         xModi->setModified(true);
3321                                     }
3322                                 }
3323                                 if (!bChartFound)
3324                                 {
3325                                     lcl_LogWarning("FillApi: No chart match the filter: '"
3326                                                    + aItem2.first + "'");
3327                                 }
3328                             }
3329                             else
3330                             {
3331                                 lcl_LogWarning("FillApi chart filter type not recognised: '"
3332                                                + aItem2.first + "'");
3333                             }
3334                         }
3335 
3336                         if (aItem2.first.starts_with("ContentControls"))
3337                         {
3338                             std::string aTextEnd = aItem2.first.substr(15);
3339                             std::string aValue = "";
3340                             ContentFilterType iKeyId = ContentFilterType::ERROR;
3341                             // Find how the content control is identified: ByIndex, ByAlias...
3342                             for (size_t i = 0; i < aIdTexts.size(); i++)
3343                             {
3344                                 if (aTextEnd.starts_with(aIdTexts[i]))
3345                                 {
3346                                     iKeyId = static_cast<ContentFilterType>(i);
3347                                     aValue = aTextEnd.substr(aIdTexts[i].length());
3348                                     break;
3349                                 }
3350                             }
3351                             if (iKeyId != ContentFilterType::ERROR)
3352                             {
3353                                 // Check all the content controls, if they match
3354                                 bool bCCFound = false;
3355                                 for (int i = 0; i < iCCcount; ++i)
3356                                 {
3357                                     uno::Reference<text::XTextContent> xContentControl;
3358                                     xContentControls->getByIndex(i) >>= xContentControl;
3359 
3360                                     uno::Reference<beans::XPropertySet> xContentControlProps(
3361                                         xContentControl, uno::UNO_QUERY);
3362                                     if (!xContentControlProps.is())
3363                                         continue;
3364 
3365                                     // Compare the loaded and the actual identifier
3366                                     switch (iKeyId)
3367                                     {
3368                                         case ContentFilterType::INDEX:
3369                                         {
3370                                             if (stoi(aValue) != i)
3371                                                 continue;
3372                                         }
3373                                         break;
3374                                         case ContentFilterType::ID:
3375                                         {
3376                                             sal_Int32 iID = -1;
3377                                             xContentControlProps->getPropertyValue(UNO_NAME_ID)
3378                                                 >>= iID;
3379                                             if (stoi(aValue) != iID)
3380                                                 continue;
3381                                         }
3382                                         break;
3383                                         case ContentFilterType::ALIAS:
3384                                         {
3385                                             OUString aAlias;
3386                                             xContentControlProps->getPropertyValue(UNO_NAME_ALIAS)
3387                                                 >>= aAlias;
3388                                             if (OStringToOUString(aValue, RTL_TEXTENCODING_UTF8)
3389                                                 != aAlias)
3390                                                 continue;
3391                                         }
3392                                         break;
3393                                         case ContentFilterType::TAG:
3394                                         {
3395                                             OUString aTag;
3396                                             xContentControlProps->getPropertyValue(UNO_NAME_TAG)
3397                                                 >>= aTag;
3398                                             if (OStringToOUString(aValue, RTL_TEXTENCODING_UTF8)
3399                                                 != aTag)
3400                                                 continue;
3401                                         }
3402                                         break;
3403                                         default:
3404                                             continue;
3405                                     }
3406 
3407                                     // We have a match, this content control need to be transformed
3408                                     // Set all the values (of the content control) what is needed
3409                                     bCCFound = true;
3410                                     for (const auto& aItem3 : aItem2.second)
3411                                     {
3412                                         if (aItem3.first == "content")
3413                                         {
3414                                             std::string aContent
3415                                                 = aItem3.second.get_value<std::string>();
3416 
3417                                             uno::Reference<text::XText> xContentControlText(
3418                                                 xContentControl, uno::UNO_QUERY);
3419                                             if (!xContentControlText.is())
3420                                                 continue;
3421 
3422                                             xContentControlText->setString(
3423                                                 OStringToOUString(aContent, RTL_TEXTENCODING_UTF8));
3424 
3425                                             sal_Int32 iType = 0;
3426                                             xContentControlProps->getPropertyValue(
3427                                                 UNO_NAME_CONTENT_CONTROL_TYPE)
3428                                                 >>= iType;
3429                                             SwContentControlType aType
3430                                                 = static_cast<SwContentControlType>(iType);
3431 
3432                                             // if we set the content of a checkbox, then we
3433                                             // also set the checked state based on the content
3434                                             if (aType == SwContentControlType::CHECKBOX)
3435                                             {
3436                                                 OUString aCheckedContent;
3437                                                 xContentControlProps->getPropertyValue(
3438                                                     UNO_NAME_CHECKED_STATE)
3439                                                     >>= aCheckedContent;
3440                                                 bool bChecked = false;
3441                                                 if (aCheckedContent
3442                                                     == OStringToOUString(
3443                                                         aItem3.second.get_value<std::string>(),
3444                                                         RTL_TEXTENCODING_UTF8))
3445                                                     bChecked = true;
3446                                                 xContentControlProps->setPropertyValue(
3447                                                     UNO_NAME_CHECKED, uno::Any(bChecked));
3448                                             }
3449                                             else if (aType == SwContentControlType::PLAIN_TEXT
3450                                                      || aType == SwContentControlType::RICH_TEXT
3451                                                      || aType == SwContentControlType::DATE
3452                                                      || aType == SwContentControlType::COMBO_BOX
3453                                                      || aType
3454                                                             == SwContentControlType::DROP_DOWN_LIST)
3455                                             {
3456                                                 // Set the placeholder
3457                                                 bool bPlaceHolder = aContent == "" ? true : false;
3458                                                 xContentControlProps->setPropertyValue(
3459                                                     UNO_NAME_SHOWING_PLACE_HOLDER,
3460                                                     uno::Any(bPlaceHolder));
3461                                                 if (bPlaceHolder)
3462                                                 {
3463                                                     OUString aPlaceHolderText;
3464                                                     switch (aType)
3465                                                     {
3466                                                         case SwContentControlType::PLAIN_TEXT:
3467                                                         case SwContentControlType::RICH_TEXT:
3468                                                         {
3469                                                             aPlaceHolderText = SwResId(
3470                                                                 STR_CONTENT_CONTROL_PLACEHOLDER);
3471                                                         }
3472                                                         break;
3473                                                         case SwContentControlType::COMBO_BOX:
3474                                                         case SwContentControlType::DROP_DOWN_LIST:
3475                                                         {
3476                                                             aPlaceHolderText = SwResId(
3477                                                                 STR_DROPDOWN_CONTENT_CONTROL_PLACEHOLDER);
3478                                                         }
3479                                                         break;
3480                                                         case SwContentControlType::DATE:
3481                                                         {
3482                                                             aPlaceHolderText = SwResId(
3483                                                                 STR_DATE_CONTENT_CONTROL_PLACEHOLDER);
3484                                                         }
3485                                                         break;
3486                                                         default: // do nothing for picture and checkbox
3487                                                         break;
3488                                                     }
3489                                                     if (!aPlaceHolderText.isEmpty())
3490                                                         xContentControlText->setString(
3491                                                             aPlaceHolderText);
3492                                                 }
3493                                             }
3494                                         }
3495                                         else if (aItem3.first == "checked")
3496                                         {
3497                                             bool bChecked
3498                                                 = (aItem3.second.get_value<std::string>() == "true")
3499                                                       ? true
3500                                                       : false;
3501                                             xContentControlProps->setPropertyValue(
3502                                                 UNO_NAME_CHECKED,
3503                                                 uno::Any(bChecked));
3504 
3505                                             OUString aCheckContent;
3506                                             xContentControlProps->getPropertyValue(
3507                                                 bChecked ? UNO_NAME_CHECKED_STATE
3508                                                          : UNO_NAME_UNCHECKED_STATE)
3509                                                 >>= aCheckContent;
3510                                             uno::Reference<text::XText> xContentControlText(
3511                                                 xContentControl, uno::UNO_QUERY);
3512                                             if (!xContentControlText.is())
3513                                                 continue;
3514                                             xContentControlText->setString(aCheckContent);
3515                                         }
3516                                         else if (aItem3.first == "date")
3517                                         {
3518                                             std::string aDate
3519                                                 = aItem3.second.get_value<std::string>();
3520                                             xContentControlProps->setPropertyValue(
3521                                                 UNO_NAME_CURRENT_DATE,
3522                                                 uno::Any(OStringToOUString(aDate,
3523                                                                            RTL_TEXTENCODING_UTF8)));
3524                                         }
3525                                         else if (aItem3.first == "alias")
3526                                         {
3527                                             xContentControlProps->setPropertyValue(
3528                                                 UNO_NAME_ALIAS,
3529                                                 uno::Any(OStringToOUString(
3530                                                     aItem3.second.get_value<std::string>(),
3531                                                     RTL_TEXTENCODING_UTF8)));
3532                                         }
3533                                         else
3534                                         {
3535                                             lcl_LogWarning(
3536                                                 "FillApi contentControl command not recognised: '"
3537                                                 + aItem3.first + "'");
3538                                         }
3539                                     }
3540                                 }
3541                                 if (!bCCFound)
3542                                 {
3543                                     lcl_LogWarning("FillApi: No contentControl match the filter: '"
3544                                                    + aItem2.first + "'");
3545                                 }
3546                             }
3547                             else
3548                             {
3549                                 lcl_LogWarning(
3550                                     "FillApi contentControl filter type not recognised: '"
3551                                     + aItem2.first + "'");
3552                             }
3553                         }
3554                     }
3555                 }
3556             }
3557         }
3558         break;
3559     default:
3560         OSL_ENSURE(false, "wrong dispatcher");
3561         return;
3562     }
3563 }
3564 
GetState(SfxItemSet & rSet)3565 void SwTextShell::GetState( SfxItemSet &rSet )
3566 {
3567     SwWrtShell &rSh = GetShell();
3568     SfxWhichIter aIter( rSet );
3569     sal_uInt16 nWhich = aIter.FirstWhich();
3570     while ( nWhich )
3571     {
3572         const sal_uInt16 nSlotId = GetPool().GetSlotId(nWhich);
3573         switch (nSlotId)
3574         {
3575         case FN_FORMAT_CURRENT_FOOTNOTE_DLG:
3576             if( !rSh.IsCursorInFootnote() )
3577                 rSet.DisableItem( nWhich );
3578         break;
3579 
3580         case SID_LANGUAGE_STATUS:
3581             {
3582                 // the value of used script types
3583                 OUString aScriptTypesInUse( OUString::number( static_cast<int>(rSh.GetScriptType()) ) );
3584 
3585                 // get keyboard language
3586                 OUString aKeyboardLang;
3587                 SwEditWin& rEditWin = GetView().GetEditWin();
3588                 LanguageType nLang = rEditWin.GetInputLanguage();
3589                 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3590                     aKeyboardLang = SvtLanguageTable::GetLanguageString( nLang );
3591 
3592                 // get the language that is in use
3593                 OUString aCurrentLang = u"*"_ustr;
3594                 nLang = SwLangHelper::GetCurrentLanguage( rSh );
3595                 if (nLang != LANGUAGE_DONTKNOW)
3596                 {
3597                     aCurrentLang = SvtLanguageTable::GetLanguageString( nLang );
3598                     if (comphelper::LibreOfficeKit::isActive())
3599                     {
3600                         if (nLang == LANGUAGE_NONE)
3601                         {
3602                             aCurrentLang += ";-";
3603                         }
3604                         else
3605                         {
3606                             aCurrentLang += ";" + LanguageTag(nLang).getBcp47(false);
3607                         }
3608                     }
3609                 }
3610 
3611                 // build sequence for status value
3612                 uno::Sequence< OUString > aSeq{ aCurrentLang,
3613                                                 aScriptTypesInUse,
3614                                                 aKeyboardLang,
3615                                                 SwLangHelper::GetTextForLanguageGuessing( rSh ) };
3616 
3617                 // set sequence as status value
3618                 SfxStringListItem aItem( SID_LANGUAGE_STATUS );
3619                 aItem.SetStringList( aSeq );
3620                 rSet.Put( aItem );
3621             }
3622         break;
3623 
3624         case SID_THES:
3625         {
3626             // is there a valid selection to get text from?
3627             OUString aText;
3628             bool bValid = !rSh.HasSelection() ||
3629                     (rSh.IsSelOnePara() && !rSh.IsMultiSelection());
3630             // prevent context menu from showing when cursor is not in or at the end of a word
3631             // (GetCurWord will return the next word if there is none at the current position...)
3632             const sal_Int16 nWordType = ::i18n::WordType::DICTIONARY_WORD;
3633             bool bWord = rSh.IsInWord( nWordType ) || rSh.IsStartWord( nWordType ) || rSh.IsEndWord( nWordType );
3634             if (bValid && bWord)
3635                aText = rSh.HasSelection()? rSh.GetSelText() : rSh.GetCurWord();
3636 
3637             LanguageType nLang = rSh.GetCurLang();
3638             LanguageTag aLanguageTag( nLang);
3639             const lang::Locale& aLocale( aLanguageTag.getLocale());
3640 
3641             // disable "Thesaurus" context menu entry if there is nothing to look up
3642             uno::Reference< linguistic2::XThesaurus >  xThes( ::GetThesaurus() );
3643             if (aText.isEmpty() ||
3644                 !xThes.is() || nLang == LANGUAGE_NONE || !xThes->hasLocale( aLocale ))
3645                 rSet.DisableItem( SID_THES );
3646             else
3647             {
3648                 // set word and locale to look up as status value
3649                 OUString aStatusVal = aText + "#" + aLanguageTag.getBcp47();
3650                 rSet.Put( SfxStringItem( SID_THES, aStatusVal ) );
3651             }
3652         }
3653         break;
3654 
3655         case FN_NUMBER_NEWSTART :
3656             if(!rSh.GetNumRuleAtCurrCursorPos())
3657                     rSet.DisableItem(nWhich);
3658             else
3659                 rSet.Put(SfxBoolItem(FN_NUMBER_NEWSTART,
3660                     rSh.IsNumRuleStart()));
3661         break;
3662 
3663         case FN_EDIT_FORMULA:
3664         case SID_CHARMAP:
3665         case SID_CHARMAP_CONTROL:
3666             {
3667                 const SelectionType nType = rSh.GetSelectionType();
3668                 if (!(nType & SelectionType::Text) &&
3669                     !(nType & SelectionType::Table) &&
3670                     !(nType & SelectionType::NumberList))
3671                 {
3672                     rSet.DisableItem(nWhich);
3673                 }
3674                 else if ( nWhich == FN_EDIT_FORMULA
3675                           && rSh.CursorInsideInputField() )
3676                 {
3677                     rSet.DisableItem( nWhich );
3678                 }
3679             }
3680             break;
3681 
3682         case FN_INSERT_ENDNOTE:
3683         case FN_INSERT_FOOTNOTE:
3684         case FN_INSERT_FOOTNOTE_DLG:
3685             {
3686                 const FrameTypeFlags nNoType =
3687                     FrameTypeFlags::FLY_ANY | FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FOOTNOTE;
3688                 FrameTypeFlags eType = rSh.GetFrameType(nullptr, true);
3689                 bool bSplitFly = false;
3690                 if (eType & FrameTypeFlags::FLY_ATCNT)
3691                 {
3692                     SwContentFrame* pContentFrame = rSh.GetCurrFrame(/*bCalcFrame=*/false);
3693                     if (pContentFrame)
3694                     {
3695                         SwFlyFrame* pFlyFrame = pContentFrame->FindFlyFrame();
3696                         bSplitFly = pFlyFrame && pFlyFrame->IsFlySplitAllowed();
3697                     }
3698                 }
3699                 if (eType & nNoType && !bSplitFly)
3700                     rSet.DisableItem(nWhich);
3701 
3702                 if ( rSh.CursorInsideInputField() )
3703                 {
3704                     rSet.DisableItem( nWhich );
3705                 }
3706             }
3707             break;
3708 
3709         case SID_INSERTDOC:
3710         case FN_INSERT_GLOSSARY:
3711         case FN_EXPAND_GLOSSARY:
3712             if ( rSh.CursorInsideInputField() )
3713             {
3714                 rSet.DisableItem( nWhich );
3715             }
3716             break;
3717 
3718         case FN_INSERT_TABLE:
3719             if ( rSh.CursorInsideInputField()
3720                  || rSh.GetTableFormat()
3721                  || (rSh.GetFrameType(nullptr,true) & FrameTypeFlags::FOOTNOTE) )
3722             {
3723                 rSet.DisableItem( nWhich );
3724             }
3725             break;
3726 
3727         case FN_CALCULATE:
3728             if ( !rSh.IsSelection() )
3729                 rSet.DisableItem(nWhich);
3730             break;
3731         case FN_GOTO_REFERENCE:
3732             {
3733                 SwField *pField = rSh.GetCurField();
3734                 if ( !pField || (pField->GetTypeId() != SwFieldTypesEnum::GetRef) )
3735                     rSet.DisableItem(nWhich);
3736             }
3737             break;
3738         case FN_AUTOFORMAT_AUTO:
3739             {
3740                 rSet.Put( SfxBoolItem( nWhich, SvxAutoCorrCfg::Get().IsAutoFormatByInput() ));
3741             }
3742             break;
3743 
3744         case SID_DEC_INDENT:
3745         case SID_INC_INDENT:
3746         {
3747             //if the paragraph has bullet we'll do the following things:
3748             //1: if the bullet level is the first level, disable the decrease-indent button
3749             //2: if the bullet level is the last level, disable the increase-indent button
3750             if ( rSh.GetNumRuleAtCurrCursorPos() && !rSh.HasReadonlySel() )
3751             {
3752                 const sal_uInt8 nLevel = rSh.GetNumLevel();
3753                 if ( ( nLevel == ( MAXLEVEL - 1 ) && nWhich == SID_INC_INDENT )
3754                      || ( nLevel == 0 && nWhich == SID_DEC_INDENT ) )
3755                 {
3756                     rSet.DisableItem( nWhich );
3757                 }
3758             }
3759             else
3760             {
3761                 sal_uInt16 nHtmlMode = ::GetHtmlMode( GetView().GetDocShell() );
3762                 nHtmlMode &= HTMLMODE_ON | HTMLMODE_SOME_STYLES;
3763                 if ( ( nHtmlMode == HTMLMODE_ON )
3764                      || !rSh.IsMoveLeftMargin( SID_INC_INDENT == nWhich ) )
3765                 {
3766                     rSet.DisableItem( nWhich );
3767                 }
3768             }
3769         }
3770         break;
3771 
3772         case FN_DEC_INDENT_OFFSET:
3773         case FN_INC_INDENT_OFFSET:
3774             {
3775                 sal_uInt16 nHtmlMode = ::GetHtmlMode(GetView().GetDocShell());
3776                 nHtmlMode &= HTMLMODE_ON|HTMLMODE_SOME_STYLES;
3777                 if( (nHtmlMode == HTMLMODE_ON) ||
3778                     !rSh.IsMoveLeftMargin( FN_INC_INDENT_OFFSET == nWhich,
3779                                             false ))
3780                     rSet.DisableItem( nWhich );
3781             }
3782             break;
3783 
3784         case SID_ATTR_CHAR_COLOR2:
3785             {
3786                 SfxItemSet aSet( GetPool() );
3787                 rSh.GetCurAttr( aSet );
3788                 const SvxColorItem& aColorItem = aSet.Get(RES_CHRATR_COLOR);
3789                 rSet.Put( aColorItem.CloneSetWhich(SID_ATTR_CHAR_COLOR2) );
3790             }
3791             break;
3792         case SID_ATTR_CHAR_BACK_COLOR:
3793         case SID_ATTR_CHAR_COLOR_BACKGROUND:
3794             {
3795                 // Always use the visible background
3796                 SfxItemSet aSet( GetPool() );
3797                 rSh.GetCurAttr( aSet );
3798                 const SvxBrushItem& aBrushItem = aSet.Get(RES_CHRATR_HIGHLIGHT);
3799                 if( aBrushItem.GetColor() != COL_TRANSPARENT )
3800                 {
3801                     rSet.Put(SvxColorItem(aBrushItem.GetColor(), aBrushItem.getComplexColor(), nWhich));
3802                 }
3803                 else
3804                 {
3805                     const SvxBrushItem& aBrushItem2 = aSet.Get(RES_CHRATR_BACKGROUND);
3806                     rSet.Put(SvxColorItem(aBrushItem2.GetColor(), aBrushItem2.getComplexColor(), nWhich));
3807                 }
3808             }
3809             break;
3810         case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT:
3811             {
3812                 SwEditWin& rEdtWin = GetView().GetEditWin();
3813                 SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
3814                 const sal_uInt32 nColWhich = pApply ? pApply->nColor : 0;
3815                 const bool bUseTemplate = nColWhich == SID_ATTR_CHAR_BACK_COLOR
3816                                           || nColWhich == SID_ATTR_CHAR_COLOR_BACKGROUND;
3817                 rSet.Put(SfxBoolItem(nWhich, bUseTemplate));
3818             }
3819             break;
3820         case SID_ATTR_CHAR_COLOR_EXT:
3821             {
3822                 SwEditWin& rEdtWin = GetView().GetEditWin();
3823                 SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
3824                 rSet.Put(SfxBoolItem(nWhich, pApply && pApply->nColor == nWhich));
3825             }
3826             break;
3827         case FN_SET_REMINDER:
3828         case FN_INSERT_BOOKMARK:
3829             if( rSh.IsTableMode()
3830                 || rSh.CursorInsideInputField() )
3831             {
3832                 rSet.DisableItem( nWhich );
3833             }
3834             break;
3835 
3836         case FN_INSERT_BREAK:
3837             if ( rSh.HasReadonlySel()
3838                  && !rSh.CursorInsideInputField() )
3839             {
3840                 rSet.DisableItem( nWhich );
3841             }
3842             break;
3843 
3844         case FN_INSERT_BREAK_DLG:
3845         case FN_INSERT_COLUMN_BREAK:
3846         case FN_INSERT_PAGEBREAK:
3847             if( rSh.CursorInsideInputField() || rSh.CursorInsideContentControl() )
3848             {
3849                 rSet.DisableItem( nWhich );
3850             }
3851             break;
3852 
3853         case FN_INSERT_PAGEHEADER:
3854         case FN_INSERT_PAGEFOOTER:
3855             if (comphelper::LibreOfficeKit::isActive())
3856             {
3857                 bool bState = false;
3858                 bool bAllState = true;
3859                 bool bIsPhysical = false;
3860 
3861                 OUString aStyleName;
3862                 std::vector<OUString> aList;
3863                 static constexpr OUStringLiteral sPhysical(u"IsPhysical");
3864                 static constexpr OUStringLiteral sDisplay(u"DisplayName");
3865                 const OUString sHeaderOn(nWhich == FN_INSERT_PAGEHEADER ? u"HeaderIsOn"_ustr : u"FooterIsOn"_ustr);
3866 
3867                 rtl::Reference< SwXTextDocument > xSupplier(GetView().GetDocShell()->GetBaseModel());
3868                 if (xSupplier.is())
3869                 {
3870                     uno::Reference< XNameContainer > xContainer;
3871                     uno::Reference< XNameAccess > xFamilies = xSupplier->getStyleFamilies();
3872                     if (xFamilies->getByName(u"PageStyles"_ustr) >>= xContainer)
3873                     {
3874                         const uno::Sequence< OUString > aSeqNames = xContainer->getElementNames();
3875                         for (const auto& rName : aSeqNames)
3876                         {
3877                             aStyleName = rName;
3878                             uno::Reference<XPropertySet> xPropSet(xContainer->getByName(aStyleName), uno::UNO_QUERY);
3879                             if (xPropSet.is() && (xPropSet->getPropertyValue(sPhysical) >>= bIsPhysical) && bIsPhysical)
3880                             {
3881                                 xPropSet->getPropertyValue(sDisplay) >>= aStyleName;
3882                                 if ((xPropSet->getPropertyValue(sHeaderOn)>>= bState) && bState)
3883                                     aList.push_back(aStyleName);
3884                                 else
3885                                     bState = false;
3886 
3887                                 // Check if all entries have the same state
3888                                 bAllState &= bState;
3889                             }
3890                             else
3891                                 bIsPhysical = false;
3892                         }
3893                     }
3894                 }
3895 
3896                 if (bAllState && aList.size() > 1)
3897                     aList.push_back(u"_ALL_"_ustr);
3898 
3899                 rSet.Put(SfxStringListItem(nWhich, &aList));
3900             }
3901             else
3902             {
3903                 rSet.Put( SfxObjectShellItem( nWhich, GetView().GetDocShell() ));
3904             }
3905             break;
3906             case FN_TABLE_SORT_DIALOG:
3907             case FN_SORTING_DLG:
3908                 if(!rSh.HasSelection() ||
3909                         (FN_TABLE_SORT_DIALOG == nWhich && !rSh.GetTableFormat()))
3910                     rSet.DisableItem( nWhich );
3911             break;
3912 
3913             case SID_RUBY_DIALOG:
3914                 {
3915                     if( !SvtCJKOptions::IsRubyEnabled()
3916                         || rSh.CursorInsideInputField() )
3917                     {
3918                         GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, false );
3919                         rSet.DisableItem(nWhich);
3920                     }
3921                     else
3922                         GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, true );
3923                 }
3924                 break;
3925 
3926             case SID_FM_TRANSLATE:
3927                 {
3928 #if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
3929                     if (!officecfg::Office::Common::Misc::ExperimentalMode::get()
3930                         && !comphelper::LibreOfficeKit::isActive())
3931                     {
3932                         rSet.Put(SfxVisibilityItem(nWhich, false));
3933                         break;
3934                     }
3935                     std::optional<OUString> oDeeplAPIUrl = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get();
3936                     std::optional<OUString> oDeeplKey = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get();
3937                     if (!oDeeplAPIUrl || oDeeplAPIUrl->isEmpty() || !oDeeplKey || oDeeplKey->isEmpty())
3938                     {
3939                         rSet.DisableItem(nWhich);
3940                     }
3941 #endif
3942                 }
3943                 break;
3944 
3945             case SID_HYPERLINK_DIALOG:
3946                 if( GetView().GetDocShell()->IsReadOnly()
3947                     || ( !GetView().GetViewFrame().HasChildWindow(nWhich)
3948                          && rSh.HasReadonlySel() )
3949                     || rSh.CursorInsideInputField() )
3950                 {
3951                     rSet.DisableItem(nWhich);
3952                 }
3953                 else
3954                 {
3955                     rSet.Put(SfxBoolItem( nWhich, nullptr != GetView().GetViewFrame().GetChildWindow( nWhich ) ));
3956                 }
3957                 break;
3958 
3959             case SID_EDIT_HYPERLINK:
3960                 {
3961                     if (!rSh.HasReadonlySel())
3962                     {
3963                         SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
3964                         rSh.GetCurAttr(aSet);
3965                         if (SfxItemState::SET <= aSet.GetItemState(RES_TXTATR_INETFMT))
3966                             break;
3967 
3968                         // is the cursor at the beginning of a hyperlink?
3969                         const SwTextNode* pTextNd = rSh.GetCursor()->GetPointNode().GetTextNode();
3970                         if (pTextNd && !rSh.HasSelection())
3971                         {
3972                             const sal_Int32 nIndex = rSh.GetCursor()->Start()->GetContentIndex();
3973                             const SwTextAttr* pINetFmt
3974                                 = pTextNd->GetTextAttrAt(nIndex, RES_TXTATR_INETFMT);
3975                             if (pINetFmt && !pINetFmt->GetINetFormat().GetValue().isEmpty())
3976                                 break;
3977                         }
3978                     }
3979                     rSet.DisableItem(nWhich);
3980                 }
3981             break;
3982             case SID_INSERT_HYPERLINK:
3983             {
3984                 if (!rSh.HasSelection())
3985                 {
3986                     rSet.DisableItem(nWhich);
3987                     break;
3988                 }
3989                 if (!rSh.HasReadonlySel())
3990                 {
3991                     SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
3992                     rSh.GetCurAttr(aSet);
3993 
3994                     // If a hyperlink is selected, either alone or along with other text...
3995                     if (SfxItemState::SET <= aSet.GetItemState(RES_TXTATR_INETFMT)
3996                         || aSet.GetItemState(RES_TXTATR_INETFMT) == SfxItemState::INVALID)
3997                     {
3998                         rSet.DisableItem(nWhich);
3999                     }
4000 
4001                     // is the cursor at the beginning of a hyperlink?
4002                     const SwTextNode* pTextNd = rSh.GetCursor()->GetPointNode().GetTextNode();
4003                     if (pTextNd && !rSh.HasSelection())
4004                     {
4005                         const sal_Int32 nIndex = rSh.GetCursor()->Start()->GetContentIndex();
4006                         const SwTextAttr* pINetFmt
4007                             = pTextNd->GetTextAttrAt(nIndex, RES_TXTATR_INETFMT);
4008                         if (pINetFmt && !pINetFmt->GetINetFormat().GetValue().isEmpty())
4009                             rSet.DisableItem(nWhich);
4010                     }
4011                 }
4012             }
4013             break;
4014             case SID_REMOVE_HYPERLINK:
4015             {
4016                 if (!rSh.HasReadonlySel())
4017                 {
4018                     SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
4019                     rSh.GetCurAttr(aSet);
4020 
4021                     // If a hyperlink is selected, either alone or along with other text...
4022                     if (SfxItemState::SET <= aSet.GetItemState(RES_TXTATR_INETFMT)
4023                         || aSet.GetItemState(RES_TXTATR_INETFMT) == SfxItemState::INVALID)
4024                     {
4025                         break;
4026                     }
4027 
4028                     // is the cursor at the beginning of a hyperlink?
4029                     const SwTextNode* pTextNd = rSh.GetCursor()->GetPointNode().GetTextNode();
4030                     if (pTextNd && !rSh.HasSelection())
4031                     {
4032                         const sal_Int32 nIndex = rSh.GetCursor()->Start()->GetContentIndex();
4033                         const SwTextAttr* pINetFmt
4034                             = pTextNd->GetTextAttrAt(nIndex, RES_TXTATR_INETFMT);
4035                         if (pINetFmt && !pINetFmt->GetINetFormat().GetValue().isEmpty())
4036                             break;
4037                     }
4038                 }
4039                 rSet.DisableItem(nWhich);
4040             }
4041             break;
4042             case SID_TRANSLITERATE_HALFWIDTH:
4043             case SID_TRANSLITERATE_FULLWIDTH:
4044             case SID_TRANSLITERATE_HIRAGANA:
4045             case SID_TRANSLITERATE_KATAKANA:
4046             {
4047                 if(!SvtCJKOptions::IsChangeCaseMapEnabled())
4048                 {
4049                     GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, false );
4050                     rSet.DisableItem(nWhich);
4051                 }
4052                 else
4053                     GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, true );
4054             }
4055             break;
4056             case FN_READONLY_SELECTION_MODE :
4057                 if(!GetView().GetDocShell()->IsReadOnly())
4058                     rSet.DisableItem( nWhich );
4059                 else
4060                 {
4061                     rSet.Put(SfxBoolItem(nWhich, rSh.GetViewOptions()->IsSelectionInReadonly()));
4062                 }
4063             break;
4064             case FN_SELECTION_MODE_DEFAULT:
4065             case FN_SELECTION_MODE_BLOCK :
4066                     rSet.Put(SfxBoolItem(nWhich, (nWhich == FN_SELECTION_MODE_DEFAULT) != rSh.IsBlockMode()));
4067             break;
4068             case SID_COPY_HYPERLINK_LOCATION:
4069             case SID_OPEN_HYPERLINK:
4070             {
4071                 SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
4072                 rSh.GetCurAttr(aSet);
4073                 if (SfxItemState::SET <= aSet.GetItemState(RES_TXTATR_INETFMT, false))
4074                     break;
4075 
4076                 // is the cursor at the beginning of a hyperlink?
4077                 const SwTextNode* pTextNd = rSh.GetCursor()->GetPointNode().GetTextNode();
4078                 if (pTextNd && !rSh.HasSelection())
4079                 {
4080                     const sal_Int32 nIndex = rSh.GetCursor()->Start()->GetContentIndex();
4081                     const SwTextAttr* pINetFmt = pTextNd->GetTextAttrAt(nIndex, RES_TXTATR_INETFMT);
4082                     if (pINetFmt && !pINetFmt->GetINetFormat().GetValue().isEmpty())
4083                         break;
4084                 }
4085 
4086                 SwField* pField = rSh.GetCurField();
4087                 if (pField && pField->GetTyp()->Which() == SwFieldIds::TableOfAuthorities)
4088                 {
4089                     const auto& rAuthorityField = *static_cast<const SwAuthorityField*>(pField);
4090                     if (auto targetType = rAuthorityField.GetTargetType();
4091                         targetType == SwAuthorityField::TargetType::UseDisplayURL
4092                         || targetType == SwAuthorityField::TargetType::UseTargetURL)
4093                     {
4094                         // Check if the Bibliography entry has a target URL
4095                         if (rAuthorityField.GetAbsoluteURL().getLength() > 0)
4096                             break;
4097                     }
4098                 }
4099 
4100                 rSet.DisableItem(nWhich);
4101             }
4102             break;
4103             case FN_OPEN_LOCAL_URL:
4104             {
4105                 if (GetLocalURL(rSh).isEmpty())
4106                 {
4107                     rSet.DisableItem(nWhich);
4108                 }
4109             }
4110             break;
4111             case  SID_OPEN_SMARTTAGMENU:
4112             {
4113                  std::vector< OUString > aSmartTagTypes;
4114                  uno::Sequence< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
4115                  uno::Reference<text::XTextRange> xRange;
4116 
4117                  rSh.GetSmartTagTerm( aSmartTagTypes, aStringKeyMaps, xRange );
4118 
4119                  if ( xRange.is() && !aSmartTagTypes.empty() )
4120                  {
4121                      uno::Sequence < uno::Sequence< uno::Reference< smarttags::XSmartTagAction > > > aActionComponentsSequence;
4122                      uno::Sequence < uno::Sequence< sal_Int32 > > aActionIndicesSequence;
4123 
4124                      const SmartTagMgr& rSmartTagMgr = SwSmartTagMgr::Get();
4125                      rSmartTagMgr.GetActionSequences( aSmartTagTypes,
4126                                                       aActionComponentsSequence,
4127                                                       aActionIndicesSequence );
4128 
4129                      uno::Reference <frame::XController> xController = GetView().GetController();
4130                      lang::Locale aLocale( SW_BREAKITER()->GetLocale( GetAppLanguageTag() ) );
4131                      const OUString& aApplicationName( rSmartTagMgr.GetApplicationName() );
4132                      const OUString aRangeText = xRange->getString();
4133 
4134                      const SvxSmartTagItem aItem( SID_OPEN_SMARTTAGMENU,
4135                                                   aActionComponentsSequence,
4136                                                   aActionIndicesSequence,
4137                                                   aStringKeyMaps,
4138                                                   xRange,
4139                                                   std::move(xController),
4140                                                   std::move(aLocale),
4141                                                   aApplicationName,
4142                                                   aRangeText );
4143 
4144                      rSet.Put( aItem );
4145                  }
4146                  else
4147                      rSet.DisableItem(nWhich);
4148             }
4149             break;
4150 
4151             case FN_NUM_NUMBERING_ON:
4152                 rSet.Put(SfxBoolItem(FN_NUM_NUMBERING_ON,rSh.SelectionHasNumber()));
4153             break;
4154 
4155             case FN_NUM_BULLET_ON:
4156                 rSet.Put(SfxBoolItem(FN_NUM_BULLET_ON,rSh.SelectionHasBullet()));
4157             break;
4158 
4159             case FN_NUM_BULLET_OFF:
4160                 rSet.Put(SfxBoolItem(FN_NUM_BULLET_OFF, !rSh.GetNumRuleAtCurrCursorPos() &&
4161                                      !rSh.GetNumRuleAtCurrentSelection()));
4162             break;
4163 
4164             case FN_SVX_SET_OUTLINE:
4165             {
4166                 NBOTypeMgrBase* pOutline = NBOutlineTypeMgrFact::CreateInstance(NBOType::Outline);
4167                 auto pCurRule = const_cast<SwNumRule*>(rSh.GetNumRuleAtCurrCursorPos());
4168                 if (pOutline && pCurRule)
4169                 {
4170                     SvxNumRule aSvxRule = pCurRule->MakeSvxNumRule();
4171                     const sal_uInt16 nIndex = pOutline->GetNBOIndexForNumRule(aSvxRule, 0);
4172                     rSet.Put(SfxBoolItem(FN_SVX_SET_OUTLINE, nIndex < USHRT_MAX));
4173                 }
4174                 break;
4175             }
4176             case FN_BUL_NUM_RULE_INDEX:
4177             case FN_NUM_NUM_RULE_INDEX:
4178             case FN_OUTLINE_RULE_INDEX:
4179         {
4180             SwNumRule* pCurRule = const_cast<SwNumRule*>(GetShell().GetNumRuleAtCurrCursorPos());
4181             if( pCurRule )
4182             {
4183                 sal_uInt16 nActNumLvl = GetShell().GetNumLevel();
4184                 if( nActNumLvl < MAXLEVEL )
4185                 {
4186                     nActNumLvl = 1<<nActNumLvl;
4187                 }
4188                 SvxNumRule aSvxRule = pCurRule->MakeSvxNumRule();
4189                 if ( GetShell().HasBullet())
4190                 {
4191                     rSet.Put(SfxUInt16Item(FN_BUL_NUM_RULE_INDEX, USHRT_MAX));
4192                     rSet.Put(SfxUInt16Item(FN_NUM_NUM_RULE_INDEX, USHRT_MAX));
4193                     NBOTypeMgrBase* pBullets = NBOutlineTypeMgrFact::CreateInstance(NBOType::Bullets);
4194                     if ( pBullets )
4195                     {
4196                         const sal_uInt16 nBulIndex = pBullets->GetNBOIndexForNumRule(aSvxRule,nActNumLvl);
4197                         rSet.Put(SfxUInt16Item(FN_BUL_NUM_RULE_INDEX,nBulIndex));
4198                     }
4199                 }else if ( GetShell().HasNumber() )
4200                 {
4201                     rSet.Put(SfxUInt16Item(FN_BUL_NUM_RULE_INDEX, USHRT_MAX));
4202                     rSet.Put(SfxUInt16Item(FN_NUM_NUM_RULE_INDEX, USHRT_MAX));
4203                     NBOTypeMgrBase* pNumbering = NBOutlineTypeMgrFact::CreateInstance(NBOType::Numbering);
4204                     if ( pNumbering )
4205                     {
4206                         const sal_uInt16 nBulIndex = pNumbering->GetNBOIndexForNumRule(aSvxRule,nActNumLvl);
4207                         rSet.Put(SfxUInt16Item(FN_NUM_NUM_RULE_INDEX,nBulIndex));
4208                     }
4209                 }
4210 
4211                 if ( nWhich == FN_OUTLINE_RULE_INDEX )
4212                 {
4213                     rSet.Put(SfxUInt16Item(FN_OUTLINE_RULE_INDEX, USHRT_MAX));
4214                     NBOTypeMgrBase* pOutline = NBOutlineTypeMgrFact::CreateInstance(NBOType::Outline);
4215                     if ( pOutline )
4216                     {
4217                         const sal_uInt16 nIndex = pOutline->GetNBOIndexForNumRule(aSvxRule,nActNumLvl);
4218                         rSet.Put(SfxUInt16Item(FN_OUTLINE_RULE_INDEX,nIndex));
4219                     }
4220                 }
4221             }
4222         }
4223             break;
4224             case FN_BUL_GET_DOC_BULLETS:
4225             {
4226                 std::set<OUString> aBulletsSet = rSh.GetUsedBullets();
4227                 std::vector<OUString> aBullets;
4228                 std::copy(aBulletsSet.begin(), aBulletsSet.end(), std::back_inserter(aBullets));
4229                 SfxStringListItem aItem(FN_BUL_GET_DOC_BULLETS);
4230                 uno::Sequence<OUString> aSeq(aBullets.data(),
4231                                              static_cast<sal_Int32>(aBullets.size()));
4232                 aItem.SetStringList(aSeq);
4233                 rSet.Put(aItem);
4234             }
4235             break;
4236             case FN_NUM_CONTINUE:
4237             {
4238                 // #i86492#
4239                 // Search also for bullet list
4240                 OUString aDummy;
4241                 const SwNumRule* pRule =
4242                         rSh.SearchNumRule( true, aDummy );
4243                 if ( !pRule )
4244                 {
4245                     pRule = rSh.SearchNumRule( false, aDummy );
4246                 }
4247                 if ( !pRule )
4248                     rSet.DisableItem(nWhich);
4249             }
4250             break;
4251             case SID_INSERT_RLM :
4252             case SID_INSERT_LRM :
4253             {
4254                 bool bEnabled = SvtCTLOptions::IsCTLFontEnabled();
4255                 GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, bEnabled );
4256                 if(!bEnabled)
4257                     rSet.DisableItem(nWhich);
4258             }
4259             break;
4260             case SID_FM_CTL_PROPERTIES:
4261             {
4262                 bool bDisable = false;
4263 
4264                 // First get the state from the form shell
4265                 SfxItemSetFixed<SID_FM_CTL_PROPERTIES, SID_FM_CTL_PROPERTIES> aSet(GetShell().GetAttrPool());
4266                 aSet.Put(SfxBoolItem( SID_FM_CTL_PROPERTIES, true ));
4267                 GetShell().GetView().GetFormShell()->GetState( aSet );
4268 
4269                 if(SfxItemState::DISABLED == aSet.GetItemState(SID_FM_CTL_PROPERTIES))
4270                 {
4271                     bDisable = true;
4272                 }
4273 
4274                 // Enable it if we have a valid object other than what form shell knows
4275                 SwPosition aPos(*GetShell().GetCursor()->GetPoint());
4276                 sw::mark::Fieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
4277                 if ( !pFieldBM && aPos.GetContentIndex() > 0)
4278                 {
4279                     aPos.AdjustContent(-1);
4280                     pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
4281                 }
4282                 if ( pFieldBM && (pFieldBM->GetFieldname() == ODF_FORMDROPDOWN || pFieldBM->GetFieldname() == ODF_FORMDATE) )
4283                 {
4284                     bDisable = false;
4285                 }
4286 
4287                 if(bDisable)
4288                     rSet.DisableItem(nWhich);
4289             }
4290             break;
4291             case SID_COPY:
4292             case SID_CUT:
4293             {
4294                 if (GetObjectShell()->isContentExtractionLocked())
4295                     rSet.DisableItem(nWhich);
4296                 break;
4297             }
4298             case FN_PROTECT_FIELDS:
4299             case FN_PROTECT_BOOKMARKS:
4300             {
4301                 DocumentSettingId aSettingId = nWhich == FN_PROTECT_FIELDS
4302                                                    ? DocumentSettingId::PROTECT_FIELDS
4303                                                    : DocumentSettingId::PROTECT_BOOKMARKS;
4304                 bool bProtected = rSh.getIDocumentSettingAccess().get(aSettingId);
4305                 rSet.Put(SfxBoolItem(nWhich, bProtected));
4306             }
4307             break;
4308             case FN_DELETE_CONTENT_CONTROL:
4309             case FN_CONTENT_CONTROL_PROPERTIES:
4310             {
4311                 if (!GetShell().CursorInsideContentControl())
4312                 {
4313                     rSet.DisableItem(nWhich);
4314                 }
4315             }
4316             break;
4317         }
4318         nWhich = aIter.NextWhich();
4319     }
4320 }
4321 
4322 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
4323