docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / sw / source / uibase / shells / textsh1.cxx
blob6ec961fcac00004c95260eff4e58b5b6f6f36d97
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <config_features.h>
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>
30 #include <hintids.hxx>
31 #include <cmdid.h>
32 #include <comphelper/lok.hxx>
33 #include <comphelper/propertysequence.hxx>
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 <sax/tools/converter.hxx>
143 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
144 #include <com/sun/star/chart2/XInternalDataProvider.hpp>
145 #include <com/sun/star/chart2/XChartDocument.hpp>
146 #include <com/sun/star/chart/XChartDocument.hpp>
147 #include <com/sun/star/chart/XChartDataArray.hpp>
148 #include <com/sun/star/chart2/XTitle.hpp>
149 #include <com/sun/star/chart2/XTitled.hpp>
150 #include <com/sun/star/chart/ChartDataRowSource.hpp>
151 #include <com/sun/star/util/XModifiable.hpp>
153 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
154 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
155 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
156 #include <com/sun/star/util/XCloneable.hpp>
158 #include <com/sun/star/util/SearchAlgorithms2.hpp>
159 #include <com/sun/star/document/XDocumentProperties2.hpp>
160 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
162 #include <com/sun/star/beans/XPropertyAccess.hpp>
163 #include <com/sun/star/beans/PropertyAttribute.hpp>
165 using namespace ::com::sun::star;
166 using namespace com::sun::star::beans;
167 using namespace ::com::sun::star::container;
168 using namespace com::sun::star::style;
169 using namespace svx::sidebar;
171 static void sw_CharDialogResult(const SfxItemSet* pSet, SwWrtShell &rWrtSh, std::shared_ptr<SfxItemSet> const & pCoreSet, bool bSel,
172 bool bSelectionPut, bool bApplyToParagraph, SfxRequest *pReq);
174 static void sw_CharDialog(SwWrtShell& rWrtSh, bool bUseDialog, bool bApplyToParagraph,
175 sal_uInt16 nSlot, const SfxItemSet* pArgs, SfxRequest* pReq)
177 FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &rWrtSh.GetView()) != nullptr );
178 SwModule::get()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast<sal_uInt16>(eMetric)));
179 auto pCoreSet = std::make_shared<SfxItemSetFixed<
180 RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
181 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
182 RES_BACKGROUND, RES_SHADOW,
183 SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
184 SID_HTML_MODE, SID_HTML_MODE,
185 SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, SID_ATTR_CHAR_WIDTH_FIT_TO_LINE,
186 FN_PARAM_SELECTION, FN_PARAM_SELECTION>> ( rWrtSh.GetView().GetPool() );
187 rWrtSh.GetCurAttr(*pCoreSet);
189 bool bSel = rWrtSh.HasSelection();
190 bool bSelectionPut = false;
191 if(bSel || rWrtSh.IsInWord())
193 if(!bSel)
195 rWrtSh.StartAction();
196 rWrtSh.Push();
197 if(!rWrtSh.SelectTextAttr( RES_TXTATR_INETFMT ))
198 rWrtSh.SelWrd();
200 pCoreSet->Put(SfxStringItem(FN_PARAM_SELECTION, rWrtSh.GetSelText()));
201 bSelectionPut = true;
202 if(!bSel)
204 rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
205 rWrtSh.EndAction();
208 pCoreSet->Put(SfxUInt16Item(SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, rWrtSh.GetScalingOfSelectedText()));
210 ::ConvertAttrCharToGen(*pCoreSet);
212 // Setting the BoxInfo
213 ::PrepareBoxInfo(*pCoreSet, rWrtSh);
215 pCoreSet->Put(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(rWrtSh.GetView().GetDocShell())));
216 VclPtr<SfxAbstractTabDialog> pDlg;
217 if ( bUseDialog && GetActiveView() )
219 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
220 pDlg.reset(pFact->CreateSwCharDlg(rWrtSh.GetView().GetFrameWeld(), rWrtSh.GetView(), *pCoreSet, SwCharDlgMode::Std));
222 if (nSlot == SID_CHAR_DLG_EFFECT)
223 pDlg->SetCurPageId(u"fonteffects"_ustr);
224 else if (nSlot == SID_CHAR_DLG_POSITION)
225 pDlg->SetCurPageId(u"position"_ustr);
226 else if (nSlot == SID_CHAR_DLG_FOR_PARAGRAPH)
227 pDlg->SetCurPageId(u"font"_ustr);
228 else if (pReq)
230 const SfxStringItem* pItem = (*pReq).GetArg<SfxStringItem>(FN_PARAM_1);
231 if (pItem)
232 pDlg->SetCurPageId(pItem->GetValue());
236 if (bUseDialog)
238 std::shared_ptr<SfxRequest> pRequest;
239 if (pReq)
241 pRequest = std::make_shared<SfxRequest>(*pReq);
242 pReq->Ignore(); // the 'old' request is not relevant any more
244 pDlg->StartExecuteAsync([pDlg, &rWrtSh, pCoreSet=std::move(pCoreSet), bSel,
245 bSelectionPut, bApplyToParagraph,
246 pRequest=std::move(pRequest)](sal_Int32 nResult){
247 if (nResult == RET_OK)
249 sw_CharDialogResult(pDlg->GetOutputItemSet(), rWrtSh, pCoreSet, bSel, bSelectionPut,
250 bApplyToParagraph, pRequest.get());
252 pDlg->disposeOnce();
255 else if (pArgs)
257 sw_CharDialogResult(pArgs, rWrtSh, pCoreSet, bSel, bSelectionPut, bApplyToParagraph, pReq);
261 static void sw_CharDialogResult(const SfxItemSet* pSet, SwWrtShell& rWrtSh, std::shared_ptr<SfxItemSet> const & pCoreSet, bool bSel,
262 bool bSelectionPut, bool bApplyToParagraph, SfxRequest* pReq)
264 SfxItemSet aTmpSet( *pSet );
265 ::ConvertAttrGenToChar(aTmpSet, *pCoreSet);
267 const bool bWasLocked = rWrtSh.IsViewLocked();
268 if (bApplyToParagraph)
270 rWrtSh.StartAction();
271 rWrtSh.LockView(true);
272 rWrtSh.Push();
273 SwLangHelper::SelectCurrentPara(rWrtSh);
276 const SfxStringItem* pSelectionItem;
277 bool bInsert = false;
278 sal_Int32 nInsert = 0;
280 // The old item is for unknown reasons back in the set again.
281 if( !bSelectionPut && (pSelectionItem = aTmpSet.GetItemIfSet(FN_PARAM_SELECTION, false)) )
283 const OUString& sInsert = pSelectionItem->GetValue();
284 bInsert = !sInsert.isEmpty();
285 if(bInsert)
287 nInsert = sInsert.getLength();
288 rWrtSh.StartAction();
289 rWrtSh.Insert( sInsert );
290 rWrtSh.SetMark();
291 rWrtSh.ExtendSelection(false, sInsert.getLength());
292 SfxRequest aReq(rWrtSh.GetView().GetViewFrame(), FN_INSERT_STRING);
293 aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, sInsert ) );
294 aReq.Done();
295 SfxRequest aReq1(rWrtSh.GetView().GetViewFrame(), FN_CHAR_LEFT);
296 aReq1.AppendItem( SfxInt32Item(FN_PARAM_MOVE_COUNT, nInsert) );
297 aReq1.AppendItem( SfxBoolItem(FN_PARAM_MOVE_SELECTION, true) );
298 aReq1.Done();
301 aTmpSet.ClearItem(FN_PARAM_SELECTION);
303 SwTextFormatColl* pColl = rWrtSh.GetCurTextFormatColl();
304 if(bSel && rWrtSh.IsSelFullPara() && pColl && pColl->IsAutoUpdateOnDirectFormat())
306 rWrtSh.AutoUpdatePara(pColl, aTmpSet);
308 else
309 rWrtSh.SetAttrSet( aTmpSet );
310 if (pReq)
311 pReq->Done(aTmpSet);
312 if(bInsert)
314 SfxRequest aReq1(rWrtSh.GetView().GetViewFrame(), FN_CHAR_RIGHT);
315 aReq1.AppendItem( SfxInt32Item(FN_PARAM_MOVE_COUNT, nInsert) );
316 aReq1.AppendItem( SfxBoolItem(FN_PARAM_MOVE_SELECTION, false) );
317 aReq1.Done();
318 rWrtSh.SwapPam();
319 rWrtSh.ClearMark();
320 rWrtSh.DontExpandFormat();
321 rWrtSh.EndAction();
324 if (bApplyToParagraph)
326 rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
327 rWrtSh.LockView(bWasLocked);
328 rWrtSh.EndAction();
333 static void sw_ParagraphDialogResult(SfxItemSet* pSet, SwWrtShell &rWrtSh, SfxRequest& rReq, SwPaM* pPaM)
335 if (!pSet)
336 return;
338 rReq.Done( *pSet );
339 ::SfxToSwPageDescAttr( rWrtSh, *pSet );
340 // #i56253#
341 // enclose all undos.
342 // Thus, check conditions, if actions will be performed.
343 const bool bUndoNeeded( pSet->Count() ||
344 SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART) ||
345 SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART_AT) );
346 if ( bUndoNeeded )
348 rWrtSh.StartUndo( SwUndoId::INSATTR );
350 if( pSet->Count() )
352 rWrtSh.StartAction();
353 if ( const SfxStringItem* pDropTextItem = pSet->GetItemIfSet(FN_DROP_TEXT, false) )
355 if ( !pDropTextItem->GetValue().isEmpty() )
356 rWrtSh.ReplaceDropText(pDropTextItem->GetValue(), pPaM);
358 rWrtSh.SetAttrSet(*pSet, SetAttrMode::DEFAULT, pPaM);
359 rWrtSh.EndAction();
360 SwTextFormatColl* pColl = rWrtSh.GetPaMTextFormatColl(pPaM);
361 if(pColl && pColl->IsAutoUpdateOnDirectFormat())
363 rWrtSh.AutoUpdatePara(pColl, *pSet, pPaM);
367 if( SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART) )
369 //SetNumRuleStart(true) restarts the numbering at the value
370 //that is defined at the starting point of the numbering level
371 //otherwise the SetNodeNumStart() value determines the start
372 //if it's set to something different than USHRT_MAX
374 bool bStart = static_cast<const SfxBoolItem&>(pSet->Get(FN_NUMBER_NEWSTART)).GetValue();
376 // Default value for restart value has to be USHRT_MAX
377 // in order to indicate that the restart value of the list
378 // style has to be used on restart.
379 sal_uInt16 nNumStart = USHRT_MAX;
380 if( SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART_AT) )
382 nNumStart = pSet->Get(FN_NUMBER_NEWSTART_AT).GetValue();
384 rWrtSh.SetNumRuleStart(bStart, pPaM);
385 rWrtSh.SetNodeNumStart(nNumStart);
387 else if( SfxItemState::SET == pSet->GetItemState(FN_NUMBER_NEWSTART_AT) )
389 rWrtSh.SetNodeNumStart(pSet->Get(FN_NUMBER_NEWSTART_AT).GetValue());
390 rWrtSh.SetNumRuleStart(false, pPaM);
392 // #i56253#
393 if ( bUndoNeeded )
395 rWrtSh.EndUndo( SwUndoId::INSATTR );
399 namespace {
401 void InsertBreak(SwWrtShell& rWrtSh,
402 sal_uInt16 nKind,
403 ::std::optional<sal_uInt16> oPageNumber,
404 const OUString& rTemplateName, std::optional<SwLineBreakClear> oClear)
406 switch ( nKind )
408 case 1 :
409 rWrtSh.InsertLineBreak(oClear);
410 break;
411 case 2 :
412 rWrtSh.InsertColumnBreak(); break;
413 case 3 :
415 rWrtSh.StartAllAction();
416 if( !rTemplateName.isEmpty() )
417 rWrtSh.InsertPageBreak( &rTemplateName, oPageNumber );
418 else
419 rWrtSh.InsertPageBreak();
420 rWrtSh.EndAllAction();
425 OUString GetLocalURL(const SwWrtShell& rSh)
427 SwField* pField = rSh.GetCurField();
428 if (!pField)
430 return OUString();
433 if (pField->GetTyp()->Which() != SwFieldIds::TableOfAuthorities)
435 return OUString();
438 const auto& rAuthorityField = *static_cast<const SwAuthorityField*>(pField);
439 SwAuthEntry* pAuthEntry = rAuthorityField.GetAuthEntry();
440 if (!pAuthEntry)
442 return OUString();
445 const OUString& rLocalURL = pAuthEntry->GetAuthorField(AUTH_FIELD_LOCAL_URL);
446 return rLocalURL;
449 void UpdateSections(SfxRequest& rReq, SwWrtShell& rWrtSh)
451 OUString aSectionNamePrefix;
452 const SfxStringItem* pSectionNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
453 if (pSectionNamePrefix)
455 aSectionNamePrefix = pSectionNamePrefix->GetValue();
458 uno::Sequence<beans::PropertyValues> aSections;
459 const SfxUnoAnyItem* pSections = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_2);
460 if (pSections)
462 pSections->GetValue() >>= aSections;
465 rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_SECTIONS, nullptr);
466 rWrtSh.StartAction();
468 SwDoc* pDoc = rWrtSh.GetDoc();
469 sal_Int32 nSectionIndex = 0;
470 const SwSectionFormats& rFormats = pDoc->GetSections();
471 IDocumentContentOperations& rIDCO = pDoc->getIDocumentContentOperations();
472 for (size_t i = 0; i < rFormats.size(); ++i)
474 const SwSectionFormat* pFormat = rFormats[i];
475 if (!pFormat->GetName().startsWith(aSectionNamePrefix))
477 continue;
480 if (nSectionIndex >= aSections.getLength())
482 break;
485 comphelper::SequenceAsHashMap aMap(aSections[nSectionIndex++]);
486 OUString aSectionName = aMap[u"RegionName"_ustr].get<OUString>();
487 if (aSectionName != pFormat->GetName())
489 const_cast<SwSectionFormat*>(pFormat)->SetFormatName(aSectionName, /*bBroadcast=*/true);
490 SwSectionData aSectionData(*pFormat->GetSection());
491 aSectionData.SetSectionName(aSectionName);
492 pDoc->UpdateSection(i, aSectionData);
495 const SwFormatContent& rContent = pFormat->GetContent();
496 const SwNodeIndex* pContentNodeIndex = rContent.GetContentIdx();
497 if (pContentNodeIndex)
499 SwPaM aSectionStart(SwPosition{*pContentNodeIndex});
500 aSectionStart.Move(fnMoveForward, GoInContent);
501 SwPaM* pCursorPos = rWrtSh.GetCursor();
502 *pCursorPos = aSectionStart;
503 rWrtSh.EndOfSection(/*bSelect=*/true);
504 rIDCO.DeleteAndJoin(*pCursorPos);
505 rWrtSh.EndSelect();
507 OUString aSectionText = aMap[u"Content"_ustr].get<OUString>();
508 SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aSectionText.toUtf8());
512 rWrtSh.EndAction();
513 rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_SECTIONS, nullptr);
516 void DeleteSections(SfxRequest& rReq, SwWrtShell& rWrtSh)
518 OUString aSectionNamePrefix;
519 const SfxStringItem* pSectionNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
520 if (pSectionNamePrefix)
522 aSectionNamePrefix = pSectionNamePrefix->GetValue();
525 rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_SECTIONS, nullptr);
526 rWrtSh.StartAction();
527 comphelper::ScopeGuard g(
528 [&rWrtSh]
530 rWrtSh.EndAction();
531 rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_SECTIONS, nullptr);
534 SwDoc* pDoc = rWrtSh.GetDoc();
535 std::vector<SwSectionFormat*> aRemovals;
536 for (SwSectionFormat* pFormat : pDoc->GetSections())
537 if (aSectionNamePrefix.isEmpty() || pFormat->GetName().startsWith(aSectionNamePrefix))
538 aRemovals.push_back(pFormat);
540 for (const auto& pFormat : aRemovals)
542 // Just delete the format, not the content of the section.
543 pDoc->DelSectionFormat(pFormat);
547 void DeleteContentControl( SwWrtShell& rWrtSh )
549 SwTextContentControl* pTextContentControl = rWrtSh.CursorInsideContentControl();
550 if (pTextContentControl) {
551 const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl();
552 const std::shared_ptr<SwContentControl>& pContentControl = rFormatContentControl.GetContentControl();
553 pContentControl->SetReadWrite(true);
554 pTextContentControl->Delete(true);
559 void UpdateBookmarks(SfxRequest& rReq, SwWrtShell& rWrtSh)
561 if (rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
563 return;
566 OUString aBookmarkNamePrefix;
567 const SfxStringItem* pBookmarkNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
568 if (pBookmarkNamePrefix)
570 aBookmarkNamePrefix = pBookmarkNamePrefix->GetValue();
573 uno::Sequence<beans::PropertyValues> aBookmarks;
574 const SfxUnoAnyItem* pBookmarks = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_2);
575 if (pBookmarks)
577 pBookmarks->GetValue() >>= aBookmarks;
580 rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_BOOKMARKS, nullptr);
581 rWrtSh.StartAction();
583 IDocumentMarkAccess& rIDMA = *rWrtSh.GetDoc()->getIDocumentMarkAccess();
584 sal_Int32 nBookmarkIndex = 0;
585 bool bSortMarks = false;
586 for (auto it = rIDMA.getBookmarksBegin(); it != rIDMA.getBookmarksEnd(); ++it)
588 sw::mark::Bookmark* pMark = *it;
589 assert(pMark);
590 if (!pMark->GetName().startsWith(aBookmarkNamePrefix))
592 continue;
595 if (aBookmarks.getLength() <= nBookmarkIndex)
597 continue;
600 comphelper::SequenceAsHashMap aMap(aBookmarks[nBookmarkIndex++]);
601 if (aMap[u"Bookmark"_ustr].get<OUString>() != pMark->GetName())
603 rIDMA.renameMark(pMark, aMap[u"Bookmark"_ustr].get<OUString>());
606 OUString aBookmarkText = aMap[u"BookmarkText"_ustr].get<OUString>();
608 // Insert markers to remember where the paste positions are.
609 SwPaM aMarkers(pMark->GetMarkEnd());
610 IDocumentContentOperations& rIDCO = rWrtSh.GetDoc()->getIDocumentContentOperations();
611 bool bSuccess = rIDCO.InsertString(aMarkers, u"XY"_ustr);
612 if (bSuccess)
614 SwPaM aPasteEnd(pMark->GetMarkEnd());
615 aPasteEnd.Move(fnMoveForward, GoInContent);
617 // Paste HTML content.
618 SwPaM* pCursorPos = rWrtSh.GetCursor();
619 *pCursorPos = aPasteEnd;
620 SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aBookmarkText.toUtf8());
622 // Update the bookmark to point to the new content.
623 SwPaM aPasteStart(pMark->GetMarkEnd());
624 aPasteStart.Move(fnMoveForward, GoInContent);
625 SwPaM aStartMarker(pMark->GetMarkStart(), *aPasteStart.GetPoint());
626 SwPaM aEndMarker(*aPasteEnd.GetPoint(), *aPasteEnd.GetPoint());
627 aEndMarker.GetMark()->AdjustContent(1);
628 pMark->SetMarkPos(*aPasteStart.GetPoint());
629 pMark->SetOtherMarkPos(*aPasteEnd.GetPoint());
630 bSortMarks = true;
632 // Remove markers. the start marker includes the old content as well.
633 rIDCO.DeleteAndJoin(aStartMarker);
634 rIDCO.DeleteAndJoin(aEndMarker);
637 if (bSortMarks)
639 rIDMA.assureSortedMarkContainers();
642 rWrtSh.EndAction();
643 rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_BOOKMARKS, nullptr);
646 void UpdateBookmark(SfxRequest& rReq, SwWrtShell& rWrtSh)
648 if (rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
650 return;
653 OUString aBookmarkNamePrefix;
654 const SfxStringItem* pBookmarkNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
655 if (pBookmarkNamePrefix)
657 aBookmarkNamePrefix = pBookmarkNamePrefix->GetValue();
660 uno::Sequence<beans::PropertyValue> aBookmark;
661 const SfxUnoAnyItem* pBookmarks = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_2);
662 if (pBookmarks)
664 pBookmarks->GetValue() >>= aBookmark;
667 IDocumentMarkAccess& rIDMA = *rWrtSh.GetDoc()->getIDocumentMarkAccess();
668 SwPosition& rCursor = *rWrtSh.GetCursor()->GetPoint();
669 sw::mark::Bookmark* pBookmark = rIDMA.getOneInnermostBookmarkFor(rCursor);
670 if (!pBookmark || !pBookmark->GetName().startsWith(aBookmarkNamePrefix))
672 return;
675 SwRewriter aRewriter;
676 aRewriter.AddRule(UndoArg1, pBookmark->GetName());
677 rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_BOOKMARK, &aRewriter);
678 rWrtSh.StartAction();
679 comphelper::ScopeGuard g(
680 [&rWrtSh, &aRewriter]
682 rWrtSh.EndAction();
683 rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_BOOKMARK, &aRewriter);
687 comphelper::SequenceAsHashMap aMap(aBookmark);
688 if (aMap[u"Bookmark"_ustr].get<OUString>() != pBookmark->GetName())
690 rIDMA.renameMark(pBookmark, aMap[u"Bookmark"_ustr].get<OUString>());
693 // Insert markers to remember where the paste positions are.
694 SwPaM aMarkers(pBookmark->GetMarkEnd());
695 IDocumentContentOperations& rIDCO = rWrtSh.GetDoc()->getIDocumentContentOperations();
696 if (!rIDCO.InsertString(aMarkers, u"XY"_ustr))
698 return;
701 SwPaM aPasteEnd(pBookmark->GetMarkEnd());
702 aPasteEnd.Move(fnMoveForward, GoInContent);
704 OUString aBookmarkText = aMap[u"BookmarkText"_ustr].get<OUString>();
706 // Paste HTML content.
707 SwPaM* pCursorPos = rWrtSh.GetCursor();
708 *pCursorPos = aPasteEnd;
709 SwTranslateHelper::PasteHTMLToPaM(rWrtSh, pCursorPos, aBookmarkText.toUtf8());
711 // Update the bookmark to point to the new content.
712 SwPaM aPasteStart(pBookmark->GetMarkEnd());
713 aPasteStart.Move(fnMoveForward, GoInContent);
714 SwPaM aStartMarker(pBookmark->GetMarkStart(), *aPasteStart.GetPoint());
715 SwPaM aEndMarker(*aPasteEnd.GetPoint(), *aPasteEnd.GetPoint());
716 aEndMarker.GetMark()->AdjustContent(1);
717 pBookmark->SetMarkPos(*aPasteStart.GetPoint());
718 pBookmark->SetOtherMarkPos(*aPasteEnd.GetPoint());
720 // Remove markers. the start marker includes the old content as well.
721 rIDCO.DeleteAndJoin(aStartMarker);
722 rIDCO.DeleteAndJoin(aEndMarker);
723 rIDMA.assureSortedMarkContainers();
726 void DeleteBookmarks(SfxRequest& rReq, SwWrtShell& rWrtSh)
728 if (rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
730 return;
733 OUString aBookmarkNamePrefix;
734 const SfxStringItem* pBookmarkNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
735 if (pBookmarkNamePrefix)
737 aBookmarkNamePrefix = pBookmarkNamePrefix->GetValue();
740 rWrtSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_BOOKMARKS, nullptr);
741 rWrtSh.StartAction();
742 comphelper::ScopeGuard g(
743 [&rWrtSh]
745 rWrtSh.EndAction();
746 rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_BOOKMARKS, nullptr);
749 IDocumentMarkAccess* pMarkAccess = rWrtSh.GetDoc()->getIDocumentMarkAccess();
750 std::vector<sw::mark::MarkBase*> aRemovals;
751 for (auto it = pMarkAccess->getBookmarksBegin(); it != pMarkAccess->getBookmarksEnd(); ++it)
753 sw::mark::Bookmark* pBookmark = *it;
754 assert(pBookmark);
756 if (!aBookmarkNamePrefix.isEmpty())
758 if (!pBookmark->GetName().startsWith(aBookmarkNamePrefix))
760 continue;
764 aRemovals.push_back(pBookmark);
767 for (const auto& pMark : aRemovals)
769 pMarkAccess->deleteMark(pMark);
773 void DeleteFields(SfxRequest& rReq, SwWrtShell& rWrtSh)
775 const SfxStringItem* pTypeName = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
776 if (!pTypeName || pTypeName->GetValue() != "SetRef")
778 // This is implemented so far only for reference marks.
779 return;
782 OUString aNamePrefix;
783 const SfxStringItem* pNamePrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
784 if (pNamePrefix)
786 aNamePrefix = pNamePrefix->GetValue();
789 SwDoc* pDoc = rWrtSh.GetDoc();
790 pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_FIELDS, nullptr);
791 rWrtSh.StartAction();
792 comphelper::ScopeGuard g(
793 [&rWrtSh]
795 rWrtSh.EndAction();
796 rWrtSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_FIELDS, nullptr);
799 std::vector<const SwFormatRefMark*> aRemovals;
800 for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i)
802 const SwFormatRefMark* pRefMark = pDoc->GetRefMark(i);
803 if (!aNamePrefix.isEmpty())
805 if (!pRefMark->GetRefName().startsWith(aNamePrefix))
807 continue;
811 aRemovals.push_back(pRefMark);
814 for (const auto& pMark : aRemovals)
816 pDoc->DeleteFormatRefMark(pMark);
820 void lcl_LogWarning(std::string sWarning)
822 LOK_WARN("sw.transform", sWarning);
825 bool lcl_ChangeChartColumnCount(const uno::Reference<chart2::XChartDocument>& xChartDoc, sal_Int32 nId,
826 bool bInsert, bool bResize = false)
828 uno::Reference<chart2::XDiagram> xDiagram = xChartDoc->getFirstDiagram();
829 if (!xDiagram.is())
830 return false;
831 uno::Reference<chart2::XCoordinateSystemContainer> xCooSysContainer(xDiagram, uno::UNO_QUERY);
832 if (!xCooSysContainer.is())
833 return false;
834 uno::Sequence<uno::Reference<chart2::XCoordinateSystem>> xCooSysSequence(
835 xCooSysContainer->getCoordinateSystems());
836 if (xCooSysSequence.getLength() <= 0)
837 return false;
838 uno::Reference<chart2::XChartTypeContainer> xChartTypeContainer(xCooSysSequence[0],
839 uno::UNO_QUERY);
840 if (!xChartTypeContainer.is())
841 return false;
842 uno::Sequence<uno::Reference<chart2::XChartType>> xChartTypeSequence(
843 xChartTypeContainer->getChartTypes());
844 if (xChartTypeSequence.getLength() <= 0)
845 return false;
846 uno::Reference<chart2::XDataSeriesContainer> xDSContainer(xChartTypeSequence[0],
847 uno::UNO_QUERY);
848 if (!xDSContainer.is())
849 return false;
851 uno::Reference<chart2::XInternalDataProvider> xIDataProvider(xChartDoc->getDataProvider(),
852 uno::UNO_QUERY);
853 if (!xIDataProvider.is())
854 return false;
856 uno::Sequence<uno::Reference<chart2::XDataSeries>> aSeriesSeq(xDSContainer->getDataSeries());
858 int nSeriesCount = aSeriesSeq.getLength();
860 if (bResize)
862 // Resize is actually some inserts, or deletes
863 if (nId > nSeriesCount)
865 bInsert = true;
867 else if (nId < nSeriesCount)
869 bInsert = false;
871 else
873 // Resize to the same size. No change needed
874 return true;
878 // insert or delete
879 if (bInsert)
881 // insert
882 if (nId > nSeriesCount && !bResize)
883 return false;
885 int nInsertCount = bResize ? nId - nSeriesCount : 1;
887 // call dialog code
888 if (bResize)
890 for (int i = 0; i < nInsertCount; i++)
892 xIDataProvider->insertDataSeries(nSeriesCount);
894 return true;
897 xIDataProvider->insertDataSeries(nId);
899 else
901 // delete 1 or more columns
902 if (nId >= nSeriesCount)
903 return false;
904 int nDeleteCount = bResize ? nSeriesCount - nId : 1;
905 for (int i = 0; i < nDeleteCount; i++)
907 xDSContainer->removeDataSeries(aSeriesSeq[nId]);
910 return true;
913 bool lcl_ResizeChartColumns(const uno::Reference<chart2::XChartDocument>& xChartDoc, sal_Int32 nSize)
915 return lcl_ChangeChartColumnCount(xChartDoc, nSize, false, true);
918 bool lcl_InsertChartColumns(const uno::Reference<chart2::XChartDocument>& xChartDoc, sal_Int32 nId)
920 return lcl_ChangeChartColumnCount(xChartDoc, nId, true);
923 bool lcl_DeleteChartColumns(const uno::Reference<chart2::XChartDocument>& xChartDoc, sal_Int32 nId)
925 return lcl_ChangeChartColumnCount(xChartDoc, nId, false);
929 static bool AddWordToWordbook(const uno::Reference<linguistic2::XDictionary>& xDictionary, SwWrtShell &rWrtSh)
931 if (!xDictionary)
932 return false;
934 SwRect aToFill;
935 uno::Reference<linguistic2::XSpellAlternatives> xSpellAlt(rWrtSh.GetCorrection(nullptr, aToFill));
936 if (!xSpellAlt.is())
937 return false;
939 OUString sWord = xSpellAlt->getWord();
940 linguistic::DictionaryError nAddRes = linguistic::AddEntryToDic(xDictionary, sWord, false, OUString());
941 if (linguistic::DictionaryError::NONE != nAddRes && xDictionary.is() && !xDictionary->getEntry(sWord).is())
943 SvxDicError(rWrtSh.GetView().GetFrameWeld(), nAddRes);
944 return false;
946 return true;
949 void SwTextShell::Execute(SfxRequest &rReq)
951 bool bUseDialog = true;
952 const SfxItemSet *pArgs = rReq.GetArgs();
953 SwWrtShell& rWrtSh = GetShell();
954 const SfxPoolItem* pItem = nullptr;
955 const sal_uInt16 nSlot = rReq.GetSlot();
956 if(pArgs)
957 pArgs->GetItemState(GetPool().GetWhichIDFromSlotID(nSlot), false, &pItem);
958 switch( nSlot )
960 case SID_UNICODE_NOTATION_TOGGLE:
962 tools::Long nMaxUnits = 256;
963 sal_Int32 nSelLength = rWrtSh.GetSelText().getLength();
964 if( rWrtSh.IsSelection() && !rWrtSh.IsMultiSelection() && (nSelLength < nMaxUnits) )
965 nMaxUnits = nSelLength;
967 tools::Long index = 0;
968 ToggleUnicodeCodepoint aToggle;
969 while( nMaxUnits-- && aToggle.AllowMoreInput(rWrtSh.GetChar(true, index-1)) )
970 --index;
972 OUString sReplacement = aToggle.ReplacementString();
973 if( !sReplacement.isEmpty() )
975 if (rWrtSh.HasReadonlySel() && !rWrtSh.CursorInsideInputField())
977 // Only break if there's something to do; don't nag with the dialog otherwise
978 rWrtSh.InfoReadOnlyDialog(false);
979 break;
981 OUString stringToReplace = aToggle.StringToReplace();
982 SwRewriter aRewriter;
983 aRewriter.AddRule( UndoArg1, stringToReplace );
984 aRewriter.AddRule( UndoArg2, SwResId(STR_YIELDS) );
985 aRewriter.AddRule( UndoArg3, sReplacement );
986 rWrtSh.StartUndo(SwUndoId::REPLACE, &aRewriter);
987 rWrtSh.GetCursor()->Normalize(false);
989 rWrtSh.ClearMark();
990 if( rWrtSh.IsInSelect() ) // cancel any in-progress keyboard selection as well
991 rWrtSh.EndSelect();
992 // Select exactly what was chosen for replacement
993 rWrtSh.GetCursor()->SetMark();
994 rWrtSh.GetCursor()->GetPoint()->AdjustContent(-stringToReplace.getLength());
995 rWrtSh.DelLeft();
996 rWrtSh.Insert2( sReplacement );
997 rWrtSh.EndUndo(SwUndoId::REPLACE, &aRewriter);
1000 break;
1002 case SID_LANGUAGE_STATUS:
1004 // get the language
1005 OUString aNewLangText;
1006 const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(SID_LANGUAGE_STATUS);
1007 if (pItem2)
1008 aNewLangText = pItem2->GetValue();
1010 //!! Remember the view frame right now...
1011 //!! (call to GetView().GetViewFrame() will break if the
1012 //!! SwTextShell got destroyed meanwhile.)
1013 SfxViewFrame& rViewFrame = GetView().GetViewFrame();
1015 if (aNewLangText == "*")
1017 // open the dialog "Tools/Options/Languages and Locales - General"
1018 // to set the documents default language
1019 SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1020 ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog(GetView().GetFrameWeld(), SID_LANGUAGE_OPTIONS));
1021 pDlg->Execute();
1023 else
1025 //!! We have to use StartAction / EndAction bracketing in
1026 //!! order to prevent possible destruction of the SwTextShell
1027 //!! due to the selection changes coming below.
1028 rWrtSh.StartAction();
1029 // prevent view from jumping because of (temporary) selection changes
1030 rWrtSh.LockView( true );
1032 // setting the new language...
1033 if (!aNewLangText.isEmpty())
1035 static constexpr OUString aSelectionLangPrefix(u"Current_"_ustr);
1036 static constexpr OUString aParagraphLangPrefix(u"Paragraph_"_ustr);
1037 static constexpr OUString aDocumentLangPrefix(u"Default_"_ustr);
1039 SfxItemSetFixed
1040 <RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
1041 RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
1042 RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE> aCoreSet( GetPool() );
1044 sal_Int32 nPos = 0;
1045 bool bForSelection = true;
1046 bool bForParagraph = false;
1047 if (-1 != (nPos = aNewLangText.indexOf( aSelectionLangPrefix )))
1049 // ... for the current selection
1050 aNewLangText = aNewLangText.replaceAt(nPos, aSelectionLangPrefix.getLength(), u"");
1051 bForSelection = true;
1053 else if (-1 != (nPos = aNewLangText.indexOf(aParagraphLangPrefix)))
1055 // ... for the current paragraph language
1056 aNewLangText = aNewLangText.replaceAt(nPos, aParagraphLangPrefix.getLength(), u"");
1057 bForSelection = true;
1058 bForParagraph = true;
1060 else if (-1 != (nPos = aNewLangText.indexOf(aDocumentLangPrefix)))
1062 // ... as default document language
1063 aNewLangText = aNewLangText.replaceAt(nPos, aDocumentLangPrefix.getLength(), u"");
1064 bForSelection = false;
1067 if (bForParagraph || !bForSelection)
1069 rWrtSh.Push(); // save selection for later restoration
1070 rWrtSh.ClearMark(); // fdo#67796: invalidate table crsr
1073 if (bForParagraph)
1074 SwLangHelper::SelectCurrentPara( rWrtSh );
1076 if (!bForSelection) // document language to be changed...
1078 rWrtSh.SelAll();
1079 rWrtSh.ExtendedSelectAll();
1082 rWrtSh.StartUndo( ( !bForParagraph && !bForSelection ) ? SwUndoId::SETDEFTATTR : SwUndoId::EMPTY );
1083 if (aNewLangText == "LANGUAGE_NONE")
1084 SwLangHelper::SetLanguage_None( rWrtSh, bForSelection, aCoreSet );
1085 else if (aNewLangText == "RESET_LANGUAGES")
1086 SwLangHelper::ResetLanguages( rWrtSh );
1087 else
1088 SwLangHelper::SetLanguage( rWrtSh, aNewLangText, bForSelection, aCoreSet );
1089 rWrtSh.EndUndo();
1091 if (bForParagraph || !bForSelection)
1093 rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // restore selection...
1097 rWrtSh.LockView( false );
1098 rWrtSh.EndAction();
1101 // invalidate slot to get the new language displayed
1102 rViewFrame.GetBindings().Invalidate( nSlot );
1104 rReq.Done();
1105 break;
1108 case SID_THES:
1110 // replace word/selection with text from selected sub menu entry
1111 OUString aReplaceText;
1112 const SfxStringItem* pItem2 = rReq.GetArg(FN_PARAM_THES_WORD_REPLACE);
1113 if (pItem2)
1114 aReplaceText = pItem2->GetValue();
1115 if (!aReplaceText.isEmpty())
1117 SwView &rView2 = rWrtSh.GetView();
1118 const bool bSelection = rWrtSh.HasSelection();
1119 const OUString aLookUpText = rView2.GetThesaurusLookUpText( bSelection );
1120 rView2.InsertThesaurusSynonym( aReplaceText, aLookUpText, bSelection );
1123 break;
1125 case SID_CHARMAP:
1127 InsertSymbol( rReq );
1129 break;
1130 case FN_INSERT_FOOTNOTE:
1131 case FN_INSERT_ENDNOTE:
1133 OUString aStr;
1134 const SfxStringItem* pFont = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
1135 const SfxStringItem* pNameItem = rReq.GetArg<SfxStringItem>(nSlot);
1136 if ( pNameItem )
1137 aStr = pNameItem->GetValue();
1138 bool bFont = pFont && !pFont->GetValue().isEmpty();
1139 rWrtSh.StartUndo( SwUndoId::UI_INSERT_FOOTNOTE );
1140 rWrtSh.InsertFootnote( aStr, nSlot == FN_INSERT_ENDNOTE, !bFont );
1141 if ( bFont )
1143 rWrtSh.Left( SwCursorSkipMode::Chars, true, 1, false );
1144 SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONT> aSet( rWrtSh.GetAttrPool() );
1145 rWrtSh.GetCurAttr( aSet );
1146 rWrtSh.SetAttrSet( aSet, SetAttrMode::DONTEXPAND );
1147 rWrtSh.ResetSelect(nullptr, false, ScrollSizeMode::ScrollSizeDefault);
1148 rWrtSh.EndSelect();
1149 rWrtSh.GotoFootnoteText();
1151 rWrtSh.EndUndo( SwUndoId::UI_INSERT_FOOTNOTE );
1152 rReq.Done();
1154 break;
1155 case FN_INSERT_FOOTNOTE_DLG:
1157 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1158 VclPtr<AbstractInsFootNoteDlg> pDlg(pFact->CreateInsFootNoteDlg(
1159 GetView().GetFrameWeld(), rWrtSh));
1160 pDlg->SetHelpId(GetStaticInterface()->GetSlot(nSlot)->GetCommand());
1161 pDlg->StartExecuteAsync(
1162 [this, pDlg] (sal_Int32 nResult)->void
1164 if ( nResult == RET_OK )
1166 pDlg->Apply();
1167 const sal_uInt16 nId = pDlg->IsEndNote() ? FN_INSERT_ENDNOTE : FN_INSERT_FOOTNOTE;
1168 SfxRequest aReq(GetView().GetViewFrame(), nId);
1169 if ( !pDlg->GetStr().isEmpty() )
1170 aReq.AppendItem( SfxStringItem( nId, pDlg->GetStr() ) );
1171 if ( !pDlg->GetFontName().isEmpty() )
1172 aReq.AppendItem( SfxStringItem( FN_PARAM_1, pDlg->GetFontName() ) );
1173 ExecuteSlot( aReq );
1175 pDlg->disposeOnce();
1178 rReq.Ignore();
1180 break;
1181 case FN_FORMAT_FOOTNOTE_DLG:
1182 case FN_FORMAT_CURRENT_FOOTNOTE_DLG:
1184 GetView().ExecFormatFootnote();
1185 break;
1187 case SID_INSERTDOC:
1189 GetView().ExecuteInsertDoc( rReq, pItem );
1190 break;
1192 case FN_FORMAT_RESET:
1194 // #i78856, reset all attributes but not the language attributes
1195 // (for this build an array of all relevant attributes and
1196 // remove the languages from that)
1197 o3tl::sorted_vector<sal_uInt16> aAttribs;
1199 static constexpr std::pair<sal_uInt16, sal_uInt16> aResetableSetRange[] = {
1200 // tdf#40496: we don't want to change writing direction, so exclude RES_FRAMEDIR:
1201 { RES_FRMATR_BEGIN, RES_FRAMEDIR - 1 },
1202 { RES_FRAMEDIR + 1, RES_FRMATR_END - 1 },
1203 { RES_CHRATR_BEGIN, RES_CHRATR_LANGUAGE - 1 },
1204 { RES_CHRATR_LANGUAGE + 1, RES_CHRATR_CJK_LANGUAGE - 1 },
1205 { RES_CHRATR_CJK_LANGUAGE + 1, RES_CHRATR_CTL_LANGUAGE - 1 },
1206 { RES_CHRATR_CTL_LANGUAGE + 1, RES_CHRATR_END - 1 },
1207 { RES_PARATR_BEGIN, RES_PARATR_END - 1 },
1208 { RES_PARATR_LIST_AUTOFMT, RES_PARATR_LIST_AUTOFMT },
1209 { RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER },
1210 { RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END - 1 },
1212 for (const auto& [nBegin, nEnd] : aResetableSetRange)
1214 for (sal_uInt16 i = nBegin; i <= nEnd; ++i)
1215 aAttribs.insert( i );
1218 // also clear the direct formatting flag inside SwTableBox(es)
1219 if (SwFEShell* pFEShell = GetView().GetDocShell()->GetFEShell())
1220 pFEShell->UpdateTableStyleFormatting(nullptr, true);
1222 // tdf#160801 fix crash by delaying resetting of attributes
1223 // Calling SwWrtShell::ResetAttr() will sometimes delete the
1224 // current SwTextShell instance so call it after clearing the
1225 // direct formatting flag.
1226 rWrtSh.ResetAttr( aAttribs );
1228 rReq.Done();
1229 break;
1231 case FN_INSERT_BREAK_DLG:
1233 if ( pItem )
1235 ::std::optional<sal_uInt16> oPageNumber;
1236 std::optional<SwLineBreakClear> oClear;
1237 OUString aTemplateName;
1238 sal_uInt16 nKind = static_cast<const SfxInt16Item*>(pItem)->GetValue();
1239 const SfxStringItem* pTemplate = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
1240 const SfxUInt16Item* pNumber = rReq.GetArg<SfxUInt16Item>(FN_PARAM_2);
1241 const SfxBoolItem* pIsNumberFilled = rReq.GetArg<SfxBoolItem>(FN_PARAM_3);
1242 if ( pTemplate )
1243 aTemplateName = pTemplate->GetValue();
1244 if ( pNumber && pIsNumberFilled && pIsNumberFilled->GetValue() )
1245 oPageNumber = pNumber->GetValue();
1247 InsertBreak(rWrtSh, nKind, oPageNumber, aTemplateName, oClear);
1249 else
1251 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1253 std::shared_ptr<AbstractSwBreakDlg> pAbstractDialog(pFact->CreateSwBreakDlg(GetView().GetFrameWeld(), rWrtSh));
1254 std::shared_ptr<weld::DialogController> pDialogController(pAbstractDialog->getDialogController());
1256 weld::DialogController::runAsync(pDialogController,
1257 [pAbstractDialog=std::move(pAbstractDialog), &rWrtSh] (sal_Int32 nResult) {
1258 if( RET_OK == nResult )
1260 sal_uInt16 nKind = pAbstractDialog->GetKind();
1261 OUString aTemplateName = pAbstractDialog->GetTemplateName();
1262 ::std::optional<sal_uInt16> oPageNumber = pAbstractDialog->GetPageNumber();
1263 std::optional<SwLineBreakClear> oClear = pAbstractDialog->GetClear();
1265 InsertBreak(rWrtSh, nKind, oPageNumber, aTemplateName, oClear);
1270 break;
1272 case FN_INSERT_BOOKMARK:
1274 const SfxStringItem* pBookmarkText = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
1275 SwPaM* pCursorPos = rWrtSh.GetCursor();
1276 if ( pItem )
1278 rWrtSh.StartAction();
1279 OUString sName = static_cast<const SfxStringItem*>(pItem)->GetValue();
1281 if (pBookmarkText)
1283 OUString aBookmarkText = pBookmarkText->GetValue();
1284 // Split node to remember where the start position is.
1285 bool bSuccess = rWrtSh.GetDoc()->getIDocumentContentOperations().SplitNode(
1286 *pCursorPos->GetPoint(), /*bChkTableStart=*/false);
1287 if (bSuccess)
1289 SwPaM aBookmarkPam(*pCursorPos->GetPoint());
1290 aBookmarkPam.Move(fnMoveBackward, GoInContent);
1292 // Paste HTML content.
1293 SwTranslateHelper::PasteHTMLToPaM(
1294 rWrtSh, pCursorPos, aBookmarkText.toUtf8());
1295 if (pCursorPos->GetPoint()->GetContentIndex() == 0)
1297 // The paste created a last empty text node, remove it.
1298 SwPaM aPam(*pCursorPos->GetPoint());
1299 aPam.SetMark();
1300 aPam.Move(fnMoveBackward, GoInContent);
1301 rWrtSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPam);
1304 // Undo the above SplitNode().
1305 aBookmarkPam.SetMark();
1306 aBookmarkPam.Move(fnMoveForward, GoInContent);
1307 rWrtSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(
1308 aBookmarkPam);
1309 *aBookmarkPam.GetMark() = *pCursorPos->GetPoint();
1310 *pCursorPos = aBookmarkPam;
1314 rWrtSh.SetBookmark( vcl::KeyCode(), sName );
1315 if (pBookmarkText)
1317 pCursorPos->DeleteMark();
1319 rWrtSh.EndAction();
1320 break;
1322 [[fallthrough]];
1324 case FN_EDIT_BOOKMARK:
1326 ::std::optional<OUString> oName;
1327 if (pItem)
1329 oName.emplace(static_cast<const SfxStringItem*>(pItem)->GetValue());
1332 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1333 ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSwInsertBookmarkDlg(GetView().GetFrameWeld(), rWrtSh, oName ? &*oName : nullptr));
1334 VclAbstractDialog::AsyncContext aContext;
1335 aContext.maEndDialogFn = [](sal_Int32){};
1336 pDlg->StartExecuteAsync(aContext);
1339 break;
1341 case FN_UPDATE_BOOKMARKS:
1343 // This updates all bookmarks in the document that match the conditions specified in
1344 // rReq.
1345 UpdateBookmarks(rReq, rWrtSh);
1346 break;
1348 case FN_UPDATE_BOOKMARK:
1350 // This updates the bookmark under the cursor.
1351 UpdateBookmark(rReq, rWrtSh);
1352 break;
1354 case FN_DELETE_BOOKMARK:
1356 // This deletes a bookmark with the specified name.
1357 if (pItem && !rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS))
1359 IDocumentMarkAccess* const pMarkAccess = rWrtSh.getIDocumentMarkAccess();
1360 pMarkAccess->deleteMark(pMarkAccess->findMark(static_cast<const SfxStringItem*>(pItem)->GetValue()), false);
1362 break;
1364 case FN_DELETE_BOOKMARKS:
1366 // This deletes all bookmarks in the document matching a specified prefix.
1367 DeleteBookmarks(rReq, rWrtSh);
1368 break;
1370 case FN_DELETE_FIELDS:
1372 // This deletes all fields in the document matching a specified type & prefix.
1373 DeleteFields(rReq, rWrtSh);
1374 break;
1376 case FN_UPDATE_SECTIONS:
1378 UpdateSections(rReq, rWrtSh);
1379 break;
1381 case FN_DELETE_SECTIONS:
1383 // This deletes all sections in the document matching a specified prefix. Note that the
1384 // section is deleted, but not its contents.
1385 DeleteSections(rReq, rWrtSh);
1386 break;
1388 case FN_DELETE_CONTENT_CONTROL:
1390 DeleteContentControl( rWrtSh );
1391 break;
1393 case FN_SET_REMINDER:
1395 // collect and sort navigator reminder names
1396 IDocumentMarkAccess* const pMarkAccess = rWrtSh.getIDocumentMarkAccess();
1397 std::vector< OUString > vNavMarkNames;
1398 for(auto ppMark = pMarkAccess->getAllMarksBegin();
1399 ppMark != pMarkAccess->getAllMarksEnd();
1400 ++ppMark)
1402 if( IDocumentMarkAccess::GetType(**ppMark) == IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER )
1403 vNavMarkNames.push_back((*ppMark)->GetName());
1405 std::sort(vNavMarkNames.begin(), vNavMarkNames.end());
1407 // we are maxed out so delete the first one
1408 // this assumes that IDocumentMarkAccess generates Names in ascending order
1409 if(vNavMarkNames.size() == MAX_MARKS)
1410 pMarkAccess->deleteMark(pMarkAccess->findMark(vNavMarkNames[0]), false);
1412 rWrtSh.SetBookmark(vcl::KeyCode(), OUString(), IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER);
1413 SwView::SetActMark(vNavMarkNames.size() < MAX_MARKS ? vNavMarkNames.size() : MAX_MARKS-1);
1415 break;
1417 case FN_AUTOFORMAT_REDLINE_APPLY:
1419 SvxSwAutoFormatFlags aFlags(SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags());
1420 // This must always be false for the postprocessing.
1421 aFlags.bAFormatByInput = false;
1422 aFlags.bWithRedlining = true;
1423 rWrtSh.AutoFormat( &aFlags, false );
1424 aFlags.bWithRedlining = false;
1426 SfxViewFrame& rVFrame = GetView().GetViewFrame();
1427 if (rVFrame.HasChildWindow(FN_REDLINE_ACCEPT))
1428 rVFrame.ToggleChildWindow(FN_REDLINE_ACCEPT);
1430 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1431 auto xRequest = std::make_shared<SfxRequest>(rReq);
1432 rReq.Ignore(); // the 'old' request is not relevant any more
1433 VclPtr<AbstractSwModalRedlineAcceptDlg> pDlg(pFact->CreateSwModalRedlineAcceptDlg(GetView().GetEditWin().GetFrameWeld()));
1434 pDlg->StartExecuteAsync(
1435 [pDlg, xRequest=std::move(xRequest)] (sal_Int32 /*nResult*/)->void
1437 pDlg->disposeOnce();
1438 xRequest->Done();
1442 break;
1444 case FN_AUTOFORMAT_APPLY:
1446 SvxSwAutoFormatFlags aFlags(SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags());
1447 // This must always be false for the postprocessing.
1448 aFlags.bAFormatByInput = false;
1449 rWrtSh.AutoFormat( &aFlags, false );
1450 rReq.Done();
1452 break;
1453 case FN_AUTOFORMAT_AUTO:
1455 SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
1456 bool bSet = pItem ? static_cast<const SfxBoolItem*>(pItem)->GetValue() : !rACfg.IsAutoFormatByInput();
1457 if( bSet != rACfg.IsAutoFormatByInput() )
1459 rACfg.SetAutoFormatByInput( bSet );
1460 rACfg.Commit();
1461 GetView().GetViewFrame().GetBindings().Invalidate( nSlot );
1462 if ( !pItem )
1463 rReq.AppendItem( SfxBoolItem( GetPool().GetWhichIDFromSlotID(nSlot), bSet ) );
1464 rReq.Done();
1467 break;
1468 case FN_AUTO_CORRECT:
1470 // At first set to blank as default.
1471 rWrtSh.AutoCorrect( *SvxAutoCorrCfg::Get().GetAutoCorrect(), ' ' );
1472 rReq.Done();
1474 break;
1475 case FN_TABLE_SORT_DIALOG:
1476 case FN_SORTING_DLG:
1478 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1479 VclPtr<AbstractSwSortDlg> pDlg(pFact->CreateSwSortingDialog(GetView().GetFrameWeld(), rWrtSh));
1480 auto xRequest = std::make_shared<SfxRequest>(rReq);
1481 rReq.Ignore(); // the 'old' request is not relevant any more
1482 pDlg->StartExecuteAsync(
1483 [pDlg, xRequest=std::move(xRequest)] (sal_Int32 nResult)->void
1485 if (nResult == RET_OK)
1486 pDlg->Apply();
1487 pDlg->disposeOnce();
1488 xRequest->Done();
1492 break;
1493 case FN_NUMBERING_OUTLINE_DLG:
1495 GetView().ExecNumberingOutline(GetPool());
1496 rReq.Done();
1498 break;
1499 case FN_CALCULATE:
1501 rtl::Reference<SwTransferable> pTransfer = new SwTransferable( rWrtSh );
1502 pTransfer->CalculateAndCopy();
1503 rReq.Done();
1505 break;
1506 case FN_GOTO_REFERENCE:
1508 SwField *pField = rWrtSh.GetCurField();
1509 if(pField && pField->GetTypeId() == SwFieldTypesEnum::GetRef)
1511 rWrtSh.StartAllAction();
1512 rWrtSh.SwCursorShell::GotoRefMark( static_cast<SwGetRefField*>(pField)->GetSetRefName(),
1513 static_cast<SwGetRefField*>(pField)->GetSubType(),
1514 static_cast<SwGetRefField*>(pField)->GetSeqNo(),
1515 static_cast<SwGetRefField*>(pField)->GetFlags() );
1516 rWrtSh.EndAllAction();
1517 rReq.Done();
1520 break;
1521 case FN_EDIT_FORMULA:
1523 const sal_uInt16 nId = SwInputChild::GetChildWindowId();
1524 SfxViewFrame& rVFrame = GetView().GetViewFrame();
1525 if(pItem)
1527 //if the ChildWindow is active it has to be removed
1528 if( rVFrame.HasChildWindow( nId ) )
1530 rVFrame.ToggleChildWindow( nId );
1531 rVFrame.GetBindings().InvalidateAll( true );
1534 OUString sFormula(static_cast<const SfxStringItem*>(pItem)->GetValue());
1535 SwFieldMgr aFieldMgr;
1536 rWrtSh.StartAllAction();
1537 bool bDelSel = rWrtSh.HasSelection();
1538 if( bDelSel )
1540 rWrtSh.StartUndo( SwUndoId::START );
1541 rWrtSh.DelRight();
1543 else
1545 rWrtSh.EnterStdMode();
1548 if( !bDelSel && aFieldMgr.GetCurField() && SwFieldTypesEnum::Formel == aFieldMgr.GetCurTypeId() )
1549 aFieldMgr.UpdateCurField( aFieldMgr.GetCurField()->GetFormat(), OUString(), sFormula );
1550 else if( !sFormula.isEmpty() )
1552 if( rWrtSh.IsCursorInTable() )
1554 SfxItemSetFixed<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA> aSet( rWrtSh.GetAttrPool() );
1555 aSet.Put( SwTableBoxFormula( sFormula ));
1556 rWrtSh.SetTableBoxFormulaAttrs( aSet );
1557 rWrtSh.UpdateTable();
1559 else
1561 SvNumberFormatter* pFormatter = rWrtSh.GetNumberFormatter();
1562 const sal_uInt32 nSysNumFormat = pFormatter->GetFormatIndex( NF_NUMBER_STANDARD, LANGUAGE_SYSTEM);
1563 SwInsertField_Data aData(SwFieldTypesEnum::Formel, nsSwGetSetExpType::GSE_FORMULA, OUString(), sFormula, nSysNumFormat);
1564 aFieldMgr.InsertField(aData);
1568 if( bDelSel )
1569 rWrtSh.EndUndo( SwUndoId::END );
1570 rWrtSh.EndAllAction();
1571 rReq.Done();
1573 else
1575 rWrtSh.EndAllTableBoxEdit();
1576 rVFrame.ToggleChildWindow( nId );
1577 if( !rVFrame.HasChildWindow( nId ) )
1578 rVFrame.GetBindings().InvalidateAll( true );
1579 rReq.Ignore();
1583 break;
1584 case FN_TABLE_UNSET_READ_ONLY:
1586 rWrtSh.UnProtectTables();
1588 break;
1589 case SID_EDIT_HYPERLINK:
1591 if (!rWrtSh.HasSelection())
1593 SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
1594 rWrtSh.GetCurAttr(aSet);
1595 if (SfxItemState::SET > aSet.GetItemState(RES_TXTATR_INETFMT))
1597 // Didn't find a hyperlink to edit yet.
1599 // If the cursor is just before an unselected hyperlink,
1600 // the dialog will not know that it should edit that hyperlink,
1601 // so in this case, first select it so the dialog will find the hyperlink.
1602 // The dialog would leave the hyperlink selected anyway after a successful edit
1603 // (although it isn't normally selected after a cancel, but oh well).
1604 if (!rWrtSh.SelectTextAttr(RES_TXTATR_INETFMT))
1605 break;
1609 GetView().GetViewFrame().SetChildWindow(SID_HYPERLINK_DIALOG, true);
1611 break;
1612 case SID_REMOVE_HYPERLINK:
1614 bool bSel = rWrtSh.HasSelection();
1615 if(!bSel)
1617 rWrtSh.StartAction();
1618 rWrtSh.Push();
1619 if(!rWrtSh.SelectTextAttr( RES_TXTATR_INETFMT ))
1620 rWrtSh.SelWrd();
1622 //now remove the attribute
1623 rWrtSh.ResetAttr({ RES_TXTATR_INETFMT });
1624 if(!bSel)
1626 rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
1627 rWrtSh.EndAction();
1630 break;
1631 case SID_ATTR_BRUSH_CHAR :
1632 case SID_ATTR_CHAR_SCALEWIDTH :
1633 case SID_ATTR_CHAR_ROTATED :
1634 case FN_TXTATR_INET :
1636 const sal_uInt16 nWhich = GetPool().GetWhichIDFromSlotID( nSlot );
1637 if ( pArgs && pArgs->GetItemState( nWhich ) == SfxItemState::SET )
1638 bUseDialog = false;
1639 [[fallthrough]];
1641 case SID_CHAR_DLG:
1642 case SID_CHAR_DLG_EFFECT:
1643 case SID_CHAR_DLG_POSITION:
1645 sw_CharDialog(rWrtSh, bUseDialog, /*ApplyToParagraph*/false, nSlot, pArgs, &rReq);
1647 break;
1648 case SID_CHAR_DLG_FOR_PARAGRAPH:
1650 sw_CharDialog(rWrtSh, /*UseDialog*/true, /*ApplyToParagraph*/true, nSlot, pArgs, &rReq);
1652 break;
1653 case SID_ATTR_LRSPACE :
1654 case SID_ATTR_ULSPACE :
1655 case SID_ATTR_BRUSH :
1656 case SID_PARA_VERTALIGN :
1657 case SID_ATTR_PARA_NUMRULE :
1658 case SID_ATTR_PARA_REGISTER :
1659 case SID_ATTR_PARA_PAGENUM :
1660 case FN_FORMAT_LINENUMBER :
1661 case FN_NUMBER_NEWSTART :
1662 case FN_NUMBER_NEWSTART_AT :
1663 case FN_FORMAT_DROPCAPS :
1664 case FN_DROP_TEXT:
1665 case SID_ATTR_PARA_LRSPACE:
1667 const sal_uInt16 nWhich = GetPool().GetWhichIDFromSlotID( nSlot );
1668 if ( pArgs && pArgs->GetItemState( nWhich ) == SfxItemState::SET )
1669 bUseDialog = false;
1670 [[fallthrough]];
1672 case SID_PARA_DLG:
1674 SwPaM* pPaM = nullptr;
1676 if ( pArgs )
1678 const SwPaMItem* pPaMItem = pArgs->GetItemIfSet( GetPool().GetWhichIDFromSlotID( FN_PARAM_PAM ), false );
1679 if ( pPaMItem )
1680 pPaM = pPaMItem->GetValue( );
1683 if ( !pPaM )
1684 pPaM = rWrtSh.GetCursor();
1686 FieldUnit eMetric = ::GetDfltMetric( dynamic_cast<SwWebView*>( &GetView()) != nullptr );
1687 SwModule* mod = SwModule::get();
1688 mod->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast<sal_uInt16>(eMetric)));
1690 bool bApplyCharUnit = ::HasCharUnit( dynamic_cast<SwWebView*>( &GetView()) != nullptr );
1691 mod->PutItem(SfxBoolItem(SID_ATTR_APPLYCHARUNIT, bApplyCharUnit));
1693 SfxItemSetFixed<
1694 RES_PARATR_BEGIN, RES_FRMATR_END - 1,
1695 // FillAttribute support:
1696 XATTR_FILL_FIRST, XATTR_FILL_LAST,
1697 // Includes SID_ATTR_TABSTOP_POS:
1698 SID_ATTR_TABSTOP_DEFAULTS, SID_ATTR_TABSTOP_OFFSET,
1699 SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
1700 SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP,
1701 // Items to hand over XPropertyList things like XColorList,
1702 // XHatchList, XGradientList, and XBitmapList to the Area
1703 // TabPage:
1704 SID_COLOR_TABLE, SID_PATTERN_LIST,
1705 SID_HTML_MODE, SID_HTML_MODE,
1706 SID_ATTR_PARA_PAGENUM, SID_ATTR_PARA_PAGENUM,
1707 FN_PARAM_1, FN_PARAM_1,
1708 FN_NUMBER_NEWSTART, FN_NUMBER_NEWSTART_AT,
1709 FN_DROP_TEXT, FN_DROP_CHAR_STYLE_NAME> aCoreSet( GetPool() );
1711 // get also the list level indent values merged as LR-SPACE item, if needed.
1712 rWrtSh.GetPaMAttr( pPaM, aCoreSet, true );
1714 // create needed items for XPropertyList entries from the DrawModel so that
1715 // the Area TabPage can access them
1716 // Do this after GetCurAttr, this resets the ItemSet content again
1717 SwDrawModel* pDrawModel = GetView().GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
1719 aCoreSet.Put(SvxColorListItem(pDrawModel->GetColorList(), SID_COLOR_TABLE));
1720 aCoreSet.Put(SvxGradientListItem(pDrawModel->GetGradientList(), SID_GRADIENT_LIST));
1721 aCoreSet.Put(SvxHatchListItem(pDrawModel->GetHatchList(), SID_HATCH_LIST));
1722 aCoreSet.Put(SvxBitmapListItem(pDrawModel->GetBitmapList(), SID_BITMAP_LIST));
1723 aCoreSet.Put(SvxPatternListItem(pDrawModel->GetPatternList(), SID_PATTERN_LIST));
1724 aCoreSet.Put(SfxUInt16Item(SID_HTML_MODE,
1725 ::GetHtmlMode(GetView().GetDocShell())));
1727 // Tabulators: Put DefaultTabs into ItemSet
1728 const SvxTabStopItem& rDefTabs =
1729 GetPool().GetUserOrPoolDefaultItem(RES_PARATR_TABSTOP);
1731 const sal_uInt16 nDefDist = o3tl::narrowing<sal_uInt16>(::GetTabDist( rDefTabs ));
1732 SfxUInt16Item aDefDistItem( SID_ATTR_TABSTOP_DEFAULTS, nDefDist );
1733 aCoreSet.Put( aDefDistItem );
1735 // Current tabulator
1736 SfxUInt16Item aTabPos( SID_ATTR_TABSTOP_POS, 0 );
1737 aCoreSet.Put( aTabPos );
1739 // Left border as offset
1740 //#i24363# tab stops relative to indent
1741 const tools::Long nOff
1742 = rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT)
1743 ? aCoreSet.Get(RES_MARGIN_TEXTLEFT).ResolveTextLeft({})
1744 : 0;
1745 SfxInt32Item aOff( SID_ATTR_TABSTOP_OFFSET, nOff );
1746 aCoreSet.Put( aOff );
1748 // Setting the BoxInfo
1749 ::PrepareBoxInfo( aCoreSet, rWrtSh );
1751 // Current page format
1752 ::SwToSfxPageDescAttr( aCoreSet );
1754 // Properties of numbering
1755 if (rWrtSh.GetNumRuleAtCurrCursorPos())
1757 SfxBoolItem aStart( FN_NUMBER_NEWSTART, rWrtSh.IsNumRuleStart( pPaM ) );
1758 aCoreSet.Put(aStart);
1759 SfxUInt16Item aStartAt( FN_NUMBER_NEWSTART_AT,
1760 rWrtSh.GetNodeNumStart( pPaM ) );
1761 aCoreSet.Put(aStartAt);
1763 VclPtr<SfxAbstractTabDialog> pDlg;
1765 if ( bUseDialog && GetActiveView() )
1767 OUString sDefPage;
1768 if (pItem)
1769 sDefPage = static_cast<const SfxStringItem*>(pItem)->GetValue();
1771 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1772 pDlg.reset(pFact->CreateSwParaDlg(GetView().GetFrameWeld(), GetView(), aCoreSet, false, sDefPage));
1775 if ( !bUseDialog )
1777 if ( nSlot == SID_ATTR_PARA_LRSPACE)
1779 SvxLRSpaceItem aParaMargin(static_cast<const SvxLRSpaceItem&>(pArgs->Get(nSlot)));
1780 SvxFirstLineIndentItem firstLine(RES_MARGIN_FIRSTLINE);
1781 SvxTextLeftMarginItem leftMargin(RES_MARGIN_TEXTLEFT);
1782 SvxRightMarginItem rightMargin(RES_MARGIN_RIGHT);
1783 firstLine.SetTextFirstLineOffset(aParaMargin.GetTextFirstLineOffset(),
1784 aParaMargin.GetPropTextFirstLineOffset());
1785 firstLine.SetAutoFirst(aParaMargin.IsAutoFirst());
1786 leftMargin.SetTextLeft(aParaMargin.GetTextLeft(), aParaMargin.GetPropLeft());
1787 rightMargin.SetRight(aParaMargin.GetRight(), aParaMargin.GetPropRight());
1788 aCoreSet.Put(firstLine);
1789 aCoreSet.Put(leftMargin);
1790 aCoreSet.Put(rightMargin);
1792 sw_ParagraphDialogResult(&aCoreSet, rWrtSh, rReq, pPaM);
1794 else
1795 sw_ParagraphDialogResult(const_cast<SfxItemSet*>(pArgs), rWrtSh, rReq, pPaM);
1797 else if (pDlg)
1799 auto pRequest = std::make_shared<SfxRequest>(rReq);
1800 rReq.Ignore(); // the 'old' request is not relevant any more
1802 auto vCursors = CopyPaMRing(*pPaM); // tdf#134439 make a copy to use at later apply
1803 pDlg->StartExecuteAsync([pDlg, &rWrtSh, pDrawModel, pRequest=std::move(pRequest), nDefDist, vCursors=std::move(vCursors)](sal_Int32 nResult){
1804 if (nResult == RET_OK)
1806 // Apply defaults if necessary.
1807 SfxItemSet* pSet = const_cast<SfxItemSet*>(pDlg->GetOutputItemSet());
1808 sal_uInt16 nNewDist;
1809 const SfxUInt16Item* pDefaultsItem = pSet->GetItemIfSet(SID_ATTR_TABSTOP_DEFAULTS, false);
1810 if (pDefaultsItem && nDefDist != (nNewDist = pDefaultsItem->GetValue()) )
1812 SvxTabStopItem aDefTabs( 0, 0, SvxTabAdjust::Default, RES_PARATR_TABSTOP );
1813 MakeDefTabs( nNewDist, aDefTabs );
1814 rWrtSh.SetDefault( aDefTabs );
1815 pSet->ClearItem( SID_ATTR_TABSTOP_DEFAULTS );
1818 const SfxPoolItem* pItem2 = nullptr;
1819 if (SfxItemState::SET == pSet->GetItemState(FN_PARAM_1, false, &pItem2))
1821 pSet->Put(SfxStringItem(FN_DROP_TEXT, static_cast<const SfxStringItem*>(pItem2)->GetValue()));
1822 pSet->ClearItem(FN_PARAM_1);
1825 if (const SwFormatDrop* pDropItem = pSet->GetItemIfSet(RES_PARATR_DROP, false))
1827 OUString sCharStyleName;
1828 if (pDropItem->GetCharFormat())
1829 sCharStyleName = pDropItem->GetCharFormat()->GetName();
1830 pSet->Put(SfxStringItem(FN_DROP_CHAR_STYLE_NAME, sCharStyleName));
1833 const XFillStyleItem* pFS = pSet->GetItem<XFillStyleItem>(XATTR_FILLSTYLE);
1834 bool bSet = pFS && pFS->GetValue() == drawing::FillStyle_GRADIENT;
1835 const XFillGradientItem* pTempGradItem
1836 = bSet ? pSet->GetItem<XFillGradientItem>(XATTR_FILLGRADIENT) : nullptr;
1837 if (pTempGradItem && pTempGradItem->GetName().isEmpty())
1839 // MigrateItemSet guarantees unique gradient names
1840 SfxItemSetFixed<XATTR_FILLGRADIENT, XATTR_FILLGRADIENT> aMigrateSet(rWrtSh.GetView().GetPool());
1841 aMigrateSet.Put(XFillGradientItem(u"gradient"_ustr, pTempGradItem->GetGradientValue()));
1842 SdrModel::MigrateItemSet(&aMigrateSet, pSet, *pDrawModel);
1845 bSet = pFS && pFS->GetValue() == drawing::FillStyle_HATCH;
1846 const XFillHatchItem* pTempHatchItem
1847 = bSet ? pSet->GetItem<XFillHatchItem>(XATTR_FILLHATCH) : nullptr;
1848 if (pTempHatchItem && pTempHatchItem->GetName().isEmpty())
1850 SfxItemSetFixed<XATTR_FILLHATCH, XATTR_FILLHATCH> aMigrateSet(rWrtSh.GetView().GetPool());
1851 aMigrateSet.Put(XFillHatchItem(u"hatch"_ustr, pTempHatchItem->GetHatchValue()));
1852 SdrModel::MigrateItemSet(&aMigrateSet, pSet, *pDrawModel);
1855 sw_ParagraphDialogResult(pSet, rWrtSh, *pRequest, vCursors->front().get());
1857 pDlg->disposeOnce();
1861 break;
1862 case FN_NUM_CONTINUE:
1864 OUString sContinuedListId;
1865 const SwNumRule* pRule =
1866 rWrtSh.SearchNumRule( true, sContinuedListId );
1867 // #i86492#
1868 // Search also for bullet list
1869 if ( !pRule )
1871 pRule = rWrtSh.SearchNumRule( false, sContinuedListId );
1873 if ( pRule )
1875 rWrtSh.SetCurNumRule( *pRule, false, sContinuedListId );
1878 break;
1880 case FN_SELECT_PARA:
1882 if ( !rWrtSh.IsSttOfPara() )
1883 rWrtSh.SttPara();
1884 else
1885 rWrtSh.EnterStdMode();
1886 rWrtSh.EndPara( true );
1888 break;
1890 case SID_DEC_INDENT:
1891 case SID_INC_INDENT:
1892 //According to the requirement, modified the behavior when user
1893 //using the indent button on the toolbar. Now if we increase/decrease indent for a
1894 //paragraph which has bullet style it will increase/decrease the bullet level.
1896 //If the current paragraph has bullet call the function to
1897 //increase or decrease the bullet level.
1898 //Why could I know whether a paragraph has bullet or not by checking the below conditions?
1899 //Please refer to the "case KEY_TAB:" section in SwEditWin::KeyInput(..) :
1900 // if( rSh.GetCurNumRule() && rSh.IsSttOfPara() &&
1901 // !rSh.HasReadonlySel() )
1902 // eKeyState = KS_NumDown;
1903 //Above code demonstrates that when the cursor is at the start of a paragraph which has bullet,
1904 //press TAB will increase the bullet level.
1905 //So I copied from that ^^
1906 if ( rWrtSh.GetNumRuleAtCurrCursorPos() && !rWrtSh.HasReadonlySel() )
1908 rWrtSh.NumUpDown( SID_INC_INDENT == nSlot );
1910 else //execute the original processing functions
1912 //below is copied of the old codes
1913 rWrtSh.MoveLeftMargin( SID_INC_INDENT == nSlot, rReq.GetModifier() != KEY_MOD1 );
1916 rReq.Done();
1917 break;
1919 case FN_DEC_INDENT_OFFSET:
1920 case FN_INC_INDENT_OFFSET:
1921 rWrtSh.MoveLeftMargin( FN_INC_INDENT_OFFSET == nSlot, rReq.GetModifier() == KEY_MOD1 );
1922 rReq.Done();
1923 break;
1925 case SID_ATTR_CHAR_COLOR2:
1927 std::unique_ptr<const SvxColorItem> pRecentColor; // manage lifecycle scope
1928 if (!pItem)
1930 // no color provided: use the pre-selected color shown in the toolbar/sidebar
1931 const std::optional<NamedColor> oColor
1932 = GetView().GetDocShell()->GetRecentColor(SID_ATTR_CHAR_COLOR);
1933 if (oColor.has_value())
1935 const model::ComplexColor aCol = (*oColor).getComplexColor();
1936 pRecentColor = std::make_unique<const SvxColorItem>(
1937 aCol.getFinalColor(), aCol, RES_CHRATR_COLOR);
1938 pItem = pRecentColor.get();
1942 if (pItem)
1944 auto* pColorItem = static_cast<const SvxColorItem*>(pItem);
1945 SwEditWin& rEditWin = GetView().GetEditWin();
1946 rEditWin.SetWaterCanTextColor(pColorItem->GetValue());
1947 SwApplyTemplate* pApply = rEditWin.GetApplyTemplate();
1949 // If there is a selection, then set the color on it
1950 // otherwise, it'll be the color for the next text to be typed
1951 if (!pApply || pApply->nColor != SID_ATTR_CHAR_COLOR_EXT)
1953 rWrtSh.SetAttrItem(SvxColorItem(pColorItem->GetValue(), pColorItem->getComplexColor(), RES_CHRATR_COLOR));
1956 rReq.Done();
1959 break;
1960 case SID_ATTR_CHAR_BACK_COLOR:
1961 case SID_ATTR_CHAR_COLOR_BACKGROUND: // deprecated
1962 case SID_ATTR_CHAR_COLOR_EXT:
1964 Color aColor = COL_TRANSPARENT;
1965 model::ComplexColor aComplexColor;
1967 if (pItem)
1969 auto* pColorItem = static_cast<const SvxColorItem*>(pItem);
1970 aColor = pColorItem->GetValue();
1971 aComplexColor = pColorItem->getComplexColor();
1973 else if (nSlot == SID_ATTR_CHAR_BACK_COLOR)
1975 // no color provided: use the pre-selected color shown in the toolbar/sidebar
1976 const std::optional<NamedColor> oColor
1977 = GetView().GetDocShell()->GetRecentColor(nSlot);
1978 if (oColor.has_value())
1980 aComplexColor = (*oColor).getComplexColor();
1981 aColor = aComplexColor.getFinalColor();
1985 SwEditWin& rEdtWin = GetView().GetEditWin();
1986 if (nSlot != SID_ATTR_CHAR_COLOR_EXT)
1987 rEdtWin.SetWaterCanTextBackColor(aColor);
1988 else if (pItem)
1989 rEdtWin.SetWaterCanTextColor(aColor);
1991 SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
1992 SwApplyTemplate aTempl;
1993 if (!pApply && (rWrtSh.HasSelection() || rReq.IsAPI()))
1995 if (nSlot != SID_ATTR_CHAR_COLOR_EXT)
1997 SfxItemSetFixed<RES_CHRATR_BACKGROUND, RES_CHRATR_BACKGROUND> aCoreSet( rWrtSh.GetView().GetPool() );
1999 rWrtSh.GetCurAttr(aCoreSet);
2001 // Remove highlight if already set of the same color
2002 const SvxBrushItem& rBrushItem = aCoreSet.Get(RES_CHRATR_BACKGROUND);
2003 if (aColor == rBrushItem.GetColor())
2005 aComplexColor = model::ComplexColor();
2006 aColor = COL_TRANSPARENT;
2008 ApplyCharBackground(aColor, aComplexColor, rWrtSh);
2010 else
2011 rWrtSh.SetAttrItem(SvxColorItem(aColor, aComplexColor, RES_CHRATR_COLOR));
2013 else
2015 if(!pApply || pApply->nColor != nSlot)
2016 aTempl.nColor = nSlot;
2017 rEdtWin.SetApplyTemplate(aTempl);
2020 rReq.Done();
2022 break;
2024 case FN_NUM_BULLET_MOVEDOWN:
2025 if (!rWrtSh.IsAddMode())
2026 rWrtSh.MoveParagraph();
2027 rReq.Done();
2028 break;
2030 case FN_NUM_BULLET_MOVEUP:
2031 if (!rWrtSh.IsAddMode())
2032 rWrtSh.MoveParagraph(SwNodeOffset(-1));
2033 rReq.Done();
2034 break;
2035 case SID_RUBY_DIALOG:
2036 case SID_HYPERLINK_DIALOG:
2038 SfxRequest aReq(nSlot, SfxCallMode::SLOT, SfxGetpApp()->GetPool());
2039 GetView().GetViewFrame().ExecuteSlot( aReq);
2040 rReq.Ignore();
2042 break;
2043 case FN_INSERT_PAGEHEADER:
2044 case FN_INSERT_PAGEFOOTER:
2045 if(pArgs && pArgs->Count())
2047 OUString sStyleName;
2048 if(pItem)
2049 sStyleName = static_cast<const SfxStringItem*>(pItem)->GetValue();
2050 bool bOn = true;
2051 if( SfxItemState::SET == pArgs->GetItemState(FN_PARAM_1, false, &pItem))
2052 bOn = static_cast<const SfxBoolItem*>(pItem)->GetValue();
2053 rWrtSh.ChangeHeaderOrFooter(sStyleName, FN_INSERT_PAGEHEADER == nSlot, bOn, !rReq.IsAPI());
2054 rReq.Done();
2056 break;
2057 case FN_READONLY_SELECTION_MODE :
2058 if(GetView().GetDocShell()->IsReadOnly())
2060 rWrtSh.SetReadonlySelectionOption(
2061 !rWrtSh.GetViewOptions()->IsSelectionInReadonly());
2062 rWrtSh.ShowCursor();
2064 break;
2065 case FN_SELECTION_MODE_DEFAULT:
2066 case FN_SELECTION_MODE_BLOCK :
2068 bool bSetBlockMode = !rWrtSh.IsBlockMode();
2069 if( pArgs && SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem))
2070 bSetBlockMode = static_cast<const SfxBoolItem*>(pItem)->GetValue();
2071 if( ( nSlot == FN_SELECTION_MODE_DEFAULT ) != bSetBlockMode )
2072 rWrtSh.EnterBlockMode();
2073 else
2074 rWrtSh.EnterStdMode();
2075 SfxBindings &rBnd = GetView().GetViewFrame().GetBindings();
2076 rBnd.Invalidate(FN_STAT_SELMODE);
2077 rBnd.Update(FN_STAT_SELMODE);
2079 break;
2080 case SID_OPEN_HYPERLINK:
2081 case SID_COPY_HYPERLINK_LOCATION:
2083 SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
2084 rWrtSh.GetCurAttr(aSet);
2086 const SwFormatINetFormat* pINetFormat = nullptr;
2087 if(SfxItemState::SET <= aSet.GetItemState( RES_TXTATR_INETFMT ))
2088 pINetFormat = &aSet.Get(RES_TXTATR_INETFMT);
2089 else if (!rWrtSh.HasSelection())
2091 // is the cursor at the beginning of a hyperlink?
2092 const SwTextNode* pTextNd = rWrtSh.GetCursor()->GetPointNode().GetTextNode();
2093 if (pTextNd)
2095 const sal_Int32 nIndex = rWrtSh.GetCursor()->Start()->GetContentIndex();
2096 const SwTextAttr* pINetFmt = pTextNd->GetTextAttrAt(nIndex, RES_TXTATR_INETFMT);
2097 if (pINetFmt && !pINetFmt->GetINetFormat().GetValue().isEmpty())
2098 pINetFormat = &pINetFmt->GetINetFormat();
2102 if (pINetFormat)
2104 if (nSlot == SID_OPEN_HYPERLINK)
2106 rWrtSh.ClickToINetAttr(*pINetFormat);
2108 else if (nSlot == SID_COPY_HYPERLINK_LOCATION)
2110 OUString hyperlinkLocation = pINetFormat->GetValue();
2111 ::uno::Reference< datatransfer::clipboard::XClipboard > xClipboard = GetView().GetEditWin().GetClipboard();
2112 vcl::unohelper::TextDataObject::CopyStringTo(hyperlinkLocation, xClipboard, SfxViewShell::Current());
2115 else
2117 SwField* pField = rWrtSh.GetCurField();
2118 if (pField && pField->GetTyp()->Which() == SwFieldIds::TableOfAuthorities)
2120 const auto& rAuthorityField = *static_cast<const SwAuthorityField*>(pField);
2121 OUString targetURL = u""_ustr;
2123 if (auto targetType = rAuthorityField.GetTargetType();
2124 targetType == SwAuthorityField::TargetType::UseDisplayURL
2125 || targetType == SwAuthorityField::TargetType::UseTargetURL)
2127 // Bibliography entry with URL also provides a hyperlink.
2128 targetURL = rAuthorityField.GetAbsoluteURL();
2131 if (targetURL.getLength() > 0)
2133 if (nSlot == SID_OPEN_HYPERLINK)
2135 ::LoadURL(rWrtSh, targetURL, LoadUrlFlags::NewView, /*rTargetFrameName=*/OUString());
2137 else if (nSlot == SID_COPY_HYPERLINK_LOCATION)
2139 ::uno::Reference< datatransfer::clipboard::XClipboard > xClipboard = GetView().GetEditWin().GetClipboard();
2140 vcl::unohelper::TextDataObject::CopyStringTo(targetURL, xClipboard, SfxViewShell::Current());
2146 break;
2147 case FN_OPEN_LOCAL_URL:
2149 OUString aLocalURL = GetLocalURL(rWrtSh);
2150 if (!aLocalURL.isEmpty())
2152 ::LoadURL(rWrtSh, aLocalURL, LoadUrlFlags::NewView, /*rTargetFrameName=*/OUString());
2155 break;
2156 case SID_OPEN_XML_FILTERSETTINGS:
2158 HandleOpenXmlFilterSettings(rReq);
2160 break;
2161 case FN_FORMAT_APPLY_HEAD1:
2164 break;
2165 case FN_FORMAT_APPLY_HEAD2:
2168 break;
2169 case FN_FORMAT_APPLY_HEAD3:
2172 break;
2173 case FN_FORMAT_APPLY_DEFAULT:
2176 break;
2177 case FN_FORMAT_APPLY_TEXTBODY:
2180 break;
2181 case FN_WORDCOUNT_DIALOG:
2183 GetView().UpdateWordCount(this, nSlot);
2185 break;
2186 case FN_PROTECT_FIELDS:
2187 case FN_PROTECT_BOOKMARKS:
2189 IDocumentSettingAccess& rIDSA = rWrtSh.getIDocumentSettingAccess();
2190 DocumentSettingId aSettingId = nSlot == FN_PROTECT_FIELDS
2191 ? DocumentSettingId::PROTECT_FIELDS
2192 : DocumentSettingId::PROTECT_BOOKMARKS;
2193 rIDSA.set(aSettingId, !rIDSA.get(aSettingId));
2194 // Invalidate so that toggle state gets updated
2195 SfxViewFrame& rViewFrame = GetView().GetViewFrame();
2196 rViewFrame.GetBindings().Invalidate(nSlot);
2197 rViewFrame.GetBindings().Update(nSlot);
2199 break;
2200 case SID_FM_CTL_PROPERTIES:
2202 SwPosition aPos(*GetShell().GetCursor()->GetPoint());
2203 sw::mark::Fieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
2204 if ( !pFieldBM )
2206 aPos.AdjustContent(-1);
2207 pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
2210 if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN
2211 && !(rWrtSh.GetCurrSection() && rWrtSh.GetCurrSection()->IsProtect()) )
2213 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2214 VclPtr<AbstractDropDownFormFieldDialog> pDlg(pFact->CreateDropDownFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pFieldBM));
2215 auto xRequest = std::make_shared<SfxRequest>(rReq);
2216 rReq.Ignore(); // the 'old' request is not relevant any more
2217 auto pWrtSh = &rWrtSh;
2218 pDlg->StartExecuteAsync(
2219 [pDlg, pFieldBM, pWrtSh, xRequest=std::move(xRequest)] (sal_Int32 nResult)->void
2221 if (nResult == RET_OK)
2223 pDlg->Apply();
2224 pFieldBM->Invalidate();
2225 pWrtSh->InvalidateWindows( SwRect(pWrtSh->GetView().GetVisArea()) );
2226 pWrtSh->UpdateCursor(); // cursor position might be invalid
2228 pDlg->disposeOnce();
2229 xRequest->Done();
2233 else if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDATE )
2235 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2236 sw::mark::DateFieldmark* pDateField = &dynamic_cast<sw::mark::DateFieldmark&>(*pFieldBM);
2237 VclPtr<AbstractDateFormFieldDialog> pDlg(pFact->CreateDateFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pDateField, *GetView().GetDocShell()->GetDoc()));
2238 auto pWrtSh = &rWrtSh;
2239 auto xRequest = std::make_shared<SfxRequest>(rReq);
2240 rReq.Ignore(); // the 'old' request is not relevant any more
2241 pDlg->StartExecuteAsync(
2242 [pDlg, pWrtSh, pDateField, xRequest=std::move(xRequest)] (sal_Int32 nResult)->void
2244 if (nResult == RET_OK)
2246 pDlg->Apply();
2247 pDateField->Invalidate();
2248 pWrtSh->InvalidateWindows( SwRect(pWrtSh->GetView().GetVisArea()) );
2249 pWrtSh->UpdateCursor(); // cursor position might be invalid
2251 pDlg->disposeOnce();
2252 xRequest->Done();
2256 else
2258 SfxRequest aReq(GetView().GetViewFrame(), SID_FM_CTL_PROPERTIES);
2259 aReq.AppendItem( SfxBoolItem( SID_FM_CTL_PROPERTIES, true ) );
2260 rWrtSh.GetView().GetFormShell()->Execute( aReq );
2263 break;
2264 case SID_FM_TRANSLATE:
2266 #if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
2267 const SfxPoolItem* pTargetLangStringItem = nullptr;
2268 if (pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_TARGETLANG_STR, false, &pTargetLangStringItem))
2270 std::optional<OUString> oDeeplAPIUrl = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get();
2271 std::optional<OUString> oDeeplKey = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get();
2272 if (!oDeeplAPIUrl || oDeeplAPIUrl->isEmpty() || !oDeeplKey || oDeeplKey->isEmpty())
2274 SAL_WARN("sw.ui", "SID_FM_TRANSLATE: API options are not set");
2275 break;
2277 const OString aAPIUrl = OUStringToOString(rtl::Concat2View(*oDeeplAPIUrl + "?tag_handling=html"), RTL_TEXTENCODING_UTF8).trim();
2278 const OString aAuthKey = OUStringToOString(*oDeeplKey, RTL_TEXTENCODING_UTF8).trim();
2279 OString aTargetLang = OUStringToOString(static_cast<const SfxStringItem*>(pTargetLangStringItem)->GetValue(), RTL_TEXTENCODING_UTF8);
2280 SwTranslateHelper::TranslateAPIConfig aConfig({aAPIUrl, aAuthKey, aTargetLang});
2281 SwTranslateHelper::TranslateDocument(rWrtSh, aConfig);
2283 else
2285 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2286 std::shared_ptr<AbstractSwTranslateLangSelectDlg> pAbstractDialog(pFact->CreateSwTranslateLangSelectDlg(GetView().GetFrameWeld(), rWrtSh));
2287 std::shared_ptr<weld::DialogController> pDialogController(pAbstractDialog->getDialogController());
2288 weld::DialogController::runAsync(pDialogController, [] (sal_Int32 /*nResult*/) { });
2290 #endif // HAVE_FEATURE_CURL && ENABLE_WASM_STRIP_EXTRA
2292 break;
2293 case SID_SPELLCHECK_IGNORE:
2295 SwPaM *pPaM = rWrtSh.GetCursor();
2296 if (pPaM)
2297 SwEditShell::IgnoreGrammarErrorAt( *pPaM );
2299 break;
2300 case SID_SPELLCHECK_IGNORE_ALL:
2302 OUString sApplyText;
2303 const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
2304 if (pItem2)
2305 sApplyText = pItem2->GetValue();
2307 if(sApplyText == "Grammar")
2309 linguistic2::ProofreadingResult aGrammarCheckRes;
2310 sal_Int32 nErrorInResult = -1;
2311 uno::Sequence< OUString > aSuggestions;
2312 sal_Int32 nErrorPosInText = -1;
2313 SwRect aToFill;
2314 bool bCorrectionRes = rWrtSh.GetGrammarCorrection( aGrammarCheckRes, nErrorPosInText, nErrorInResult, aSuggestions, nullptr, aToFill );
2315 if(bCorrectionRes)
2317 try {
2318 uno::Reference< linguistic2::XDictionary > xDictionary = LinguMgr::GetIgnoreAllList();
2319 aGrammarCheckRes.xProofreader->ignoreRule(
2320 aGrammarCheckRes.aErrors[ nErrorInResult ].aRuleIdentifier,
2321 aGrammarCheckRes.aLocale );
2322 // refresh the layout of the actual paragraph (faster)
2323 SwPaM *pPaM = rWrtSh.GetCursor();
2324 if (pPaM)
2325 SwEditShell::IgnoreGrammarErrorAt( *pPaM );
2326 if (xDictionary.is() && pPaM)
2328 linguistic::AddEntryToDic( xDictionary, pPaM->GetText(), false, OUString() );
2329 // refresh the layout of all paragraphs (workaround to launch a dictionary event)
2330 xDictionary->setActive(false);
2331 xDictionary->setActive(true);
2334 catch( const uno::Exception& )
2339 else if (sApplyText == "Spelling")
2341 AddWordToWordbook(LinguMgr::GetIgnoreAllList(), rWrtSh);
2344 break;
2345 case SID_ADD_TO_WORDBOOK:
2347 OUString aDicName;
2348 if (const SfxStringItem* pItem1 = rReq.GetArg<SfxStringItem>(FN_PARAM_1))
2349 aDicName = pItem1->GetValue();
2351 uno::Reference<linguistic2::XSearchableDictionaryList> xDicList(LinguMgr::GetDictionaryList());
2352 uno::Reference<linguistic2::XDictionary> xDic = xDicList.is() ? xDicList->getDictionaryByName(aDicName) : nullptr;
2353 if (AddWordToWordbook(xDic, rWrtSh))
2355 // save modified user-dictionary if it is persistent
2356 uno::Reference<frame::XStorable> xSavDic(xDic, uno::UNO_QUERY);
2357 if (xSavDic.is())
2358 xSavDic->store();
2360 break;
2362 break;
2363 case SID_SPELLCHECK_APPLY_SUGGESTION:
2365 OUString sApplyText;
2366 const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
2367 if (pItem2)
2368 sApplyText = pItem2->GetValue();
2370 static constexpr OUString sSpellingRule(u"Spelling_"_ustr);
2371 static constexpr OUString sGrammarRule(u"Grammar_"_ustr);
2373 bool bGrammar = false;
2374 sal_Int32 nPos = 0;
2375 uno::Reference< linguistic2::XSpellAlternatives > xSpellAlt;
2376 if(-1 != (nPos = sApplyText.indexOf( sGrammarRule )))
2378 sApplyText = sApplyText.replaceAt(nPos, sGrammarRule.getLength(), u"");
2379 bGrammar = true;
2381 else if (-1 != (nPos = sApplyText.indexOf( sSpellingRule )))
2383 sApplyText = sApplyText.replaceAt(nPos, sSpellingRule.getLength(), u"");
2384 SwRect aToFill;
2385 xSpellAlt.set(rWrtSh.GetCorrection(nullptr, aToFill));
2386 bGrammar = false;
2389 if (!bGrammar && !xSpellAlt.is())
2390 return;
2392 bool bOldIns = rWrtSh.IsInsMode();
2393 rWrtSh.SetInsMode();
2395 OUString aTmp( sApplyText );
2396 OUString aOrig( bGrammar ? OUString() : xSpellAlt->getWord() );
2398 // if original word has a trailing . (likely the end of a sentence)
2399 // and the replacement text hasn't, then add it to the replacement
2400 if (!aTmp.isEmpty() && !aOrig.isEmpty() &&
2401 aOrig.endsWith(".") && /* !IsAlphaNumeric ??*/
2402 !aTmp.endsWith("."))
2404 aTmp += ".";
2407 SwRewriter aRewriter;
2409 aRewriter.AddRule(UndoArg1, rWrtSh.GetCursorDescr()
2410 // don't show the hidden control character of the comment
2411 .replaceAll(OUStringChar(CH_TXTATR_INWORD), "") );
2412 aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
2414 OUString aTmpStr = SwResId(STR_START_QUOTE) +
2415 aTmp + SwResId(STR_END_QUOTE);
2416 aRewriter.AddRule(UndoArg3, aTmpStr);
2418 rWrtSh.StartUndo(SwUndoId::UI_REPLACE, &aRewriter);
2419 rWrtSh.StartAction();
2421 // keep comments at the end of the replacement in case spelling correction is
2422 // invoked via the context menu. The spell check dialog does the correction in edlingu.cxx.
2423 rWrtSh.ReplaceKeepComments(aTmp);
2425 rWrtSh.EndAction();
2426 rWrtSh.EndUndo();
2428 rWrtSh.SetInsMode( bOldIns );
2430 break;
2431 case FN_TRANSFORM_DOCUMENT_STRUCTURE:
2433 // get the parameter, what to transform
2434 OUString aDataJson;
2435 const SfxStringItem* pDataJson = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
2436 if (pDataJson)
2438 aDataJson = pDataJson->GetValue();
2439 aDataJson = rtl::Uri::decode(aDataJson, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
2442 // parse the JSON got prom parameter
2443 boost::property_tree::ptree aTree;
2444 std::stringstream aStream(
2445 (std::string(OUStringToOString(aDataJson, RTL_TEXTENCODING_UTF8))));
2448 boost::property_tree::read_json(aStream, aTree);
2450 catch (...)
2452 lcl_LogWarning("FillApi Transform parameter, Wrong JSON format. ");
2453 throw;
2456 // get the loaded content controls
2457 uno::Reference<text::XContentControlsSupplier> xCCSupplier(
2458 GetView().GetDocShell()->GetModel(), uno::UNO_QUERY);
2459 if (!xCCSupplier.is())
2460 break;
2462 uno::Reference<container::XIndexAccess> xContentControls
2463 = xCCSupplier->getContentControls();
2464 int iCCcount = xContentControls->getCount();
2466 enum class ContentFilterType
2468 ERROR = -1,
2469 INDEX,
2470 TAG,
2471 ALIAS,
2474 std::vector<std::string> aIdTexts = { ".ByIndex.", ".ByTag.", ".ByAlias.", ".ById." };
2476 // get charts
2477 uno::Reference<text::XTextEmbeddedObjectsSupplier> xEOS(
2478 GetView().GetDocShell()->GetModel(), uno::UNO_QUERY);
2479 if (!xEOS.is())
2480 break;
2481 uno::Reference<container::XIndexAccess> xEmbeddeds(xEOS->getEmbeddedObjects(),
2482 uno::UNO_QUERY);
2483 if (!xEmbeddeds.is())
2484 break;
2486 sal_Int32 nEOcount = xEmbeddeds->getCount();
2488 enum class ChartFilterType
2490 ERROR = -1,
2491 INDEX,
2492 NAME,
2493 TITLE,
2494 SUBTITLE
2496 std::vector<std::string> aIdChartTexts
2497 = { ".ByEmbedIndex.", ".ByEmbedName.", ".ByTitle.", ".BySubTitle." };
2499 // Iterate through the JSON data loaded into a tree structure
2500 for (const auto& aItem : aTree)
2502 if (aItem.first == "Transforms")
2504 // Handle all transformations
2505 for (const auto& aItem2 : aItem.second)
2507 if (aItem2.first == "DocumentProperties")
2509 uno::Reference<document::XDocumentPropertiesSupplier>
2510 xDocumentPropsSupplier(GetView().GetDocShell()->GetModel(),
2511 uno::UNO_QUERY);
2512 if (!xDocumentPropsSupplier.is())
2513 continue;
2514 uno::Reference<document::XDocumentProperties2> xDocProps(
2515 xDocumentPropsSupplier->getDocumentProperties(), uno::UNO_QUERY);
2516 if (!xDocProps.is())
2517 continue;
2519 for (const auto& aItem3 : aItem2.second)
2521 if (aItem3.first == "Author")
2523 xDocProps->setAuthor(
2524 OStringToOUString(aItem3.second.get_value<std::string>(),
2525 RTL_TEXTENCODING_UTF8));
2527 else if (aItem3.first == "Generator")
2529 xDocProps->setGenerator(
2530 OStringToOUString(aItem3.second.get_value<std::string>(),
2531 RTL_TEXTENCODING_UTF8));
2533 else if (aItem3.first == "CreationDate")
2535 util::DateTime aDateTime;
2536 sax::Converter::parseDateTime(
2537 aDateTime,
2538 OStringToOUString(aItem3.second.get_value<std::string>(),
2539 RTL_TEXTENCODING_UTF8));
2540 xDocProps->setCreationDate(aDateTime);
2542 else if (aItem3.first == "Title")
2544 xDocProps->setTitle(
2545 OStringToOUString(aItem3.second.get_value<std::string>(),
2546 RTL_TEXTENCODING_UTF8));
2548 else if (aItem3.first == "Subject")
2550 xDocProps->setSubject(
2551 OStringToOUString(aItem3.second.get_value<std::string>(),
2552 RTL_TEXTENCODING_UTF8));
2554 else if (aItem3.first == "Description")
2556 xDocProps->setDescription(
2557 OStringToOUString(aItem3.second.get_value<std::string>(),
2558 RTL_TEXTENCODING_UTF8));
2560 else if (aItem3.first == "Keywords")
2562 uno::Sequence<OUString> aStringSeq(aItem3.second.size());
2563 auto aStringArray = aStringSeq.getArray();
2564 int nId = 0;
2565 for (const auto& aItem4 : aItem3.second)
2567 aStringArray[nId++] = OStringToOUString(aItem4.second.get_value<std::string>(),
2568 RTL_TEXTENCODING_UTF8);
2570 xDocProps->setKeywords(aStringSeq);
2572 else if (aItem3.first == "Language")
2574 OUString aLanguageStr
2575 = OStringToOUString(aItem3.second.get_value<std::string>(),
2576 RTL_TEXTENCODING_UTF8);
2577 lang::Locale aLanguageLang
2578 = LanguageTag::convertToLocale(aLanguageStr);
2579 xDocProps->setLanguage(aLanguageLang);
2581 else if (aItem3.first == "ModifiedBy")
2583 xDocProps->setModifiedBy(
2584 OStringToOUString(aItem3.second.get_value<std::string>(),
2585 RTL_TEXTENCODING_UTF8));
2587 else if (aItem3.first == "ModificationDate")
2589 util::DateTime aDateTime;
2590 sax::Converter::parseDateTime(
2591 aDateTime,
2592 OStringToOUString(aItem3.second.get_value<std::string>(),
2593 RTL_TEXTENCODING_UTF8));
2594 xDocProps->setModificationDate(aDateTime);
2596 else if (aItem3.first == "PrintedBy")
2598 xDocProps->setPrintedBy(
2599 OStringToOUString(aItem3.second.get_value<std::string>(),
2600 RTL_TEXTENCODING_UTF8));
2602 else if (aItem3.first == "PrintDate")
2604 util::DateTime aDateTime;
2605 sax::Converter::parseDateTime(
2606 aDateTime,
2607 OStringToOUString(aItem3.second.get_value<std::string>(),
2608 RTL_TEXTENCODING_UTF8));
2609 xDocProps->setPrintDate(aDateTime);
2611 else if (aItem3.first == "TemplateName")
2613 xDocProps->setTemplateName(
2614 OStringToOUString(aItem3.second.get_value<std::string>(),
2615 RTL_TEXTENCODING_UTF8));
2617 else if (aItem3.first == "TemplateURL")
2619 xDocProps->setTemplateURL(
2620 OStringToOUString(aItem3.second.get_value<std::string>(),
2621 RTL_TEXTENCODING_UTF8));
2623 else if (aItem3.first == "TemplateDate")
2625 util::DateTime aDateTime;
2626 sax::Converter::parseDateTime(
2627 aDateTime,
2628 OStringToOUString(aItem3.second.get_value<std::string>(),
2629 RTL_TEXTENCODING_UTF8));
2630 xDocProps->setTemplateDate(aDateTime);
2632 else if (aItem3.first == "AutoloadURL")
2634 // Warning: wrong data here, can freeze LO.
2635 xDocProps->setAutoloadURL(
2636 OStringToOUString(aItem3.second.get_value<std::string>(),
2637 RTL_TEXTENCODING_UTF8));
2639 else if (aItem3.first == "AutoloadSecs")
2641 //sal_Int32
2642 xDocProps->setAutoloadSecs(aItem3.second.get_value<int>());
2644 else if (aItem3.first == "DefaultTarget")
2646 xDocProps->setDefaultTarget(
2647 OStringToOUString(aItem3.second.get_value<std::string>(),
2648 RTL_TEXTENCODING_UTF8));
2650 else if (aItem3.first == "DocumentStatistics")
2652 uno::Sequence<beans::NamedValue> aNamedValueSeq(
2653 aItem3.second.size());
2654 auto aNamedValueArray = aNamedValueSeq.getArray();
2655 int nId = 0;
2656 for (const auto& aItem4 : aItem3.second)
2658 OUString aName = OStringToOUString(aItem4.first,
2659 RTL_TEXTENCODING_UTF8);
2660 sal_Int32 nValue = aItem4.second.get_value<int>();
2661 aNamedValueArray[nId].Name = aName;
2662 aNamedValueArray[nId].Value <<= nValue;
2663 nId++;
2665 xDocProps->setDocumentStatistics(aNamedValueSeq);
2667 else if (aItem3.first == "EditingCycles")
2669 //sal_Int16
2670 xDocProps->setEditingCycles(aItem3.second.get_value<int>());
2672 else if (aItem3.first == "EditingDuration")
2674 //sal_Int32
2675 xDocProps->setEditingDuration(aItem3.second.get_value<int>());
2677 else if (aItem3.first == "Contributor")
2679 uno::Sequence<OUString> aStringSeq(aItem3.second.size());
2680 auto aStringArray = aStringSeq.getArray();
2681 int nId = 0;
2682 for (const auto& aItem4 : aItem3.second)
2684 aStringArray[nId++] = OStringToOUString(
2685 aItem4.second.get_value<std::string>(),
2686 RTL_TEXTENCODING_UTF8);
2688 xDocProps->setContributor(aStringSeq);
2690 else if (aItem3.first == "Coverage")
2692 xDocProps->setCoverage(
2693 OStringToOUString(aItem3.second.get_value<std::string>(),
2694 RTL_TEXTENCODING_UTF8));
2696 else if (aItem3.first == "Identifier")
2698 xDocProps->setIdentifier(
2699 OStringToOUString(aItem3.second.get_value<std::string>(),
2700 RTL_TEXTENCODING_UTF8));
2702 else if (aItem3.first == "Publisher")
2704 uno::Sequence<OUString> aStringSeq(aItem3.second.size());
2705 auto aStringArray = aStringSeq.getArray();
2706 int nId = 0;
2707 for (const auto& aItem4 : aItem3.second)
2709 aStringArray[nId++] = OStringToOUString(
2710 aItem4.second.get_value<std::string>(),
2711 RTL_TEXTENCODING_UTF8);
2713 xDocProps->setPublisher(aStringSeq);
2715 else if (aItem3.first == "Relation")
2717 uno::Sequence<OUString> aStringSeq(aItem3.second.size());
2718 auto aStringArray = aStringSeq.getArray();
2719 int nId = 0;
2720 for (const auto& aItem4 : aItem3.second)
2722 aStringArray[nId++] = OStringToOUString(
2723 aItem4.second.get_value<std::string>(),
2724 RTL_TEXTENCODING_UTF8);
2726 xDocProps->setRelation(aStringSeq);
2728 else if (aItem3.first == "Rights")
2730 xDocProps->setRights(
2731 OStringToOUString(aItem3.second.get_value<std::string>(),
2732 RTL_TEXTENCODING_UTF8));
2734 else if (aItem3.first == "Source")
2736 xDocProps->setSource(
2737 OStringToOUString(aItem3.second.get_value<std::string>(),
2738 RTL_TEXTENCODING_UTF8));
2740 else if (aItem3.first == "Type")
2742 xDocProps->setType(
2743 OStringToOUString(aItem3.second.get_value<std::string>(),
2744 RTL_TEXTENCODING_UTF8));
2746 else if (aItem3.first == "UserDefinedProperties")
2748 const uno::Reference<beans::XPropertyContainer> xUserProps
2749 = xDocProps->getUserDefinedProperties();
2750 if (!xUserProps.is())
2751 continue;
2752 uno::Reference<beans::XPropertyAccess> xUserPropsAccess(
2753 xDocProps->getUserDefinedProperties(), uno::UNO_QUERY);
2754 if (!xUserPropsAccess.is())
2755 continue;
2757 for (const auto& aItem4 : aItem3.second)
2759 if (aItem4.first == "Delete")
2761 std::string aPropName
2762 = aItem4.second.get_value<std::string>();
2765 xUserProps->removeProperty(OStringToOUString(
2766 aPropName, RTL_TEXTENCODING_UTF8));
2768 catch (...)
2770 lcl_LogWarning("FillApi DocumentProperties "
2771 "UserDefinedPropertieschart, failed "
2772 "to delete property: '"
2773 + aPropName + "'");
2776 else if (aItem4.first.starts_with("Add."))
2778 std::string aPropName = aItem4.first.substr(4);
2780 comphelper::SequenceAsHashMap aUserDefinedProperties(
2781 xUserPropsAccess->getPropertyValues());
2782 comphelper::SequenceAsHashMap::iterator it
2783 = aUserDefinedProperties.find(OStringToOUString(
2784 aPropName, RTL_TEXTENCODING_UTF8));
2785 bool bToDelete = (it != aUserDefinedProperties.end());
2789 std::stringstream aStreamPart;
2790 aStreamPart << "{\n\"" << aPropName << "\" : ";
2791 boost::property_tree::json_parser::write_json(
2792 aStreamPart, aItem4.second);
2793 aStreamPart << "}";
2795 OString aJSONPart(aStreamPart.str());
2796 std::vector<beans::PropertyValue> aPropVec
2797 = comphelper::JsonToPropertyValues(aJSONPart);
2799 if (bToDelete)
2800 xUserProps->removeProperty(aPropVec[0].Name);
2802 xUserProps->addProperty(
2803 aPropVec[0].Name,
2804 beans::PropertyAttribute::REMOVABLE,
2805 aPropVec[0].Value);
2807 catch(...)
2809 lcl_LogWarning("FillApi DocumentProperties "
2810 "UserDefinedPropertieschart, failed "
2811 "to add property: '"
2812 + aPropName + "'");
2819 if (aItem2.first.starts_with("Charts"))
2821 std::string aTextEnd = aItem2.first.substr(6);
2822 std::string aValue = "";
2823 ChartFilterType iKeyId = ChartFilterType::ERROR;
2824 // Find how the chart is identified: ByIndex, ByTitle...
2825 for (size_t i = 0; i < aIdChartTexts.size(); i++)
2827 if (aTextEnd.starts_with(aIdChartTexts[i]))
2829 iKeyId = static_cast<ChartFilterType>(i);
2830 aValue = aTextEnd.substr(aIdChartTexts[i].length());
2831 break;
2834 if (iKeyId != ChartFilterType::ERROR)
2836 // A chart transformation filter can match multiple charts
2837 // In that case every matching charts will be transformed
2838 // If no chart match to the filter, then we show warning
2839 bool bChartFound = false;
2840 for (int i = 0; i < nEOcount; ++i)
2842 uno::Reference<beans::XPropertySet> xShapeProps(
2843 xEmbeddeds->getByIndex(i), uno::UNO_QUERY);
2844 if (!xShapeProps.is())
2845 continue;
2847 uno::Reference<frame::XModel> xDocModel;
2848 xShapeProps->getPropertyValue(u"Model"_ustr) >>= xDocModel;
2849 if (!xDocModel.is())
2850 continue;
2852 uno::Reference<chart2::XChartDocument> xChartDoc(
2853 xDocModel, uno::UNO_QUERY);
2854 if (!xChartDoc.is())
2855 continue;
2857 uno::Reference<chart2::data::XDataProvider> xDataProvider(
2858 xChartDoc->getDataProvider());
2859 if (!xDataProvider.is())
2860 continue;
2862 uno::Reference<chart::XChartDataArray> xDataArray(
2863 xChartDoc->getDataProvider(), uno::UNO_QUERY);
2864 if (!xDataArray.is())
2865 continue;
2867 uno::Reference<chart2::XInternalDataProvider> xIDataProvider(
2868 xChartDoc->getDataProvider(), uno::UNO_QUERY);
2869 if (!xIDataProvider.is())
2870 continue;
2872 uno::Reference<util::XModifiable> xModi(xDocModel,
2873 uno::UNO_QUERY);
2874 if (!xModi.is())
2875 continue;
2877 switch (iKeyId)
2879 case ChartFilterType::INDEX:
2881 if (stoi(aValue) != i)
2882 continue;
2884 break;
2885 case ChartFilterType::NAME:
2887 uno::Reference<container::XNamed> xNamedShape(
2888 xEmbeddeds->getByIndex(i), uno::UNO_QUERY);
2889 if (xNamedShape.is())
2891 OUString aName;
2892 aName = xNamedShape->getName();
2893 if (OStringToOUString(aValue, RTL_TEXTENCODING_UTF8)
2894 != aName)
2895 continue;
2898 break;
2899 case ChartFilterType::TITLE:
2901 uno::Reference<chart2::XTitled> xTitled(
2902 xChartDoc, uno::UNO_QUERY_THROW);
2903 if (!xTitled.is())
2904 continue;
2905 uno::Reference<chart2::XTitle> xTitle
2906 = xTitled->getTitleObject();
2907 if (!xTitle.is())
2908 continue;
2910 OUString aTitle;
2911 const uno::Sequence<
2912 uno::Reference<chart2::XFormattedString>>
2913 aFSSeq = xTitle->getText();
2914 for (auto const& fs : aFSSeq)
2915 aTitle += fs->getString();
2916 if (OStringToOUString(aValue, RTL_TEXTENCODING_UTF8)
2917 != aTitle)
2918 continue;
2920 break;
2921 case ChartFilterType::SUBTITLE:
2923 uno::Reference<chart2::XDiagram> xDiagram
2924 = xChartDoc->getFirstDiagram();
2925 if (!xDiagram.is())
2926 continue;
2928 uno::Reference<chart2::XTitled> xTitled(
2929 xDiagram, uno::UNO_QUERY_THROW);
2930 if (!xTitled.is())
2931 continue;
2933 uno::Reference<chart2::XTitle> xSubTitle(
2934 xTitled->getTitleObject());
2935 if (!xSubTitle.is())
2936 continue;
2938 OUString aSubTitle;
2939 const uno::Sequence<
2940 uno::Reference<chart2::XFormattedString>>
2941 aFSSeq = xSubTitle->getText();
2942 for (auto const& fs : aFSSeq)
2943 aSubTitle += fs->getString();
2944 if (OStringToOUString(aValue, RTL_TEXTENCODING_UTF8)
2945 != aSubTitle)
2946 continue;
2948 break;
2949 default:
2950 continue;
2953 // We have a match, this chart need to be transformed
2954 // Set all the values (of the chart) what is needed
2955 bChartFound = true;
2957 // Check if the InternalDataProvider is row or column based.
2958 bool bChartUseColumns = false;
2959 uno::Sequence<beans::PropertyValue> aArguments(
2960 xDataProvider->detectArguments(nullptr));
2961 for (sal_Int32 j = 0; j < aArguments.getLength(); ++j)
2963 if (aArguments[j].Name == "DataRowSource")
2965 css::chart::ChartDataRowSource eRowSource;
2966 if (aArguments[j].Value >>= eRowSource)
2967 bChartUseColumns
2968 = (eRowSource
2969 == css::chart::ChartDataRowSource_COLUMNS);
2970 break;
2974 for (const auto& aItem3 : aItem2.second)
2976 if (aItem3.first.starts_with("deletecolumn.")
2977 || aItem3.first.starts_with("deleterow.")
2978 || aItem3.first.starts_with("insertcolumn.")
2979 || aItem3.first.starts_with("insertrow.")
2980 || aItem3.first.starts_with("modifycolumn.")
2981 || aItem3.first.starts_with("modifyrow."))
2983 // delete insert, or modify a row, or column
2984 // column, or row?
2985 bool bSetColumn = (aItem3.first[6] == 'c');
2986 int nId = stoi(aItem3.first.substr(bSetColumn ? 13 : 10));
2987 bool bDelete = aItem3.first.starts_with("delete");
2988 // delete/insert a row/column if needed
2989 if (!aItem3.first.starts_with("modify"))
2991 if (bChartUseColumns == bSetColumn)
2993 if (bDelete)
2995 if (!lcl_DeleteChartColumns(xChartDoc, nId))
2996 continue;
2997 xIDataProvider->deleteSequence(nId);
2999 else
3001 if (!lcl_InsertChartColumns(xChartDoc, nId))
3002 continue;
3005 else
3007 if (bDelete)
3009 xIDataProvider
3010 ->deleteDataPointForAllSequences(nId);
3012 else
3014 xIDataProvider
3015 ->insertDataPointForAllSequences(nId
3016 - 1);
3020 // set values also, if needed
3021 if (!bDelete && aItem3.second.size() > 0)
3023 uno::Sequence<uno::Sequence<double>> aData
3024 = xDataArray->getData();
3025 uno::Sequence<double>* pRows = aData.getArray();
3027 int nIndex = 0;
3028 int nX = nId;
3029 int nY = nId;
3030 bool bIndexWarning = false;
3031 for (const auto& aItem4 : aItem3.second)
3033 if (bSetColumn)
3035 nY = nIndex;
3037 else
3039 nX = nIndex;
3041 if (nY < aData.getLength() && nY >= 0
3042 && nX < pRows[nY].getLength() && nX >= 0)
3044 double* pCols = pRows[nY].getArray();
3045 pCols[nX]
3046 = aItem4.second.get_value<double>();
3048 else
3050 bIndexWarning = true;
3053 nIndex++;
3055 if (bIndexWarning)
3057 std::string sValues = "";
3058 for (const auto& atemp : aItem3.second)
3060 if (sValues != "")
3062 sValues += ", ";
3064 sValues += atemp.second
3065 .get_value<std::string>();
3067 lcl_LogWarning(
3068 "FillApi chart: Invalid Cell Index at: '"
3069 + aItem3.first + ": " + sValues
3070 + "' (probably too many parameters)");
3073 xDataArray->setData(aData);
3076 else if (aItem3.first.starts_with("setrowdesc"))
3078 // set row descriptions
3079 uno::Sequence<OUString> aRowDesc
3080 = xDataArray->getRowDescriptions();
3081 OUString* aRowdata = aRowDesc.getArray();
3083 if (aItem3.first.starts_with("setrowdesc."))
3085 // set only 1 description
3086 int nValue = stoi(aItem3.first.substr(11));
3087 if (nValue >= 0 && nValue < aRowDesc.getLength())
3089 aRowdata[nValue] = OStringToOUString(
3090 aItem3.second.get_value<std::string>(),
3091 RTL_TEXTENCODING_UTF8);
3093 else
3095 lcl_LogWarning("FillApi chart setrowdesc: "
3096 "invalid Index at: '"
3097 + aItem3.first + "'");
3100 else
3102 // set an array of description at once
3103 int nIndex = 0;
3104 for (const auto& aItem4 : aItem3.second)
3106 if (nIndex >= aRowDesc.getLength())
3108 lcl_LogWarning("FillApi chart setrowdesc: "
3109 "too many params");
3110 break;
3112 aRowdata[nIndex] = OStringToOUString(
3113 aItem4.second.get_value<std::string>(),
3114 RTL_TEXTENCODING_UTF8);
3115 nIndex++;
3118 xDataArray->setRowDescriptions(aRowDesc);
3120 else if (aItem3.first.starts_with("setcolumndesc"))
3122 // set column descriptions
3123 uno::Sequence<OUString> aColDesc
3124 = xDataArray->getColumnDescriptions();
3125 OUString* aColdata = aColDesc.getArray();
3127 if (aItem3.first.starts_with("setcolumndesc."))
3129 int nValue = stoi(aItem3.first.substr(14));
3130 if (nValue >= 0 && nValue < aColDesc.getLength())
3132 aColdata[nValue] = OStringToOUString(
3133 aItem3.second.get_value<std::string>(),
3134 RTL_TEXTENCODING_UTF8);
3136 else
3138 lcl_LogWarning("FillApi chart setcolumndesc: "
3139 "invalid Index at: '"
3140 + aItem3.first + "'");
3143 else
3145 int nIndex = 0;
3146 for (const auto& aItem4 : aItem3.second)
3148 if (nIndex >= aColDesc.getLength())
3150 lcl_LogWarning(
3151 "FillApi chart setcolumndesc:"
3152 " too many parameters");
3153 break;
3155 aColdata[nIndex] = OStringToOUString(
3156 aItem4.second.get_value<std::string>(),
3157 RTL_TEXTENCODING_UTF8);
3158 nIndex++;
3161 xDataArray->setColumnDescriptions(aColDesc);
3163 else if (aItem3.first.starts_with("resize"))
3165 if (aItem3.second.size() >= 2)
3167 auto aItem4 = aItem3.second.begin();
3168 int nY = aItem4->second.get_value<int>();
3169 int nX = (++aItem4)->second.get_value<int>();
3171 if (nX < 1 || nY < 1)
3173 lcl_LogWarning(
3174 "FillApi chart resize: wrong param"
3175 " (Needed: x,y >= 1)");
3176 continue;
3178 // here we need to use the new insert column thing
3179 if (!lcl_ResizeChartColumns(xChartDoc, nX))
3180 continue;
3182 uno::Sequence<uno::Sequence<double>> aData
3183 = xDataArray->getData();
3184 if (aData.getLength() != nY)
3185 aData.realloc(nY);
3187 for (sal_Int32 j = 0; j < nY; ++j)
3189 uno::Sequence<double>* pRows = aData.getArray();
3190 // resize row if needed
3191 if (pRows[j].getLength() != nX)
3193 pRows[j].realloc(nX);
3196 xDataArray->setData(aData);
3198 else
3200 lcl_LogWarning(
3201 "FillApi chart resize: not enough parameters"
3202 " (x,y is needed)");
3205 else if (aItem3.first.starts_with("data"))
3207 // set table data values
3208 uno::Sequence<uno::Sequence<double>> aData
3209 = xDataArray->getData();
3211 // set only 1 cell data
3212 if (aItem3.first.starts_with("datayx."))
3214 int nPoint = aItem3.first.find('.', 7);
3215 int nY = stoi(aItem3.first.substr(7, nPoint - 7));
3216 int nX = stoi(aItem3.first.substr(nPoint + 1));
3217 bool bValidIndex = false;
3218 if (nY < aData.getLength() && nY >= 0)
3220 uno::Sequence<double>* pRows = aData.getArray();
3221 if (nX < pRows[nY].getLength() && nX >= 0)
3223 double* pCols = pRows[nY].getArray();
3224 pCols[nX]
3225 = aItem3.second.get_value<double>();
3226 bValidIndex = true;
3229 if (!bValidIndex)
3231 lcl_LogWarning(
3232 "FillApi chart datayx: invalid Index at: '"
3233 + aItem3.first + "'");
3236 else
3238 // set the whole data table
3239 // resize if needed
3240 int nRowsCount = aItem3.second.size();
3241 int nColsCount = 0;
3243 for (const auto& aItem4 : aItem3.second)
3245 if (nColsCount
3246 < static_cast<int>(aItem4.second.size()))
3248 nColsCount = aItem4.second.size();
3252 if (nColsCount > 0)
3254 // here we need to use the new insert column thing
3255 if(!lcl_ResizeChartColumns(xChartDoc, nColsCount))
3256 continue;
3258 if (aData.getLength() != nRowsCount)
3259 aData.realloc(nRowsCount);
3261 // set all the rows
3262 sal_Int32 nY = 0;
3263 for (const auto& aItem4 : aItem3.second)
3265 uno::Sequence<double>* pRows
3266 = aData.getArray();
3267 // resize row if needed
3268 if (pRows[nY].getLength() != nColsCount)
3270 pRows[nY].realloc(nColsCount);
3272 double* pCols = pRows[nY].getArray();
3273 // set all values in the row
3274 sal_Int32 nX = 0;
3275 for (const auto& aItem5 : aItem4.second)
3277 if (nX >= nColsCount)
3279 // This should never happen
3280 break;
3282 pCols[nX]
3283 = aItem5.second.get_value<double>();
3284 nX++;
3286 nY++;
3290 xDataArray->setData(aData);
3292 else
3294 lcl_LogWarning("FillApi chart command not recognised: '"
3295 + aItem3.first + "'");
3297 xModi->setModified(true);
3300 if (!bChartFound)
3302 lcl_LogWarning("FillApi: No chart match the filter: '"
3303 + aItem2.first + "'");
3306 else
3308 lcl_LogWarning("FillApi chart filter type not recognised: '"
3309 + aItem2.first + "'");
3313 if (aItem2.first.starts_with("ContentControls"))
3315 std::string aTextEnd = aItem2.first.substr(15);
3316 std::string aValue = "";
3317 ContentFilterType iKeyId = ContentFilterType::ERROR;
3318 // Find how the content control is identified: ByIndex, ByAlias...
3319 for (size_t i = 0; i < aIdTexts.size(); i++)
3321 if (aTextEnd.starts_with(aIdTexts[i]))
3323 iKeyId = static_cast<ContentFilterType>(i);
3324 aValue = aTextEnd.substr(aIdTexts[i].length());
3325 break;
3328 if (iKeyId != ContentFilterType::ERROR)
3330 // Check all the content controls, if they match
3331 bool bCCFound = false;
3332 for (int i = 0; i < iCCcount; ++i)
3334 uno::Reference<text::XTextContent> xContentControl;
3335 xContentControls->getByIndex(i) >>= xContentControl;
3337 uno::Reference<beans::XPropertySet> xContentControlProps(
3338 xContentControl, uno::UNO_QUERY);
3339 if (!xContentControlProps.is())
3340 continue;
3342 // Compare the loaded and the actual identifier
3343 switch (iKeyId)
3345 case ContentFilterType::INDEX:
3347 if (stoi(aValue) != i)
3348 continue;
3350 break;
3351 case ContentFilterType::ID:
3353 sal_Int32 iID = -1;
3354 xContentControlProps->getPropertyValue(UNO_NAME_ID)
3355 >>= iID;
3356 if (stoi(aValue) != iID)
3357 continue;
3359 break;
3360 case ContentFilterType::ALIAS:
3362 OUString aAlias;
3363 xContentControlProps->getPropertyValue(UNO_NAME_ALIAS)
3364 >>= aAlias;
3365 if (OStringToOUString(aValue, RTL_TEXTENCODING_UTF8)
3366 != aAlias)
3367 continue;
3369 break;
3370 case ContentFilterType::TAG:
3372 OUString aTag;
3373 xContentControlProps->getPropertyValue(UNO_NAME_TAG)
3374 >>= aTag;
3375 if (OStringToOUString(aValue, RTL_TEXTENCODING_UTF8)
3376 != aTag)
3377 continue;
3379 break;
3380 default:
3381 continue;
3384 // We have a match, this content control need to be transformed
3385 // Set all the values (of the content control) what is needed
3386 bCCFound = true;
3387 for (const auto& aItem3 : aItem2.second)
3389 if (aItem3.first == "content")
3391 std::string aContent
3392 = aItem3.second.get_value<std::string>();
3394 uno::Reference<text::XText> xContentControlText(
3395 xContentControl, uno::UNO_QUERY);
3396 if (!xContentControlText.is())
3397 continue;
3399 xContentControlText->setString(
3400 OStringToOUString(aContent, RTL_TEXTENCODING_UTF8));
3402 sal_Int32 iType = 0;
3403 xContentControlProps->getPropertyValue(
3404 UNO_NAME_CONTENT_CONTROL_TYPE)
3405 >>= iType;
3406 SwContentControlType aType
3407 = static_cast<SwContentControlType>(iType);
3409 // if we set the content of a checkbox, then we
3410 // also set the checked state based on the content
3411 if (aType == SwContentControlType::CHECKBOX)
3413 OUString aCheckedContent;
3414 xContentControlProps->getPropertyValue(
3415 UNO_NAME_CHECKED_STATE)
3416 >>= aCheckedContent;
3417 bool bChecked = false;
3418 if (aCheckedContent
3419 == OStringToOUString(
3420 aItem3.second.get_value<std::string>(),
3421 RTL_TEXTENCODING_UTF8))
3422 bChecked = true;
3423 xContentControlProps->setPropertyValue(
3424 UNO_NAME_CHECKED, uno::Any(bChecked));
3426 else if (aType == SwContentControlType::PLAIN_TEXT
3427 || aType == SwContentControlType::RICH_TEXT
3428 || aType == SwContentControlType::DATE
3429 || aType == SwContentControlType::COMBO_BOX
3430 || aType
3431 == SwContentControlType::DROP_DOWN_LIST)
3433 // Set the placeholder
3434 bool bPlaceHolder = aContent == "" ? true : false;
3435 xContentControlProps->setPropertyValue(
3436 UNO_NAME_SHOWING_PLACE_HOLDER,
3437 uno::Any(bPlaceHolder));
3438 if (bPlaceHolder)
3440 OUString aPlaceHolderText;
3441 switch (aType)
3443 case SwContentControlType::PLAIN_TEXT:
3444 case SwContentControlType::RICH_TEXT:
3446 aPlaceHolderText = SwResId(
3447 STR_CONTENT_CONTROL_PLACEHOLDER);
3449 break;
3450 case SwContentControlType::COMBO_BOX:
3451 case SwContentControlType::DROP_DOWN_LIST:
3453 aPlaceHolderText = SwResId(
3454 STR_DROPDOWN_CONTENT_CONTROL_PLACEHOLDER);
3456 break;
3457 case SwContentControlType::DATE:
3459 aPlaceHolderText = SwResId(
3460 STR_DATE_CONTENT_CONTROL_PLACEHOLDER);
3462 break;
3463 default: // do nothing for picture and checkbox
3464 break;
3466 if (!aPlaceHolderText.isEmpty())
3467 xContentControlText->setString(
3468 aPlaceHolderText);
3472 else if (aItem3.first == "checked")
3474 bool bChecked
3475 = (aItem3.second.get_value<std::string>() == "true")
3476 ? true
3477 : false;
3478 xContentControlProps->setPropertyValue(
3479 UNO_NAME_CHECKED,
3480 uno::Any(bChecked));
3482 OUString aCheckContent;
3483 xContentControlProps->getPropertyValue(
3484 bChecked ? UNO_NAME_CHECKED_STATE
3485 : UNO_NAME_UNCHECKED_STATE)
3486 >>= aCheckContent;
3487 uno::Reference<text::XText> xContentControlText(
3488 xContentControl, uno::UNO_QUERY);
3489 if (!xContentControlText.is())
3490 continue;
3491 xContentControlText->setString(aCheckContent);
3493 else if (aItem3.first == "date")
3495 std::string aDate
3496 = aItem3.second.get_value<std::string>();
3497 xContentControlProps->setPropertyValue(
3498 UNO_NAME_CURRENT_DATE,
3499 uno::Any(OStringToOUString(aDate,
3500 RTL_TEXTENCODING_UTF8)));
3502 else if (aItem3.first == "alias")
3504 xContentControlProps->setPropertyValue(
3505 UNO_NAME_ALIAS,
3506 uno::Any(OStringToOUString(
3507 aItem3.second.get_value<std::string>(),
3508 RTL_TEXTENCODING_UTF8)));
3510 else
3512 lcl_LogWarning(
3513 "FillApi contentControl command not recognised: '"
3514 + aItem3.first + "'");
3518 if (!bCCFound)
3520 lcl_LogWarning("FillApi: No contentControl match the filter: '"
3521 + aItem2.first + "'");
3524 else
3526 lcl_LogWarning(
3527 "FillApi contentControl filter type not recognised: '"
3528 + aItem2.first + "'");
3535 break;
3536 default:
3537 OSL_ENSURE(false, "wrong dispatcher");
3538 return;
3542 void SwTextShell::GetState( SfxItemSet &rSet )
3544 SwWrtShell &rSh = GetShell();
3545 SfxWhichIter aIter( rSet );
3546 sal_uInt16 nWhich = aIter.FirstWhich();
3547 while ( nWhich )
3549 const sal_uInt16 nSlotId = GetPool().GetSlotId(nWhich);
3550 switch (nSlotId)
3552 case FN_FORMAT_CURRENT_FOOTNOTE_DLG:
3553 if( !rSh.IsCursorInFootnote() )
3554 rSet.DisableItem( nWhich );
3555 break;
3557 case SID_LANGUAGE_STATUS:
3559 // the value of used script types
3560 OUString aScriptTypesInUse( OUString::number( static_cast<int>(rSh.GetScriptType()) ) );
3562 // get keyboard language
3563 OUString aKeyboardLang;
3564 SwEditWin& rEditWin = GetView().GetEditWin();
3565 LanguageType nLang = rEditWin.GetInputLanguage();
3566 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
3567 aKeyboardLang = SvtLanguageTable::GetLanguageString( nLang );
3569 // get the language that is in use
3570 OUString aCurrentLang = u"*"_ustr;
3571 nLang = SwLangHelper::GetCurrentLanguage( rSh );
3572 if (nLang != LANGUAGE_DONTKNOW)
3574 aCurrentLang = SvtLanguageTable::GetLanguageString( nLang );
3575 if (comphelper::LibreOfficeKit::isActive())
3577 if (nLang == LANGUAGE_NONE)
3579 aCurrentLang += ";-";
3581 else
3583 aCurrentLang += ";" + LanguageTag(nLang).getBcp47(false);
3588 // build sequence for status value
3589 uno::Sequence< OUString > aSeq{ aCurrentLang,
3590 aScriptTypesInUse,
3591 aKeyboardLang,
3592 SwLangHelper::GetTextForLanguageGuessing( rSh ) };
3594 // set sequence as status value
3595 SfxStringListItem aItem( SID_LANGUAGE_STATUS );
3596 aItem.SetStringList( aSeq );
3597 rSet.Put( aItem );
3599 break;
3601 case SID_THES:
3603 // is there a valid selection to get text from?
3604 OUString aText;
3605 bool bValid = !rSh.HasSelection() ||
3606 (rSh.IsSelOnePara() && !rSh.IsMultiSelection());
3607 // prevent context menu from showing when cursor is not in or at the end of a word
3608 // (GetCurWord will return the next word if there is none at the current position...)
3609 const sal_Int16 nWordType = ::i18n::WordType::DICTIONARY_WORD;
3610 bool bWord = rSh.IsInWord( nWordType ) || rSh.IsStartWord( nWordType ) || rSh.IsEndWord( nWordType );
3611 if (bValid && bWord)
3612 aText = rSh.HasSelection()? rSh.GetSelText() : rSh.GetCurWord();
3614 LanguageType nLang = rSh.GetCurLang();
3615 LanguageTag aLanguageTag( nLang);
3616 const lang::Locale& aLocale( aLanguageTag.getLocale());
3618 // disable "Thesaurus" context menu entry if there is nothing to look up
3619 uno::Reference< linguistic2::XThesaurus > xThes( ::GetThesaurus() );
3620 if (aText.isEmpty() ||
3621 !xThes.is() || nLang == LANGUAGE_NONE || !xThes->hasLocale( aLocale ))
3622 rSet.DisableItem( SID_THES );
3623 else
3625 // set word and locale to look up as status value
3626 OUString aStatusVal = aText + "#" + aLanguageTag.getBcp47();
3627 rSet.Put( SfxStringItem( SID_THES, aStatusVal ) );
3630 break;
3632 case FN_NUMBER_NEWSTART :
3633 if(!rSh.GetNumRuleAtCurrCursorPos())
3634 rSet.DisableItem(nWhich);
3635 else
3636 rSet.Put(SfxBoolItem(FN_NUMBER_NEWSTART,
3637 rSh.IsNumRuleStart()));
3638 break;
3640 case FN_EDIT_FORMULA:
3641 case SID_CHARMAP:
3642 case SID_CHARMAP_CONTROL:
3644 const SelectionType nType = rSh.GetSelectionType();
3645 if (!(nType & SelectionType::Text) &&
3646 !(nType & SelectionType::Table) &&
3647 !(nType & SelectionType::NumberList))
3649 rSet.DisableItem(nWhich);
3651 else if ( nWhich == FN_EDIT_FORMULA
3652 && rSh.CursorInsideInputField() )
3654 rSet.DisableItem( nWhich );
3657 break;
3659 case FN_INSERT_ENDNOTE:
3660 case FN_INSERT_FOOTNOTE:
3661 case FN_INSERT_FOOTNOTE_DLG:
3663 const FrameTypeFlags nNoType =
3664 FrameTypeFlags::FLY_ANY | FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FOOTNOTE;
3665 FrameTypeFlags eType = rSh.GetFrameType(nullptr, true);
3666 bool bSplitFly = false;
3667 if (eType & FrameTypeFlags::FLY_ATCNT)
3669 SwContentFrame* pContentFrame = rSh.GetCurrFrame(/*bCalcFrame=*/false);
3670 if (pContentFrame)
3672 SwFlyFrame* pFlyFrame = pContentFrame->FindFlyFrame();
3673 bSplitFly = pFlyFrame && pFlyFrame->IsFlySplitAllowed();
3676 if (eType & nNoType && !bSplitFly)
3677 rSet.DisableItem(nWhich);
3679 if ( rSh.CursorInsideInputField() )
3681 rSet.DisableItem( nWhich );
3684 break;
3686 case SID_INSERTDOC:
3687 case FN_INSERT_GLOSSARY:
3688 case FN_EXPAND_GLOSSARY:
3689 if ( rSh.CursorInsideInputField() )
3691 rSet.DisableItem( nWhich );
3693 break;
3695 case FN_INSERT_TABLE:
3696 if ( rSh.CursorInsideInputField()
3697 || rSh.GetTableFormat()
3698 || (rSh.GetFrameType(nullptr,true) & FrameTypeFlags::FOOTNOTE) )
3700 rSet.DisableItem( nWhich );
3702 break;
3704 case FN_CALCULATE:
3705 if ( !rSh.IsSelection() )
3706 rSet.DisableItem(nWhich);
3707 break;
3708 case FN_GOTO_REFERENCE:
3710 SwField *pField = rSh.GetCurField();
3711 if ( !pField || (pField->GetTypeId() != SwFieldTypesEnum::GetRef) )
3712 rSet.DisableItem(nWhich);
3714 break;
3715 case FN_AUTOFORMAT_AUTO:
3717 rSet.Put( SfxBoolItem( nWhich, SvxAutoCorrCfg::Get().IsAutoFormatByInput() ));
3719 break;
3721 case SID_DEC_INDENT:
3722 case SID_INC_INDENT:
3724 //if the paragraph has bullet we'll do the following things:
3725 //1: if the bullet level is the first level, disable the decrease-indent button
3726 //2: if the bullet level is the last level, disable the increase-indent button
3727 if ( rSh.GetNumRuleAtCurrCursorPos() && !rSh.HasReadonlySel() )
3729 const sal_uInt8 nLevel = rSh.GetNumLevel();
3730 if ( ( nLevel == ( MAXLEVEL - 1 ) && nWhich == SID_INC_INDENT )
3731 || ( nLevel == 0 && nWhich == SID_DEC_INDENT ) )
3733 rSet.DisableItem( nWhich );
3736 else
3738 sal_uInt16 nHtmlMode = ::GetHtmlMode( GetView().GetDocShell() );
3739 nHtmlMode &= HTMLMODE_ON | HTMLMODE_SOME_STYLES;
3740 if ( ( nHtmlMode == HTMLMODE_ON )
3741 || !rSh.IsMoveLeftMargin( SID_INC_INDENT == nWhich ) )
3743 rSet.DisableItem( nWhich );
3747 break;
3749 case FN_DEC_INDENT_OFFSET:
3750 case FN_INC_INDENT_OFFSET:
3752 sal_uInt16 nHtmlMode = ::GetHtmlMode(GetView().GetDocShell());
3753 nHtmlMode &= HTMLMODE_ON|HTMLMODE_SOME_STYLES;
3754 if( (nHtmlMode == HTMLMODE_ON) ||
3755 !rSh.IsMoveLeftMargin( FN_INC_INDENT_OFFSET == nWhich,
3756 false ))
3757 rSet.DisableItem( nWhich );
3759 break;
3761 case SID_ATTR_CHAR_COLOR2:
3763 SfxItemSet aSet( GetPool() );
3764 rSh.GetCurAttr( aSet );
3765 const SvxColorItem& aColorItem = aSet.Get(RES_CHRATR_COLOR);
3766 rSet.Put( aColorItem.CloneSetWhich(SID_ATTR_CHAR_COLOR2) );
3768 break;
3769 case SID_ATTR_CHAR_BACK_COLOR:
3770 case SID_ATTR_CHAR_COLOR_BACKGROUND:
3772 // Always use the visible background
3773 SfxItemSet aSet( GetPool() );
3774 rSh.GetCurAttr( aSet );
3775 const SvxBrushItem& aBrushItem = aSet.Get(RES_CHRATR_HIGHLIGHT);
3776 if( aBrushItem.GetColor() != COL_TRANSPARENT )
3778 rSet.Put(SvxColorItem(aBrushItem.GetColor(), aBrushItem.getComplexColor(), nWhich));
3780 else
3782 const SvxBrushItem& aBrushItem2 = aSet.Get(RES_CHRATR_BACKGROUND);
3783 rSet.Put(SvxColorItem(aBrushItem2.GetColor(), aBrushItem2.getComplexColor(), nWhich));
3786 break;
3787 case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT:
3789 SwEditWin& rEdtWin = GetView().GetEditWin();
3790 SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
3791 const sal_uInt32 nColWhich = pApply ? pApply->nColor : 0;
3792 const bool bUseTemplate = nColWhich == SID_ATTR_CHAR_BACK_COLOR
3793 || nColWhich == SID_ATTR_CHAR_COLOR_BACKGROUND;
3794 rSet.Put(SfxBoolItem(nWhich, bUseTemplate));
3796 break;
3797 case SID_ATTR_CHAR_COLOR_EXT:
3799 SwEditWin& rEdtWin = GetView().GetEditWin();
3800 SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate();
3801 rSet.Put(SfxBoolItem(nWhich, pApply && pApply->nColor == nWhich));
3803 break;
3804 case FN_SET_REMINDER:
3805 case FN_INSERT_BOOKMARK:
3806 if( rSh.IsTableMode()
3807 || rSh.CursorInsideInputField() )
3809 rSet.DisableItem( nWhich );
3811 break;
3813 case FN_INSERT_BREAK:
3814 if ( rSh.HasReadonlySel()
3815 && !rSh.CursorInsideInputField() )
3817 rSet.DisableItem( nWhich );
3819 break;
3821 case FN_INSERT_BREAK_DLG:
3822 case FN_INSERT_COLUMN_BREAK:
3823 case FN_INSERT_PAGEBREAK:
3824 if( rSh.CursorInsideInputField() || rSh.CursorInsideContentControl() )
3826 rSet.DisableItem( nWhich );
3828 break;
3830 case FN_INSERT_PAGEHEADER:
3831 case FN_INSERT_PAGEFOOTER:
3832 if (comphelper::LibreOfficeKit::isActive())
3834 bool bState = false;
3835 bool bAllState = true;
3836 bool bIsPhysical = false;
3838 OUString aStyleName;
3839 std::vector<OUString> aList;
3840 static constexpr OUStringLiteral sPhysical(u"IsPhysical");
3841 static constexpr OUStringLiteral sDisplay(u"DisplayName");
3842 const OUString sHeaderOn(nWhich == FN_INSERT_PAGEHEADER ? u"HeaderIsOn"_ustr : u"FooterIsOn"_ustr);
3844 rtl::Reference< SwXTextDocument > xSupplier(GetView().GetDocShell()->GetBaseModel());
3845 if (xSupplier.is())
3847 uno::Reference< XNameContainer > xContainer;
3848 uno::Reference< XNameAccess > xFamilies = xSupplier->getStyleFamilies();
3849 if (xFamilies->getByName(u"PageStyles"_ustr) >>= xContainer)
3851 const uno::Sequence< OUString > aSeqNames = xContainer->getElementNames();
3852 for (const auto& rName : aSeqNames)
3854 aStyleName = rName;
3855 uno::Reference<XPropertySet> xPropSet(xContainer->getByName(aStyleName), uno::UNO_QUERY);
3856 if (xPropSet.is() && (xPropSet->getPropertyValue(sPhysical) >>= bIsPhysical) && bIsPhysical)
3858 xPropSet->getPropertyValue(sDisplay) >>= aStyleName;
3859 if ((xPropSet->getPropertyValue(sHeaderOn)>>= bState) && bState)
3860 aList.push_back(aStyleName);
3861 else
3862 bState = false;
3864 // Check if all entries have the same state
3865 bAllState &= bState;
3867 else
3868 bIsPhysical = false;
3873 if (bAllState && aList.size() > 1)
3874 aList.push_back(u"_ALL_"_ustr);
3876 rSet.Put(SfxStringListItem(nWhich, &aList));
3878 else
3880 rSet.Put( SfxObjectShellItem( nWhich, GetView().GetDocShell() ));
3882 break;
3883 case FN_TABLE_SORT_DIALOG:
3884 case FN_SORTING_DLG:
3885 if(!rSh.HasSelection() ||
3886 (FN_TABLE_SORT_DIALOG == nWhich && !rSh.GetTableFormat()))
3887 rSet.DisableItem( nWhich );
3888 break;
3890 case SID_RUBY_DIALOG:
3892 if( !SvtCJKOptions::IsRubyEnabled()
3893 || rSh.CursorInsideInputField() )
3895 GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, false );
3896 rSet.DisableItem(nWhich);
3898 else
3899 GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, true );
3901 break;
3903 case SID_FM_TRANSLATE:
3905 #if HAVE_FEATURE_CURL && !ENABLE_WASM_STRIP_EXTRA
3906 if (!officecfg::Office::Common::Misc::ExperimentalMode::get()
3907 && !comphelper::LibreOfficeKit::isActive())
3909 rSet.Put(SfxVisibilityItem(nWhich, false));
3910 break;
3912 std::optional<OUString> oDeeplAPIUrl = officecfg::Office::Linguistic::Translation::Deepl::ApiURL::get();
3913 std::optional<OUString> oDeeplKey = officecfg::Office::Linguistic::Translation::Deepl::AuthKey::get();
3914 if (!oDeeplAPIUrl || oDeeplAPIUrl->isEmpty() || !oDeeplKey || oDeeplKey->isEmpty())
3916 rSet.DisableItem(nWhich);
3918 #endif
3920 break;
3922 case SID_HYPERLINK_DIALOG:
3923 if( GetView().GetDocShell()->IsReadOnly()
3924 || ( !GetView().GetViewFrame().HasChildWindow(nWhich)
3925 && rSh.HasReadonlySel() )
3926 || rSh.CursorInsideInputField() )
3928 rSet.DisableItem(nWhich);
3930 else
3932 rSet.Put(SfxBoolItem( nWhich, nullptr != GetView().GetViewFrame().GetChildWindow( nWhich ) ));
3934 break;
3936 case SID_EDIT_HYPERLINK:
3938 if (!rSh.HasReadonlySel())
3940 SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
3941 rSh.GetCurAttr(aSet);
3942 if (SfxItemState::SET <= aSet.GetItemState(RES_TXTATR_INETFMT))
3943 break;
3945 // is the cursor at the beginning of a hyperlink?
3946 const SwTextNode* pTextNd = rSh.GetCursor()->GetPointNode().GetTextNode();
3947 if (pTextNd && !rSh.HasSelection())
3949 const sal_Int32 nIndex = rSh.GetCursor()->Start()->GetContentIndex();
3950 const SwTextAttr* pINetFmt
3951 = pTextNd->GetTextAttrAt(nIndex, RES_TXTATR_INETFMT);
3952 if (pINetFmt && !pINetFmt->GetINetFormat().GetValue().isEmpty())
3953 break;
3956 rSet.DisableItem(nWhich);
3958 break;
3959 case SID_REMOVE_HYPERLINK:
3961 if (!rSh.HasReadonlySel())
3963 SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
3964 rSh.GetCurAttr(aSet);
3966 // If a hyperlink is selected, either alone or along with other text...
3967 if (SfxItemState::SET <= aSet.GetItemState(RES_TXTATR_INETFMT)
3968 || aSet.GetItemState(RES_TXTATR_INETFMT) == SfxItemState::INVALID)
3970 break;
3973 // is the cursor at the beginning of a hyperlink?
3974 const SwTextNode* pTextNd = rSh.GetCursor()->GetPointNode().GetTextNode();
3975 if (pTextNd && !rSh.HasSelection())
3977 const sal_Int32 nIndex = rSh.GetCursor()->Start()->GetContentIndex();
3978 const SwTextAttr* pINetFmt
3979 = pTextNd->GetTextAttrAt(nIndex, RES_TXTATR_INETFMT);
3980 if (pINetFmt && !pINetFmt->GetINetFormat().GetValue().isEmpty())
3981 break;
3984 rSet.DisableItem(nWhich);
3986 break;
3987 case SID_TRANSLITERATE_HALFWIDTH:
3988 case SID_TRANSLITERATE_FULLWIDTH:
3989 case SID_TRANSLITERATE_HIRAGANA:
3990 case SID_TRANSLITERATE_KATAKANA:
3992 if(!SvtCJKOptions::IsChangeCaseMapEnabled())
3994 GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, false );
3995 rSet.DisableItem(nWhich);
3997 else
3998 GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, true );
4000 break;
4001 case FN_READONLY_SELECTION_MODE :
4002 if(!GetView().GetDocShell()->IsReadOnly())
4003 rSet.DisableItem( nWhich );
4004 else
4006 rSet.Put(SfxBoolItem(nWhich, rSh.GetViewOptions()->IsSelectionInReadonly()));
4008 break;
4009 case FN_SELECTION_MODE_DEFAULT:
4010 case FN_SELECTION_MODE_BLOCK :
4011 rSet.Put(SfxBoolItem(nWhich, (nWhich == FN_SELECTION_MODE_DEFAULT) != rSh.IsBlockMode()));
4012 break;
4013 case SID_COPY_HYPERLINK_LOCATION:
4014 case SID_OPEN_HYPERLINK:
4016 SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
4017 rSh.GetCurAttr(aSet);
4018 if (SfxItemState::SET <= aSet.GetItemState(RES_TXTATR_INETFMT, false))
4019 break;
4021 // is the cursor at the beginning of a hyperlink?
4022 const SwTextNode* pTextNd = rSh.GetCursor()->GetPointNode().GetTextNode();
4023 if (pTextNd && !rSh.HasSelection())
4025 const sal_Int32 nIndex = rSh.GetCursor()->Start()->GetContentIndex();
4026 const SwTextAttr* pINetFmt = pTextNd->GetTextAttrAt(nIndex, RES_TXTATR_INETFMT);
4027 if (pINetFmt && !pINetFmt->GetINetFormat().GetValue().isEmpty())
4028 break;
4031 SwField* pField = rSh.GetCurField();
4032 if (pField && pField->GetTyp()->Which() == SwFieldIds::TableOfAuthorities)
4034 const auto& rAuthorityField = *static_cast<const SwAuthorityField*>(pField);
4035 if (auto targetType = rAuthorityField.GetTargetType();
4036 targetType == SwAuthorityField::TargetType::UseDisplayURL
4037 || targetType == SwAuthorityField::TargetType::UseTargetURL)
4039 // Check if the Bibliography entry has a target URL
4040 if (rAuthorityField.GetAbsoluteURL().getLength() > 0)
4041 break;
4045 rSet.DisableItem(nWhich);
4047 break;
4048 case FN_OPEN_LOCAL_URL:
4050 if (GetLocalURL(rSh).isEmpty())
4052 rSet.DisableItem(nWhich);
4055 break;
4056 case SID_OPEN_SMARTTAGMENU:
4058 std::vector< OUString > aSmartTagTypes;
4059 uno::Sequence< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
4060 uno::Reference<text::XTextRange> xRange;
4062 rSh.GetSmartTagTerm( aSmartTagTypes, aStringKeyMaps, xRange );
4064 if ( xRange.is() && !aSmartTagTypes.empty() )
4066 uno::Sequence < uno::Sequence< uno::Reference< smarttags::XSmartTagAction > > > aActionComponentsSequence;
4067 uno::Sequence < uno::Sequence< sal_Int32 > > aActionIndicesSequence;
4069 const SmartTagMgr& rSmartTagMgr = SwSmartTagMgr::Get();
4070 rSmartTagMgr.GetActionSequences( aSmartTagTypes,
4071 aActionComponentsSequence,
4072 aActionIndicesSequence );
4074 uno::Reference <frame::XController> xController = GetView().GetController();
4075 lang::Locale aLocale( SW_BREAKITER()->GetLocale( GetAppLanguageTag() ) );
4076 const OUString& aApplicationName( rSmartTagMgr.GetApplicationName() );
4077 const OUString aRangeText = xRange->getString();
4079 const SvxSmartTagItem aItem( SID_OPEN_SMARTTAGMENU,
4080 aActionComponentsSequence,
4081 aActionIndicesSequence,
4082 aStringKeyMaps,
4083 xRange,
4084 std::move(xController),
4085 std::move(aLocale),
4086 aApplicationName,
4087 aRangeText );
4089 rSet.Put( aItem );
4091 else
4092 rSet.DisableItem(nWhich);
4094 break;
4096 case FN_NUM_NUMBERING_ON:
4097 rSet.Put(SfxBoolItem(FN_NUM_NUMBERING_ON,rSh.SelectionHasNumber()));
4098 break;
4100 case FN_NUM_BULLET_ON:
4101 rSet.Put(SfxBoolItem(FN_NUM_BULLET_ON,rSh.SelectionHasBullet()));
4102 break;
4104 case FN_NUM_BULLET_OFF:
4105 rSet.Put(SfxBoolItem(FN_NUM_BULLET_OFF, !rSh.GetNumRuleAtCurrCursorPos() &&
4106 !rSh.GetNumRuleAtCurrentSelection()));
4107 break;
4109 case FN_SVX_SET_OUTLINE:
4111 NBOTypeMgrBase* pOutline = NBOutlineTypeMgrFact::CreateInstance(NBOType::Outline);
4112 auto pCurRule = const_cast<SwNumRule*>(rSh.GetNumRuleAtCurrCursorPos());
4113 if (pOutline && pCurRule)
4115 SvxNumRule aSvxRule = pCurRule->MakeSvxNumRule();
4116 const sal_uInt16 nIndex = pOutline->GetNBOIndexForNumRule(aSvxRule, 0);
4117 rSet.Put(SfxBoolItem(FN_SVX_SET_OUTLINE, nIndex < USHRT_MAX));
4119 break;
4121 case FN_BUL_NUM_RULE_INDEX:
4122 case FN_NUM_NUM_RULE_INDEX:
4123 case FN_OUTLINE_RULE_INDEX:
4125 SwNumRule* pCurRule = const_cast<SwNumRule*>(GetShell().GetNumRuleAtCurrCursorPos());
4126 if( pCurRule )
4128 sal_uInt16 nActNumLvl = GetShell().GetNumLevel();
4129 if( nActNumLvl < MAXLEVEL )
4131 nActNumLvl = 1<<nActNumLvl;
4133 SvxNumRule aSvxRule = pCurRule->MakeSvxNumRule();
4134 if ( GetShell().HasBullet())
4136 rSet.Put(SfxUInt16Item(FN_BUL_NUM_RULE_INDEX, USHRT_MAX));
4137 rSet.Put(SfxUInt16Item(FN_NUM_NUM_RULE_INDEX, USHRT_MAX));
4138 NBOTypeMgrBase* pBullets = NBOutlineTypeMgrFact::CreateInstance(NBOType::Bullets);
4139 if ( pBullets )
4141 const sal_uInt16 nBulIndex = pBullets->GetNBOIndexForNumRule(aSvxRule,nActNumLvl);
4142 rSet.Put(SfxUInt16Item(FN_BUL_NUM_RULE_INDEX,nBulIndex));
4144 }else if ( GetShell().HasNumber() )
4146 rSet.Put(SfxUInt16Item(FN_BUL_NUM_RULE_INDEX, USHRT_MAX));
4147 rSet.Put(SfxUInt16Item(FN_NUM_NUM_RULE_INDEX, USHRT_MAX));
4148 NBOTypeMgrBase* pNumbering = NBOutlineTypeMgrFact::CreateInstance(NBOType::Numbering);
4149 if ( pNumbering )
4151 const sal_uInt16 nBulIndex = pNumbering->GetNBOIndexForNumRule(aSvxRule,nActNumLvl);
4152 rSet.Put(SfxUInt16Item(FN_NUM_NUM_RULE_INDEX,nBulIndex));
4156 if ( nWhich == FN_OUTLINE_RULE_INDEX )
4158 rSet.Put(SfxUInt16Item(FN_OUTLINE_RULE_INDEX, USHRT_MAX));
4159 NBOTypeMgrBase* pOutline = NBOutlineTypeMgrFact::CreateInstance(NBOType::Outline);
4160 if ( pOutline )
4162 const sal_uInt16 nIndex = pOutline->GetNBOIndexForNumRule(aSvxRule,nActNumLvl);
4163 rSet.Put(SfxUInt16Item(FN_OUTLINE_RULE_INDEX,nIndex));
4168 break;
4169 case FN_BUL_GET_DOC_BULLETS:
4171 std::set<OUString> aBulletsSet = rSh.GetUsedBullets();
4172 std::vector<OUString> aBullets;
4173 std::copy(aBulletsSet.begin(), aBulletsSet.end(), std::back_inserter(aBullets));
4174 SfxStringListItem aItem(FN_BUL_GET_DOC_BULLETS);
4175 uno::Sequence<OUString> aSeq(aBullets.data(),
4176 static_cast<sal_Int32>(aBullets.size()));
4177 aItem.SetStringList(aSeq);
4178 rSet.Put(aItem);
4180 break;
4181 case FN_NUM_CONTINUE:
4183 // #i86492#
4184 // Search also for bullet list
4185 OUString aDummy;
4186 const SwNumRule* pRule =
4187 rSh.SearchNumRule( true, aDummy );
4188 if ( !pRule )
4190 pRule = rSh.SearchNumRule( false, aDummy );
4192 if ( !pRule )
4193 rSet.DisableItem(nWhich);
4195 break;
4196 case SID_INSERT_RLM :
4197 case SID_INSERT_LRM :
4199 bool bEnabled = SvtCTLOptions::IsCTLFontEnabled();
4200 GetView().GetViewFrame().GetBindings().SetVisibleState( nWhich, bEnabled );
4201 if(!bEnabled)
4202 rSet.DisableItem(nWhich);
4204 break;
4205 case SID_FM_CTL_PROPERTIES:
4207 bool bDisable = false;
4209 // First get the state from the form shell
4210 SfxItemSetFixed<SID_FM_CTL_PROPERTIES, SID_FM_CTL_PROPERTIES> aSet(GetShell().GetAttrPool());
4211 aSet.Put(SfxBoolItem( SID_FM_CTL_PROPERTIES, true ));
4212 GetShell().GetView().GetFormShell()->GetState( aSet );
4214 if(SfxItemState::DISABLED == aSet.GetItemState(SID_FM_CTL_PROPERTIES))
4216 bDisable = true;
4219 // Enable it if we have a valid object other than what form shell knows
4220 SwPosition aPos(*GetShell().GetCursor()->GetPoint());
4221 sw::mark::Fieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
4222 if ( !pFieldBM && aPos.GetContentIndex() > 0)
4224 aPos.AdjustContent(-1);
4225 pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
4227 if ( pFieldBM && (pFieldBM->GetFieldname() == ODF_FORMDROPDOWN || pFieldBM->GetFieldname() == ODF_FORMDATE) )
4229 bDisable = false;
4232 if(bDisable)
4233 rSet.DisableItem(nWhich);
4235 break;
4236 case SID_COPY:
4237 case SID_CUT:
4239 if (GetObjectShell()->isContentExtractionLocked())
4240 rSet.DisableItem(nWhich);
4241 break;
4243 case FN_PROTECT_FIELDS:
4244 case FN_PROTECT_BOOKMARKS:
4246 DocumentSettingId aSettingId = nWhich == FN_PROTECT_FIELDS
4247 ? DocumentSettingId::PROTECT_FIELDS
4248 : DocumentSettingId::PROTECT_BOOKMARKS;
4249 bool bProtected = rSh.getIDocumentSettingAccess().get(aSettingId);
4250 rSet.Put(SfxBoolItem(nWhich, bProtected));
4252 break;
4253 case FN_DELETE_CONTENT_CONTROL:
4254 case FN_CONTENT_CONTROL_PROPERTIES:
4256 if (!GetShell().CursorInsideContentControl())
4258 rSet.DisableItem(nWhich);
4261 break;
4263 nWhich = aIter.NextWhich();
4267 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */