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