Coverage Report

Created: 2025-12-08 09:28

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