/src/libreoffice/sw/source/uibase/shells/textfld.cxx
Line | Count | Source |
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 <com/sun/star/beans/PropertyValues.hpp> |
21 | | #include <AnnotationWin.hxx> |
22 | | #include <comphelper/lok.hxx> |
23 | | #include <hintids.hxx> |
24 | | #include <IDocumentFieldsAccess.hxx> |
25 | | #include <sfx2/bindings.hxx> |
26 | | #include <sfx2/lnkbase.hxx> |
27 | | #include <txtfld.hxx> |
28 | | #include <svl/itempool.hxx> |
29 | | #include <svl/numformat.hxx> |
30 | | #include <editeng/editobj.hxx> |
31 | | #include <tools/lineend.hxx> |
32 | | #include <svl/whiter.hxx> |
33 | | #include <svl/eitem.hxx> |
34 | | #include <svl/macitem.hxx> |
35 | | #include <sfx2/viewfrm.hxx> |
36 | | #include <sfx2/request.hxx> |
37 | | #include <svx/postattr.hxx> |
38 | | #include <svx/hlnkitem.hxx> |
39 | | #include <svx/svxdlg.hxx> |
40 | | #include <osl/diagnose.h> |
41 | | #include <charatr.hxx> |
42 | | #include <fmtfsize.hxx> |
43 | | #include <fmthdft.hxx> |
44 | | #include <fmtinfmt.hxx> |
45 | | #include <fldwrap.hxx> |
46 | | #include <frmatr.hxx> |
47 | | #include <hfspacingitem.hxx> |
48 | | #include <redline.hxx> |
49 | | #include <swfont.hxx> |
50 | | #include <view.hxx> |
51 | | #include <viewopt.hxx> |
52 | | #include <wrtsh.hxx> |
53 | | #include <textsh.hxx> |
54 | | #include <docufld.hxx> |
55 | | #include <ddefld.hxx> |
56 | | #include <fldmgr.hxx> |
57 | | #include <uitool.hxx> |
58 | | #include <cmdid.h> |
59 | | #include <strings.hrc> |
60 | | #include <sfx2/event.hxx> |
61 | | #include <swabstdlg.hxx> |
62 | | #include <doc.hxx> |
63 | | #include <PostItMgr.hxx> |
64 | | #include <swmodule.hxx> |
65 | | #include <svtools/strings.hrc> |
66 | | #include <svtools/svtresid.hxx> |
67 | | |
68 | | #include <xmloff/odffields.hxx> |
69 | | #include <IDocumentContentOperations.hxx> |
70 | | #include <IDocumentLayoutAccess.hxx> |
71 | | #include <IDocumentRedlineAccess.hxx> |
72 | | #include <IDocumentUndoRedo.hxx> |
73 | | #include <svl/zforlist.hxx> |
74 | | #include <svl/zformat.hxx> |
75 | | #include <svx/xfillit0.hxx> |
76 | | #include <svx/pageitem.hxx> |
77 | | #include <comphelper/sequenceashashmap.hxx> |
78 | | #include <IMark.hxx> |
79 | | #include <officecfg/Office/Common.hxx> |
80 | | #include <officecfg/Office/Compatibility.hxx> |
81 | | #include <ndtxt.hxx> |
82 | | #include <translatehelper.hxx> |
83 | | #include <sfx2/dispatch.hxx> |
84 | | |
85 | | |
86 | | static OUString lcl_BuildTitleWithRedline( const SwRangeRedline *pRedline ) |
87 | 0 | { |
88 | 0 | const OUString sTitle(SwResId(STR_REDLINE_COMMENT)); |
89 | |
|
90 | 0 | TranslateId pResId; |
91 | 0 | switch( pRedline->GetType() ) |
92 | 0 | { |
93 | 0 | case RedlineType::Insert: |
94 | 0 | pResId = STR_REDLINE_INSERTED; |
95 | 0 | break; |
96 | 0 | case RedlineType::Delete: |
97 | 0 | pResId = STR_REDLINE_DELETED; |
98 | 0 | break; |
99 | 0 | case RedlineType::Format: |
100 | 0 | case RedlineType::ParagraphFormat: |
101 | 0 | pResId = STR_REDLINE_FORMATTED; |
102 | 0 | break; |
103 | 0 | case RedlineType::Table: |
104 | 0 | pResId = STR_REDLINE_TABLECHG; |
105 | 0 | break; |
106 | 0 | case RedlineType::FmtColl: |
107 | 0 | pResId = STR_REDLINE_FMTCOLLSET; |
108 | 0 | break; |
109 | 0 | default: |
110 | 0 | return sTitle; |
111 | 0 | } |
112 | | |
113 | 0 | return sTitle + SwResId(pResId); |
114 | 0 | } |
115 | | |
116 | | static bool lcl_canUserModifyAnnotation(const SwView& rView, std::u16string_view sAuthor) |
117 | 0 | { |
118 | 0 | return !comphelper::LibreOfficeKit::isActive() || !rView.IsLokReadOnlyView() |
119 | 0 | || sAuthor == rView.GetRedlineAuthor(); |
120 | 0 | } |
121 | | |
122 | | static bool lcl_canUserModifyAnnotation(const SwView& rView, |
123 | | const sw::annotation::SwAnnotationWin* pAnnotationWin) |
124 | 0 | { |
125 | 0 | return pAnnotationWin && lcl_canUserModifyAnnotation(rView, pAnnotationWin->GetAuthor()); |
126 | 0 | } |
127 | | |
128 | | static bool lcl_canUserModifyAnnotation(const SwView& rView, sal_uInt32 nPostItId) |
129 | 0 | { |
130 | 0 | return lcl_canUserModifyAnnotation(rView, rView.GetPostItMgr()->GetAnnotationWin(nPostItId)); |
131 | 0 | } |
132 | | |
133 | | void SwTextShell::ExecField(SfxRequest &rReq) |
134 | 0 | { |
135 | 0 | SwWrtShell& rSh = GetShell(); |
136 | 0 | const SfxPoolItem* pItem = nullptr; |
137 | |
|
138 | 0 | sal_uInt16 nSlot = rReq.GetSlot(); |
139 | 0 | const SfxItemSet* pArgs = rReq.GetArgs(); |
140 | 0 | if(pArgs) |
141 | 0 | pArgs->GetItemState(GetPool().GetWhichIDFromSlotID(nSlot), false, &pItem); |
142 | |
|
143 | 0 | bool bMore = false; |
144 | 0 | bool bIsText = true; |
145 | 0 | SwFieldTypesEnum nInsertType = SwFieldTypesEnum::Date; |
146 | 0 | sal_uInt16 nInsertSubType = 0; |
147 | 0 | sal_uInt32 nInsertFormat = 0; |
148 | |
|
149 | 0 | switch(nSlot) |
150 | 0 | { |
151 | 0 | case FN_EDIT_FIELD: |
152 | 0 | { |
153 | 0 | SwField* pField = rSh.GetCurField(true); |
154 | 0 | if( pField ) |
155 | 0 | { |
156 | 0 | switch ( pField->GetTypeId() ) |
157 | 0 | { |
158 | 0 | case SwFieldTypesEnum::DDE: |
159 | 0 | { |
160 | 0 | ::sfx2::SvBaseLink& rLink = static_cast<SwDDEFieldType*>(pField->GetTyp())-> |
161 | 0 | GetBaseLink(); |
162 | 0 | if(rLink.IsVisible()) |
163 | 0 | { |
164 | 0 | if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get()) |
165 | 0 | { |
166 | 0 | std::unique_ptr<weld::MessageDialog> xError( |
167 | 0 | Application::CreateMessageDialog( |
168 | 0 | nullptr, VclMessageType::Warning, VclButtonsType::Ok, |
169 | 0 | SvtResId(STR_WARNING_EXTERNAL_LINK_EDIT_DISABLED))); |
170 | 0 | xError->run(); |
171 | 0 | break; |
172 | 0 | } |
173 | | |
174 | 0 | SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); |
175 | 0 | VclPtr<SfxAbstractLinksDialog> pDlg(pFact->CreateLinksDialog(GetView().GetFrameWeld(), &rSh.GetLinkManager(), false, &rLink)); |
176 | 0 | pDlg->StartExecuteAsync( |
177 | 0 | [pDlg] (sal_Int32 /*nResult*/)->void |
178 | 0 | { |
179 | 0 | pDlg->disposeOnce(); |
180 | 0 | } |
181 | 0 | ); |
182 | 0 | } |
183 | 0 | break; |
184 | 0 | } |
185 | 0 | default: |
186 | 0 | { |
187 | 0 | SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); |
188 | 0 | VclPtr<SfxAbstractDialog> pDlg(pFact->CreateSwFieldEditDlg( GetView() )); |
189 | | // without TabPage no dialog |
190 | 0 | if (pDlg) |
191 | 0 | pDlg->StartExecuteAsync( |
192 | 0 | [pDlg] (sal_Int32 /*nResult*/)->void |
193 | 0 | { |
194 | 0 | pDlg->disposeOnce(); |
195 | 0 | } |
196 | 0 | ); |
197 | 0 | } |
198 | 0 | } |
199 | 0 | } |
200 | 0 | break; |
201 | 0 | } |
202 | 0 | case FN_COPY_FIELD: |
203 | 0 | { |
204 | | //call copy field dialog with field string - if there is any! |
205 | 0 | SwField* pField = rSh.GetCurField(true); |
206 | 0 | if( pField && pField->ExpandField(true, nullptr).getLength()) |
207 | 0 | { |
208 | 0 | SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); |
209 | 0 | VclPtr<AbstractCopyFieldDlg> pDlg(pFact->CreateCopyFieldDlg( |
210 | 0 | GetView().GetFrameWeld(), pField->ExpandField(true, nullptr))); |
211 | 0 | pDlg->StartExecuteAsync( |
212 | 0 | [pDlg] (sal_Int32 /*nResult*/)->void |
213 | 0 | { |
214 | 0 | pDlg->disposeOnce(); |
215 | 0 | } |
216 | 0 | ); |
217 | 0 | } |
218 | 0 | break; |
219 | 0 | } |
220 | 0 | case FN_UPDATE_SEL_FIELD: |
221 | 0 | { |
222 | 0 | SwField *pField = rSh.GetCurField(); |
223 | |
|
224 | 0 | if (pField) |
225 | 0 | { |
226 | 0 | rSh.UpdateOneField(*pField); |
227 | 0 | } |
228 | 0 | break; |
229 | 0 | } |
230 | 0 | case FN_CONVERT_SEL_FIELD: |
231 | 0 | { |
232 | 0 | SwField* pField = rSh.GetCurField(); |
233 | 0 | if (pField) |
234 | 0 | { |
235 | 0 | rSh.ConvertOneFieldToText(*pField); |
236 | 0 | } |
237 | 0 | break; |
238 | 0 | } |
239 | 0 | case FN_EXECUTE_MACROFIELD: |
240 | 0 | { |
241 | 0 | SwField* pField = rSh.GetCurField(); |
242 | 0 | if(pField && pField->GetTyp()->Which() == SwFieldIds::Macro) |
243 | 0 | { |
244 | |
|
245 | 0 | const OUString& rMacro = static_cast<SwMacroField*>(pField)->GetMacro(); |
246 | 0 | sal_Int32 nPos = rMacro.indexOf('.'); |
247 | 0 | if(nPos != -1) |
248 | 0 | { |
249 | 0 | SvxMacro aMacro( rMacro.copy(nPos + 1), rMacro.copy(0,nPos), STARBASIC ); |
250 | 0 | rSh.ExecMacro(aMacro); |
251 | 0 | } |
252 | 0 | } |
253 | 0 | } |
254 | 0 | break; |
255 | | |
256 | 0 | case FN_GOTO_NEXT_INPUTFLD: |
257 | 0 | case FN_GOTO_PREV_INPUTFLD: |
258 | 0 | { |
259 | 0 | bool bRet = false; |
260 | 0 | SwFieldType* pField = rSh.GetFieldType( 0, SwFieldIds::Input ); |
261 | 0 | const bool bAddSetExpressionFields = !( rSh.GetViewOptions()->IsReadonly() ); |
262 | 0 | if ( pField != nullptr |
263 | 0 | && rSh.MoveFieldType( |
264 | 0 | pField, |
265 | 0 | FN_GOTO_NEXT_INPUTFLD == nSlot, |
266 | 0 | SwFieldIds::Unknown, |
267 | 0 | bAddSetExpressionFields ) ) |
268 | 0 | { |
269 | 0 | rSh.ClearMark(); |
270 | 0 | if (!rSh.IsMultiSelection() |
271 | 0 | && (nullptr != dynamic_cast<const SwTextInputField*>( |
272 | 0 | SwCursorShell::GetTextFieldAtCursor(rSh.GetCursor(), ::sw::GetTextAttrMode::Default)))) |
273 | 0 | { |
274 | 0 | rSh.SttSelect(); |
275 | 0 | rSh.SelectTextModel( |
276 | 0 | SwCursorShell::StartOfInputFieldAtPos( *(rSh.GetCursor()->Start()) ) + 1, |
277 | 0 | SwCursorShell::EndOfInputFieldAtPos( *(rSh.GetCursor()->Start()) ) - 1 ); |
278 | 0 | } |
279 | 0 | else if (SwField* pCurrentField = rSh.GetCurField(true)) |
280 | 0 | { |
281 | 0 | rSh.StartInputFieldDlg(pCurrentField, false, false, GetView().GetFrameWeld()); |
282 | 0 | } |
283 | 0 | bRet = true; |
284 | 0 | } |
285 | |
|
286 | 0 | rReq.SetReturnValue( SfxBoolItem( nSlot, bRet )); |
287 | 0 | } |
288 | 0 | break; |
289 | | |
290 | 0 | case FN_GOTO_MARK: |
291 | 0 | { |
292 | 0 | const SfxStringItem* pName = rReq.GetArg<SfxStringItem>(FN_GOTO_MARK); |
293 | 0 | if (pName) |
294 | 0 | { |
295 | 0 | rSh.GotoMark(SwMarkName(pName->GetValue())); |
296 | 0 | } |
297 | 0 | } |
298 | 0 | break; |
299 | 0 | default: |
300 | 0 | bMore = true; |
301 | 0 | } |
302 | 0 | if(!bMore) |
303 | 0 | return; |
304 | | |
305 | | // Here come the slots with FieldMgr. |
306 | 0 | SwFieldMgr aFieldMgr(GetShellPtr()); |
307 | 0 | switch(nSlot) |
308 | 0 | { |
309 | 0 | case FN_INSERT_DBFIELD: |
310 | 0 | { |
311 | 0 | bool bRes = false; |
312 | 0 | if( pItem ) |
313 | 0 | { |
314 | 0 | sal_uInt32 nFormat = 0; |
315 | 0 | SwFieldTypesEnum nType = SwFieldTypesEnum::Date; |
316 | 0 | OUString aPar1 = static_cast<const SfxStringItem *>(pItem)->GetValue(); |
317 | 0 | OUString aPar2; |
318 | 0 | sal_Int32 nCommand = 0; |
319 | |
|
320 | 0 | if( const SfxUInt16Item* pFieldItem = pArgs->GetItemIfSet( FN_PARAM_FIELD_TYPE, |
321 | 0 | false )) |
322 | 0 | nType = static_cast<SwFieldTypesEnum>(pFieldItem->GetValue()); |
323 | 0 | aPar1 += OUStringChar(DB_DELIM); |
324 | 0 | if( SfxItemState::SET == pArgs->GetItemState( |
325 | 0 | FN_PARAM_1, false, &pItem )) |
326 | 0 | { |
327 | 0 | aPar1 += static_cast<const SfxStringItem *>(pItem)->GetValue(); |
328 | 0 | } |
329 | 0 | if( SfxItemState::SET == pArgs->GetItemState( |
330 | 0 | FN_PARAM_3, false, &pItem )) |
331 | 0 | nCommand = static_cast<const SfxInt32Item*>(pItem)->GetValue(); |
332 | 0 | aPar1 += OUStringChar(DB_DELIM) |
333 | 0 | + OUString::number(nCommand) |
334 | 0 | + OUStringChar(DB_DELIM); |
335 | 0 | if( SfxItemState::SET == pArgs->GetItemState( |
336 | 0 | FN_PARAM_2, false, &pItem )) |
337 | 0 | { |
338 | 0 | aPar1 += static_cast<const SfxStringItem *>(pItem)->GetValue(); |
339 | 0 | } |
340 | 0 | if( const SfxStringItem* pContentItem = pArgs->GetItemIfSet( |
341 | 0 | FN_PARAM_FIELD_CONTENT, false )) |
342 | 0 | aPar2 = pContentItem->GetValue(); |
343 | 0 | if( const SfxUInt32Item* pFormatItem = pArgs->GetItemIfSet( |
344 | 0 | FN_PARAM_FIELD_FORMAT, false )) |
345 | 0 | nFormat = pFormatItem->GetValue(); |
346 | 0 | OSL_FAIL("Command is not yet used"); |
347 | 0 | SwInsertField_Data aData(nType, 0, aPar1, aPar2, nFormat, GetShellPtr(), ' '/*separator*/ ); |
348 | 0 | bRes = aFieldMgr.InsertField(aData); |
349 | 0 | } |
350 | 0 | rReq.SetReturnValue(SfxBoolItem( nSlot, bRes )); |
351 | 0 | } |
352 | 0 | break; |
353 | 0 | case FN_INSERT_FIELD_CTRL: |
354 | 0 | case FN_INSERT_FIELD: |
355 | 0 | { |
356 | 0 | bool bRes = false; |
357 | 0 | if( pItem && nSlot != FN_INSERT_FIELD_CTRL) |
358 | 0 | { |
359 | 0 | sal_uInt32 nFormat = 0; |
360 | 0 | SwFieldTypesEnum nType = SwFieldTypesEnum::Date; |
361 | 0 | sal_uInt16 nSubType = 0; |
362 | 0 | OUString aPar1 = static_cast<const SfxStringItem *>(pItem)->GetValue(); |
363 | 0 | OUString aPar2; |
364 | 0 | sal_Unicode cSeparator = ' '; |
365 | |
|
366 | 0 | if( const SfxUInt16Item* pTypeItem = pArgs->GetItemIfSet( FN_PARAM_FIELD_TYPE, |
367 | 0 | false )) |
368 | 0 | nType = static_cast<SwFieldTypesEnum>(pTypeItem->GetValue()); |
369 | 0 | else if (pArgs->GetItemState(FN_PARAM_4, false, &pItem) == SfxItemState::SET) |
370 | 0 | { |
371 | 0 | const OUString& rTypeName = static_cast<const SfxStringItem *>(pItem)->GetValue(); |
372 | 0 | nType = SwFieldTypeFromString(rTypeName); |
373 | 0 | } |
374 | 0 | if( const SfxUInt16Item* pSubtypeItem = pArgs->GetItemIfSet( FN_PARAM_FIELD_SUBTYPE, |
375 | 0 | false )) |
376 | 0 | nSubType = pSubtypeItem->GetValue(); |
377 | 0 | if( const SfxStringItem* pContentItem = pArgs->GetItemIfSet( |
378 | 0 | FN_PARAM_FIELD_CONTENT, false )) |
379 | 0 | aPar2 = pContentItem->GetValue(); |
380 | 0 | if( const SfxUInt32Item* pFormatItem = pArgs->GetItemIfSet( |
381 | 0 | FN_PARAM_FIELD_FORMAT, false )) |
382 | 0 | nFormat = pFormatItem->GetValue(); |
383 | 0 | if( SfxItemState::SET == pArgs->GetItemState( |
384 | 0 | FN_PARAM_3, false, &pItem )) |
385 | 0 | { |
386 | 0 | OUString sTmp = static_cast<const SfxStringItem *>(pItem)->GetValue(); |
387 | 0 | if(!sTmp.isEmpty()) |
388 | 0 | cSeparator = sTmp[0]; |
389 | 0 | } |
390 | 0 | if (pArgs->GetItemState(FN_PARAM_5, false, &pItem) == SfxItemState::SET) |
391 | 0 | { |
392 | | // Wrap the field in the requested container instead of inserting it |
393 | | // directly at the cursor position. |
394 | 0 | const OUString& rWrapper = static_cast<const SfxStringItem *>(pItem)->GetValue(); |
395 | 0 | if (rWrapper == "Footnote") |
396 | 0 | { |
397 | 0 | GetShellPtr()->InsertFootnote(OUString()); |
398 | 0 | } |
399 | 0 | else if (rWrapper == "Endnote") |
400 | 0 | { |
401 | 0 | GetShellPtr()->InsertFootnote(OUString(), /*bEndNote=*/true); |
402 | 0 | } |
403 | 0 | } |
404 | 0 | bool bNeverExpand = false; |
405 | 0 | const SfxBoolItem* pNeverExpand = rReq.GetArg<SfxBoolItem>(FN_PARAM_6); |
406 | 0 | if (pNeverExpand) |
407 | 0 | { |
408 | 0 | bNeverExpand = pNeverExpand->GetValue(); |
409 | 0 | } |
410 | 0 | SwInsertField_Data aData(nType, nSubType, aPar1, aPar2, nFormat, GetShellPtr(), |
411 | 0 | cSeparator, true, bNeverExpand); |
412 | 0 | bRes = aFieldMgr.InsertField( aData ); |
413 | 0 | } |
414 | 0 | else |
415 | 0 | { |
416 | | //#i5788# prevent closing of the field dialog while a modal dialog ( Input field dialog ) is active |
417 | 0 | if(!GetView().GetViewFrame().IsInModalMode()) |
418 | 0 | { |
419 | 0 | SfxViewFrame& rVFrame = GetView().GetViewFrame(); |
420 | 0 | rVFrame.ToggleChildWindow(FN_INSERT_FIELD); |
421 | 0 | bRes = rVFrame.GetChildWindow( nSlot ) != nullptr; |
422 | 0 | Invalidate(rReq.GetSlot()); |
423 | 0 | Invalidate(FN_INSERT_FIELD_CTRL); |
424 | 0 | rReq.Ignore(); |
425 | 0 | } |
426 | 0 | } |
427 | 0 | rReq.SetReturnValue(SfxBoolItem( nSlot, bRes )); |
428 | 0 | } |
429 | 0 | break; |
430 | | |
431 | 0 | case FN_INSERT_REF_FIELD: |
432 | 0 | { |
433 | 0 | SfxViewFrame& rVFrame = GetView().GetViewFrame(); |
434 | 0 | if (!rVFrame.HasChildWindow(FN_INSERT_FIELD)) |
435 | 0 | rVFrame.ToggleChildWindow(FN_INSERT_FIELD); // Show dialog |
436 | | |
437 | | // Switch Fielddlg at a new TabPage |
438 | 0 | sal_uInt16 nId = SwFieldDlgWrapper::GetChildWindowId(); |
439 | 0 | SwFieldDlgWrapper *pWrp = static_cast<SwFieldDlgWrapper*>(rVFrame.GetChildWindow(nId)); |
440 | 0 | if (pWrp) |
441 | 0 | pWrp->ShowReferencePage(); |
442 | 0 | rReq.Ignore(); |
443 | 0 | } |
444 | 0 | break; |
445 | 0 | case FN_DELETE_COMMENT: |
446 | 0 | { |
447 | 0 | const SvxPostItIdItem* pIdItem = rReq.GetArg(SID_ATTR_POSTIT_ID); |
448 | 0 | if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr()) |
449 | 0 | { |
450 | 0 | sal_uInt32 nPostItId = pIdItem->GetValue().toUInt32(); |
451 | 0 | if (lcl_canUserModifyAnnotation(GetView(), nPostItId)) |
452 | 0 | GetView().GetPostItMgr()->Delete(nPostItId); |
453 | 0 | } |
454 | 0 | else if ( GetView().GetPostItMgr() && |
455 | 0 | GetView().GetPostItMgr()->HasActiveSidebarWin() ) |
456 | 0 | { |
457 | 0 | sw::annotation::SwAnnotationWin* pAnnotationWin |
458 | 0 | = GetView().GetPostItMgr()->GetActiveSidebarWin(); |
459 | 0 | if (lcl_canUserModifyAnnotation(GetView(), pAnnotationWin)) |
460 | 0 | GetView().GetPostItMgr()->DeleteActiveSidebarWin(); |
461 | 0 | } |
462 | 0 | break; |
463 | 0 | } |
464 | 0 | case FN_DELETE_COMMENT_THREAD: |
465 | 0 | { |
466 | 0 | const SvxPostItIdItem* pIdItem = rReq.GetArg(SID_ATTR_POSTIT_ID); |
467 | 0 | if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr()) |
468 | 0 | { |
469 | 0 | sal_uInt32 nPostItId = pIdItem->GetValue().toUInt32(); |
470 | 0 | if (lcl_canUserModifyAnnotation(GetView(), nPostItId)) |
471 | 0 | GetView().GetPostItMgr()->DeleteCommentThread(nPostItId); |
472 | 0 | } |
473 | 0 | else if (GetView().GetPostItMgr() && GetView().GetPostItMgr()->HasActiveSidebarWin()) |
474 | 0 | { |
475 | 0 | sw::annotation::SwAnnotationWin* pAnnotationWin |
476 | 0 | = GetView().GetPostItMgr()->GetActiveSidebarWin(); |
477 | 0 | if (lcl_canUserModifyAnnotation(GetView(), pAnnotationWin)) |
478 | 0 | GetView().GetPostItMgr()->DeleteActiveSidebarWin(); |
479 | 0 | } |
480 | 0 | break; |
481 | 0 | } |
482 | 0 | case FN_RESOLVE_NOTE: |
483 | 0 | { |
484 | 0 | const SvxPostItIdItem* pIdItem = rReq.GetArg(SID_ATTR_POSTIT_ID); |
485 | 0 | if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr()) |
486 | 0 | { |
487 | 0 | GetView().GetPostItMgr()->ToggleResolved(pIdItem->GetValue().toUInt32()); |
488 | 0 | } |
489 | 0 | break; |
490 | 0 | } |
491 | 0 | case FN_RESOLVE_NOTE_THREAD: |
492 | 0 | { |
493 | 0 | const SvxPostItIdItem* pIdItem = rReq.GetArg(SID_ATTR_POSTIT_ID); |
494 | 0 | if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr()) |
495 | 0 | { |
496 | 0 | GetView().GetPostItMgr()->ToggleResolvedForThread(pIdItem->GetValue().toUInt32()); |
497 | 0 | } |
498 | 0 | break; |
499 | 0 | } |
500 | 0 | case FN_DELETE_ALL_NOTES: |
501 | 0 | if ( GetView().GetPostItMgr() ) |
502 | 0 | GetView().GetPostItMgr()->Delete(); |
503 | 0 | break; |
504 | 0 | case FN_FORMAT_ALL_NOTES: |
505 | 0 | { |
506 | 0 | SwPostItMgr* pPostItMgr = GetView().GetPostItMgr(); |
507 | 0 | if (pPostItMgr) |
508 | 0 | pPostItMgr->ExecuteFormatAllDialog(GetView()); |
509 | 0 | } |
510 | 0 | break; |
511 | 0 | case FN_DELETE_NOTE_AUTHOR: |
512 | 0 | { |
513 | 0 | const SfxStringItem* pNoteItem = rReq.GetArg<SfxStringItem>(nSlot); |
514 | 0 | if (pNoteItem && GetView().GetPostItMgr() |
515 | 0 | && lcl_canUserModifyAnnotation(GetView(), pNoteItem->GetValue())) |
516 | 0 | GetView().GetPostItMgr()->Delete(pNoteItem->GetValue()); |
517 | 0 | } |
518 | 0 | break; |
519 | 0 | case FN_HIDE_NOTE: |
520 | 0 | if ( GetView().GetPostItMgr() && |
521 | 0 | GetView().GetPostItMgr()->HasActiveSidebarWin() ) |
522 | 0 | { |
523 | 0 | GetView().GetPostItMgr()->HideActiveSidebarWin(); |
524 | 0 | } |
525 | 0 | break; |
526 | 0 | case FN_HIDE_ALL_NOTES: |
527 | 0 | if ( GetView().GetPostItMgr() ) |
528 | 0 | GetView().GetPostItMgr()->Hide(); |
529 | 0 | break; |
530 | 0 | case FN_HIDE_NOTE_AUTHOR: |
531 | 0 | { |
532 | 0 | const SfxStringItem* pNoteItem = rReq.GetArg<SfxStringItem>(nSlot); |
533 | 0 | if ( pNoteItem && GetView().GetPostItMgr() ) |
534 | 0 | GetView().GetPostItMgr()->Hide( pNoteItem->GetValue() ); |
535 | 0 | } |
536 | 0 | break; |
537 | 0 | case FN_REPLY: |
538 | 0 | { |
539 | 0 | const SvxPostItIdItem* pIdItem = rReq.GetArg(SID_ATTR_POSTIT_ID); |
540 | 0 | if (pIdItem && !pIdItem->GetValue().isEmpty()) |
541 | 0 | { |
542 | 0 | SwFieldType* pType = rSh.GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit, OUString(), false); |
543 | 0 | if(pType->FindFormatForPostItId(pIdItem->GetValue().toUInt32())) |
544 | 0 | { |
545 | 0 | auto pMgr = GetView().GetPostItMgr(); |
546 | 0 | auto pWin = pMgr->GetAnnotationWin(pIdItem->GetValue().toUInt32()); |
547 | 0 | if(pWin) |
548 | 0 | { |
549 | 0 | if (const SvxPostItTextItem* pHtmlItem = rReq.GetArg(SID_ATTR_POSTIT_HTML)) |
550 | 0 | { |
551 | 0 | SwDocShell* pDocSh = GetView().GetDocShell(); |
552 | 0 | Outliner aOutliner(&pDocSh->GetPool(), OutlinerMode::TextObject); |
553 | 0 | SwPostItHelper::ImportHTML(aOutliner, pHtmlItem->GetValue()); |
554 | 0 | if (std::optional<OutlinerParaObject> oPara = aOutliner.CreateParaObject()) |
555 | 0 | pMgr->RegisterAnswer(oPara.value()); |
556 | 0 | } |
557 | |
|
558 | 0 | OUString sText; |
559 | 0 | if(const auto pTextItem = rReq.GetArg(SID_ATTR_POSTIT_TEXT)) |
560 | 0 | sText = pTextItem->GetValue(); |
561 | 0 | pMgr->RegisterAnswerText(sText); |
562 | 0 | pWin->ExecuteCommand(nSlot); |
563 | 0 | } |
564 | 0 | } |
565 | 0 | } |
566 | 0 | } |
567 | 0 | break; |
568 | 0 | case FN_POSTIT: |
569 | 0 | { |
570 | 0 | rSh.InsertPostIt(aFieldMgr, rReq); |
571 | 0 | } |
572 | 0 | break; |
573 | 0 | case SID_EDIT_POSTIT: |
574 | 0 | { |
575 | 0 | const SvxPostItIdItem* pIdItem = rReq.GetArg(SID_ATTR_POSTIT_ID); |
576 | 0 | if (pIdItem && !pIdItem->GetValue().isEmpty()) |
577 | 0 | { |
578 | 0 | sw::annotation::SwAnnotationWin* pAnnotationWin = GetView().GetPostItMgr()->GetAnnotationWin(pIdItem->GetValue().toUInt32()); |
579 | 0 | if (pAnnotationWin && lcl_canUserModifyAnnotation(GetView(), pAnnotationWin)) |
580 | 0 | { |
581 | 0 | if (const SvxPostItTextItem* pHtmlItem = rReq.GetArg(SID_ATTR_POSTIT_HTML)) |
582 | 0 | pAnnotationWin->UpdateHTML(pHtmlItem->GetValue()); |
583 | 0 | else |
584 | 0 | { |
585 | 0 | const SvxPostItTextItem* pTextItem = rReq.GetArg(SID_ATTR_POSTIT_TEXT); |
586 | 0 | OUString sText; |
587 | 0 | if (pTextItem) |
588 | 0 | sText = pTextItem->GetValue(); |
589 | 0 | pAnnotationWin->UpdateText(sText); |
590 | 0 | } |
591 | | |
592 | | // explicit state update to get the Undo state right |
593 | 0 | GetView().AttrChangedNotify(nullptr); |
594 | 0 | } |
595 | 0 | } |
596 | 0 | } |
597 | 0 | break; |
598 | 0 | case FN_PROMOTE_COMMENT: |
599 | 0 | { |
600 | 0 | const SvxPostItIdItem* pIdItem = rReq.GetArg(SID_ATTR_POSTIT_ID); |
601 | 0 | if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr()) |
602 | 0 | { |
603 | 0 | GetView().GetPostItMgr()->PromoteToRoot(pIdItem->GetValue().toUInt32()); |
604 | 0 | } |
605 | 0 | break; |
606 | 0 | } |
607 | 0 | case FN_REDLINE_COMMENT: |
608 | 0 | { |
609 | 0 | const SwRangeRedline *pRedline = rSh.GetCurrRedline(); |
610 | 0 | SwDoc *pDoc = rSh.GetDoc(); |
611 | | // If index is specified, goto and select the appropriate redline |
612 | 0 | if (pArgs && pArgs->GetItemState(nSlot, false, &pItem) == SfxItemState::SET) |
613 | 0 | { |
614 | 0 | const sal_uInt32 nChangeId = static_cast<const SfxUInt32Item*>(pItem)->GetValue(); |
615 | 0 | const SwRedlineTable& rRedlineTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable(); |
616 | 0 | for (SwRedlineTable::size_type nRedline = 0; nRedline < rRedlineTable.size(); ++nRedline) |
617 | 0 | { |
618 | 0 | if (nChangeId == rRedlineTable[nRedline]->GetId()) |
619 | 0 | pRedline = rSh.GotoRedline(nRedline, true); |
620 | 0 | } |
621 | 0 | } |
622 | |
|
623 | 0 | OUString sCommentText; |
624 | 0 | const SfxStringItem* pTextItem = rReq.GetArg(SID_ATTR_POSTIT_TEXT); |
625 | 0 | if (pTextItem) |
626 | 0 | sCommentText = pTextItem->GetValue(); |
627 | |
|
628 | 0 | if (pRedline) |
629 | 0 | { |
630 | | // In case of LOK and comment text is already provided, skip |
631 | | // dialog creation and just change the redline comment directly |
632 | 0 | if (comphelper::LibreOfficeKit::isActive() && !sCommentText.isEmpty()) |
633 | 0 | { |
634 | 0 | rSh.SetRedlineComment(sCommentText); |
635 | 0 | GetView().AttrChangedNotify(nullptr); |
636 | 0 | MaybeNotifyRedlineModification(const_cast<SwRangeRedline&>(*pRedline), pRedline->GetDoc()); |
637 | 0 | break; |
638 | 0 | } |
639 | | |
640 | 0 | OUString sComment = convertLineEnd(pRedline->GetComment(), GetSystemLineEnd()); |
641 | |
|
642 | 0 | bool bTravel = false; |
643 | |
|
644 | 0 | SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); |
645 | 0 | ::DialogGetRanges fnGetRange = pFact->GetDialogGetRangesFunc(); |
646 | 0 | SfxItemSet aSet(GetPool(), fnGetRange()); |
647 | 0 | aSet.Put(SvxPostItTextItem(sComment, SID_ATTR_POSTIT_TEXT)); |
648 | 0 | aSet.Put(SvxPostItAuthorItem(pRedline->GetAuthorString(), SID_ATTR_POSTIT_AUTHOR)); |
649 | |
|
650 | 0 | aSet.Put( SvxPostItDateItem( GetAppLangDateTimeString( |
651 | 0 | pRedline->GetRedlineData().GetTimeStamp() ), |
652 | 0 | SID_ATTR_POSTIT_DATE )); |
653 | | |
654 | | // Traveling only if more than one field. |
655 | 0 | rSh.StartAction(); |
656 | |
|
657 | 0 | rSh.Push(); |
658 | 0 | const SwRangeRedline *pActRed = rSh.SelPrevRedline(); |
659 | |
|
660 | 0 | if (pActRed == pRedline) |
661 | 0 | { // New cursor is at the beginning of the current redlines. |
662 | 0 | rSh.Pop(); // Throw old cursor away |
663 | 0 | rSh.Push(); |
664 | 0 | pActRed = rSh.SelPrevRedline(); |
665 | 0 | } |
666 | |
|
667 | 0 | bool bPrev = pActRed != nullptr; |
668 | 0 | rSh.Pop(SwCursorShell::PopMode::DeleteCurrent); |
669 | 0 | rSh.EndAction(); |
670 | |
|
671 | 0 | rSh.ClearMark(); |
672 | | // Select current redline. |
673 | 0 | pActRed = rSh.SelNextRedline(); |
674 | 0 | if (pActRed != pRedline) |
675 | 0 | rSh.SelPrevRedline(); |
676 | |
|
677 | 0 | rSh.StartAction(); |
678 | 0 | rSh.Push(); |
679 | 0 | pActRed = rSh.SelNextRedline(); |
680 | 0 | bool bNext = pActRed != nullptr; |
681 | 0 | rSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore cursor position |
682 | |
|
683 | 0 | if( rSh.IsCursorPtAtEnd() ) |
684 | 0 | rSh.SwapPam(); |
685 | |
|
686 | 0 | rSh.EndAction(); |
687 | |
|
688 | 0 | bTravel |= bNext || bPrev; |
689 | |
|
690 | 0 | SvxAbstractDialogFactory* pFact2 = SvxAbstractDialogFactory::Create(); |
691 | 0 | ScopedVclPtr<AbstractSvxPostItDialog> pDlg(pFact2->CreateSvxPostItDialog(GetView().GetFrameWeld(), aSet, bTravel)); |
692 | 0 | pDlg->HideAuthor(); |
693 | |
|
694 | 0 | pDlg->SetText(lcl_BuildTitleWithRedline(pRedline)); |
695 | |
|
696 | 0 | if (bTravel) |
697 | 0 | { |
698 | 0 | pDlg->EnableTravel(bNext, bPrev); |
699 | 0 | pDlg->SetPrevHdl(LINK(this, SwTextShell, RedlinePrevHdl)); |
700 | 0 | pDlg->SetNextHdl(LINK(this, SwTextShell, RedlineNextHdl)); |
701 | 0 | } |
702 | |
|
703 | 0 | SwViewShell::SetCareDialog(pDlg->GetDialog()); |
704 | 0 | g_bNoInterrupt = true; |
705 | |
|
706 | 0 | if ( pDlg->Execute() == RET_OK ) |
707 | 0 | { |
708 | 0 | const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); |
709 | 0 | OUString sMsg(pOutSet->Get(SID_ATTR_POSTIT_TEXT).GetValue()); |
710 | | |
711 | | // Insert or change a comment |
712 | 0 | rSh.SetRedlineComment(sMsg); |
713 | 0 | } |
714 | |
|
715 | 0 | SwViewShell::SetCareDialog(nullptr); |
716 | 0 | pDlg.disposeAndClear(); |
717 | 0 | g_bNoInterrupt = false; |
718 | 0 | rSh.ClearMark(); |
719 | 0 | GetView().AttrChangedNotify(nullptr); |
720 | 0 | } |
721 | 0 | } |
722 | 0 | break; |
723 | | |
724 | 0 | case FN_JAVAEDIT: |
725 | 0 | { |
726 | 0 | OUString aType, aText; |
727 | 0 | bool bIsUrl=false; |
728 | 0 | bool bNew=false; |
729 | 0 | bool bUpdate = false; |
730 | 0 | SwFieldMgr aMgr; |
731 | 0 | if ( pItem ) |
732 | 0 | { |
733 | 0 | aText = static_cast<const SfxStringItem*>(pItem)->GetValue(); |
734 | 0 | const SfxStringItem* pType = rReq.GetArg<SfxStringItem>(FN_PARAM_2); |
735 | 0 | const SfxBoolItem* pIsUrl = rReq.GetArg<SfxBoolItem>(FN_PARAM_1); |
736 | 0 | if ( pType ) |
737 | 0 | aType = pType->GetValue(); |
738 | 0 | if ( pIsUrl ) |
739 | 0 | bIsUrl = pIsUrl->GetValue(); |
740 | |
|
741 | 0 | SwScriptField* pField = static_cast<SwScriptField*>(aMgr.GetCurField()); |
742 | 0 | bNew = !pField || (pField->GetTyp()->Which() != SwFieldIds::Script); |
743 | 0 | bUpdate = pField && ( bIsUrl != pField->IsCodeURL() || pField->GetPar2() != aType || pField->GetPar1() != aText ); |
744 | 0 | } |
745 | 0 | else |
746 | 0 | { |
747 | 0 | SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); |
748 | 0 | ScopedVclPtr<AbstractJavaEditDialog> pDlg(pFact->CreateJavaEditDialog(GetView().GetFrameWeld(), &rSh)); |
749 | 0 | if ( pDlg->Execute() ) |
750 | 0 | { |
751 | 0 | aType = pDlg->GetScriptType(); |
752 | 0 | aText = pDlg->GetScriptText(); |
753 | 0 | bIsUrl = pDlg->IsUrl(); |
754 | 0 | bNew = pDlg->IsNew(); |
755 | 0 | bUpdate = pDlg->IsUpdate(); |
756 | 0 | rReq.AppendItem( SfxStringItem( FN_JAVAEDIT, aText ) ); |
757 | 0 | rReq.AppendItem( SfxStringItem( FN_PARAM_2, aType ) ); |
758 | 0 | rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bIsUrl ) ); |
759 | 0 | } |
760 | 0 | } |
761 | |
|
762 | 0 | if( bNew ) |
763 | 0 | { |
764 | 0 | SwInsertField_Data aData(SwFieldTypesEnum::Script, 0, aType, aText, bIsUrl ? 1 : 0); |
765 | 0 | aMgr.InsertField(aData); |
766 | 0 | rReq.Done(); |
767 | 0 | } |
768 | 0 | else if( bUpdate ) |
769 | 0 | { |
770 | 0 | aMgr.UpdateCurField( bIsUrl ? 1 : 0, aType, aText ); |
771 | 0 | rSh.SetUndoNoResetModified(); |
772 | 0 | rReq.Done(); |
773 | 0 | } |
774 | 0 | else |
775 | 0 | rReq.Ignore(); |
776 | 0 | } |
777 | 0 | break; |
778 | | |
779 | 0 | case FN_INSERT_FLD_DATE : |
780 | 0 | case FN_INSERT_FLD_DATE_VAR: |
781 | 0 | { |
782 | 0 | nInsertType = SwFieldTypesEnum::Date; |
783 | 0 | nInsertSubType = nSlot == FN_INSERT_FLD_DATE ? 0 : 1; |
784 | 0 | bIsText = false; |
785 | | // use long date format for Hungarian |
786 | 0 | SwPaM* pCursorPos = rSh.GetCursor(); |
787 | 0 | if( pCursorPos ) |
788 | 0 | { |
789 | 0 | LanguageType nLang = pCursorPos->GetPoint()->GetNode().GetTextNode()->GetLang(pCursorPos->GetPoint()->GetContentIndex()); |
790 | 0 | if (nLang == LANGUAGE_HUNGARIAN) |
791 | 0 | nInsertFormat = rSh.GetNumberFormatter()->GetFormatIndex(NF_DATE_SYSTEM_LONG, nLang); |
792 | 0 | } |
793 | 0 | goto FIELD_INSERT; |
794 | 0 | } |
795 | 0 | case FN_INSERT_FLD_TIME : |
796 | 0 | case FN_INSERT_FLD_TIME_VAR: |
797 | 0 | nInsertType = SwFieldTypesEnum::Time; |
798 | 0 | nInsertSubType = nSlot == FN_INSERT_FLD_TIME ? 0 : 1; |
799 | 0 | bIsText = false; |
800 | 0 | goto FIELD_INSERT; |
801 | 0 | case FN_INSERT_FLD_PGNUMBER: |
802 | 0 | nInsertType = SwFieldTypesEnum::PageNumber; |
803 | 0 | nInsertFormat = SVX_NUM_PAGEDESC; // Like page template |
804 | 0 | bIsText = false; |
805 | 0 | goto FIELD_INSERT; |
806 | 0 | case FN_INSERT_FLD_PGCOUNT : |
807 | 0 | case FN_INSERT_FLD_RANGE_PGCOUNT: |
808 | 0 | nInsertType = SwFieldTypesEnum::DocumentStatistics; |
809 | 0 | nInsertSubType = FN_INSERT_FLD_RANGE_PGCOUNT == nSlot ? 1 : 0; |
810 | 0 | bIsText = false; |
811 | 0 | nInsertFormat = SVX_NUM_PAGEDESC; |
812 | 0 | goto FIELD_INSERT; |
813 | 0 | case FN_INSERT_FLD_TOPIC : |
814 | 0 | nInsertType = SwFieldTypesEnum::DocumentInfo; |
815 | 0 | nInsertSubType = static_cast<sal_uInt16>(SwDocInfoSubType::Subject); |
816 | 0 | goto FIELD_INSERT; |
817 | 0 | case FN_INSERT_FLD_TITLE : |
818 | 0 | nInsertType = SwFieldTypesEnum::DocumentInfo; |
819 | 0 | nInsertSubType = static_cast<sal_uInt16>(SwDocInfoSubType::Title); |
820 | 0 | goto FIELD_INSERT; |
821 | 0 | case FN_INSERT_FLD_AUTHOR : |
822 | 0 | nInsertType = SwFieldTypesEnum::DocumentInfo; |
823 | 0 | nInsertSubType = static_cast<sal_uInt16>(SwDocInfoSubType::Create | SwDocInfoSubType::SubAuthor); |
824 | |
|
825 | 0 | FIELD_INSERT: |
826 | 0 | { |
827 | | //format conversion should only be done for number formatter formats |
828 | 0 | if(!nInsertFormat) |
829 | 0 | nInsertFormat = aFieldMgr.GetDefaultFormat(nInsertType, bIsText, rSh.GetNumberFormatter()); |
830 | 0 | SwInsertField_Data aData(nInsertType, nInsertSubType, |
831 | 0 | OUString(), OUString(), nInsertFormat); |
832 | 0 | aFieldMgr.InsertField(aData); |
833 | 0 | rReq.Done(); |
834 | 0 | } |
835 | 0 | break; |
836 | | |
837 | 0 | case FN_INSERT_TEXT_FORMFIELD: |
838 | 0 | { |
839 | 0 | OUString aFieldType(ODF_FORMTEXT); |
840 | 0 | const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1); |
841 | 0 | if (pFieldType) |
842 | 0 | { |
843 | | // Allow overwriting the default type. |
844 | 0 | aFieldType = pFieldType->GetValue(); |
845 | 0 | } |
846 | |
|
847 | 0 | OUString aFieldCode; |
848 | 0 | const SfxStringItem* pFieldCode = rReq.GetArg<SfxStringItem>(FN_PARAM_2); |
849 | 0 | if (pFieldCode) |
850 | 0 | { |
851 | | // Allow specifying a field code/command. |
852 | 0 | aFieldCode = pFieldCode->GetValue(); |
853 | 0 | } |
854 | |
|
855 | 0 | if (rSh.HasReadonlySel()) |
856 | 0 | { |
857 | | // Inform the user that the request has been ignored. |
858 | 0 | auto xInfo = std::make_shared<weld::GenericDialogController>( |
859 | 0 | GetView().GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", |
860 | 0 | "InfoReadonlyDialog"); |
861 | 0 | weld::DialogController::runAsync(xInfo, [](sal_Int32 /*nResult*/) {}); |
862 | 0 | break; |
863 | 0 | } |
864 | | |
865 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); |
866 | |
|
867 | 0 | SwPaM* pCursorPos = rSh.GetCursor(); |
868 | 0 | if(pCursorPos) |
869 | 0 | { |
870 | | // Insert five En Space into the text field so the field has extent |
871 | 0 | OUString aFieldResult(vEnSpaces); |
872 | 0 | const SfxStringItem* pFieldResult = rReq.GetArg<SfxStringItem>(FN_PARAM_3); |
873 | 0 | if (pFieldResult) |
874 | 0 | { |
875 | | // Allow specifying a field result / expanded value. |
876 | 0 | aFieldResult = pFieldResult->GetValue(); |
877 | 0 | } |
878 | |
|
879 | 0 | const SfxStringItem* pWrapper = rReq.GetArg<SfxStringItem>(FN_PARAM_4); |
880 | 0 | if (pWrapper) |
881 | 0 | { |
882 | | // Wrap the fieldmark in the requested container instead of inserting it |
883 | | // directly at the cursor position. |
884 | 0 | OUString aWrapper = pWrapper->GetValue(); |
885 | 0 | if (aWrapper == "Footnote") |
886 | 0 | { |
887 | 0 | rSh.InsertFootnote(OUString()); |
888 | 0 | } |
889 | 0 | else if (aWrapper == "Endnote") |
890 | 0 | { |
891 | | // It's important that there is no Start/EndAction() around this, so the |
892 | | // inner EndAction() triggers a layout update and the cursor can jump to the |
893 | | // created SwFootnoteFrame. |
894 | 0 | rSh.InsertFootnote(OUString(), /*bEndNote=*/true); |
895 | 0 | } |
896 | 0 | } |
897 | | |
898 | | // Don't update the layout after inserting content and before deleting temporary |
899 | | // text nodes. |
900 | 0 | rSh.StartAction(); |
901 | | |
902 | | // Split node to remember where the start position is. |
903 | 0 | bool bSuccess = rSh.GetDoc()->getIDocumentContentOperations().SplitNode( |
904 | 0 | *pCursorPos->GetPoint(), false); |
905 | 0 | if(bSuccess) |
906 | 0 | { |
907 | 0 | SwPaM aFieldPam(*pCursorPos->GetPoint()); |
908 | 0 | aFieldPam.Move(fnMoveBackward, GoInContent); |
909 | 0 | if (pFieldResult) |
910 | 0 | { |
911 | | // Paste HTML content. |
912 | 0 | SwTranslateHelper::PasteHTMLToPaM(rSh, pCursorPos, aFieldResult.toUtf8()); |
913 | 0 | if (pCursorPos->GetPoint()->GetContentIndex() == 0) |
914 | 0 | { |
915 | | // The paste created a last empty text node, remove it. |
916 | 0 | SwPaM aPam(*pCursorPos->GetPoint()); |
917 | 0 | aPam.SetMark(); |
918 | 0 | aPam.Move(fnMoveBackward, GoInContent); |
919 | 0 | rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPam); |
920 | 0 | } |
921 | 0 | } |
922 | 0 | else |
923 | 0 | { |
924 | | // Insert default placeholder. |
925 | 0 | rSh.GetDoc()->getIDocumentContentOperations().InsertString(*pCursorPos, |
926 | 0 | aFieldResult); |
927 | 0 | } |
928 | | // Undo the above SplitNode(). |
929 | 0 | aFieldPam.SetMark(); |
930 | 0 | aFieldPam.Move(fnMoveForward, GoInContent); |
931 | 0 | rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aFieldPam); |
932 | 0 | *aFieldPam.GetMark() = *pCursorPos->GetPoint(); |
933 | |
|
934 | 0 | IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess(); |
935 | 0 | sw::mark::Fieldmark* pFieldmark = pMarksAccess->makeFieldBookmark( |
936 | 0 | aFieldPam, SwMarkName(), aFieldType, aFieldPam.Start()); |
937 | 0 | if (pFieldmark && !aFieldCode.isEmpty()) |
938 | 0 | { |
939 | 0 | pFieldmark->GetParameters()->insert( |
940 | 0 | std::pair<OUString, uno::Any>(ODF_CODE_PARAM, uno::Any(aFieldCode))); |
941 | 0 | } |
942 | 0 | } |
943 | 0 | rSh.EndAction(); |
944 | 0 | } |
945 | |
|
946 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); |
947 | 0 | rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO ); |
948 | 0 | } |
949 | 0 | break; |
950 | 0 | case FN_INSERT_CHECKBOX_FORMFIELD: |
951 | 0 | { |
952 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); |
953 | |
|
954 | 0 | SwPaM* pCursorPos = rSh.GetCursor(); |
955 | 0 | if(pCursorPos) |
956 | 0 | { |
957 | 0 | IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess(); |
958 | 0 | pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, SwMarkName(), ODF_FORMCHECKBOX); |
959 | 0 | } |
960 | |
|
961 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); |
962 | 0 | rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO ); |
963 | 0 | } |
964 | 0 | break; |
965 | 0 | case FN_INSERT_DROPDOWN_FORMFIELD: |
966 | 0 | { |
967 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); |
968 | |
|
969 | 0 | SwPaM* pCursorPos = rSh.GetCursor(); |
970 | 0 | if(pCursorPos) |
971 | 0 | { |
972 | 0 | IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess(); |
973 | 0 | pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, SwMarkName(), ODF_FORMDROPDOWN); |
974 | 0 | } |
975 | |
|
976 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); |
977 | 0 | rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO ); |
978 | 0 | } |
979 | 0 | break; |
980 | 0 | case FN_INSERT_DATE_FORMFIELD: |
981 | 0 | { |
982 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); |
983 | |
|
984 | 0 | SwPaM* pCursorPos = rSh.GetCursor(); |
985 | 0 | if(pCursorPos) |
986 | 0 | { |
987 | | // Insert five enspaces into the text field so the field has extent |
988 | 0 | bool bSuccess = rSh.GetDoc()->getIDocumentContentOperations().InsertString(*pCursorPos, vEnSpaces); |
989 | 0 | if(bSuccess) |
990 | 0 | { |
991 | 0 | IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess(); |
992 | 0 | SwPaM aFieldPam(pCursorPos->GetPoint()->GetNode(), pCursorPos->GetPoint()->GetContentIndex() - ODF_FORMFIELD_DEFAULT_LENGTH, |
993 | 0 | pCursorPos->GetPoint()->GetNode(), pCursorPos->GetPoint()->GetContentIndex()); |
994 | 0 | sw::mark::Fieldmark* pFieldBM = pMarksAccess->makeFieldBookmark(aFieldPam, SwMarkName(), ODF_FORMDATE, |
995 | 0 | aFieldPam.Start()); |
996 | | |
997 | | // Use a default date format and language |
998 | 0 | sw::mark::Fieldmark::parameter_map_t* pParameters = pFieldBM->GetParameters(); |
999 | 0 | SvNumberFormatter* pFormatter = rSh.GetDoc()->GetNumberFormatter(); |
1000 | 0 | sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(SvNumFormatType::DATE); |
1001 | 0 | const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat); |
1002 | |
|
1003 | 0 | (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring(); |
1004 | 0 | (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(pFormat->GetLanguage()).getBcp47(); |
1005 | 0 | } |
1006 | 0 | } |
1007 | |
|
1008 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); |
1009 | 0 | rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO ); |
1010 | 0 | } |
1011 | 0 | break; |
1012 | 0 | case FN_UPDATE_TEXT_FORMFIELDS: |
1013 | 0 | { |
1014 | | // This updates multiple fieldmarks in a document, based on their field name & field command |
1015 | | // prefix. |
1016 | 0 | OUString aFieldType; |
1017 | 0 | const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1); |
1018 | 0 | if (pFieldType) |
1019 | 0 | { |
1020 | 0 | aFieldType = pFieldType->GetValue(); |
1021 | 0 | } |
1022 | 0 | OUString aFieldCommandPrefix; |
1023 | 0 | const SfxStringItem* pFieldCommandPrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2); |
1024 | 0 | if (pFieldCommandPrefix) |
1025 | 0 | { |
1026 | 0 | aFieldCommandPrefix = pFieldCommandPrefix->GetValue(); |
1027 | 0 | } |
1028 | 0 | uno::Sequence<beans::PropertyValues> aFields; |
1029 | 0 | const SfxUnoAnyItem* pFields = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_3); |
1030 | 0 | if (pFields) |
1031 | 0 | { |
1032 | 0 | pFields->GetValue() >>= aFields; |
1033 | 0 | } |
1034 | |
|
1035 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_FORM_FIELDS, nullptr); |
1036 | 0 | rSh.StartAction(); |
1037 | |
|
1038 | 0 | IDocumentMarkAccess* pMarkAccess = rSh.GetDoc()->getIDocumentMarkAccess(); |
1039 | 0 | sal_Int32 nFieldIndex = 0; |
1040 | 0 | for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it) |
1041 | 0 | { |
1042 | 0 | sw::mark::Fieldmark* pFieldmark = *it; |
1043 | 0 | assert(pFieldmark); |
1044 | 0 | if (pFieldmark->GetFieldname() != aFieldType) |
1045 | 0 | { |
1046 | 0 | continue; |
1047 | 0 | } |
1048 | | |
1049 | 0 | auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM); |
1050 | 0 | if (itParam == pFieldmark->GetParameters()->end()) |
1051 | 0 | { |
1052 | 0 | continue; |
1053 | 0 | } |
1054 | | |
1055 | 0 | OUString aCommand; |
1056 | 0 | itParam->second >>= aCommand; |
1057 | 0 | if (!aCommand.startsWith(aFieldCommandPrefix)) |
1058 | 0 | { |
1059 | 0 | continue; |
1060 | 0 | } |
1061 | | |
1062 | 0 | if (aFields.getLength() <= nFieldIndex) |
1063 | 0 | { |
1064 | 0 | continue; |
1065 | 0 | } |
1066 | | |
1067 | 0 | comphelper::SequenceAsHashMap aMap(aFields[nFieldIndex++]); |
1068 | 0 | itParam->second = aMap[u"FieldCommand"_ustr]; |
1069 | 0 | SwPaM aPaM(pFieldmark->GetMarkPos(), pFieldmark->GetOtherMarkPos()); |
1070 | 0 | aPaM.Normalize(); |
1071 | | // Skip field start & separator. |
1072 | 0 | aPaM.GetPoint()->AdjustContent(2); |
1073 | | // Skip field end. |
1074 | 0 | aPaM.GetMark()->AdjustContent(-1); |
1075 | 0 | rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPaM); |
1076 | 0 | OUString aFieldResult; |
1077 | 0 | aMap[u"FieldResult"_ustr] >>= aFieldResult; |
1078 | 0 | SwTranslateHelper::PasteHTMLToPaM(rSh, &aPaM, aFieldResult.toUtf8()); |
1079 | 0 | } |
1080 | |
|
1081 | 0 | rSh.EndAction(); |
1082 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_FORM_FIELDS, nullptr); |
1083 | 0 | } |
1084 | 0 | break; |
1085 | 0 | case FN_DELETE_TEXT_FORMFIELDS: |
1086 | 0 | { |
1087 | | // This deletes all fieldmarks that match the provided field type & field command prefix. |
1088 | 0 | OUString aFieldType; |
1089 | 0 | const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1); |
1090 | 0 | if (pFieldType) |
1091 | 0 | { |
1092 | 0 | aFieldType = pFieldType->GetValue(); |
1093 | 0 | } |
1094 | 0 | OUString aFieldCommandPrefix; |
1095 | 0 | const SfxStringItem* pFieldCommandPrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2); |
1096 | 0 | if (pFieldCommandPrefix) |
1097 | 0 | { |
1098 | 0 | aFieldCommandPrefix = pFieldCommandPrefix->GetValue(); |
1099 | 0 | } |
1100 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_FORM_FIELDS, nullptr); |
1101 | 0 | rSh.StartAction(); |
1102 | |
|
1103 | 0 | IDocumentMarkAccess* pMarkAccess = rSh.GetDoc()->getIDocumentMarkAccess(); |
1104 | 0 | std::vector<sw::mark::MarkBase*> aRemovals; |
1105 | 0 | for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it) |
1106 | 0 | { |
1107 | 0 | sw::mark::Fieldmark* pFieldmark = *it; |
1108 | 0 | assert(pFieldmark); |
1109 | 0 | if (pFieldmark->GetFieldname() != aFieldType) |
1110 | 0 | { |
1111 | 0 | continue; |
1112 | 0 | } |
1113 | | |
1114 | 0 | if (!aFieldCommandPrefix.isEmpty()) |
1115 | 0 | { |
1116 | 0 | auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM); |
1117 | 0 | if (itParam == pFieldmark->GetParameters()->end()) |
1118 | 0 | { |
1119 | 0 | continue; |
1120 | 0 | } |
1121 | | |
1122 | 0 | OUString aCommand; |
1123 | 0 | itParam->second >>= aCommand; |
1124 | 0 | if (!aCommand.startsWith(aFieldCommandPrefix)) |
1125 | 0 | { |
1126 | 0 | continue; |
1127 | 0 | } |
1128 | 0 | } |
1129 | | |
1130 | 0 | aRemovals.push_back(pFieldmark); |
1131 | 0 | } |
1132 | |
|
1133 | 0 | for (const auto& pMark : aRemovals) |
1134 | 0 | { |
1135 | 0 | pMarkAccess->deleteMark(pMark); |
1136 | 0 | } |
1137 | |
|
1138 | 0 | rSh.EndAction(); |
1139 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_FORM_FIELDS, nullptr); |
1140 | 0 | } |
1141 | 0 | break; |
1142 | 0 | case FN_PGNUMBER_WIZARD: |
1143 | 0 | { |
1144 | 0 | SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); |
1145 | 0 | VclPtr<AbstractSwPageNumberDlg> pDlg( |
1146 | 0 | pFact->CreateSwPageNumberDlg(GetView().GetFrameWeld())); |
1147 | 0 | auto pShell = GetShellPtr(); |
1148 | |
|
1149 | 0 | const SwPageDesc& rCurrDesc = rSh.GetPageDesc(rSh.GetCurPageDesc()); |
1150 | 0 | pDlg->SetPageNumberType(rCurrDesc.GetNumType().GetNumberingType()); |
1151 | |
|
1152 | 0 | pDlg->StartExecuteAsync([pShell, &rSh, pDlg](int nResult) { |
1153 | 0 | if ( nResult == RET_OK ) |
1154 | 0 | { |
1155 | 0 | auto& rDoc = *rSh.GetDoc(); |
1156 | |
|
1157 | 0 | rSh.LockView(true); |
1158 | 0 | rSh.StartAllAction(); |
1159 | 0 | rSh.SwCursorShell::Push(); |
1160 | 0 | rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_PAGE_NUMBER, nullptr); |
1161 | |
|
1162 | 0 | const size_t nPageDescIndex = rSh.GetCurPageDesc(); |
1163 | 0 | const SwPageDesc& rDesc = rSh.GetPageDesc(nPageDescIndex); |
1164 | 0 | const bool bHeader = !pDlg->GetPageNumberPosition(); |
1165 | 0 | const bool bHeaderAlreadyOn = rDesc.GetMaster().GetHeader().IsActive(); |
1166 | 0 | const bool bFooterAlreadyOn = rDesc.GetMaster().GetFooter().IsActive(); |
1167 | 0 | const bool bIsSinglePage = rDesc.GetFollow() != &rDesc; |
1168 | 0 | const size_t nMirrorPagesNeeded = rDesc.IsFirstShared() ? 2 : 3; |
1169 | 0 | const OUString sBookmarkName(OUString::Concat("PageNumWizard_") |
1170 | 0 | + (bHeader ? "HEADER" : "FOOTER") + "_" + rDesc.GetName().toString()); |
1171 | 0 | IDocumentMarkAccess& rIDMA = *rSh.getIDocumentMarkAccess(); |
1172 | | |
1173 | | // Allow wizard to be re-run: delete previously wizard-inserted page number. |
1174 | | // Try before creating non-shared header: avoid copying ODD bookmark onto EVEN page. |
1175 | 0 | SwMarkName sBookmarkOddPage(sBookmarkName + OUString::number(rSh.GetVirtPageNum())); |
1176 | 0 | auto ppMark = rIDMA.findMark(sBookmarkOddPage); |
1177 | 0 | if (ppMark != rIDMA.getAllMarksEnd() && *ppMark) |
1178 | 0 | { |
1179 | 0 | SwPaM aDeleteOldPageNum((*ppMark)->GetMarkStart(), (*ppMark)->GetMarkEnd()); |
1180 | 0 | rDoc.getIDocumentContentOperations().DeleteAndJoin(aDeleteOldPageNum); |
1181 | 0 | } |
1182 | |
|
1183 | 0 | SwPageDesc aNewDesc(rDesc); |
1184 | 0 | bool bChangePageDesc = false; |
1185 | 0 | if (pDlg->GetPageNumberType() != aNewDesc.GetNumType().GetNumberingType()) |
1186 | 0 | { |
1187 | 0 | bChangePageDesc = true; |
1188 | 0 | SvxNumberType aNewType(rDesc.GetNumType()); |
1189 | 0 | aNewType.SetNumberingType(pDlg->GetPageNumberType()); |
1190 | 0 | aNewDesc.SetNumType(aNewType); |
1191 | 0 | } |
1192 | | |
1193 | | // Insert header/footer |
1194 | 0 | if ((bHeader && !bHeaderAlreadyOn) || (!bHeader && !bFooterAlreadyOn)) |
1195 | 0 | { |
1196 | 0 | bChangePageDesc = true; |
1197 | 0 | SwFrameFormat &rMaster = aNewDesc.GetMaster(); |
1198 | 0 | if (bHeader) |
1199 | 0 | rMaster.SetFormatAttr(SwFormatHeader(/*On=*/true)); |
1200 | 0 | else |
1201 | 0 | rMaster.SetFormatAttr(SwFormatFooter(/*On=*/true)); |
1202 | | |
1203 | | // Init copied from ChangeHeaderOrFooter: keep in sync |
1204 | 0 | constexpr tools::Long constTwips_5mm = o3tl::toTwips(5, o3tl::Length::mm); |
1205 | 0 | const SvxULSpaceItem aUL(bHeader ? 0 : constTwips_5mm, |
1206 | 0 | bHeader ? constTwips_5mm : 0, |
1207 | 0 | RES_UL_SPACE); |
1208 | 0 | const XFillStyleItem aFill(drawing::FillStyle_NONE); |
1209 | 0 | SwFrameFormat& rFormat |
1210 | 0 | = bHeader |
1211 | 0 | ? const_cast<SwFrameFormat&>(*rMaster.GetHeader().GetHeaderFormat()) |
1212 | 0 | : const_cast<SwFrameFormat&>(*rMaster.GetFooter().GetFooterFormat()); |
1213 | 0 | rFormat.SetFormatAttr(aUL); |
1214 | 0 | rFormat.SetFormatAttr(aFill); |
1215 | |
|
1216 | 0 | if (pDlg->GetFitIntoExistingMargins()) |
1217 | 0 | { |
1218 | 0 | SvxULSpaceItem aPageUL(aNewDesc.GetMaster().GetULSpace()); |
1219 | 0 | tools::Long nPageMargin = bHeader ? aPageUL.GetUpper() : aPageUL.GetLower(); |
1220 | | |
1221 | | // most printers can't print to paper edge - use arbitrary ~14pt as minimum |
1222 | 0 | if (nPageMargin > constTwips_5mm) |
1223 | 0 | { |
1224 | | // reduce existing margin by the "Spacing" |
1225 | 0 | nPageMargin -= constTwips_5mm; |
1226 | | |
1227 | | // also reduce by the "Height" (as calculated from the font) |
1228 | 0 | tools::Long nFontHeight = constTwips_5mm; // appropriate for 12pt font |
1229 | 0 | const OutputDevice* pOutDev = Application::GetDefaultDevice(); |
1230 | 0 | const SwViewShell* pViewSh |
1231 | 0 | = rDoc.getIDocumentLayoutAccess().GetCurrentViewShell(); |
1232 | 0 | UIName sParaStyle(bHeader ? "Header" : "Footer"); |
1233 | 0 | SwTextFormatColl* pStyle = rDoc.FindTextFormatCollByName(sParaStyle); |
1234 | 0 | if (pStyle && pOutDev) |
1235 | 0 | { |
1236 | 0 | SwFont aFont( |
1237 | 0 | &pStyle->GetAttrSet(), /*IDocumentSettingAccess=*/nullptr); |
1238 | | |
1239 | | // sledgehammer approach: since the in-use-font (Latin/CTL/CKJ) |
1240 | | // is not known, use the tallest of the three just to ensure fit. |
1241 | 0 | sal_uInt16 nHeight = aFont.GetHeight(pViewSh, *pOutDev); // Latin |
1242 | |
|
1243 | 0 | aFont.SetActual(SwFontScript::CTL); |
1244 | 0 | nHeight = std::max(nHeight, aFont.GetHeight(pViewSh, *pOutDev)); |
1245 | |
|
1246 | 0 | aFont.SetActual(SwFontScript::CJK); |
1247 | 0 | nFontHeight = std::max(nHeight, aFont.GetHeight(pViewSh, *pOutDev)); |
1248 | | |
1249 | | // Spacing: above and below paragraph |
1250 | 0 | const SvxULSpaceItem& rParaStyleUL = pStyle->GetULSpace(); |
1251 | 0 | nFontHeight += rParaStyleUL.GetUpper() + rParaStyleUL.GetLower(); |
1252 | | |
1253 | | // Border padding: top and bottom |
1254 | 0 | const SvxBoxItem rBorders = pStyle->GetBox(); |
1255 | 0 | nFontHeight += rBorders.CalcLineSpace(SvxBoxItemLine::TOP, true); |
1256 | 0 | nFontHeight += rBorders.CalcLineSpace(SvxBoxItemLine::BOTTOM, true); |
1257 | 0 | } |
1258 | 0 | nPageMargin -= nFontHeight; |
1259 | |
|
1260 | 0 | nPageMargin = std::max(nPageMargin, constTwips_5mm); |
1261 | 0 | if (bHeader) |
1262 | 0 | aPageUL.SetUpper(nPageMargin); |
1263 | 0 | else |
1264 | 0 | aPageUL.SetLower(nPageMargin); |
1265 | 0 | aNewDesc.GetMaster().SetFormatAttr(aPageUL); |
1266 | | |
1267 | | // force aggressively calculated font height as minimum to ensure |
1268 | | // effective margin stays the same (instead of getting smaller) |
1269 | 0 | SwFormatFrameSize aSize(rFormat.GetFrameSize()); |
1270 | 0 | aSize.SetHeightSizeType(SwFrameSize::Minimum); |
1271 | | // frame size property includes both Spacing + Height |
1272 | 0 | aSize.SetHeight(constTwips_5mm + nFontHeight); |
1273 | 0 | rFormat.SetFormatAttr(aSize); |
1274 | | |
1275 | | // in case the calculated font height isn't actually large enough, |
1276 | | // eat into spacing first before pushing into the content area. |
1277 | 0 | rFormat.SetFormatAttr(SwHeaderAndFooterEatSpacingItem( |
1278 | 0 | RES_HEADER_FOOTER_EAT_SPACING, true)); |
1279 | 0 | } |
1280 | 0 | } |
1281 | | |
1282 | | // Might as well turn on margin mirroring too - if appropriate |
1283 | 0 | if (pDlg->GetMirrorOnEvenPages() && !bHeaderAlreadyOn && !bFooterAlreadyOn |
1284 | 0 | && !bIsSinglePage |
1285 | 0 | && (aNewDesc.ReadUseOn() & UseOnPage::Mirror) == UseOnPage::All) |
1286 | 0 | { |
1287 | 0 | aNewDesc.WriteUseOn(rDesc.ReadUseOn() | UseOnPage::Mirror); |
1288 | 0 | } |
1289 | 0 | } |
1290 | |
|
1291 | 0 | const bool bCreateMirror = !bIsSinglePage && pDlg->GetMirrorOnEvenPages() |
1292 | 0 | && nMirrorPagesNeeded <= rSh.GetPageCnt(); |
1293 | 0 | if (bCreateMirror) |
1294 | 0 | { |
1295 | | // Use different left/right header/footer |
1296 | 0 | if ((bHeader && rDesc.IsHeaderShared()) || (!bHeader && rDesc.IsFooterShared())) |
1297 | 0 | { |
1298 | 0 | bChangePageDesc = true; |
1299 | 0 | if (bHeader) |
1300 | 0 | aNewDesc.ChgHeaderShare(/*Share=*/false); |
1301 | 0 | else |
1302 | 0 | aNewDesc.ChgFooterShare(/*Share=*/false); |
1303 | 0 | } |
1304 | 0 | } |
1305 | |
|
1306 | 0 | if (bChangePageDesc) |
1307 | 0 | rSh.ChgPageDesc(nPageDescIndex, aNewDesc); |
1308 | | |
1309 | | // Go to the header or footer insert position |
1310 | 0 | bool bInHF = false; |
1311 | 0 | bool bSkipMirror = true; |
1312 | 0 | size_t nEvenPage = 0; |
1313 | 0 | if (bCreateMirror || !rSh.GetCurrFrame()) |
1314 | 0 | { |
1315 | | // Come here if Currframe can't be found, otherwise Goto*Text will crash. |
1316 | | // Get*PageNum will also be invalid (0), so we have no idea where we are. |
1317 | | // (Since not asking for mirror, the likelihood is that the bHeader is shared, |
1318 | | // in which case it doesn't matter anyway, and we just hope for the best.) |
1319 | | // Read the code in this block assuming that bCreateMirror is true. |
1320 | | |
1321 | | // There are enough pages that there probably is a valid odd page. |
1322 | | // However, that is not guaranteed: perhaps the page style switched, |
1323 | | // or a blank page was forced, or some other complexity. |
1324 | 0 | bInHF = rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/true); |
1325 | 0 | if (bInHF) |
1326 | 0 | { |
1327 | | // Remember valid EVEN page. Mirror it if also a valid ODD or FIRST page |
1328 | 0 | nEvenPage = rSh.GetVirtPageNum(); |
1329 | 0 | assert (nEvenPage && "couldn't find page number. Use a bool instead"); |
1330 | 0 | } |
1331 | |
|
1332 | 0 | bInHF = rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/false); |
1333 | 0 | if (bInHF && nEvenPage) |
1334 | 0 | { |
1335 | | // Even though the cursor may be on a FIRST page, |
1336 | | // the user requested mirrored pages, and we have both ODD and EVEN, |
1337 | | // so set page numbers on these two pages, and leave FIRST alone. |
1338 | 0 | bSkipMirror = false; |
1339 | 0 | } |
1340 | 0 | if (!bInHF) |
1341 | 0 | { |
1342 | | // no ODD page, look for FIRST page |
1343 | 0 | bInHF = rSh.SetCursorInHdFt(nPageDescIndex, bHeader, false, /*First=*/true); |
1344 | 0 | if (bInHF && nEvenPage) |
1345 | 0 | { |
1346 | | // Unlikely but valid situation: EVEN and FIRST pages, but no ODD page. |
1347 | | // In this case, the first header gets the specified page number |
1348 | | // and the even header is mirrored, with an empty odd header, |
1349 | | // as the user (somewhat) requested. |
1350 | 0 | bSkipMirror = false; |
1351 | 0 | } |
1352 | 0 | } |
1353 | 0 | assert((bInHF || nEvenPage) && "Impossible - why couldn't the move happen?"); |
1354 | 0 | assert((bInHF || nEvenPage == rSh.GetVirtPageNum()) && "Unexpected move"); |
1355 | 0 | } |
1356 | 0 | else |
1357 | 0 | { |
1358 | 0 | if (bHeader) |
1359 | 0 | bInHF = rSh.GotoHeaderText(); |
1360 | 0 | else |
1361 | 0 | bInHF = rSh.GotoFooterText(); |
1362 | 0 | assert(bInHF && "shouldn't have a problem going to text when no mirroring"); |
1363 | 0 | } |
1364 | | |
1365 | | // Allow wizard to be re-run: delete previously wizard-inserted page number. |
1366 | | // Now that the cursor may have moved to a different page, try delete again. |
1367 | 0 | sBookmarkOddPage |
1368 | 0 | = SwMarkName(sBookmarkName + OUString::number(rSh.GetVirtPageNum())); |
1369 | 0 | ppMark = rIDMA.findMark(sBookmarkOddPage); |
1370 | 0 | if (ppMark != rIDMA.getAllMarksEnd() && *ppMark) |
1371 | 0 | { |
1372 | 0 | SwPaM aDeleteOldPageNum((*ppMark)->GetMarkStart(), (*ppMark)->GetMarkEnd()); |
1373 | 0 | rDoc.getIDocumentContentOperations().DeleteAndJoin(aDeleteOldPageNum); |
1374 | 0 | } |
1375 | |
|
1376 | 0 | SwTextNode* pTextNode = rSh.GetCursor()->GetPoint()->GetNode().GetTextNode(); |
1377 | | |
1378 | | // Insert new line if there is already text in header/footer |
1379 | 0 | if (pTextNode && !pTextNode->GetText().isEmpty()) |
1380 | 0 | { |
1381 | 0 | rDoc.getIDocumentContentOperations().SplitNode(*rSh.GetCursor()->GetPoint(), false); |
1382 | | |
1383 | | // Go back to start of header/footer |
1384 | 0 | if (bHeader) |
1385 | 0 | rSh.GotoHeaderText(); |
1386 | 0 | else |
1387 | 0 | rSh.GotoFooterText(); |
1388 | 0 | } |
1389 | | |
1390 | | // Set alignment for the new line |
1391 | 0 | switch (pDlg->GetPageNumberAlignment()) |
1392 | 0 | { |
1393 | 0 | case 0: |
1394 | 0 | { |
1395 | 0 | SvxAdjustItem aAdjustItem(SvxAdjust::Left, RES_PARATR_ADJUST); |
1396 | 0 | rSh.SetAttrItem(aAdjustItem); |
1397 | 0 | break; |
1398 | 0 | } |
1399 | 0 | case 1: |
1400 | 0 | { |
1401 | 0 | SvxAdjustItem aAdjustItem(SvxAdjust::Center, RES_PARATR_ADJUST); |
1402 | 0 | rSh.SetAttrItem(aAdjustItem); |
1403 | 0 | break; |
1404 | 0 | } |
1405 | 0 | case 2: |
1406 | 0 | { |
1407 | 0 | SvxAdjustItem aAdjustItem(SvxAdjust::Right, RES_PARATR_ADJUST); |
1408 | 0 | rSh.SetAttrItem(aAdjustItem); |
1409 | 0 | break; |
1410 | 0 | } |
1411 | 0 | } |
1412 | | |
1413 | 0 | sal_Int32 nStartContentIndex = rSh.GetCursor()->Start()->GetContentIndex(); |
1414 | 0 | assert(!nStartContentIndex && "earlier split node if not empty, but not zero?"); |
1415 | | |
1416 | | // Insert page number |
1417 | 0 | SwFieldMgr aMgr(pShell); |
1418 | 0 | SwInsertField_Data aData(SwFieldTypesEnum::PageNumber, 0, |
1419 | 0 | OUString(), OUString(), SVX_NUM_PAGEDESC); |
1420 | 0 | aMgr.InsertField(aData); |
1421 | 0 | if (pDlg->GetIncludePageTotal() || |
1422 | 0 | pDlg->GetIncludePageRangeTotal()) |
1423 | 0 | { |
1424 | 0 | rDoc.getIDocumentContentOperations().InsertString(*rSh.GetCursor(), u" / "_ustr); |
1425 | 0 | SwInsertField_Data aPageTotalData(SwFieldTypesEnum::DocumentStatistics, |
1426 | 0 | static_cast<sal_uInt16>(pDlg->GetIncludePageTotal() ? SwDocStatSubType::Page : SwDocStatSubType::PageRange), |
1427 | 0 | OUString(), OUString(), SVX_NUM_PAGEDESC); |
1428 | 0 | aMgr.InsertField(aPageTotalData); |
1429 | 0 | } |
1430 | | |
1431 | | // Mark inserted fields with a bookmark - so it can be found/removed if re-run |
1432 | 0 | SwPaM aNewBookmarkPaM(*rSh.GetCursor()->Start()); |
1433 | 0 | aNewBookmarkPaM.SetMark(); |
1434 | 0 | assert(aNewBookmarkPaM.GetPointContentNode() && "only SetContent on content node"); |
1435 | 0 | aNewBookmarkPaM.Start()->SetContent(nStartContentIndex); |
1436 | 0 | rIDMA.makeMark(aNewBookmarkPaM, |
1437 | 0 | sBookmarkOddPage, |
1438 | 0 | IDocumentMarkAccess::MarkType::BOOKMARK, |
1439 | 0 | sw::mark::InsertMode::New); |
1440 | | |
1441 | | // Mirror on the even pages |
1442 | 0 | if (!bSkipMirror && bCreateMirror |
1443 | 0 | && rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/true)) |
1444 | 0 | { |
1445 | 0 | assert(nEvenPage && "what? no even page and yet we got here?"); |
1446 | 0 | SwMarkName sBookmarkEvenPage( |
1447 | 0 | sBookmarkName + OUString::number(rSh.GetVirtPageNum())); |
1448 | 0 | ppMark = rIDMA.findMark(sBookmarkEvenPage); |
1449 | 0 | if (ppMark != rIDMA.getAllMarksEnd() && *ppMark) |
1450 | 0 | { |
1451 | 0 | SwPaM aDeleteOldPageNum((*ppMark)->GetMarkStart(), (*ppMark)->GetMarkEnd()); |
1452 | 0 | rDoc.getIDocumentContentOperations().DeleteAndJoin(aDeleteOldPageNum); |
1453 | 0 | } |
1454 | |
|
1455 | 0 | pTextNode = rSh.GetCursor()->GetPoint()->GetNode().GetTextNode(); |
1456 | | |
1457 | | // Insert new line if there is already text in header/footer |
1458 | 0 | if (pTextNode && !pTextNode->GetText().isEmpty()) |
1459 | 0 | { |
1460 | 0 | rDoc.getIDocumentContentOperations().SplitNode( |
1461 | 0 | *rSh.GetCursor()->GetPoint(), false); |
1462 | | // Go back to start of header/footer |
1463 | 0 | rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/true); |
1464 | 0 | } |
1465 | | |
1466 | | // mirror the adjustment |
1467 | 0 | assert(pDlg->GetPageNumberAlignment() != 1 && "cannot have Center and bMirror"); |
1468 | 0 | SvxAdjust eAdjust = SvxAdjust::Left; |
1469 | 0 | if (!pDlg->GetPageNumberAlignment()) |
1470 | 0 | eAdjust = SvxAdjust::Right; |
1471 | 0 | SvxAdjustItem aMirrorAdjustItem(eAdjust, RES_PARATR_ADJUST); |
1472 | 0 | rSh.SetAttrItem(aMirrorAdjustItem); |
1473 | |
|
1474 | 0 | nStartContentIndex = rSh.GetCursor()->Start()->GetContentIndex(); |
1475 | | |
1476 | | // Insert page number |
1477 | 0 | SwFieldMgr aEvenMgr(pShell); |
1478 | 0 | aEvenMgr.InsertField(aData); |
1479 | 0 | if (pDlg->GetIncludePageTotal()) |
1480 | 0 | { |
1481 | 0 | rDoc.getIDocumentContentOperations().InsertString(*rSh.GetCursor(), u" / "_ustr); |
1482 | 0 | SwInsertField_Data aPageTotalData(SwFieldTypesEnum::DocumentStatistics, |
1483 | 0 | static_cast<sal_uInt16>(SwDocStatSubType::Page), OUString(), OUString(), |
1484 | 0 | SVX_NUM_PAGEDESC); |
1485 | 0 | aMgr.InsertField(aPageTotalData); |
1486 | 0 | } |
1487 | | |
1488 | | // Mark inserted fields with a bookmark - so it can be found/removed if re-run |
1489 | 0 | SwPaM aNewEvenBookmarkPaM(*rSh.GetCursor()->Start()); |
1490 | 0 | aNewEvenBookmarkPaM.SetMark(); |
1491 | 0 | aNewEvenBookmarkPaM.Start()->SetContent(nStartContentIndex); |
1492 | 0 | rIDMA.makeMark(aNewEvenBookmarkPaM, |
1493 | 0 | sBookmarkEvenPage, |
1494 | 0 | IDocumentMarkAccess::MarkType::BOOKMARK, |
1495 | 0 | sw::mark::InsertMode::New); |
1496 | 0 | } |
1497 | |
|
1498 | 0 | rSh.SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent); |
1499 | 0 | rSh.EndAllAction(); |
1500 | 0 | rSh.LockView(false); |
1501 | 0 | rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_PAGE_NUMBER, nullptr); |
1502 | | |
1503 | | // avoid various ways to crash related to undo of SwPageDesc (tdf#161741, tdf#161705) |
1504 | 0 | if (bChangePageDesc) |
1505 | 0 | rDoc.GetIDocumentUndoRedo().DelAllUndoObj(); |
1506 | 0 | } |
1507 | 0 | pDlg->disposeOnce(); |
1508 | 0 | }); |
1509 | 0 | rReq.Done(); |
1510 | 0 | } |
1511 | 0 | break; |
1512 | 0 | case FN_UPDATE_TEXT_FORMFIELD: |
1513 | 0 | { |
1514 | | // This updates a single fieldmark under the current cursor. |
1515 | 0 | OUString aFieldType; |
1516 | 0 | const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1); |
1517 | 0 | if (pFieldType) |
1518 | 0 | { |
1519 | 0 | aFieldType = pFieldType->GetValue(); |
1520 | 0 | } |
1521 | 0 | OUString aFieldCommandPrefix; |
1522 | 0 | const SfxStringItem* pFieldCommandPrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2); |
1523 | 0 | if (pFieldCommandPrefix) |
1524 | 0 | { |
1525 | 0 | aFieldCommandPrefix = pFieldCommandPrefix->GetValue(); |
1526 | 0 | } |
1527 | 0 | uno::Sequence<beans::PropertyValue> aField; |
1528 | 0 | const SfxUnoAnyItem* pFields = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_3); |
1529 | 0 | if (pFields) |
1530 | 0 | { |
1531 | 0 | pFields->GetValue() >>= aField; |
1532 | 0 | } |
1533 | |
|
1534 | 0 | IDocumentMarkAccess& rIDMA = *rSh.getIDocumentMarkAccess(); |
1535 | 0 | SwPosition& rCursor = *rSh.GetCursor()->GetPoint(); |
1536 | 0 | sw::mark::Fieldmark* pFieldmark = rIDMA.getInnerFieldmarkFor(rCursor); |
1537 | 0 | if (!pFieldmark) |
1538 | 0 | { |
1539 | 0 | break; |
1540 | 0 | } |
1541 | | |
1542 | 0 | if (pFieldmark->GetFieldname() != aFieldType) |
1543 | 0 | { |
1544 | 0 | break; |
1545 | 0 | } |
1546 | | |
1547 | 0 | auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM); |
1548 | 0 | if (itParam == pFieldmark->GetParameters()->end()) |
1549 | 0 | { |
1550 | 0 | break; |
1551 | 0 | } |
1552 | | |
1553 | 0 | OUString aCommand; |
1554 | 0 | itParam->second >>= aCommand; |
1555 | 0 | if (!aCommand.startsWith(aFieldCommandPrefix)) |
1556 | 0 | { |
1557 | 0 | break; |
1558 | 0 | } |
1559 | | |
1560 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_FORM_FIELD, nullptr); |
1561 | 0 | rSh.StartAction(); |
1562 | 0 | comphelper::SequenceAsHashMap aMap(aField); |
1563 | 0 | itParam->second = aMap[u"FieldCommand"_ustr]; |
1564 | 0 | SwPaM aPaM(pFieldmark->GetMarkPos(), pFieldmark->GetOtherMarkPos()); |
1565 | 0 | aPaM.Normalize(); |
1566 | | // Skip field start & separator. |
1567 | 0 | aPaM.GetPoint()->AdjustContent(2); |
1568 | | // Skip field end. |
1569 | 0 | aPaM.GetMark()->AdjustContent(-1); |
1570 | 0 | rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPaM); |
1571 | 0 | OUString aFieldResult; |
1572 | 0 | aMap[u"FieldResult"_ustr] >>= aFieldResult; |
1573 | 0 | SwTranslateHelper::PasteHTMLToPaM(rSh, &aPaM, aFieldResult.toUtf8()); |
1574 | |
|
1575 | 0 | rSh.EndAction(); |
1576 | 0 | rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_FORM_FIELD, nullptr); |
1577 | 0 | } |
1578 | 0 | break; |
1579 | 0 | default: |
1580 | 0 | OSL_FAIL("wrong dispatcher"); |
1581 | 0 | return; |
1582 | 0 | } |
1583 | 0 | } |
1584 | | |
1585 | | void SwTextShell::StateField( SfxItemSet &rSet ) |
1586 | 0 | { |
1587 | 0 | SwWrtShell& rSh = GetShell(); |
1588 | 0 | SfxWhichIter aIter( rSet ); |
1589 | 0 | const SwField* pField = nullptr; |
1590 | 0 | bool bGetField = false; |
1591 | 0 | sal_uInt16 nWhich = aIter.FirstWhich(); |
1592 | |
|
1593 | 0 | while (nWhich) |
1594 | 0 | { |
1595 | 0 | switch (nWhich) |
1596 | 0 | { |
1597 | 0 | case FN_DELETE_COMMENT: |
1598 | 0 | case FN_DELETE_NOTE_AUTHOR: |
1599 | 0 | case FN_DELETE_ALL_NOTES: |
1600 | 0 | case FN_FORMAT_ALL_NOTES: |
1601 | 0 | case FN_HIDE_NOTE: |
1602 | 0 | case FN_HIDE_NOTE_AUTHOR: |
1603 | 0 | case FN_HIDE_ALL_NOTES: |
1604 | 0 | { |
1605 | 0 | SwPostItMgr* pPostItMgr = GetView().GetPostItMgr(); |
1606 | 0 | if ( !pPostItMgr ) |
1607 | 0 | rSet.InvalidateItem( nWhich ); |
1608 | 0 | else if ( !pPostItMgr->HasActiveSidebarWin() ) |
1609 | 0 | { |
1610 | 0 | rSet.InvalidateItem( FN_DELETE_COMMENT ); |
1611 | 0 | rSet.InvalidateItem( FN_HIDE_NOTE ); |
1612 | 0 | } |
1613 | | // tdf#137568 do not offer comment formatting, if no comments are present |
1614 | 0 | if (!pPostItMgr || !pPostItMgr->HasNotes()) |
1615 | 0 | rSet.DisableItem( FN_FORMAT_ALL_NOTES ); |
1616 | 0 | } |
1617 | 0 | break; |
1618 | | |
1619 | 0 | case FN_EDIT_FIELD: |
1620 | 0 | { |
1621 | 0 | if( !bGetField ) |
1622 | 0 | { |
1623 | 0 | pField = rSh.GetCurField(true); |
1624 | 0 | bGetField = true; |
1625 | 0 | } |
1626 | |
|
1627 | 0 | SwFieldIds nTempWhich = pField ? pField->GetTyp()->Which() : SwFieldIds::Unknown; |
1628 | 0 | if( SwFieldIds::Unknown == nTempWhich || |
1629 | 0 | SwFieldIds::Postit == nTempWhich || |
1630 | 0 | SwFieldIds::Script == nTempWhich || |
1631 | 0 | SwFieldIds::TableOfAuthorities == nTempWhich ) |
1632 | 0 | rSet.DisableItem( nWhich ); |
1633 | 0 | else if( SwFieldIds::Dde == nTempWhich && |
1634 | 0 | !static_cast<SwDDEFieldType*>(pField->GetTyp())->GetBaseLink().IsVisible()) |
1635 | 0 | { |
1636 | | // nested links cannot be edited |
1637 | 0 | rSet.DisableItem( nWhich ); |
1638 | 0 | } |
1639 | 0 | } |
1640 | 0 | break; |
1641 | 0 | case FN_COPY_FIELD: |
1642 | 0 | { |
1643 | 0 | if( !bGetField ) |
1644 | 0 | { |
1645 | 0 | pField = rSh.GetCurField(true); |
1646 | 0 | bGetField = true; |
1647 | 0 | } |
1648 | 0 | SwFieldIds nTempWhich = pField ? pField->GetTyp()->Which() : SwFieldIds::Unknown; |
1649 | 0 | if (SwFieldIds::Unknown == nTempWhich |
1650 | 0 | || !pField->ExpandField(true, nullptr).getLength()) |
1651 | 0 | rSet.DisableItem( nWhich ); |
1652 | 0 | } |
1653 | 0 | break; |
1654 | 0 | case FN_UPDATE_SEL_FIELD: |
1655 | 0 | { |
1656 | 0 | pField = rSh.GetCurField(); |
1657 | 0 | if (!pField) |
1658 | 0 | rSet.DisableItem( nWhich ); |
1659 | 0 | } |
1660 | 0 | break; |
1661 | 0 | case FN_CONVERT_SEL_FIELD: |
1662 | 0 | { |
1663 | 0 | pField = rSh.GetCurField(); |
1664 | 0 | SwFieldIds eFieldIds = pField ? pField->GetTyp()->Which() : SwFieldIds::Unknown; |
1665 | 0 | bool bInHeaderFooter = rSh.IsInHeaderFooter(); |
1666 | 0 | if (!pField || |
1667 | 0 | eFieldIds == SwFieldIds::Postit || |
1668 | 0 | eFieldIds == SwFieldIds::SetRef || |
1669 | 0 | eFieldIds == SwFieldIds::SetExp || |
1670 | 0 | eFieldIds == SwFieldIds::RefPageSet|| |
1671 | 0 | eFieldIds == SwFieldIds::Input || |
1672 | 0 | eFieldIds == SwFieldIds::JumpEdit || |
1673 | 0 | (bInHeaderFooter && |
1674 | 0 | (eFieldIds == SwFieldIds::PageNumber || |
1675 | 0 | eFieldIds == SwFieldIds::Chapter || |
1676 | 0 | eFieldIds == SwFieldIds::GetExp || |
1677 | 0 | eFieldIds == SwFieldIds::RefPageGet || |
1678 | 0 | eFieldIds == SwFieldIds::GetRef |
1679 | 0 | ))) |
1680 | 0 | rSet.DisableItem( nWhich ); |
1681 | 0 | } |
1682 | 0 | break; |
1683 | | |
1684 | 0 | case FN_EXECUTE_MACROFIELD: |
1685 | 0 | { |
1686 | 0 | if(!bGetField) |
1687 | 0 | { |
1688 | 0 | pField = rSh.GetCurField(); |
1689 | 0 | bGetField = true; |
1690 | 0 | } |
1691 | 0 | if(!pField || pField->GetTyp()->Which() != SwFieldIds::Macro) |
1692 | 0 | rSet.DisableItem(nWhich); |
1693 | 0 | } |
1694 | 0 | break; |
1695 | | |
1696 | 0 | case FN_INSERT_FIELD: |
1697 | 0 | { |
1698 | 0 | if ( rSh.CursorInsideInputField() ) |
1699 | 0 | { |
1700 | 0 | rSet.DisableItem(nWhich); |
1701 | 0 | } |
1702 | 0 | else |
1703 | 0 | { |
1704 | 0 | SfxViewFrame& rVFrame = GetView().GetViewFrame(); |
1705 | | //#i5788# prevent closing of the field dialog while a modal dialog ( Input field dialog ) is active |
1706 | 0 | if(!rVFrame.IsInModalMode() && |
1707 | 0 | rVFrame.KnowsChildWindow(FN_INSERT_FIELD) && !rVFrame.HasChildWindow(FN_INSERT_FIELD_DATA_ONLY) ) |
1708 | 0 | rSet.Put(SfxBoolItem( FN_INSERT_FIELD, rVFrame.HasChildWindow(nWhich))); |
1709 | 0 | else |
1710 | 0 | rSet.DisableItem(FN_INSERT_FIELD); |
1711 | 0 | } |
1712 | 0 | } |
1713 | 0 | break; |
1714 | | |
1715 | 0 | case FN_INSERT_REF_FIELD: |
1716 | 0 | { |
1717 | 0 | SfxViewFrame& rVFrame = GetView().GetViewFrame(); |
1718 | 0 | if ( !rVFrame.KnowsChildWindow(FN_INSERT_FIELD) |
1719 | 0 | || rSh.CursorInsideInputField() ) |
1720 | 0 | { |
1721 | 0 | rSet.DisableItem(FN_INSERT_REF_FIELD); |
1722 | 0 | } |
1723 | 0 | } |
1724 | 0 | break; |
1725 | | |
1726 | 0 | case FN_INSERT_FIELD_CTRL: |
1727 | 0 | if ( rSh.CursorInsideInputField() ) |
1728 | 0 | { |
1729 | 0 | rSet.DisableItem(nWhich); |
1730 | 0 | } |
1731 | 0 | else |
1732 | 0 | { |
1733 | 0 | rSet.Put(SfxBoolItem( nWhich, GetView().GetViewFrame().HasChildWindow(FN_INSERT_FIELD))); |
1734 | 0 | } |
1735 | 0 | break; |
1736 | | |
1737 | 0 | case FN_REDLINE_COMMENT: |
1738 | 0 | if (!comphelper::LibreOfficeKit::isActive() && !rSh.GetCurrRedline()) |
1739 | 0 | rSet.DisableItem(nWhich); |
1740 | 0 | break; |
1741 | | |
1742 | 0 | case FN_REPLY: |
1743 | 0 | if (!comphelper::LibreOfficeKit::isActive()) |
1744 | 0 | rSet.DisableItem(nWhich); |
1745 | 0 | break; |
1746 | | |
1747 | 0 | case FN_POSTIT : |
1748 | 0 | case FN_JAVAEDIT : |
1749 | 0 | { |
1750 | 0 | bool bCurField = false; |
1751 | 0 | pField = rSh.GetCurField(); |
1752 | 0 | if(nWhich == FN_POSTIT) |
1753 | 0 | bCurField = pField && pField->GetTyp()->Which() == SwFieldIds::Postit; |
1754 | 0 | else |
1755 | 0 | bCurField = pField && pField->GetTyp()->Which() == SwFieldIds::Script; |
1756 | |
|
1757 | 0 | if( !bCurField && rSh.IsReadOnlyAvailable() && rSh.HasReadonlySel() ) |
1758 | 0 | { |
1759 | 0 | rSet.DisableItem(nWhich); |
1760 | 0 | } |
1761 | 0 | else if ( rSh.CursorInsideInputField() ) |
1762 | 0 | { |
1763 | 0 | rSet.DisableItem(nWhich); |
1764 | 0 | } |
1765 | | // tdf#86188, tdf#135794: Allow disabling comment insertion |
1766 | | // on footnote/endnote/header/frames for better OOXML interoperability |
1767 | 0 | else if (!officecfg::Office::Compatibility::View::AllowCommentsInFootnotes::get() && |
1768 | 0 | (rSh.IsCursorInFootnote() || rSh.IsInHeaderFooter() || |
1769 | 0 | rSh.GetCurrFlyFrame(/*bCalcFrame=*/false))) |
1770 | 0 | { |
1771 | 0 | rSet.DisableItem(nWhich); |
1772 | 0 | } |
1773 | 0 | } |
1774 | |
|
1775 | 0 | break; |
1776 | | |
1777 | 0 | case FN_INSERT_FLD_AUTHOR: |
1778 | 0 | case FN_INSERT_FLD_DATE: |
1779 | 0 | case FN_INSERT_FLD_PGCOUNT: |
1780 | 0 | case FN_INSERT_FLD_RANGE_PGCOUNT: |
1781 | 0 | case FN_INSERT_FLD_PGNUMBER: |
1782 | 0 | case FN_INSERT_FLD_TIME: |
1783 | 0 | case FN_INSERT_FLD_TITLE: |
1784 | 0 | case FN_INSERT_FLD_TOPIC: |
1785 | 0 | case FN_INSERT_DBFIELD: |
1786 | 0 | if ( rSh.CursorInsideInputField() ) |
1787 | 0 | { |
1788 | 0 | rSet.DisableItem(nWhich); |
1789 | 0 | } |
1790 | 0 | break; |
1791 | | |
1792 | 0 | case FN_INSERT_TEXT_FORMFIELD: |
1793 | 0 | case FN_INSERT_CHECKBOX_FORMFIELD: |
1794 | 0 | case FN_INSERT_DROPDOWN_FORMFIELD: |
1795 | 0 | case FN_INSERT_DATE_FORMFIELD: |
1796 | 0 | if ( rSh.CursorInsideInputField() ) |
1797 | 0 | { |
1798 | 0 | rSet.DisableItem(nWhich); |
1799 | 0 | } |
1800 | 0 | else |
1801 | 0 | { |
1802 | | // Check whether we are in a text form field |
1803 | 0 | SwPosition aCursorPos(*rSh.GetCursor()->GetPoint()); |
1804 | 0 | sw::mark::Fieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aCursorPos); |
1805 | 0 | if ((!pFieldBM || pFieldBM->GetFieldname() != ODF_FORMTEXT) |
1806 | 0 | && aCursorPos.GetContentIndex() > 0) |
1807 | 0 | { |
1808 | 0 | SwPosition aPos(*aCursorPos.GetContentNode(), aCursorPos.GetContentIndex() - 1); |
1809 | 0 | pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos); |
1810 | 0 | } |
1811 | 0 | if (pFieldBM && pFieldBM->GetFieldname() == ODF_FORMTEXT && |
1812 | 0 | (aCursorPos > pFieldBM->GetMarkStart() && aCursorPos < pFieldBM->GetMarkEnd() )) |
1813 | 0 | { |
1814 | 0 | rSet.DisableItem(nWhich); |
1815 | 0 | } |
1816 | 0 | } |
1817 | 0 | break; |
1818 | |
|
1819 | 0 | } |
1820 | 0 | nWhich = aIter.NextWhich(); |
1821 | 0 | } |
1822 | 0 | } |
1823 | | |
1824 | | void SwTextShell::InsertHyperlink(const SvxHyperlinkItem& rHlnkItem) |
1825 | 0 | { |
1826 | 0 | const OUString& rName = rHlnkItem.GetName(); |
1827 | 0 | const OUString& rURL = rHlnkItem.GetURL(); |
1828 | 0 | const OUString& rTarget = rHlnkItem.GetTargetFrame(); |
1829 | 0 | const OUString& rReplacementText = rHlnkItem.GetReplacementText(); |
1830 | 0 | sal_uInt16 nType = o3tl::narrowing<sal_uInt16>(rHlnkItem.GetInsertMode()); |
1831 | 0 | nType &= ~HLINK_HTMLMODE; |
1832 | 0 | const SvxMacroTableDtor* pMacroTable = rHlnkItem.GetMacroTable(); |
1833 | |
|
1834 | 0 | SwWrtShell& rSh = GetShell(); |
1835 | |
|
1836 | 0 | if( !(rSh.GetSelectionType() & SelectionType::Text) ) |
1837 | 0 | return; |
1838 | | |
1839 | 0 | rSh.StartAction(); |
1840 | 0 | SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool()); |
1841 | 0 | rSh.GetCurAttr( aSet ); |
1842 | |
|
1843 | 0 | if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false)) |
1844 | 0 | { |
1845 | | // Select links |
1846 | 0 | rSh.SwCursorShell::SelectTextAttr(RES_TXTATR_INETFMT, false); |
1847 | 0 | } |
1848 | 0 | switch (nType) |
1849 | 0 | { |
1850 | 0 | case HLINK_DEFAULT: |
1851 | 0 | case HLINK_FIELD: |
1852 | 0 | { |
1853 | 0 | SwFormatINetFormat aINetFormat( rURL, rTarget ); |
1854 | 0 | aINetFormat.SetName(rHlnkItem.GetIntName()); |
1855 | 0 | if(pMacroTable) |
1856 | 0 | { |
1857 | 0 | const SvxMacro *pMacro = pMacroTable->Get( SvMacroItemId::OnMouseOver ); |
1858 | 0 | if( pMacro ) |
1859 | 0 | aINetFormat.SetMacro(SvMacroItemId::OnMouseOver, *pMacro); |
1860 | 0 | pMacro = pMacroTable->Get( SvMacroItemId::OnClick ); |
1861 | 0 | if( pMacro ) |
1862 | 0 | aINetFormat.SetMacro(SvMacroItemId::OnClick, *pMacro); |
1863 | 0 | pMacro = pMacroTable->Get( SvMacroItemId::OnMouseOut ); |
1864 | 0 | if( pMacro ) |
1865 | 0 | aINetFormat.SetMacro(SvMacroItemId::OnMouseOut, *pMacro); |
1866 | 0 | } |
1867 | 0 | rSh.SttSelect(); |
1868 | | // inserting mention |
1869 | 0 | if (comphelper::LibreOfficeKit::isActive() && !rReplacementText.isEmpty()) |
1870 | 0 | { |
1871 | 0 | SwPaM* pCursorPos = rSh.GetCursor(); |
1872 | | // move cursor backwards to select @mention |
1873 | 0 | for(int i=0; i < rReplacementText.getLength(); i++) |
1874 | 0 | pCursorPos->Move(fnMoveBackward); |
1875 | 0 | rSh.InsertURL( aINetFormat, rName, false ); |
1876 | 0 | } |
1877 | 0 | else |
1878 | 0 | { |
1879 | 0 | rSh.InsertURL( aINetFormat, rName, true ); |
1880 | 0 | } |
1881 | 0 | rSh.EndSelect(); |
1882 | 0 | } |
1883 | 0 | break; |
1884 | | |
1885 | 0 | case HLINK_BUTTON: |
1886 | 0 | bool bSel = rSh.HasSelection(); |
1887 | 0 | if(bSel) |
1888 | 0 | rSh.DelRight(); |
1889 | 0 | InsertURLButton( rURL, rTarget, rName ); |
1890 | 0 | rSh.EnterStdMode(); |
1891 | 0 | break; |
1892 | 0 | } |
1893 | 0 | rSh.EndAction(); |
1894 | 0 | } |
1895 | | |
1896 | | IMPL_LINK( SwTextShell, RedlineNextHdl, AbstractSvxPostItDialog&, rDlg, void ) |
1897 | 0 | { |
1898 | 0 | SwWrtShell* pSh = GetShellPtr(); |
1899 | | |
1900 | | // Insert or change a comment. |
1901 | 0 | pSh->SetRedlineComment(rDlg.GetNote()); |
1902 | |
|
1903 | 0 | const SwRangeRedline *pRedline = pSh->GetCurrRedline(); |
1904 | |
|
1905 | 0 | if (!pRedline) |
1906 | 0 | return; |
1907 | | |
1908 | | // Traveling only if more than one field. |
1909 | 0 | if( !pSh->IsCursorPtAtEnd() ) |
1910 | 0 | pSh->SwapPam(); // Move the cursor behind the Redline. |
1911 | |
|
1912 | 0 | pSh->Push(); |
1913 | 0 | const SwRangeRedline *pActRed = pSh->SelNextRedline(); |
1914 | 0 | pSh->Pop((pActRed != nullptr) ? SwCursorShell::PopMode::DeleteStack : SwCursorShell::PopMode::DeleteCurrent); |
1915 | |
|
1916 | 0 | bool bEnable = false; |
1917 | |
|
1918 | 0 | if (pActRed) |
1919 | 0 | { |
1920 | 0 | pSh->StartAction(); |
1921 | 0 | pSh->Push(); |
1922 | 0 | bEnable = pSh->SelNextRedline() != nullptr; |
1923 | 0 | pSh->Pop(SwCursorShell::PopMode::DeleteCurrent); |
1924 | 0 | pSh->EndAction(); |
1925 | 0 | } |
1926 | |
|
1927 | 0 | rDlg.EnableTravel(bEnable, true); |
1928 | |
|
1929 | 0 | if( pSh->IsCursorPtAtEnd() ) |
1930 | 0 | pSh->SwapPam(); |
1931 | |
|
1932 | 0 | pRedline = pSh->GetCurrRedline(); |
1933 | 0 | OUString sComment = convertLineEnd(pRedline->GetComment(), GetSystemLineEnd()); |
1934 | |
|
1935 | 0 | rDlg.SetNote(sComment); |
1936 | 0 | rDlg.ShowLastAuthor( pRedline->GetAuthorString(), |
1937 | 0 | GetAppLangDateTimeString( |
1938 | 0 | pRedline->GetRedlineData().GetTimeStamp() )); |
1939 | |
|
1940 | 0 | rDlg.SetText(lcl_BuildTitleWithRedline(pRedline)); |
1941 | |
|
1942 | 0 | } |
1943 | | |
1944 | | IMPL_LINK( SwTextShell, RedlinePrevHdl, AbstractSvxPostItDialog&, rDlg, void ) |
1945 | 0 | { |
1946 | 0 | SwWrtShell* pSh = GetShellPtr(); |
1947 | | |
1948 | | // Insert or change a comment. |
1949 | 0 | pSh->SetRedlineComment(rDlg.GetNote()); |
1950 | |
|
1951 | 0 | const SwRangeRedline *pRedline = pSh->GetCurrRedline(); |
1952 | |
|
1953 | 0 | if (!pRedline) |
1954 | 0 | return; |
1955 | | |
1956 | | // Traveling only if more than one field. |
1957 | 0 | pSh->Push(); |
1958 | 0 | const SwRangeRedline *pActRed = pSh->SelPrevRedline(); |
1959 | 0 | pSh->Pop((pActRed != nullptr) ? SwCursorShell::PopMode::DeleteStack : SwCursorShell::PopMode::DeleteCurrent); |
1960 | |
|
1961 | 0 | bool bEnable = false; |
1962 | |
|
1963 | 0 | if (pActRed) |
1964 | 0 | { |
1965 | 0 | pSh->StartAction(); |
1966 | 0 | pSh->Push(); |
1967 | 0 | bEnable = pSh->SelPrevRedline() != nullptr; |
1968 | 0 | pSh->Pop(SwCursorShell::PopMode::DeleteCurrent); |
1969 | 0 | pSh->EndAction(); |
1970 | 0 | } |
1971 | |
|
1972 | 0 | rDlg.EnableTravel(true, bEnable); |
1973 | |
|
1974 | 0 | pRedline = pSh->GetCurrRedline(); |
1975 | 0 | OUString sComment = convertLineEnd(pRedline->GetComment(), GetSystemLineEnd()); |
1976 | |
|
1977 | 0 | rDlg.SetNote(sComment); |
1978 | 0 | rDlg.ShowLastAuthor(pRedline->GetAuthorString(), |
1979 | 0 | GetAppLangDateTimeString( |
1980 | 0 | pRedline->GetRedlineData().GetTimeStamp() )); |
1981 | |
|
1982 | 0 | rDlg.SetText(lcl_BuildTitleWithRedline(pRedline)); |
1983 | |
|
1984 | 0 | } |
1985 | | |
1986 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |