Coverage Report

Created: 2026-11-06 11:29

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